1
target-arm queue: I have a lot more still in my to-review
1
Hi; here's another Arm pullreq: the big thing in here is
2
queue, but my rule of thumb is when I get to 50 patches or
2
Bernhard's imx8mp-evk board model; there's also various cleanup
3
so to send out what I have.
3
type patches from me, as well as some bugfixes.
4
4
5
thanks
5
thanks
6
-- PMM
6
-- PMM
7
7
8
The following changes since commit 9a7beaad3dbba982f7a461d676b55a5c3851d312:
8
The following changes since commit b69801dd6b1eb4d107f7c2f643adf0a4e3ec9124:
9
9
10
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210304' into staging (2021-03-05 10:47:46 +0000)
10
Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging (2025-02-22 05:06:39 +0800)
11
11
12
are available in the Git repository at:
12
are available in the Git repository at:
13
13
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210305
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20250225
15
15
16
for you to fetch changes up to 2c669ff88ec6733420a000103a2b8b9e93df4945:
16
for you to fetch changes up to 1aaf3478684ff1cd02d1b36c32a00bfac9a5dbd5:
17
17
18
hw/arm/mps2: Update old infocenter.arm.com URLs (2021-03-05 15:17:38 +0000)
18
hw/arm/fsl-imx8mp: Add on-chip RAM (2025-02-25 17:24:00 +0000)
19
19
20
----------------------------------------------------------------
20
----------------------------------------------------------------
21
* sbsa-ref: remove cortex-a53 from list of supported cpus
21
target-arm queue:
22
* sbsa-ref: add 'max' to list of allowed cpus
22
* hw/arm/smmuv3: Fill u.f_cd_fetch.addr for SMMU_EVT_F_CD_FETCH
23
* target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
23
* hw/arm/virt: Support larger highmem MMIO regions
24
* npcm7xx: add EMC model
24
* machine: Centralize -machine dumpdtb option handling and report
25
* xlnx-zynqmp: Remove obsolete 'has_rpu' property
25
attempt to dump nonexistent DTB as an error
26
* target/arm: Speed up aarch64 TBL/TBX
26
* fpu: remove target ifdefs and build it only once
27
* virtio-mmio: improve virtio-mmio get_dev_path alog
27
* target/arm: Refactor to move TCG-only vfp_helper code into tcg/
28
* target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
28
* target/arm/hvf: Disable SME feature
29
* target/arm: Restrict v8M IDAU to TCG
29
* target/arm/hvf: sign extend the data for a load operation when SSE=1
30
* target/arm/cpu: Update coding style to make checkpatch.pl happy
30
* hw/misc/npcm_clk: fix buffer-overflow
31
* musicpal, tc6393xb, omap_lcdc, tcx: drop dead code for non-32-bit-RGB surfaces
31
* hw/arm: Add i.MX 8M Plus EVK board ("imx8mp-evk")
32
* Add new board: mps3-an524
33
32
34
----------------------------------------------------------------
33
----------------------------------------------------------------
35
Doug Evans (3):
34
Bernhard Beschow (16):
36
hw/net: Add npcm7xx emc model
35
hw/usb/hcd-dwc3: Align global registers size with Linux
37
hw/arm: Add npcm7xx emc model
36
hw/pci-host/designware: Prevent device attachment on internal PCIe root bus
38
tests/qtests: Add npcm7xx emc model test
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
39
51
40
Marcin Juszkiewicz (2):
52
Joelle van Dyne (2):
41
sbsa-ref: remove cortex-a53 from list of supported cpus
53
target/arm/hvf: Disable SME feature
42
sbsa-ref: add 'max' to list of allowed cpus
54
target/arm/hvf: sign extend the data for a load operation when SSE=1
43
55
44
Peter Collingbourne (1):
56
Matthew R. Ochs (1):
45
target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
57
hw/arm/virt: Support larger highmem MMIO regions
46
58
47
Peter Maydell (34):
59
Nicolin Chen (1):
48
hw/arm/musicpal: Remove dead code for non-32-bit-RGB surfaces
60
hw/arm/smmuv3: Fill u.f_cd_fetch.addr for SMMU_EVT_F_CD_FETCH
49
hw/display/tc6393xb: Remove dead code for handling non-32bpp surfaces
50
hw/display/tc6393xb: Expand out macros in template header
51
hw/display/tc6393xb: Inline tc6393xb_draw_graphic32() at its callsite
52
hw/display/omap_lcdc: Expand out macros in template header
53
hw/display/omap_lcdc: Drop broken bigendian ifdef
54
hw/display/omap_lcdc: Fix coding style issues in template header
55
hw/display/omap_lcdc: Inline template header into C file
56
hw/display/omap_lcdc: Delete unnecessary macro
57
hw/display/tcx: Drop unnecessary code for handling BGR format outputs
58
hw/arm/mps2-tz: Make SYSCLK frequency board-specific
59
hw/misc/mps2-scc: Support configurable number of OSCCLK values
60
hw/arm/mps2-tz: Correct the OSCCLK settings for mps2-an505 and mps2-an511
61
hw/arm/mps2-tz: Make the OSCCLK settings be configurable per-board
62
hw/misc/mps2-fpgaio: Make number of LEDs configurable by board
63
hw/misc/mps2-fpgaio: Support SWITCH register
64
hw/arm/mps2-tz: Make FPGAIO switch and LED config per-board
65
hw/arm/mps2-tz: Condition IRQ splitting on number of CPUs, not board type
66
hw/arm/mps2-tz: Make number of IRQs board-specific
67
hw/misc/mps2-scc: Implement CFG_REG5 and CFG_REG6 for MPS3 AN524
68
hw/arm/mps2-tz: Correct wrong interrupt numbers for DMA and SPI
69
hw/arm/mps2-tz: Allow PPCPortInfo structures to specify device interrupts
70
hw/arm/mps2-tz: Move device IRQ info to data structures
71
hw/arm/mps2-tz: Size the uart-irq-orgate based on the number of UARTs
72
hw/arm/mps2-tz: Allow boards to have different PPCInfo data
73
hw/arm/mps2-tz: Make RAM arrangement board-specific
74
hw/arm/mps2-tz: Set MachineClass default_ram info from RAMInfo data
75
hw/arm/mps2-tz: Support ROMs as well as RAMs
76
hw/arm/mps2-tz: Get armv7m_load_kernel() size argument from RAMInfo
77
hw/arm/mps2-tz: Add new mps3-an524 board
78
hw/arm/mps2-tz: Stub out USB controller for mps3-an524
79
hw/arm/mps2-tz: Provide PL031 RTC on mps3-an524
80
docs/system/arm/mps2.rst: Document the new mps3-an524 board
81
hw/arm/mps2: Update old infocenter.arm.com URLs
82
61
83
Philippe Mathieu-Daudé (4):
62
Peter Maydell (22):
84
hw/arm/xlnx-zynqmp: Remove obsolete 'has_rpu' property
63
monitor/hmp-cmds.c: Clean up hmp_dumpdtb printf
85
hw/i2c/npcm7xx_smbus: Simplify npcm7xx_smbus_init()
64
hw/openrisc: Support monitor dumpdtb command
86
target/arm: Restrict v8M IDAU to TCG
65
hw/mips/boston: Check for error return from boston_fdt_filter()
87
target/arm/cpu: Update coding style to make checkpatch.pl happy
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
88
85
89
Rebecca Cran (3):
86
Pierrick Bouvier (1):
90
target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
87
hw/misc/npcm_clk: fix buffer-overflow
91
target/arm: Enable FEAT_SSBS for "max" AARCH64 CPU
92
target/arm: Set ID_PFR2.SSBS to 1 for "max" 32-bit CPU
93
88
94
Richard Henderson (1):
89
MAINTAINERS | 13 +
95
target/arm: Speed up aarch64 TBL/TBX
90
docs/system/arm/imx8mp-evk.rst | 70 ++++
96
91
docs/system/arm/virt.rst | 4 +
97
schspa (1):
92
docs/system/target-arm.rst | 1 +
98
virtio-mmio: improve virtio-mmio get_dev_path alog
93
include/fpu/softfloat-helpers.h | 12 +
99
94
include/fpu/softfloat-types.h | 51 +++
100
docs/system/arm/mps2.rst | 24 +-
95
include/fpu/softfloat.h | 91 ++---
101
docs/system/arm/nuvoton.rst | 3 +-
96
include/hw/arm/fsl-imx8mp.h | 284 ++++++++++++++
102
hw/display/omap_lcd_template.h | 169 --------
97
include/hw/loader-fit.h | 21 +-
103
hw/display/tc6393xb_template.h | 72 ----
98
include/hw/misc/imx8mp_analog.h | 81 ++++
104
include/hw/arm/armsse.h | 4 +-
99
include/hw/misc/imx8mp_ccm.h | 30 ++
105
include/hw/arm/npcm7xx.h | 2 +
100
include/hw/openrisc/boot.h | 3 +-
106
include/hw/arm/xlnx-zynqmp.h | 2 -
101
include/hw/pci-host/designware.h | 7 +
107
include/hw/misc/armsse-cpuid.h | 2 +-
102
include/hw/pci-host/fsl_imx8m_phy.h | 28 ++
108
include/hw/misc/armsse-mhu.h | 2 +-
103
include/hw/timer/imx_gpt.h | 1 +
109
include/hw/misc/iotkit-secctl.h | 2 +-
104
include/hw/usb/hcd-dwc3.h | 2 +-
110
include/hw/misc/iotkit-sysctl.h | 2 +-
105
include/system/device_tree.h | 2 -
111
include/hw/misc/iotkit-sysinfo.h | 2 +-
106
target/arm/internals.h | 9 +
112
include/hw/misc/mps2-fpgaio.h | 8 +-
107
fpu/softfloat.c | 23 +-
113
include/hw/misc/mps2-scc.h | 10 +-
108
hw/arm/boot.c | 2 -
114
include/hw/net/npcm7xx_emc.h | 286 +++++++++++++
109
hw/arm/fsl-imx8mp.c | 714 ++++++++++++++++++++++++++++++++++++
115
include/ui/console.h | 10 -
110
hw/arm/imx8mp-evk.c | 74 ++++
116
target/arm/cpu.h | 15 +-
111
hw/arm/smmuv3.c | 2 +-
117
target/arm/helper-a64.h | 2 +-
112
hw/arm/virt.c | 52 ++-
118
target/arm/internals.h | 6 +
113
hw/core/loader-fit.c | 38 +-
119
hw/arm/mps2-tz.c | 632 +++++++++++++++++++++++-----
114
hw/core/machine.c | 23 ++
120
hw/arm/mps2.c | 5 +
115
hw/loongarch/virt-fdt-build.c | 1 -
121
hw/arm/musicpal.c | 64 ++-
116
hw/mips/boston.c | 16 +-
122
hw/arm/npcm7xx.c | 50 ++-
117
hw/misc/imx8mp_analog.c | 160 ++++++++
123
hw/arm/sbsa-ref.c | 2 +-
118
hw/misc/imx8mp_ccm.c | 175 +++++++++
124
hw/arm/xlnx-zynqmp.c | 6 -
119
hw/misc/npcm_clk.c | 5 +-
125
hw/display/omap_lcdc.c | 129 +++++-
120
hw/openrisc/boot.c | 8 +-
126
hw/display/tc6393xb.c | 48 +--
121
hw/openrisc/openrisc_sim.c | 2 +-
127
hw/display/tcx.c | 31 +-
122
hw/openrisc/virt.c | 2 +-
128
hw/i2c/npcm7xx_smbus.c | 1 -
123
hw/pci-host/designware.c | 18 +-
129
hw/misc/armsse-cpuid.c | 2 +-
124
hw/pci-host/fsl_imx8m_phy.c | 98 +++++
130
hw/misc/armsse-mhu.c | 2 +-
125
hw/ppc/e500.c | 1 -
131
hw/misc/iotkit-sysctl.c | 2 +-
126
hw/ppc/pegasos2.c | 1 -
132
hw/misc/iotkit-sysinfo.c | 2 +-
127
hw/ppc/pnv.c | 1 -
133
hw/misc/mps2-fpgaio.c | 43 +-
128
hw/ppc/spapr.c | 1 -
134
hw/misc/mps2-scc.c | 93 ++++-
129
hw/riscv/boot.c | 2 -
135
hw/net/npcm7xx_emc.c | 857 ++++++++++++++++++++++++++++++++++++++
130
hw/timer/imx_gpt.c | 25 ++
136
hw/virtio/virtio-mmio.c | 13 +-
131
hw/usb/hcd-dwc3.c | 5 +
137
target/arm/cpu.c | 23 +-
132
monitor/hmp-cmds.c | 2 +-
138
target/arm/cpu64.c | 5 +
133
system/device_tree-stub.c | 5 +-
139
target/arm/cpu_tcg.c | 8 +
134
system/device_tree.c | 22 +-
140
target/arm/helper-a64.c | 32 --
135
target/arm/hvf/hvf.c | 16 +
141
target/arm/helper.c | 39 +-
136
target/arm/tcg-stubs.c | 22 ++
142
target/arm/mte_helper.c | 13 +-
137
target/arm/{ => tcg}/vfp_helper.c | 189 +---------
143
target/arm/translate-a64.c | 70 +---
138
target/arm/vfp_fpscr.c | 155 ++++++++
144
target/arm/vec_helper.c | 48 +++
139
target/hppa/fpu_helper.c | 1 +
145
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++++++++
140
target/i386/tcg/fpu_helper.c | 51 +--
146
hw/net/meson.build | 1 +
141
target/m68k/cpu.c | 35 ++
147
hw/net/trace-events | 17 +
142
target/m68k/fpu_helper.c | 2 +-
148
tests/qtest/meson.build | 3 +-
143
target/m68k/softfloat.c | 47 +--
149
49 files changed, 3098 insertions(+), 628 deletions(-)
144
target/sh4/cpu.c | 1 +
150
delete mode 100644 hw/display/omap_lcd_template.h
145
fpu/softfloat-parts.c.inc | 27 +-
151
delete mode 100644 hw/display/tc6393xb_template.h
146
fpu/softfloat-specialize.c.inc | 29 +-
152
create mode 100644 include/hw/net/npcm7xx_emc.h
147
fpu/meson.build | 2 +-
153
create mode 100644 hw/net/npcm7xx_emc.c
148
hw/arm/Kconfig | 24 ++
154
create mode 100644 tests/qtest/npcm7xx_emc-test.c
149
hw/arm/meson.build | 2 +
155
150
hw/gpio/Kconfig | 8 +
151
hw/misc/Kconfig | 14 +-
152
hw/misc/meson.build | 2 +
153
hw/pci-host/Kconfig | 3 +
154
hw/pci-host/meson.build | 1 +
155
target/arm/meson.build | 2 +-
156
target/arm/tcg/meson.build | 1 +
157
68 files changed, 2439 insertions(+), 383 deletions(-)
158
create mode 100644 docs/system/arm/imx8mp-evk.rst
159
create mode 100644 include/hw/arm/fsl-imx8mp.h
160
create mode 100644 include/hw/misc/imx8mp_analog.h
161
create mode 100644 include/hw/misc/imx8mp_ccm.h
162
create mode 100644 include/hw/pci-host/fsl_imx8m_phy.h
163
create mode 100644 hw/arm/fsl-imx8mp.c
164
create mode 100644 hw/arm/imx8mp-evk.c
165
create mode 100644 hw/misc/imx8mp_analog.c
166
create mode 100644 hw/misc/imx8mp_ccm.c
167
create mode 100644 hw/pci-host/fsl_imx8m_phy.c
168
rename target/arm/{ => tcg}/vfp_helper.c (90%)
169
create mode 100644 target/arm/vfp_fpscr.c
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Nicolin Chen <nicolinc@nvidia.com>
2
2
3
We will move this code in the next commit. Clean it up
3
When we fill in the SMMUEventInfo for SMMU_EVT_F_CD_FETCH we write
4
first to avoid checkpatch.pl errors.
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.
5
7
6
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
7
Message-id: 20210221222617.2579610-3-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
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
target/arm/cpu.c | 12 ++++++++----
17
hw/arm/smmuv3.c | 2 +-
12
1 file changed, 8 insertions(+), 4 deletions(-)
18
1 file changed, 1 insertion(+), 1 deletion(-)
13
19
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
22
--- a/hw/arm/smmuv3.c
17
+++ b/target/arm/cpu.c
23
+++ b/hw/arm/smmuv3.c
18
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
24
@@ -XXX,XX +XXX,XX @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, SMMUTransCfg *cfg,
19
}
25
qemu_log_mask(LOG_GUEST_ERROR,
20
26
"Cannot fetch pte at address=0x%"PRIx64"\n", addr);
21
static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
27
event->type = SMMU_EVT_F_CD_FETCH;
22
- /* power_control should be set to maximum latency. Again,
28
- event->u.f_ste_fetch.addr = addr;
23
+ /*
29
+ event->u.f_cd_fetch.addr = addr;
24
+ * power_control should be set to maximum latency. Again,
30
return -EINVAL;
25
* default to 0 and set by private hook
31
}
26
*/
32
for (i = 0; i < ARRAY_SIZE(buf->word); i++) {
27
{ .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
28
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
29
set_feature(&cpu->env, ARM_FEATURE_NEON);
30
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
31
set_feature(&cpu->env, ARM_FEATURE_EL3);
32
- /* Note that A9 supports the MP extensions even for
33
+ /*
34
+ * Note that A9 supports the MP extensions even for
35
* A9UP and single-core A9MP (which are both different
36
* and valid configurations; we don't model A9UP).
37
*/
38
@@ -XXX,XX +XXX,XX @@ static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
39
{
40
MachineState *ms = MACHINE(qdev_get_machine());
41
42
- /* Linux wants the number of processors from here.
43
+ /*
44
+ * Linux wants the number of processors from here.
45
* Might as well set the interrupt-controller bit too.
46
*/
47
return ((ms->smp.cpus - 1) << 24) | (1 << 23);
48
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
49
cpu->isar.id_mmfr1 = 0x40000000;
50
cpu->isar.id_mmfr2 = 0x01240000;
51
cpu->isar.id_mmfr3 = 0x02102211;
52
- /* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
53
+ /*
54
+ * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
55
* table 4-41 gives 0x02101110, which includes the arm div insns.
56
*/
57
cpu->isar.id_isar0 = 0x02101110;
58
--
33
--
59
2.20.1
34
2.43.0
60
61
diff view generated by jsdifflib
1
The AN524 has a PL031 RTC, which we have a model of; provide it
1
From: "Matthew R. Ochs" <mochs@nvidia.com>
2
rather than an unimplemented-device stub.
3
2
3
The MMIO region size required to support virtualized environments with
4
large PCI BAR regions can exceed the hardcoded limit configured in QEMU.
5
For example, a VM with multiple NVIDIA Grace-Hopper GPUs passed through
6
requires more MMIO memory than the amount provided by VIRT_HIGH_PCIE_MMIO
7
(currently 512GB). Instead of updating VIRT_HIGH_PCIE_MMIO, introduce a
8
new parameter, highmem-mmio-size, that specifies the MMIO size required
9
to support the VM configuration.
10
11
Example usage with 1TB MMIO region size:
12
    -machine virt,gic-version=3,highmem-mmio-size=1T
13
14
Signed-off-by: Matthew R. Ochs <mochs@nvidia.com>
15
Reviewed-by: Gavin Shan <gshan@redhat.com>
16
Reviewed-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
17
Reviewed-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
19
Message-id: 20250221145419.1281890-1-mochs@nvidia.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-23-peter.maydell@linaro.org
8
---
22
---
9
hw/arm/mps2-tz.c | 22 ++++++++++++++++++++--
23
docs/system/arm/virt.rst | 4 ++++
10
1 file changed, 20 insertions(+), 2 deletions(-)
24
hw/arm/virt.c | 52 +++++++++++++++++++++++++++++++++++++++-
25
2 files changed, 55 insertions(+), 1 deletion(-)
11
26
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
27
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
13
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
29
--- a/docs/system/arm/virt.rst
15
+++ b/hw/arm/mps2-tz.c
30
+++ b/docs/system/arm/virt.rst
31
@@ -XXX,XX +XXX,XX @@ highmem-mmio
32
Set ``on``/``off`` to enable/disable the high memory region for PCI MMIO.
33
The default is ``on``.
34
35
+highmem-mmio-size
36
+ Set the high memory region size for PCI MMIO. Must be a power of 2 and
37
+ greater than or equal to the default size (512G).
38
+
39
gic-version
40
Specify the version of the Generic Interrupt Controller (GIC) to provide.
41
Valid values are:
42
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/virt.c
45
+++ b/hw/arm/virt.c
16
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@
17
#include "hw/misc/tz-msc.h"
47
#include "hw/loader.h"
18
#include "hw/arm/armsse.h"
48
#include "qapi/error.h"
19
#include "hw/dma/pl080.h"
49
#include "qemu/bitops.h"
20
+#include "hw/rtc/pl031.h"
50
+#include "qemu/cutils.h"
21
#include "hw/ssi/pl022.h"
51
#include "qemu/error-report.h"
22
#include "hw/i2c/arm_sbcon_i2c.h"
52
#include "qemu/module.h"
23
#include "hw/net/lan9118.h"
53
#include "hw/pci-host/gpex.h"
24
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
54
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry base_memmap[] = {
25
UnimplementedDeviceState gpio[4];
55
[VIRT_MEM] = { GiB, LEGACY_RAMLIMIT_BYTES },
26
UnimplementedDeviceState gfx;
56
};
27
UnimplementedDeviceState cldc;
57
28
- UnimplementedDeviceState rtc;
58
+/* Update the docs for highmem-mmio-size when changing this default */
29
UnimplementedDeviceState usb;
59
+#define DEFAULT_HIGH_PCIE_MMIO_SIZE_GB 512
30
+ PL031State rtc;
60
+#define DEFAULT_HIGH_PCIE_MMIO_SIZE (DEFAULT_HIGH_PCIE_MMIO_SIZE_GB * GiB)
31
PL080State dma[4];
61
+
32
TZMSC msc[4];
62
/*
33
CMSDKAPBUART uart[6];
63
* Highmem IO Regions: This memory map is floating, located after the RAM.
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
64
* Each MemMapEntry base (GPA) will be dynamically computed, depending on the
35
return sysbus_mmio_get_region(s, 0);
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;
36
}
85
}
37
86
38
+static MemoryRegion *make_rtc(MPS2TZMachineState *mms, void *opaque,
87
+static void virt_get_highmem_mmio_size(Object *obj, Visitor *v,
39
+ const char *name, hwaddr size,
88
+ const char *name, void *opaque,
40
+ const int *irqs)
89
+ Error **errp)
41
+{
90
+{
42
+ PL031State *pl031 = opaque;
91
+ uint64_t size = extended_memmap[VIRT_HIGH_PCIE_MMIO].size;
43
+ SysBusDevice *s;
44
+
92
+
45
+ object_initialize_child(OBJECT(mms), name, pl031, TYPE_PL031);
93
+ visit_type_size(v, name, &size, errp);
46
+ s = SYS_BUS_DEVICE(pl031);
47
+ sysbus_realize(s, &error_fatal);
48
+ /*
49
+ * The board docs don't give an IRQ number for the PL031, so
50
+ * presumably it is not connected.
51
+ */
52
+ return sysbus_mmio_get_region(s, 0);
53
+}
94
+}
54
+
95
+
55
static void create_non_mpc_ram(MPS2TZMachineState *mms)
96
+static void virt_set_highmem_mmio_size(Object *obj, Visitor *v,
97
+ const char *name, void *opaque,
98
+ Error **errp)
99
+{
100
+ uint64_t size;
101
+
102
+ if (!visit_type_size(v, name, &size, errp)) {
103
+ return;
104
+ }
105
+
106
+ if (!is_power_of_2(size)) {
107
+ error_setg(errp, "highmem-mmio-size is not a power of 2");
108
+ return;
109
+ }
110
+
111
+ if (size < DEFAULT_HIGH_PCIE_MMIO_SIZE) {
112
+ char *sz = size_to_str(DEFAULT_HIGH_PCIE_MMIO_SIZE);
113
+ error_setg(errp, "highmem-mmio-size cannot be set to a lower value "
114
+ "than the default (%s)", sz);
115
+ g_free(sz);
116
+ return;
117
+ }
118
+
119
+ extended_memmap[VIRT_HIGH_PCIE_MMIO].size = size;
120
+}
121
122
static bool virt_get_its(Object *obj, Error **errp)
56
{
123
{
57
/*
124
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
125
"Set on/off to enable/disable high "
59
126
"memory region for PCI MMIO");
60
{ /* port 9 reserved */ },
127
61
{ "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
128
+ object_class_property_add(oc, "highmem-mmio-size", "size",
62
- { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
129
+ virt_get_highmem_mmio_size,
63
+ { "rtc", make_rtc, &mms->rtc, 0x4130b000, 0x1000 },
130
+ virt_set_highmem_mmio_size,
64
},
131
+ NULL, NULL);
65
}, {
132
+ object_class_property_set_description(oc, "highmem-mmio-size",
66
.name = "ahb_ppcexp0",
133
+ "Set the high memory region size "
134
+ "for PCI MMIO");
135
+
136
object_class_property_add_str(oc, "gic-version", virt_get_gic_version,
137
virt_set_gic_version);
138
object_class_property_set_description(oc, "gic-version",
67
--
139
--
68
2.20.1
140
2.43.0
69
70
diff view generated by jsdifflib
1
The AN505 and AN521 have the same device layout, but the AN524 is
1
In hmp_dumpdtb(), we print a message when the command succeeds. This
2
somewhat different. Allow for more than one PPCInfo array, which can
2
message is missing the trailing \n, so the HMP command prompt is
3
be selected based on the board type.
3
printed immediately after it. We also weren't capitalizing 'DTB', or
4
quoting the filename in the message. Fix these nits.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-16-peter.maydell@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20250206151214.2947842-2-peter.maydell@linaro.org
8
---
10
---
9
hw/arm/mps2-tz.c | 16 ++++++++++++++--
11
monitor/hmp-cmds.c | 2 +-
10
1 file changed, 14 insertions(+), 2 deletions(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
11
13
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
16
--- a/monitor/hmp-cmds.c
15
+++ b/hw/arm/mps2-tz.c
17
+++ b/monitor/hmp-cmds.c
16
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
18
@@ -XXX,XX +XXX,XX @@ void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
17
MemoryRegion *system_memory = get_system_memory();
19
return;
18
DeviceState *iotkitdev;
20
}
19
DeviceState *dev_splitter;
21
20
+ const PPCInfo *ppcs;
22
- monitor_printf(mon, "dtb dumped to %s", filename);
21
+ int num_ppcs;
23
+ monitor_printf(mon, "DTB dumped to '%s'\n", filename);
22
int i;
24
}
23
25
#endif
24
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
26
* + wire up the PPC's control lines to the IoTKit object
27
*/
28
29
- const PPCInfo ppcs[] = { {
30
+ const PPCInfo an505_ppcs[] = { {
31
.name = "apb_ppcexp0",
32
.ports = {
33
{ "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
34
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
35
},
36
};
37
38
- for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
39
+ switch (mmc->fpga_type) {
40
+ case FPGA_AN505:
41
+ case FPGA_AN521:
42
+ ppcs = an505_ppcs;
43
+ num_ppcs = ARRAY_SIZE(an505_ppcs);
44
+ break;
45
+ default:
46
+ g_assert_not_reached();
47
+ }
48
+
49
+ for (i = 0; i < num_ppcs; i++) {
50
const PPCInfo *ppcinfo = &ppcs[i];
51
TZPPC *ppc = &mms->ppc[i];
52
DeviceState *ppcdev;
53
--
26
--
54
2.20.1
27
2.43.0
55
28
56
29
diff view generated by jsdifflib
1
Fix some minor coding style issues in the template header,
1
The openrisc machines don't set MachineState::fdt to point to their
2
so checkpatch doesn't complain when we move the code.
2
DTB blob. This means that although the command line '-machine
3
dumpdtb=file.dtb' option works, the equivalent QMP and HMP monitor
4
commands do not, but instead produce the error "This machine doesn't
5
have a FDT".
6
7
Set MachineState::fdt in openrisc_load_fdt(), when we write it to
8
guest memory.
3
9
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20210215103215.4944-8-peter.maydell@linaro.org
13
Message-id: 20250206151214.2947842-3-peter.maydell@linaro.org
8
---
14
---
9
hw/display/omap_lcd_template.h | 6 +++---
15
include/hw/openrisc/boot.h | 3 ++-
10
1 file changed, 3 insertions(+), 3 deletions(-)
16
hw/openrisc/boot.c | 7 +++++--
17
hw/openrisc/openrisc_sim.c | 2 +-
18
hw/openrisc/virt.c | 2 +-
19
4 files changed, 9 insertions(+), 5 deletions(-)
11
20
12
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
21
diff --git a/include/hw/openrisc/boot.h b/include/hw/openrisc/boot.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/display/omap_lcd_template.h
23
--- a/include/hw/openrisc/boot.h
15
+++ b/hw/display/omap_lcd_template.h
24
+++ b/include/hw/openrisc/boot.h
16
@@ -XXX,XX +XXX,XX @@ static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
25
@@ -XXX,XX +XXX,XX @@
17
b = (pal[v & 3] << 4) & 0xf0;
26
#define OPENRISC_BOOT_H
18
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
27
19
d += 4;
28
#include "exec/cpu-defs.h"
20
- s ++;
29
+#include "hw/boards.h"
21
+ s++;
30
22
width -= 4;
31
hwaddr openrisc_load_kernel(ram_addr_t ram_size,
23
} while (width > 0);
32
const char *kernel_filename,
33
@@ -XXX,XX +XXX,XX @@ hwaddr openrisc_load_kernel(ram_addr_t ram_size,
34
hwaddr openrisc_load_initrd(void *fdt, const char *filename,
35
hwaddr load_start, uint64_t mem_size);
36
37
-uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
38
+uint32_t openrisc_load_fdt(MachineState *ms, void *fdt, hwaddr load_start,
39
uint64_t mem_size);
40
41
#endif /* OPENRISC_BOOT_H */
42
diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/openrisc/boot.c
45
+++ b/hw/openrisc/boot.c
46
@@ -XXX,XX +XXX,XX @@ hwaddr openrisc_load_initrd(void *fdt, const char *filename,
47
return start + size;
24
}
48
}
25
@@ -XXX,XX +XXX,XX @@ static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
49
26
b = (pal[v & 0xf] << 4) & 0xf0;
50
-uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
27
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
51
- uint64_t mem_size)
28
d += 4;
52
+uint32_t openrisc_load_fdt(MachineState *ms, void *fdt,
29
- s ++;
53
+ hwaddr load_start, uint64_t mem_size)
30
+ s++;
54
{
31
width -= 2;
55
uint32_t fdt_addr;
32
} while (width > 0);
56
int ret;
57
@@ -XXX,XX +XXX,XX @@ uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
58
/* copy in the device tree */
59
qemu_fdt_dumpdtb(fdt, fdtsize);
60
61
+ /* Save FDT for dumpdtb monitor command */
62
+ ms->fdt = fdt;
63
+
64
rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
65
&address_space_memory);
66
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
67
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/openrisc/openrisc_sim.c
70
+++ b/hw/openrisc/openrisc_sim.c
71
@@ -XXX,XX +XXX,XX @@ static void openrisc_sim_init(MachineState *machine)
72
machine->initrd_filename,
73
load_addr, machine->ram_size);
74
}
75
- boot_info.fdt_addr = openrisc_load_fdt(state->fdt, load_addr,
76
+ boot_info.fdt_addr = openrisc_load_fdt(machine, state->fdt, load_addr,
77
machine->ram_size);
78
}
33
}
79
}
34
@@ -XXX,XX +XXX,XX @@ static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
80
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
35
g = pal[v] & 0xf0;
81
index XXXXXXX..XXXXXXX 100644
36
b = (pal[v] << 4) & 0xf0;
82
--- a/hw/openrisc/virt.c
37
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
83
+++ b/hw/openrisc/virt.c
38
- s ++;
84
@@ -XXX,XX +XXX,XX @@ static void openrisc_virt_init(MachineState *machine)
39
+ s++;
85
machine->initrd_filename,
40
d += 4;
86
load_addr, machine->ram_size);
41
} while (-- width != 0);
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
}
42
}
92
}
43
--
93
--
44
2.20.1
94
2.43.0
45
95
46
96
diff view generated by jsdifflib
1
Add brief documentation of the new mps3-an524 board.
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: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20250206151214.2947842-4-peter.maydell@linaro.org
6
Message-id: 20210215115138.20465-24-peter.maydell@linaro.org
7
---
10
---
8
docs/system/arm/mps2.rst | 24 ++++++++++++++++++------
11
hw/mips/boston.c | 4 ++++
9
1 file changed, 18 insertions(+), 6 deletions(-)
12
1 file changed, 4 insertions(+)
10
13
11
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
14
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/system/arm/mps2.rst
16
--- a/hw/mips/boston.c
14
+++ b/docs/system/arm/mps2.rst
17
+++ b/hw/mips/boston.c
15
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
16
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
19
17
-================================================================================================================
20
dtb_load_data = boston_fdt_filter(s, dtb_file_data,
18
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
21
NULL, &dtb_vaddr);
19
+=========================================================================================================================================
22
+ if (!dtb_load_data) {
20
23
+ /* boston_fdt_filter() already printed the error for us */
21
These board models all use Arm M-profile CPUs.
24
+ exit(1);
22
25
+ }
23
-The Arm MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
26
24
-FPGA but is otherwise the same as the 2). Since the CPU itself
27
/* Calculate real fdt size after filter */
25
-and most of the devices are in the FPGA, the details of the board
28
dt_size = fdt_totalsize(dtb_load_data);
26
-as seen by the guest depend significantly on the FPGA image.
27
+The Arm MPS2, MPS2+ and MPS3 dev boards are FPGA based (the 2+ has a
28
+bigger FPGA but is otherwise the same as the 2; the 3 has a bigger
29
+FPGA again, can handle 4GB of RAM and has a USB controller and QSPI flash).
30
+
31
+Since the CPU itself and most of the devices are in the FPGA, the
32
+details of the board as seen by the guest depend significantly on the
33
+FPGA image.
34
35
QEMU models the following FPGA images:
36
37
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
38
Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
39
``mps2-an521``
40
Dual Cortex-M33 as documented in Arm Application Note AN521
41
+``mps3-an524``
42
+ Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
43
44
Differences between QEMU and real hardware:
45
46
- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
47
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
48
if zbt_boot_ctrl is always zero)
49
+- AN524 remapping of low memory to either BRAM or to QSPI flash is
50
+ unimplemented (QEMU always maps this to BRAM, ignoring the
51
+ SCC CFG_REG0 memory-remap bit)
52
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
53
visible difference is that the LAN9118 doesn't support checksum
54
offloading
55
+- QEMU does not model the QSPI flash in MPS3 boards as real QSPI
56
+ flash, but only as simple ROM, so attempting to rewrite the flash
57
+ from the guest will fail
58
+- QEMU does not model the USB controller in MPS3 boards
59
--
29
--
60
2.20.1
30
2.43.0
61
31
62
32
diff view generated by jsdifflib
1
The mps2-tz code uses PPCPortInfo data structures to define what
1
The boston machine doesn't set MachineState::fdt to the DTB blob that
2
devices are present and how they are wired up. Currently we use
2
it has loaded or created, which means that the QMP/HMP dumpdtb
3
these to specify device types and addresses, but hard-code the
3
monitor commands don't work.
4
interrupt line wiring in each make_* helper function. This works for
4
5
the two boards we have at the moment, but the AN524 has some devices
5
Setting MachineState::fdt is easy in the non-FIT codepath: we can
6
with different interrupt assignments.
6
simply do so immediately before loading the DTB into guest memory.
7
7
The FIT codepath is a bit more awkward as currently the FIT loader
8
This commit adds the framework to allow PPCPortInfo structures to
8
throws away the memory that the FDT was in after it loads it into
9
specify interrupt numbers. We add an array of interrupt numbers to
9
guest memory. So we add a void *pfdt argument to load_fit() for it
10
the PPCPortInfo struct, and pass it through to the make_* helpers.
10
to store the FDT pointer into.
11
The following commit will change the make_* helpers over to using the
11
12
framework.
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).
13
18
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
16
Message-id: 20210215115138.20465-13-peter.maydell@linaro.org
21
Message-id: 20250206151214.2947842-5-peter.maydell@linaro.org
17
---
22
---
18
hw/arm/mps2-tz.c | 36 ++++++++++++++++++++++++------------
23
include/hw/loader-fit.h | 21 ++++++++++++++++++---
19
1 file changed, 24 insertions(+), 12 deletions(-)
24
hw/core/loader-fit.c | 38 +++++++++++++++++++++-----------------
20
25
hw/mips/boston.c | 11 +++++++----
21
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.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
22
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/mps2-tz.c
30
--- a/include/hw/loader-fit.h
24
+++ b/hw/arm/mps2-tz.c
31
+++ b/include/hw/loader-fit.h
25
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
32
@@ -XXX,XX +XXX,XX @@ struct fit_loader_match {
26
* needs to be plugged into the downstream end of the PPC port.
33
struct fit_loader {
27
*/
34
const struct fit_loader_match *matches;
28
typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
35
hwaddr (*addr_to_phys)(void *opaque, uint64_t addr);
29
- const char *name, hwaddr size);
36
- const void *(*fdt_filter)(void *opaque, const void *fdt,
30
+ const char *name, hwaddr size,
37
- const void *match_data, hwaddr *load_addr);
31
+ const int *irqs);
38
+ void *(*fdt_filter)(void *opaque, const void *fdt,
32
39
+ const void *match_data, hwaddr *load_addr);
33
typedef struct PPCPortInfo {
40
const void *(*kernel_filter)(void *opaque, const void *kernel,
41
hwaddr *load_addr, hwaddr *entry_addr);
42
};
43
44
-int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque);
45
+/**
46
+ * load_fit: load a FIT format image
47
+ * @ldr: structure defining board specific properties and hooks
48
+ * @filename: image to load
49
+ * @pfdt: pointer to update with address of FDT blob
50
+ * @opaque: opaque value passed back to the hook functions in @ldr
51
+ * Returns: 0 on success, or a negative errno on failure
52
+ *
53
+ * @pfdt is used to tell the caller about the FDT blob. On return, it
54
+ * has been set to point to the FDT blob, and it is now the caller's
55
+ * responsibility to free that memory with g_free(). Usually the caller
56
+ * will want to pass in &machine->fdt here, to record the FDT blob for
57
+ * the dumpdtb option and QMP/HMP commands.
58
+ */
59
+int load_fit(const struct fit_loader *ldr, const char *filename, void **pfdt,
60
+ void *opaque);
61
62
#endif /* HW_LOADER_FIT_H */
63
diff --git a/hw/core/loader-fit.c b/hw/core/loader-fit.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/core/loader-fit.c
66
+++ b/hw/core/loader-fit.c
67
@@ -XXX,XX +XXX,XX @@
68
69
#define FIT_LOADER_MAX_PATH (128)
70
71
-static const void *fit_load_image_alloc(const void *itb, const char *name,
72
- int *poff, size_t *psz, Error **errp)
73
+static void *fit_load_image_alloc(const void *itb, const char *name,
74
+ int *poff, size_t *psz, Error **errp)
75
{
76
const void *data;
77
const char *comp;
78
@@ -XXX,XX +XXX,XX @@ static const void *fit_load_image_alloc(const void *itb, const char *name,
79
return NULL;
80
}
81
82
- data = g_realloc(uncomp_data, uncomp_len);
83
+ uncomp_data = g_realloc(uncomp_data, uncomp_len);
84
if (psz) {
85
*psz = uncomp_len;
86
}
87
- return data;
88
+ return uncomp_data;
89
}
90
91
error_setg(errp, "unknown compression '%s'", comp);
92
@@ -XXX,XX +XXX,XX @@ out:
93
94
static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
95
int cfg, void *opaque, const void *match_data,
96
- hwaddr kernel_end, Error **errp)
97
+ hwaddr kernel_end, void **pfdt, Error **errp)
98
{
99
ERRP_GUARD();
100
Error *err = NULL;
34
const char *name;
101
const char *name;
35
@@ -XXX,XX +XXX,XX @@ typedef struct PPCPortInfo {
102
- const void *data;
36
void *opaque;
103
- const void *load_data;
37
hwaddr addr;
104
+ void *data;
38
hwaddr size;
105
hwaddr load_addr;
39
+ int irqs[3]; /* currently no device needs more IRQ lines than this */
106
int img_off;
40
} PPCPortInfo;
107
size_t sz;
41
108
@@ -XXX,XX +XXX,XX @@ static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
42
typedef struct PPCInfo {
109
return 0;
43
@@ -XXX,XX +XXX,XX @@ typedef struct PPCInfo {
110
}
44
} PPCInfo;
111
45
112
- load_data = data = fit_load_image_alloc(itb, name, &img_off, &sz, errp);
46
static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
113
+ data = fit_load_image_alloc(itb, name, &img_off, &sz, errp);
47
- void *opaque,
114
if (!data) {
48
- const char *name, hwaddr size)
115
error_prepend(errp, "unable to load FDT image from FIT: ");
49
+ void *opaque,
116
return -EINVAL;
50
+ const char *name, hwaddr size,
117
@@ -XXX,XX +XXX,XX @@ static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
51
+ const int *irqs)
118
}
52
{
119
53
/* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
120
if (ldr->fdt_filter) {
54
* and return a pointer to its MemoryRegion.
121
- load_data = ldr->fdt_filter(opaque, data, match_data, &load_addr);
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
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;
56
}
146
}
57
147
58
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
148
@@ -XXX,XX +XXX,XX @@ out:
59
- const char *name, hwaddr size)
149
return ret;
60
+ const char *name, hwaddr size,
61
+ const int *irqs)
62
{
63
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
64
CMSDKAPBUART *uart = opaque;
65
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
66
}
150
}
67
151
68
static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
152
-int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
69
- const char *name, hwaddr size)
153
+int load_fit(const struct fit_loader *ldr, const char *filename,
70
+ const char *name, hwaddr size,
154
+ void **pfdt, void *opaque)
71
+ const int *irqs)
155
{
72
{
156
Error *err = NULL;
73
MPS2SCC *scc = opaque;
157
const struct fit_loader_match *match;
74
DeviceState *sccdev;
158
@@ -XXX,XX +XXX,XX @@ int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
75
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
159
goto out;
160
}
161
162
- ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end,
163
+ ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end, pfdt,
164
&err);
165
if (ret) {
166
error_report_err(err);
167
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
168
index XXXXXXX..XXXXXXX 100644
169
--- a/hw/mips/boston.c
170
+++ b/hw/mips/boston.c
171
@@ -XXX,XX +XXX,XX @@ static void gen_firmware(void *p, hwaddr kernel_entry, hwaddr fdt_addr)
172
kernel_entry);
76
}
173
}
77
174
78
static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
175
-static const void *boston_fdt_filter(void *opaque, const void *fdt_orig,
79
- const char *name, hwaddr size)
176
- const void *match_data, hwaddr *load_addr)
80
+ const char *name, hwaddr size,
177
+static void *boston_fdt_filter(void *opaque, const void *fdt_orig,
81
+ const int *irqs)
178
+ const void *match_data, hwaddr *load_addr)
82
{
179
{
83
MPS2FPGAIO *fpgaio = opaque;
180
BostonState *s = BOSTON(opaque);
84
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
181
MachineState *machine = s->mach;
85
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
182
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
86
}
183
if (kernel_size > 0) {
87
184
int dt_size;
88
static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
185
g_autofree const void *dtb_file_data = NULL;
89
- const char *name, hwaddr size)
186
- g_autofree const void *dtb_load_data = NULL;
90
+ const char *name, hwaddr size,
187
+ void *dtb_load_data = NULL;
91
+ const int *irqs)
188
hwaddr dtb_paddr = QEMU_ALIGN_UP(kernel_high, 64 * KiB);
92
{
189
hwaddr dtb_vaddr = cpu_mips_phys_to_kseg0(NULL, dtb_paddr);
93
SysBusDevice *s;
190
94
NICInfo *nd = &nd_table[0];
191
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
95
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
192
exit(1);
96
}
97
98
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
99
- const char *name, hwaddr size)
100
+ const char *name, hwaddr size,
101
+ const int *irqs)
102
{
103
TZMPC *mpc = opaque;
104
int i = mpc - &mms->ssram_mpc[0];
105
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
106
}
107
108
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
109
- const char *name, hwaddr size)
110
+ const char *name, hwaddr size,
111
+ const int *irqs)
112
{
113
PL080State *dma = opaque;
114
int i = dma - &mms->dma[0];
115
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
116
}
117
118
static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
119
- const char *name, hwaddr size)
120
+ const char *name, hwaddr size,
121
+ const int *irqs)
122
{
123
/*
124
* The AN505 has five PL022 SPI controllers.
125
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
126
}
127
128
static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
129
- const char *name, hwaddr size)
130
+ const char *name, hwaddr size,
131
+ const int *irqs)
132
{
133
ArmSbconI2CState *i2c = opaque;
134
SysBusDevice *s;
135
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
136
continue;
137
}
193
}
138
194
139
- mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
195
+ machine->fdt = dtb_load_data;
140
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size,
196
+
141
+ pinfo->irqs);
197
/* Calculate real fdt size after filter */
142
portname = g_strdup_printf("port[%d]", port);
198
dt_size = fdt_totalsize(dtb_load_data);
143
object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
199
rom_add_blob_fixed("dtb", dtb_load_data, dt_size, dtb_paddr);
144
&error_fatal);
200
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
201
rom_ptr(dtb_paddr, dt_size));
202
} else {
203
/* Try to load file as FIT */
204
- fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s);
205
+ fit_err = load_fit(&boston_fit_loader, machine->kernel_filename,
206
+ &machine->fdt, s);
207
if (fit_err) {
208
error_report("unable to load kernel image");
209
exit(1);
145
--
210
--
146
2.20.1
211
2.43.0
147
212
148
213
diff view generated by jsdifflib
1
The armv7m_load_kernel() function takes a mem_size argument which it
1
Currently we handle the 'dumpdtb' machine sub-option ad-hoc in every
2
expects to be the size of the memory region at guest address 0. (It
2
board model that has an FDT. It's up to the board code to make sure
3
uses this argument only as a limit on how large a raw image file it
3
it calls qemu_fdt_dumpdtb() in the right place.
4
can load at address zero).
4
5
5
This means we're inconsistent and often just ignore the user's
6
Instead of hardcoding this value, find the RAMInfo corresponding to
6
command line argument:
7
the 0 address and extract its size.
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.
8
23
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210215115138.20465-20-peter.maydell@linaro.org
13
---
26
---
14
hw/arm/mps2-tz.c | 17 ++++++++++++++++-
27
include/system/device_tree.h | 2 --
15
1 file changed, 16 insertions(+), 1 deletion(-)
28
hw/arm/boot.c | 2 --
16
29
hw/core/machine.c | 25 +++++++++++++++++++++++++
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
30
hw/loongarch/virt-fdt-build.c | 1 -
18
index XXXXXXX..XXXXXXX 100644
31
hw/mips/boston.c | 1 -
19
--- a/hw/arm/mps2-tz.c
32
hw/openrisc/boot.c | 1 -
20
+++ b/hw/arm/mps2-tz.c
33
hw/ppc/e500.c | 1 -
21
@@ -XXX,XX +XXX,XX @@ static void create_non_mpc_ram(MPS2TZMachineState *mms)
34
hw/ppc/pegasos2.c | 1 -
35
hw/ppc/pnv.c | 1 -
36
hw/ppc/spapr.c | 1 -
37
hw/riscv/boot.c | 2 --
38
system/device_tree.c | 15 ---------------
39
12 files changed, 25 insertions(+), 28 deletions(-)
40
41
diff --git a/include/system/device_tree.h b/include/system/device_tree.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/system/device_tree.h
44
+++ b/include/system/device_tree.h
45
@@ -XXX,XX +XXX,XX @@ int qemu_fdt_add_path(void *fdt, const char *path);
46
sizeof(qdt_tmp)); \
47
} while (0)
48
49
-void qemu_fdt_dumpdtb(void *fdt, int size);
50
-
51
/**
52
* qemu_fdt_setprop_sized_cells_from_array:
53
* @fdt: device tree blob
54
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/boot.c
57
+++ b/hw/arm/boot.c
58
@@ -XXX,XX +XXX,XX @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
59
binfo->modify_dtb(binfo, fdt);
22
}
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);
23
}
81
}
24
82
25
+static uint32_t boot_ram_size(MPS2TZMachineState *mms)
83
+static void handle_machine_dumpdtb(MachineState *ms)
26
+{
84
+{
27
+ /* Return the size of the RAM block at guest address zero */
85
+ if (!ms->dumpdtb) {
28
+ const RAMInfo *p;
86
+ return;
29
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
30
+
31
+ for (p = mmc->raminfo; p->name; p++) {
32
+ if (p->base == 0) {
33
+ return p->size;
34
+ }
35
+ }
87
+ }
36
+ g_assert_not_reached();
88
+ if (!ms->fdt) {
89
+ /* Silently ignore dumpdtb option if there is nothing to dump */
90
+ return;
91
+ }
92
+#ifdef CONFIG_FDT
93
+ qmp_dumpdtb(ms->dumpdtb, &error_fatal);
94
+ exit(0);
95
+#else
96
+ error_report("This machine doesn't have an FDT");
97
+ exit(1);
98
+#endif
37
+}
99
+}
38
+
100
+
39
static void mps2tz_common_init(MachineState *machine)
101
void qdev_machine_creation_done(void)
40
{
102
{
41
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
103
cpu_synchronize_all_post_init();
42
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
104
@@ -XXX,XX +XXX,XX @@ void qdev_machine_creation_done(void)
43
105
phase_advance(PHASE_MACHINE_READY);
44
create_non_mpc_ram(mms);
106
qdev_assert_realized_properly();
45
107
46
- armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
108
+ /*
47
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
109
+ * If the user used -machine dumpdtb=file.dtb to request that we
48
+ boot_ram_size(mms));
110
+ * dump the DTB to a file, do it now, and exit.
111
+ */
112
+ handle_machine_dumpdtb(current_machine);
113
+
114
/* TODO: once all bus devices are qdevified, this should be done
115
* when bus is created by qdev.c */
116
/*
117
diff --git a/hw/loongarch/virt-fdt-build.c b/hw/loongarch/virt-fdt-build.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/hw/loongarch/virt-fdt-build.c
120
+++ b/hw/loongarch/virt-fdt-build.c
121
@@ -XXX,XX +XXX,XX @@ void virt_fdt_setup(LoongArchVirtMachineState *lvms)
122
* Put the FDT into the memory map as a ROM image: this will ensure
123
* the FDT is copied again upon reset, even if addr points into RAM.
124
*/
125
- qemu_fdt_dumpdtb(machine->fdt, lvms->fdt_size);
126
rom_add_blob_fixed_as("fdt", machine->fdt, lvms->fdt_size, FDT_BASE,
127
&address_space_memory);
128
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
129
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/mips/boston.c
132
+++ b/hw/mips/boston.c
133
@@ -XXX,XX +XXX,XX @@ static void *boston_fdt_filter(void *opaque, const void *fdt_orig,
134
1, ram_high_sz);
135
136
fdt = g_realloc(fdt, fdt_totalsize(fdt));
137
- qemu_fdt_dumpdtb(fdt, fdt_sz);
138
139
s->fdt_base = *load_addr;
140
141
diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/hw/openrisc/boot.c
144
+++ b/hw/openrisc/boot.c
145
@@ -XXX,XX +XXX,XX @@ uint32_t openrisc_load_fdt(MachineState *ms, void *fdt,
146
/* Should only fail if we've built a corrupted tree */
147
g_assert(ret == 0);
148
/* copy in the device tree */
149
- qemu_fdt_dumpdtb(fdt, fdtsize);
150
151
/* Save FDT for dumpdtb monitor command */
152
ms->fdt = fdt;
153
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/ppc/e500.c
156
+++ b/hw/ppc/e500.c
157
@@ -XXX,XX +XXX,XX @@ static int ppce500_load_device_tree(PPCE500MachineState *pms,
158
159
done:
160
if (!dry_run) {
161
- qemu_fdt_dumpdtb(fdt, fdt_size);
162
cpu_physical_memory_write(addr, fdt, fdt_size);
163
164
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
165
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/hw/ppc/pegasos2.c
168
+++ b/hw/ppc/pegasos2.c
169
@@ -XXX,XX +XXX,XX @@ static void pegasos2_machine_reset(MachineState *machine, ResetType type)
170
d[1] = cpu_to_be64(pm->kernel_size - (pm->kernel_entry - pm->kernel_addr));
171
qemu_fdt_setprop(fdt, "/chosen", "qemu,boot-kernel", d, sizeof(d));
172
173
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
174
g_free(pm->fdt_blob);
175
pm->fdt_blob = fdt;
176
177
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
178
index XXXXXXX..XXXXXXX 100644
179
--- a/hw/ppc/pnv.c
180
+++ b/hw/ppc/pnv.c
181
@@ -XXX,XX +XXX,XX @@ static void pnv_reset(MachineState *machine, ResetType type)
182
_FDT((fdt_pack(fdt)));
183
}
184
185
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
186
cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
187
188
/* Update machine->fdt with latest fdt */
189
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
190
index XXXXXXX..XXXXXXX 100644
191
--- a/hw/ppc/spapr.c
192
+++ b/hw/ppc/spapr.c
193
@@ -XXX,XX +XXX,XX @@ static void spapr_machine_reset(MachineState *machine, ResetType type)
194
0, fdt_addr, 0);
195
cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
196
}
197
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
198
199
g_free(spapr->fdt_blob);
200
spapr->fdt_size = fdt_totalsize(fdt);
201
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
202
index XXXXXXX..XXXXXXX 100644
203
--- a/hw/riscv/boot.c
204
+++ b/hw/riscv/boot.c
205
@@ -XXX,XX +XXX,XX @@ void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
206
uint32_t fdtsize = fdt_totalsize(fdt);
207
208
/* copy in the device tree */
209
- qemu_fdt_dumpdtb(fdt, fdtsize);
210
-
211
rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
212
&address_space_memory);
213
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
214
diff --git a/system/device_tree.c b/system/device_tree.c
215
index XXXXXXX..XXXXXXX 100644
216
--- a/system/device_tree.c
217
+++ b/system/device_tree.c
218
@@ -XXX,XX +XXX,XX @@ int qemu_fdt_add_path(void *fdt, const char *path)
219
return retval;
49
}
220
}
50
221
51
static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
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,
52
--
240
--
53
2.20.1
241
2.43.0
54
55
diff view generated by jsdifflib
1
The omap_lcdc template header is already only included once, for
1
Currently if the user requests via -machine dumpdtb=file.dtb that we
2
DEPTH==32, but it still has all the macro-driven parameterization
2
dump the DTB, but the machine doesn't have a DTB, we silently ignore
3
for other depths. Expand out all the macros in the header.
3
the option. This is confusing to users, and is a legacy of the old
4
board-specific implementation of the option, where if the execution
5
codepath didn't go via a call to qemu_fdt_dumpdtb() we would never
6
handle the option.
4
7
8
Now we handle the option in one place in machine.c, we can provide
9
the user with a useful message if they asked us to dump a DTB when
10
none exists. qmp_dumpdtb() already produces this error; remove the
11
logic in handle_machine_dumpdtb() that was there specifically to
12
avoid hitting it.
13
14
While we're here, beef up the error message a bit with a hint, and
15
make it consistent about "an FDT" rather than "a FDT". (In the
16
qmp_dumpdtb() case this needs an ERRP_GUARD to make
17
error_append_hint() work when the caller passes error_fatal.)
18
19
Note that the three places where we might report "doesn't have an
20
FDT" are hit in different situations:
21
22
(1) in handle_machine_dumpdtb(), if CONFIG_FDT is not set: this is
23
because the QEMU binary was built without libfdt at all. The
24
build system will not let you build with a machine type that
25
needs an FDT but no libfdt, so here we know both that the machine
26
doesn't use FDT and that QEMU doesn't have the support:
27
28
(2) in the device_tree-stub.c qmp_dumpdtb(): this is used when
29
we had libfdt at build time but the target architecture didn't
30
enable any machines which did "select DEVICE_TREE", so here we
31
know that the machine doesn't use FDT.
32
33
(3) in qmp_dumpdtb(), if current_machine->fdt is NULL all we know
34
is that this machine never set it. That might be because it doesn't
35
use FDT, or it might be because the user didn't pass an FDT
36
on the command line and the machine doesn't autogenerate an FDT.
37
38
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2733
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
41
Message-id: 20250206151214.2947842-7-peter.maydell@linaro.org
8
Message-id: 20210215103215.4944-6-peter.maydell@linaro.org
9
---
42
---
10
hw/display/omap_lcd_template.h | 67 ++++++++++++++--------------------
43
hw/core/machine.c | 6 ++----
11
1 file changed, 28 insertions(+), 39 deletions(-)
44
system/device_tree-stub.c | 5 ++++-
45
system/device_tree.c | 7 ++++++-
46
3 files changed, 12 insertions(+), 6 deletions(-)
12
47
13
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
48
diff --git a/hw/core/machine.c b/hw/core/machine.c
14
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/display/omap_lcd_template.h
50
--- a/hw/core/machine.c
16
+++ b/hw/display/omap_lcd_template.h
51
+++ b/hw/core/machine.c
17
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@ static void handle_machine_dumpdtb(MachineState *ms)
18
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53
if (!ms->dumpdtb) {
19
*/
54
return;
20
55
}
21
-#if DEPTH == 32
56
- if (!ms->fdt) {
22
-# define BPP 4
57
- /* Silently ignore dumpdtb option if there is nothing to dump */
23
-# define PIXEL_TYPE uint32_t
58
- return;
24
-#else
59
- }
25
-# error unsupport depth
60
#ifdef CONFIG_FDT
26
-#endif
61
qmp_dumpdtb(ms->dumpdtb, &error_fatal);
27
-
62
exit(0);
28
/*
63
#else
29
* 2-bit colour
64
error_report("This machine doesn't have an FDT");
30
*/
65
+ error_printf("(this machine type definitely doesn't use FDT, and "
31
-static void glue(draw_line2_, DEPTH)(void *opaque,
66
+ "this QEMU doesn't have FDT support compiled in)\n");
32
- uint8_t *d, const uint8_t *s, int width, int deststep)
67
exit(1);
33
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
34
+ int width, int deststep)
35
{
36
uint16_t *pal = opaque;
37
uint8_t v, r, g, b;
38
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
39
r = (pal[v & 3] >> 4) & 0xf0;
40
g = pal[v & 3] & 0xf0;
41
b = (pal[v & 3] << 4) & 0xf0;
42
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
43
- d += BPP;
44
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
45
+ d += 4;
46
v >>= 2;
47
r = (pal[v & 3] >> 4) & 0xf0;
48
g = pal[v & 3] & 0xf0;
49
b = (pal[v & 3] << 4) & 0xf0;
50
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
51
- d += BPP;
52
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
53
+ d += 4;
54
v >>= 2;
55
r = (pal[v & 3] >> 4) & 0xf0;
56
g = pal[v & 3] & 0xf0;
57
b = (pal[v & 3] << 4) & 0xf0;
58
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
59
- d += BPP;
60
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
61
+ d += 4;
62
v >>= 2;
63
r = (pal[v & 3] >> 4) & 0xf0;
64
g = pal[v & 3] & 0xf0;
65
b = (pal[v & 3] << 4) & 0xf0;
66
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
67
- d += BPP;
68
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
69
+ d += 4;
70
s ++;
71
width -= 4;
72
} while (width > 0);
73
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
74
/*
75
* 4-bit colour
76
*/
77
-static void glue(draw_line4_, DEPTH)(void *opaque,
78
- uint8_t *d, const uint8_t *s, int width, int deststep)
79
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
80
+ int width, int deststep)
81
{
82
uint16_t *pal = opaque;
83
uint8_t v, r, g, b;
84
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
85
r = (pal[v & 0xf] >> 4) & 0xf0;
86
g = pal[v & 0xf] & 0xf0;
87
b = (pal[v & 0xf] << 4) & 0xf0;
88
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
89
- d += BPP;
90
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
91
+ d += 4;
92
v >>= 4;
93
r = (pal[v & 0xf] >> 4) & 0xf0;
94
g = pal[v & 0xf] & 0xf0;
95
b = (pal[v & 0xf] << 4) & 0xf0;
96
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
97
- d += BPP;
98
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
99
+ d += 4;
100
s ++;
101
width -= 2;
102
} while (width > 0);
103
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
104
/*
105
* 8-bit colour
106
*/
107
-static void glue(draw_line8_, DEPTH)(void *opaque,
108
- uint8_t *d, const uint8_t *s, int width, int deststep)
109
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
110
+ int width, int deststep)
111
{
112
uint16_t *pal = opaque;
113
uint8_t v, r, g, b;
114
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line8_, DEPTH)(void *opaque,
115
r = (pal[v] >> 4) & 0xf0;
116
g = pal[v] & 0xf0;
117
b = (pal[v] << 4) & 0xf0;
118
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
119
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
120
s ++;
121
- d += BPP;
122
+ d += 4;
123
} while (-- width != 0);
124
}
125
126
/*
127
* 12-bit colour
128
*/
129
-static void glue(draw_line12_, DEPTH)(void *opaque,
130
- uint8_t *d, const uint8_t *s, int width, int deststep)
131
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
132
+ int width, int deststep)
133
{
134
uint16_t v;
135
uint8_t r, g, b;
136
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line12_, DEPTH)(void *opaque,
137
r = (v >> 4) & 0xf0;
138
g = v & 0xf0;
139
b = (v << 4) & 0xf0;
140
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
141
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
142
s += 2;
143
- d += BPP;
144
+ d += 4;
145
} while (-- width != 0);
146
}
147
148
/*
149
* 16-bit colour
150
*/
151
-static void glue(draw_line16_, DEPTH)(void *opaque,
152
- uint8_t *d, const uint8_t *s, int width, int deststep)
153
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
154
+ int width, int deststep)
155
{
156
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
157
memcpy(d, s, width * 2);
158
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line16_, DEPTH)(void *opaque,
159
r = (v >> 8) & 0xf8;
160
g = (v >> 3) & 0xfc;
161
b = (v << 3) & 0xf8;
162
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
163
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
164
s += 2;
165
- d += BPP;
166
+ d += 4;
167
} while (-- width != 0);
168
#endif
68
#endif
169
}
69
}
170
-
70
diff --git a/system/device_tree-stub.c b/system/device_tree-stub.c
171
-#undef DEPTH
71
index XXXXXXX..XXXXXXX 100644
172
-#undef BPP
72
--- a/system/device_tree-stub.c
173
-#undef PIXEL_TYPE
73
+++ b/system/device_tree-stub.c
74
@@ -XXX,XX +XXX,XX @@
75
#ifdef CONFIG_FDT
76
void qmp_dumpdtb(const char *filename, Error **errp)
77
{
78
- error_setg(errp, "This machine doesn't have a FDT");
79
+ ERRP_GUARD();
80
+
81
+ error_setg(errp, "This machine doesn't have an FDT");
82
+ error_append_hint(errp, "(this machine type definitely doesn't use FDT)\n");
83
}
84
#endif
85
diff --git a/system/device_tree.c b/system/device_tree.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/system/device_tree.c
88
+++ b/system/device_tree.c
89
@@ -XXX,XX +XXX,XX @@ out:
90
91
void qmp_dumpdtb(const char *filename, Error **errp)
92
{
93
+ ERRP_GUARD();
94
+
95
g_autoptr(GError) err = NULL;
96
uint32_t size;
97
98
if (!current_machine->fdt) {
99
- error_setg(errp, "This machine doesn't have a FDT");
100
+ error_setg(errp, "This machine doesn't have an FDT");
101
+ error_append_hint(errp,
102
+ "(Perhaps it doesn't support FDT at all, or perhaps "
103
+ "you need to provide an FDT with the -fdt option?)\n");
104
return;
105
}
106
174
--
107
--
175
2.20.1
108
2.43.0
176
177
diff view generated by jsdifflib
1
The AN505 and AN521 have the same layout of RAM; the AN524 does not.
1
Currently we hardcode at compile time whether the floatx80 default
2
Replace the current hard-coding of where the RAM is and which parts
2
Infinity value has the explicit integer bit set or not (x86 sets it;
3
of it are behind which MPCs with a data-driven approach.
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.
4
32
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
34
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-17-peter.maydell@linaro.org
35
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
36
Message-id: 20250224111524.1101196-2-peter.maydell@linaro.org
37
Message-id: 20250217125055.160887-2-peter.maydell@linaro.org
8
---
38
---
9
hw/arm/mps2-tz.c | 175 +++++++++++++++++++++++++++++++++++++----------
39
include/fpu/softfloat-helpers.h | 12 ++++++++++++
10
1 file changed, 138 insertions(+), 37 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(-)
11
46
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
47
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
13
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
49
--- a/include/fpu/softfloat-helpers.h
15
+++ b/hw/arm/mps2-tz.c
50
+++ b/include/fpu/softfloat-helpers.h
16
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@ static inline void set_floatx80_rounding_precision(FloatX80RoundPrec val,
17
#include "qom/object.h"
52
status->floatx80_rounding_precision = val;
18
53
}
19
#define MPS2TZ_NUMIRQ_MAX 92
54
20
+#define MPS2TZ_RAM_MAX 4
55
+static inline void set_floatx80_behaviour(FloatX80Behaviour b,
21
56
+ float_status *status)
22
typedef enum MPS2TZFPGAType {
23
FPGA_AN505,
24
FPGA_AN521,
25
} MPS2TZFPGAType;
26
27
+/*
28
+ * Define the layout of RAM in a board, including which parts are
29
+ * behind which MPCs.
30
+ * mrindex specifies the index into mms->ram[] to use for the backing RAM;
31
+ * -1 means "use the system RAM".
32
+ */
33
+typedef struct RAMInfo {
34
+ const char *name;
35
+ uint32_t base;
36
+ uint32_t size;
37
+ int mpc; /* MPC number, -1 for "not behind an MPC" */
38
+ int mrindex;
39
+ int flags;
40
+} RAMInfo;
41
+
42
+/*
43
+ * Flag values:
44
+ * IS_ALIAS: this RAM area is an alias to the upstream end of the
45
+ * MPC specified by its .mpc value
46
+ */
47
+#define IS_ALIAS 1
48
+
49
struct MPS2TZMachineClass {
50
MachineClass parent;
51
MPS2TZFPGAType fpga_type;
52
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
53
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
54
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
55
int numirq; /* Number of external interrupts */
56
+ const RAMInfo *raminfo;
57
const char *armsse_type;
58
};
59
60
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
61
MachineState parent;
62
63
ARMSSE iotkit;
64
- MemoryRegion ssram[3];
65
- MemoryRegion ssram1_m;
66
+ MemoryRegion ram[MPS2TZ_RAM_MAX];
67
MPS2SCC scc;
68
MPS2FPGAIO fpgaio;
69
TZPPC ppc[5];
70
- TZMPC ssram_mpc[3];
71
+ TZMPC mpc[3];
72
PL022State spi[5];
73
ArmSbconI2CState i2c[4];
74
UnimplementedDeviceState i2s_audio;
75
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
76
25000000,
77
};
78
79
+static const RAMInfo an505_raminfo[] = { {
80
+ .name = "ssram-0",
81
+ .base = 0x00000000,
82
+ .size = 0x00400000,
83
+ .mpc = 0,
84
+ .mrindex = 0,
85
+ }, {
86
+ .name = "ssram-1",
87
+ .base = 0x28000000,
88
+ .size = 0x00200000,
89
+ .mpc = 1,
90
+ .mrindex = 1,
91
+ }, {
92
+ .name = "ssram-2",
93
+ .base = 0x28200000,
94
+ .size = 0x00200000,
95
+ .mpc = 2,
96
+ .mrindex = 2,
97
+ }, {
98
+ .name = "ssram-0-alias",
99
+ .base = 0x00400000,
100
+ .size = 0x00400000,
101
+ .mpc = 0,
102
+ .mrindex = 3,
103
+ .flags = IS_ALIAS,
104
+ }, {
105
+ /* Use the largest bit of contiguous RAM as our "system memory" */
106
+ .name = "mps.ram",
107
+ .base = 0x80000000,
108
+ .size = 16 * MiB,
109
+ .mpc = -1,
110
+ .mrindex = -1,
111
+ }, {
112
+ .name = NULL,
113
+ },
114
+};
115
+
116
+static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
117
+{
57
+{
118
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
58
+ status->floatx80_behaviour = b;
119
+ const RAMInfo *p;
120
+
121
+ for (p = mmc->raminfo; p->name; p++) {
122
+ if (p->mpc == mpc && !(p->flags & IS_ALIAS)) {
123
+ return p;
124
+ }
125
+ }
126
+ /* if raminfo array doesn't have an entry for each MPC this is a bug */
127
+ g_assert_not_reached();
128
+}
59
+}
129
+
60
+
130
+static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
61
static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
131
+ const RAMInfo *raminfo)
62
float_status *status)
63
{
64
@@ -XXX,XX +XXX,XX @@ get_floatx80_rounding_precision(const float_status *status)
65
return status->floatx80_rounding_precision;
66
}
67
68
+static inline FloatX80Behaviour
69
+get_floatx80_behaviour(const float_status *status)
132
+{
70
+{
133
+ /* Return an initialized MemoryRegion for the RAMInfo. */
71
+ return status->floatx80_behaviour;
134
+ MemoryRegion *ram;
135
+
136
+ if (raminfo->mrindex < 0) {
137
+ /* Means this RAMInfo is for QEMU's "system memory" */
138
+ MachineState *machine = MACHINE(mms);
139
+ return machine->ram;
140
+ }
141
+
142
+ assert(raminfo->mrindex < MPS2TZ_RAM_MAX);
143
+ ram = &mms->ram[raminfo->mrindex];
144
+
145
+ memory_region_init_ram(ram, NULL, raminfo->name,
146
+ raminfo->size, &error_fatal);
147
+ return ram;
148
+}
72
+}
149
+
73
+
150
/* Create an alias of an entire original MemoryRegion @orig
74
static inline Float2NaNPropRule
151
* located at @base in the memory map.
75
get_float_2nan_prop_rule(const float_status *status)
152
*/
153
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
154
const int *irqs)
155
{
76
{
156
TZMPC *mpc = opaque;
77
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
157
- int i = mpc - &mms->ssram_mpc[0];
78
index XXXXXXX..XXXXXXX 100644
158
- MemoryRegion *ssram = &mms->ssram[i];
79
--- a/include/fpu/softfloat-types.h
159
+ int i = mpc - &mms->mpc[0];
80
+++ b/include/fpu/softfloat-types.h
160
MemoryRegion *upstream;
81
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
161
- char *mpcname = g_strdup_printf("%s-mpc", name);
82
float_ftz_before_rounding = 1,
162
- static uint32_t ramsize[] = { 0x00400000, 0x00200000, 0x00200000 };
83
} FloatFTZDetection;
163
- static uint32_t rambase[] = { 0x00000000, 0x28000000, 0x28200000 };
84
164
+ const RAMInfo *raminfo = find_raminfo_for_mpc(mms, i);
85
+/*
165
+ MemoryRegion *ram = mr_for_raminfo(mms, raminfo);
86
+ * floatx80 is primarily used by x86 and m68k, and there are
166
87
+ * differences in the handling, largely related to the explicit
167
- memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal);
88
+ * Integer bit which floatx80 has and the other float formats do not.
168
-
89
+ * These flag values allow specification of the target's requirements
169
- object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC);
90
+ * and can be ORed together to set floatx80_behaviour.
170
- object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ssram),
91
+ */
171
+ object_initialize_child(OBJECT(mms), name, mpc, TYPE_TZ_MPC);
92
+typedef enum __attribute__((__packed__)) {
172
+ object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ram),
93
+ /* In the default Infinity value, is the Integer bit 0 ? */
173
&error_fatal);
94
+ floatx80_default_inf_int_bit_is_zero = 1,
174
sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal);
95
+} FloatX80Behaviour;
175
/* Map the upstream end of the MPC into system memory */
96
+
176
upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
97
/*
177
- memory_region_add_subregion(get_system_memory(), rambase[i], upstream);
98
* Floating Point Status. Individual architectures may maintain
178
+ memory_region_add_subregion(get_system_memory(), raminfo->base, upstream);
99
* several versions of float_status for different functions. The
179
/* and connect its interrupt to the IoTKit */
100
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
180
qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
101
uint16_t float_exception_flags;
181
qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
102
FloatRoundMode float_rounding_mode;
182
"mpcexp_status", i));
103
FloatX80RoundPrec floatx80_rounding_precision;
183
104
+ FloatX80Behaviour floatx80_behaviour;
184
- /* The first SSRAM is a special case as it has an alias; accesses to
105
Float2NaNPropRule float_2nan_prop_rule;
185
- * the alias region at 0x00400000 must also go to the MPC upstream.
106
Float3NaNPropRule float_3nan_prop_rule;
186
- */
107
FloatInfZeroNaNRule float_infzeronan_rule;
187
- if (i == 0) {
108
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
188
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", upstream, 0x00400000);
109
index XXXXXXX..XXXXXXX 100644
189
- }
110
--- a/include/fpu/softfloat.h
190
-
111
+++ b/include/fpu/softfloat.h
191
- g_free(mpcname);
112
@@ -XXX,XX +XXX,XX @@ float128 floatx80_to_float128(floatx80, float_status *status);
192
/* Return the register interface MR for our caller to map behind the PPC */
113
| The pattern for an extended double-precision inf.
193
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
114
*----------------------------------------------------------------------------*/
194
}
115
extern const floatx80 floatx80_infinity;
195
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
116
+floatx80 floatx80_default_inf(bool zSign, float_status *status);
196
return sysbus_mmio_get_region(s, 0);
117
197
}
118
/*----------------------------------------------------------------------------
198
119
| Software IEC/IEEE extended double-precision operations.
199
+static void create_non_mpc_ram(MPS2TZMachineState *mms)
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)
200
+{
171
+{
201
+ /*
172
+ /*
202
+ * Handle the RAMs which are either not behind MPCs or which are
173
+ * Whether the Integer bit is set in the default Infinity is
203
+ * aliases to another MPC.
174
+ * target dependent.
204
+ */
175
+ */
205
+ const RAMInfo *p;
176
+ bool z = status->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero;
206
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
177
+ return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
207
+
208
+ for (p = mmc->raminfo; p->name; p++) {
209
+ if (p->flags & IS_ALIAS) {
210
+ SysBusDevice *mpc_sbd = SYS_BUS_DEVICE(&mms->mpc[p->mpc]);
211
+ MemoryRegion *upstream = sysbus_mmio_get_region(mpc_sbd, 1);
212
+ make_ram_alias(&mms->ram[p->mrindex], p->name, upstream, p->base);
213
+ } else if (p->mpc == -1) {
214
+ /* RAM not behind an MPC */
215
+ MemoryRegion *mr = mr_for_raminfo(mms, p);
216
+ memory_region_add_subregion(get_system_memory(), p->base, mr);
217
+ }
218
+ }
219
+}
178
+}
220
+
179
+
221
static void mps2tz_common_init(MachineState *machine)
180
#define floatx80_infinity_high 0x7FFF
222
{
181
#if defined(TARGET_M68K)
223
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
182
#define floatx80_infinity_low UINT64_C(0x0000000000000000)
224
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
225
qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
226
qdev_get_gpio_in(dev_splitter, 0));
227
228
- /* The IoTKit sets up much of the memory layout, including
229
+ /*
230
+ * The IoTKit sets up much of the memory layout, including
231
* the aliases between secure and non-secure regions in the
232
- * address space. The FPGA itself contains:
233
- *
234
- * 0x00000000..0x003fffff SSRAM1
235
- * 0x00400000..0x007fffff alias of SSRAM1
236
- * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
237
- * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
238
- * 0x80000000..0x80ffffff 16MB PSRAM
239
- */
240
-
241
- /* The FPGA images have an odd combination of different RAMs,
242
+ * address space, and also most of the devices in the system.
243
+ * The FPGA itself contains various RAMs and some additional devices.
244
+ * The FPGA images have an odd combination of different RAMs,
245
* because in hardware they are different implementations and
246
* connected to different buses, giving varying performance/size
247
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
248
- * call the 16MB our "system memory", as it's the largest lump.
249
+ * call the largest lump our "system memory".
250
*/
251
- memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
252
253
/*
254
* The overflow IRQs for all UARTs are ORed together.
255
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
256
const PPCInfo an505_ppcs[] = { {
257
.name = "apb_ppcexp0",
258
.ports = {
259
- { "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
260
- { "ssram-1", make_mpc, &mms->ssram_mpc[1], 0x58008000, 0x1000 },
261
- { "ssram-2", make_mpc, &mms->ssram_mpc[2], 0x58009000, 0x1000 },
262
+ { "ssram-0-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
263
+ { "ssram-1-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
264
+ { "ssram-2-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
265
},
266
}, {
267
.name = "apb_ppcexp1",
268
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
269
270
create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
271
272
+ create_non_mpc_ram(mms);
273
+
274
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
275
}
276
277
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
278
mmc->fpgaio_num_leds = 2;
279
mmc->fpgaio_has_switches = false;
280
mmc->numirq = 92;
281
+ mmc->raminfo = an505_raminfo;
282
mmc->armsse_type = TYPE_IOTKIT;
283
}
284
285
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
286
mmc->fpgaio_num_leds = 2;
287
mmc->fpgaio_has_switches = false;
288
mmc->numirq = 92;
289
+ mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
290
mmc->armsse_type = TYPE_SSE200;
291
}
292
293
--
183
--
294
2.20.1
184
2.43.0
295
185
296
186
diff view generated by jsdifflib
1
For a long time now the UI layer has guaranteed that the console
1
The global const floatx80_infinity is (unlike all the other
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
2
float*_infinity values) target-specific, because whether the explicit
3
code from the milkymist display device which was handling the
3
Integer bit is set or not varies between m68k and i386. We want to
4
possibility that the console surface was some other format.
4
be able to compile softfloat once for multiple targets, so we can't
5
continue to use a single global whose value needs to be different
6
between targets.
7
8
Replace the direct uses of floatx80_infinity in target/m68k with
9
calls to the new floatx80_default_inf() function.
5
10
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215103215.4944-2-peter.maydell@linaro.org
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Message-id: 20250224111524.1101196-3-peter.maydell@linaro.org
15
Message-id: 20250217125055.160887-3-peter.maydell@linaro.org
9
---
16
---
10
hw/arm/musicpal.c | 64 ++++++++++++++++++-----------------------------
17
target/m68k/softfloat.c | 47 ++++++++++++++---------------------------
11
1 file changed, 24 insertions(+), 40 deletions(-)
18
1 file changed, 16 insertions(+), 31 deletions(-)
12
19
13
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
20
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/musicpal.c
22
--- a/target/m68k/softfloat.c
16
+++ b/hw/arm/musicpal.c
23
+++ b/target/m68k/softfloat.c
17
@@ -XXX,XX +XXX,XX @@ static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
24
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
25
if ((uint64_t) (aSig << 1)) {
26
return propagateFloatx80NaN(a, b, status);
27
}
28
- return packFloatx80(aSign, floatx80_infinity.high,
29
- floatx80_infinity.low);
30
+ return floatx80_default_inf(aSign, status);
18
}
31
}
19
}
32
if (aExp == 0) {
20
33
if (aSig == 0) {
21
-#define SET_LCD_PIXEL(depth, type) \
34
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
22
-static inline void glue(set_lcd_pixel, depth) \
35
float_raise(float_flag_invalid, status);
23
- (musicpal_lcd_state *s, int x, int y, type col) \
36
return floatx80_default_nan(status);
24
-{ \
37
}
25
- int dx, dy; \
38
- return packFloatx80(0, floatx80_infinity.high, floatx80_infinity.low);
26
- DisplaySurface *surface = qemu_console_surface(s->con); \
39
+ return floatx80_default_inf(0, status);
27
- type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
28
-\
29
- for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
30
- for (dx = 0; dx < 3; dx++, pixel++) \
31
- *pixel = col; \
32
+static inline void set_lcd_pixel32(musicpal_lcd_state *s,
33
+ int x, int y, uint32_t col)
34
+{
35
+ int dx, dy;
36
+ DisplaySurface *surface = qemu_console_surface(s->con);
37
+ uint32_t *pixel =
38
+ &((uint32_t *) surface_data(surface))[(y * 128 * 3 + x) * 3];
39
+
40
+ for (dy = 0; dy < 3; dy++, pixel += 127 * 3) {
41
+ for (dx = 0; dx < 3; dx++, pixel++) {
42
+ *pixel = col;
43
+ }
44
+ }
45
}
46
-SET_LCD_PIXEL(8, uint8_t)
47
-SET_LCD_PIXEL(16, uint16_t)
48
-SET_LCD_PIXEL(32, uint32_t)
49
50
static void lcd_refresh(void *opaque)
51
{
52
musicpal_lcd_state *s = opaque;
53
- DisplaySurface *surface = qemu_console_surface(s->con);
54
int x, y, col;
55
56
- switch (surface_bits_per_pixel(surface)) {
57
- case 0:
58
- return;
59
-#define LCD_REFRESH(depth, func) \
60
- case depth: \
61
- col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
62
- scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
63
- scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
64
- for (x = 0; x < 128; x++) { \
65
- for (y = 0; y < 64; y++) { \
66
- if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
67
- glue(set_lcd_pixel, depth)(s, x, y, col); \
68
- } else { \
69
- glue(set_lcd_pixel, depth)(s, x, y, 0); \
70
- } \
71
- } \
72
- } \
73
- break;
74
- LCD_REFRESH(8, rgb_to_pixel8)
75
- LCD_REFRESH(16, rgb_to_pixel16)
76
- LCD_REFRESH(32, (is_surface_bgr(surface) ?
77
- rgb_to_pixel32bgr : rgb_to_pixel32))
78
- default:
79
- hw_error("unsupported colour depth %i\n",
80
- surface_bits_per_pixel(surface));
81
+ col = rgb_to_pixel32(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff),
82
+ scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff),
83
+ scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff));
84
+ for (x = 0; x < 128; x++) {
85
+ for (y = 0; y < 64; y++) {
86
+ if (s->video_ram[x + (y / 8) * 128] & (1 << (y % 8))) {
87
+ set_lcd_pixel32(s, x, y, col);
88
+ } else {
89
+ set_lcd_pixel32(s, x, y, 0);
90
+ }
91
+ }
92
}
40
}
93
41
94
dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
42
if (aExp == 0 && aSig == 0) {
43
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
44
if (aSign && aExp >= one_exp) {
45
if (aExp == one_exp && aSig == one_sig) {
46
float_raise(float_flag_divbyzero, status);
47
- return packFloatx80(aSign, floatx80_infinity.high,
48
- floatx80_infinity.low);
49
+ return floatx80_default_inf(aSign, status);
50
}
51
float_raise(float_flag_invalid, status);
52
return floatx80_default_nan(status);
53
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
54
propagateFloatx80NaNOneArg(a, status);
55
}
56
if (aSign == 0) {
57
- return packFloatx80(0, floatx80_infinity.high,
58
- floatx80_infinity.low);
59
+ return floatx80_default_inf(0, status);
60
}
61
}
62
63
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
64
if (aExp == 0) {
65
if (aSig == 0) { /* zero */
66
float_raise(float_flag_divbyzero, status);
67
- return packFloatx80(1, floatx80_infinity.high,
68
- floatx80_infinity.low);
69
+ return floatx80_default_inf(1, status);
70
}
71
if ((aSig & one_sig) == 0) { /* denormal */
72
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
73
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
74
propagateFloatx80NaNOneArg(a, status);
75
}
76
if (aSign == 0) {
77
- return packFloatx80(0, floatx80_infinity.high,
78
- floatx80_infinity.low);
79
+ return floatx80_default_inf(0, status);
80
}
81
}
82
83
if (aExp == 0 && aSig == 0) {
84
float_raise(float_flag_divbyzero, status);
85
- return packFloatx80(1, floatx80_infinity.high,
86
- floatx80_infinity.low);
87
+ return floatx80_default_inf(1, status);
88
}
89
90
if (aSign) {
91
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
92
propagateFloatx80NaNOneArg(a, status);
93
}
94
if (aSign == 0) {
95
- return packFloatx80(0, floatx80_infinity.high,
96
- floatx80_infinity.low);
97
+ return floatx80_default_inf(0, status);
98
}
99
}
100
101
if (aExp == 0) {
102
if (aSig == 0) {
103
float_raise(float_flag_divbyzero, status);
104
- return packFloatx80(1, floatx80_infinity.high,
105
- floatx80_infinity.low);
106
+ return floatx80_default_inf(1, status);
107
}
108
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
109
}
110
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
111
if (aSign) {
112
return packFloatx80(0, 0, 0);
113
}
114
- return packFloatx80(0, floatx80_infinity.high,
115
- floatx80_infinity.low);
116
+ return floatx80_default_inf(0, status);
117
}
118
119
if (aExp == 0 && aSig == 0) {
120
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
121
if (aSign) {
122
return packFloatx80(0, 0, 0);
123
}
124
- return packFloatx80(0, floatx80_infinity.high,
125
- floatx80_infinity.low);
126
+ return floatx80_default_inf(0, status);
127
}
128
129
if (aExp == 0 && aSig == 0) {
130
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
131
if (aSign) {
132
return packFloatx80(0, 0, 0);
133
}
134
- return packFloatx80(0, floatx80_infinity.high,
135
- floatx80_infinity.low);
136
+ return floatx80_default_inf(0, status);
137
}
138
139
if (aExp == 0 && aSig == 0) {
140
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
141
if (compact >= 0x3FFF8000) { /* |X| >= 1 */
142
if (aExp == one_exp && aSig == one_sig) { /* |X| == 1 */
143
float_raise(float_flag_divbyzero, status);
144
- return packFloatx80(aSign, floatx80_infinity.high,
145
- floatx80_infinity.low);
146
+ return floatx80_default_inf(aSign, status);
147
} else { /* |X| > 1 */
148
float_raise(float_flag_invalid, status);
149
return floatx80_default_nan(status);
150
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
151
if (aSign) {
152
return packFloatx80(aSign, one_exp, one_sig);
153
}
154
- return packFloatx80(0, floatx80_infinity.high,
155
- floatx80_infinity.low);
156
+ return floatx80_default_inf(0, status);
157
}
158
159
if (aExp == 0 && aSig == 0) {
160
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
161
if ((uint64_t) (aSig << 1)) {
162
return propagateFloatx80NaNOneArg(a, status);
163
}
164
- return packFloatx80(aSign, floatx80_infinity.high,
165
- floatx80_infinity.low);
166
+ return floatx80_default_inf(aSign, status);
167
}
168
169
if (aExp == 0 && aSig == 0) {
170
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
171
if ((uint64_t) (aSig << 1)) {
172
return propagateFloatx80NaNOneArg(a, status);
173
}
174
- return packFloatx80(0, floatx80_infinity.high,
175
- floatx80_infinity.low);
176
+ return floatx80_default_inf(0, status);
177
}
178
179
if (aExp == 0 && aSig == 0) {
95
--
180
--
96
2.20.1
181
2.43.0
97
182
98
183
diff view generated by jsdifflib
1
We create an OR gate to wire together the overflow IRQs for all the
1
The global const floatx80_infinity is (unlike all the other
2
UARTs on the board; this has to have twice the number of inputs as
2
float*_infinity values) target-specific, because whether the explicit
3
there are UARTs, since each UART feeds it a TX overflow and an RX
3
Integer bit is set or not varies between m68k and i386. We want to
4
overflow interrupt line. Replace the hardcoded '10' with a
4
be able to compile softfloat once for multiple targets, so we can't
5
calculation based on the size of the uart[] array in the
5
continue to use a single global whose value needs to be different
6
MPS2TZMachineState. (We rely on OR gate inputs that are never wired
6
between targets.
7
up or asserted being treated as always-zero.)
7
8
Replace the direct uses of floatx80_infinity in target/i386 with
9
calls to the new floatx80_default_inf() function. Note that because
10
we can ask the function for either a negative or positive infinity,
11
we don't need to change the sign of a positive infinity via
12
floatx80_chs() for the negative-Inf case.
8
13
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210215115138.20465-15-peter.maydell@linaro.org
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
17
Message-id: 20250224111524.1101196-4-peter.maydell@linaro.org
18
Message-id: 20250217125055.160887-4-peter.maydell@linaro.org
12
---
19
---
13
hw/arm/mps2-tz.c | 11 ++++++++---
20
target/i386/tcg/fpu_helper.c | 7 +++----
14
1 file changed, 8 insertions(+), 3 deletions(-)
21
1 file changed, 3 insertions(+), 4 deletions(-)
15
22
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
23
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/mps2-tz.c
25
--- a/target/i386/tcg/fpu_helper.c
19
+++ b/hw/arm/mps2-tz.c
26
+++ b/target/i386/tcg/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
27
@@ -XXX,XX +XXX,XX @@ void helper_fxtract(CPUX86State *env)
21
*/
28
} else if (floatx80_is_infinity(ST0)) {
22
memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
29
fpush(env);
23
30
ST0 = ST1;
24
- /* The overflow IRQs for all UARTs are ORed together.
31
- ST1 = floatx80_infinity;
25
+ /*
32
+ ST1 = floatx80_default_inf(0, &env->fp_status);
26
+ * The overflow IRQs for all UARTs are ORed together.
33
} else {
27
* Tx, Rx and "combined" IRQs are sent to the NVIC separately.
34
int expdif;
28
- * Create the OR gate for this.
35
29
+ * Create the OR gate for this: it has one input for the TX overflow
36
@@ -XXX,XX +XXX,XX @@ void helper_fscale(CPUX86State *env)
30
+ * and one for the RX overflow for each UART we might have.
37
float_raise(float_flag_invalid, &env->fp_status);
31
+ * (If the board has fewer than the maximum possible number of UARTs
38
ST0 = floatx80_default_nan(&env->fp_status);
32
+ * those inputs are never wired up and are treated as always-zero.)
39
} else {
33
*/
40
- ST0 = (floatx80_is_neg(ST0) ?
34
object_initialize_child(OBJECT(mms), "uart-irq-orgate",
41
- floatx80_chs(floatx80_infinity) :
35
&mms->uart_irq_orgate, TYPE_OR_IRQ);
42
- floatx80_infinity);
36
- object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines", 10,
43
+ ST0 = floatx80_default_inf(floatx80_is_neg(ST0),
37
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines",
44
+ &env->fp_status);
38
+ 2 * ARRAY_SIZE(mms->uart),
45
}
39
&error_fatal);
46
}
40
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
47
} else {
41
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
42
--
48
--
43
2.20.1
49
2.43.0
44
50
45
51
diff view generated by jsdifflib
1
The macro draw_line_func is used only once; just expand it.
1
Unlike the other float formats, whether a floatx80 value is
2
considered to be an Infinity is target-dependent. (On x86 if the
3
explicit integer bit is clear this is a "pseudo-infinity" and not a
4
valid infinity; m68k does not care about the value of the integer
5
bit.)
6
7
Currently we select this target-specific logic at compile time with
8
an ifdef. We're going to want to do this at runtime, so change the
9
floatx80_is_infinity() function to take a float_status.
10
11
This commit doesn't change any logic; we'll do that in the
12
next commit.
2
13
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Message-id: 20210215103215.4944-10-peter.maydell@linaro.org
17
Message-id: 20250224111524.1101196-5-peter.maydell@linaro.org
7
---
18
---
8
hw/display/omap_lcdc.c | 4 +---
19
include/fpu/softfloat.h | 2 +-
9
1 file changed, 1 insertion(+), 3 deletions(-)
20
target/i386/tcg/fpu_helper.c | 20 +++++++++++---------
21
target/m68k/fpu_helper.c | 2 +-
22
3 files changed, 13 insertions(+), 11 deletions(-)
10
23
11
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
24
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
12
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/omap_lcdc.c
26
--- a/include/fpu/softfloat.h
14
+++ b/hw/display/omap_lcdc.c
27
+++ b/include/fpu/softfloat.h
15
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
28
@@ -XXX,XX +XXX,XX @@ static inline floatx80 floatx80_chs(floatx80 a)
16
qemu_irq_lower(s->irq);
29
return a;
17
}
30
}
18
31
19
-#define draw_line_func drawfn
32
-static inline bool floatx80_is_infinity(floatx80 a)
20
-
33
+static inline bool floatx80_is_infinity(floatx80 a, float_status *status)
21
/*
22
* 2-bit colour
23
*/
24
@@ -XXX,XX +XXX,XX @@ static void omap_update_display(void *opaque)
25
{
34
{
26
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
35
#if defined(TARGET_M68K)
27
DisplaySurface *surface;
36
return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
28
- draw_line_func draw_line;
37
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
29
+ drawfn draw_line;
38
index XXXXXXX..XXXXXXX 100644
30
int size, height, first, last;
39
--- a/target/i386/tcg/fpu_helper.c
31
int width, linesize, step, bpp, frame_offset;
40
+++ b/target/i386/tcg/fpu_helper.c
32
hwaddr frame_base;
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;
33
--
126
--
34
2.20.1
127
2.43.0
35
128
36
129
diff view generated by jsdifflib
1
Move the specification of the IRQ information for the uart, ethernet,
1
In Intel terminology, a floatx80 Infinity with the explicit integer
2
dma and spi devices to the data structures. (The other devices
2
bit clear is a "pseudo-infinity"; for x86 these are not valid
3
handled by the PPCPortInfo structures don't have any interrupt lines
3
infinity values. m68k is looser and does not care whether the
4
we need to wire up.)
4
Integer bit is set or clear in an infinity.
5
6
Move this setting to runtime rather than using an ifdef in
7
floatx80_is_infinity().
8
9
Since this was the last use of the floatx80_infinity global constant,
10
we remove it and its definition here.
5
11
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-14-peter.maydell@linaro.org
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Message-id: 20250224111524.1101196-6-peter.maydell@linaro.org
16
Message-id: 20250217125055.160887-5-peter.maydell@linaro.org
9
---
17
---
10
hw/arm/mps2-tz.c | 52 +++++++++++++++++++++++-------------------------
18
include/fpu/softfloat-types.h | 5 +++++
11
1 file changed, 25 insertions(+), 27 deletions(-)
19
include/fpu/softfloat.h | 18 +++++++++++-------
20
target/m68k/cpu.c | 4 +++-
21
fpu/softfloat-specialize.c.inc | 10 ----------
22
4 files changed, 19 insertions(+), 18 deletions(-)
12
23
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
24
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
14
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
26
--- a/include/fpu/softfloat-types.h
16
+++ b/hw/arm/mps2-tz.c
27
+++ b/include/fpu/softfloat-types.h
17
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
28
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
18
const char *name, hwaddr size,
29
typedef enum __attribute__((__packed__)) {
19
const int *irqs)
30
/* In the default Infinity value, is the Integer bit 0 ? */
31
floatx80_default_inf_int_bit_is_zero = 1,
32
+ /*
33
+ * Are Pseudo-infinities (Inf with the Integer bit zero) valid?
34
+ * If so, floatx80_is_infinity() will return true for them.
35
+ */
36
+ floatx80_pseudo_inf_valid = 2,
37
} FloatX80Behaviour;
38
39
/*
40
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/fpu/softfloat.h
43
+++ b/include/fpu/softfloat.h
44
@@ -XXX,XX +XXX,XX @@ float128 floatx80_to_float128(floatx80, float_status *status);
45
/*----------------------------------------------------------------------------
46
| The pattern for an extended double-precision inf.
47
*----------------------------------------------------------------------------*/
48
-extern const floatx80 floatx80_infinity;
49
floatx80 floatx80_default_inf(bool zSign, float_status *status);
50
51
/*----------------------------------------------------------------------------
52
@@ -XXX,XX +XXX,XX @@ static inline floatx80 floatx80_chs(floatx80 a)
53
54
static inline bool floatx80_is_infinity(floatx80 a, float_status *status)
20
{
55
{
21
+ /* The irq[] array is tx, rx, combined, in that order */
56
-#if defined(TARGET_M68K)
22
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
57
- return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
23
CMSDKAPBUART *uart = opaque;
58
-#else
24
int i = uart - &mms->uart[0];
59
- return (a.high & 0x7fff) == floatx80_infinity.high &&
25
- int rxirqno = i * 2 + 32;
60
- a.low == floatx80_infinity.low;
26
- int txirqno = i * 2 + 33;
61
-#endif
27
- int combirqno = i + 42;
62
+ /*
28
SysBusDevice *s;
63
+ * It's target-specific whether the Integer bit is permitted
29
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
64
+ * to be 0 in a valid Infinity value. (x86 says no, m68k says yes).
30
65
+ */
31
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
66
+ bool intbit = a.low >> 63;
32
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
67
+
33
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
68
+ if (!intbit &&
34
s = SYS_BUS_DEVICE(uart);
69
+ !(status->floatx80_behaviour & floatx80_pseudo_inf_valid)) {
35
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
70
+ return false;
36
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno));
71
+ }
37
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
72
+ return (a.high & 0x7fff) == 0x7fff && !(a.low << 1);
38
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
39
sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
40
sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
41
- sysbus_connect_irq(s, 4, get_sse_irq_in(mms, combirqno));
42
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqs[2]));
43
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
44
}
73
}
45
74
46
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
75
static inline bool floatx80_is_neg(floatx80 a)
47
76
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
48
s = SYS_BUS_DEVICE(mms->lan9118);
77
index XXXXXXX..XXXXXXX 100644
49
sysbus_realize_and_unref(s, &error_fatal);
78
--- a/target/m68k/cpu.c
50
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
79
+++ b/target/m68k/cpu.c
51
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
80
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
52
return sysbus_mmio_get_region(s, 0);
81
/*
82
* m68k-specific floatx80 behaviour:
83
* * default Infinity values have a zero Integer bit
84
+ * * input Infinities may have the Integer bit either 0 or 1
85
*/
86
- set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
87
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
88
+ floatx80_pseudo_inf_valid,
89
&env->fp_status);
90
91
nan = floatx80_default_nan(&env->fp_status);
92
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
93
index XXXXXXX..XXXXXXX 100644
94
--- a/fpu/softfloat-specialize.c.inc
95
+++ b/fpu/softfloat-specialize.c.inc
96
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_default_inf(bool zSign, float_status *status)
97
return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
53
}
98
}
54
99
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
100
-#define floatx80_infinity_high 0x7FFF
56
const char *name, hwaddr size,
101
-#if defined(TARGET_M68K)
57
const int *irqs)
102
-#define floatx80_infinity_low UINT64_C(0x0000000000000000)
58
{
103
-#else
59
+ /* The irq[] array is DMACINTR, DMACINTERR, DMACINTTC, in that order */
104
-#define floatx80_infinity_low UINT64_C(0x8000000000000000)
60
PL080State *dma = opaque;
105
-#endif
61
int i = dma - &mms->dma[0];
106
-
62
SysBusDevice *s;
107
-const floatx80 floatx80_infinity
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
108
- = make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low);
64
109
-
65
s = SYS_BUS_DEVICE(dma);
110
/*----------------------------------------------------------------------------
66
/* Wire up DMACINTR, DMACINTERR, DMACINTTC */
111
| Returns 1 if the half-precision floating-point value `a' is a quiet
67
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3));
112
| NaN; otherwise returns 0.
68
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3));
69
- sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3));
70
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
71
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
72
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqs[2]));
73
74
g_free(mscname);
75
return sysbus_mmio_get_region(s, 0);
76
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
77
* lines are set via the "MISC" register in the MPS2 FPGAIO device.
78
*/
79
PL022State *spi = opaque;
80
- int i = spi - &mms->spi[0];
81
SysBusDevice *s;
82
83
object_initialize_child(OBJECT(mms), name, spi, TYPE_PL022);
84
sysbus_realize(SYS_BUS_DEVICE(spi), &error_fatal);
85
s = SYS_BUS_DEVICE(spi);
86
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i));
87
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
88
return sysbus_mmio_get_region(s, 0);
89
}
90
91
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
92
}, {
93
.name = "apb_ppcexp1",
94
.ports = {
95
- { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000 },
96
- { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000 },
97
- { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000 },
98
- { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000 },
99
- { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000 },
100
- { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
101
- { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
102
- { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
103
- { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
104
- { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
105
+ { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000, { 51 } },
106
+ { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000, { 52 } },
107
+ { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000, { 53 } },
108
+ { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000, { 54 } },
109
+ { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000, { 55 } },
110
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000, { 32, 33, 42 } },
111
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000, { 34, 35, 43 } },
112
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000, { 36, 37, 44 } },
113
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000, { 38, 39, 45 } },
114
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000, { 40, 41, 46 } },
115
{ "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
116
{ "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
117
{ "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
118
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
119
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
120
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
121
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
122
- { "eth", make_eth_dev, NULL, 0x42000000, 0x100000 },
123
+ { "eth", make_eth_dev, NULL, 0x42000000, 0x100000, { 48 } },
124
},
125
}, {
126
.name = "ahb_ppcexp1",
127
.ports = {
128
- { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000 },
129
- { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000 },
130
- { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000 },
131
- { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000 },
132
+ { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000, { 58, 56, 57 } },
133
+ { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000, { 61, 59, 60 } },
134
+ { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000, { 64, 62, 63 } },
135
+ { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000, { 67, 65, 66 } },
136
},
137
},
138
};
139
--
113
--
140
2.20.1
114
2.43.0
141
115
142
116
diff view generated by jsdifflib
1
The AN505 and AN521 don't have any read-only memory, but the AN524
1
The definition of which floatx80 encodings are invalid is
2
does; add a flag to ROMInfo to mark a region as ROM.
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.
3
8
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215115138.20465-19-peter.maydell@linaro.org
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20250224111524.1101196-7-peter.maydell@linaro.org
7
---
13
---
8
hw/arm/mps2-tz.c | 6 ++++++
14
include/fpu/softfloat.h | 2 +-
9
1 file changed, 6 insertions(+)
15
fpu/softfloat.c | 2 +-
16
target/i386/tcg/fpu_helper.c | 24 +++++++++++++-----------
17
3 files changed, 15 insertions(+), 13 deletions(-)
10
18
11
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
12
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/mps2-tz.c
21
--- a/include/fpu/softfloat.h
14
+++ b/hw/arm/mps2-tz.c
22
+++ b/include/fpu/softfloat.h
15
@@ -XXX,XX +XXX,XX @@ typedef struct RAMInfo {
23
@@ -XXX,XX +XXX,XX @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
16
* Flag values:
24
| pseudo-denormals, which must still be correctly handled as inputs even
17
* IS_ALIAS: this RAM area is an alias to the upstream end of the
25
| if they are never generated as outputs.
18
* MPC specified by its .mpc value
26
*----------------------------------------------------------------------------*/
19
+ * IS_ROM: this RAM area is read-only
27
-static inline bool floatx80_invalid_encoding(floatx80 a)
20
*/
28
+static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
21
#define IS_ALIAS 1
29
{
22
+#define IS_ROM 2
30
#if defined(TARGET_M68K)
23
31
/*-------------------------------------------------------------------------
24
struct MPS2TZMachineClass {
32
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
25
MachineClass parent;
33
index XXXXXXX..XXXXXXX 100644
26
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
34
--- a/fpu/softfloat.c
27
if (raminfo->mrindex < 0) {
35
+++ b/fpu/softfloat.c
28
/* Means this RAMInfo is for QEMU's "system memory" */
36
@@ -XXX,XX +XXX,XX @@ static bool floatx80_unpack_canonical(FloatParts128 *p, floatx80 f,
29
MachineState *machine = MACHINE(mms);
37
g_assert_not_reached();
30
+ assert(!(raminfo->flags & IS_ROM));
31
return machine->ram;
32
}
38
}
33
39
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
40
- if (unlikely(floatx80_invalid_encoding(f))) {
35
41
+ if (unlikely(floatx80_invalid_encoding(f, s))) {
36
memory_region_init_ram(ram, NULL, raminfo->name,
42
float_raise(float_flag_invalid, s);
37
raminfo->size, &error_fatal);
43
return false;
38
+ if (raminfo->flags & IS_ROM) {
44
}
39
+ memory_region_set_readonly(ram, true);
45
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
40
+ }
46
index XXXXXXX..XXXXXXX 100644
41
return ram;
47
--- a/target/i386/tcg/fpu_helper.c
42
}
48
+++ b/target/i386/tcg/fpu_helper.c
43
49
@@ -XXX,XX +XXX,XX @@ void helper_f2xm1(CPUX86State *env)
50
int32_t exp = extractFloatx80Exp(ST0);
51
bool sign = extractFloatx80Sign(ST0);
52
53
- if (floatx80_invalid_encoding(ST0)) {
54
+ if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
55
float_raise(float_flag_invalid, &env->fp_status);
56
ST0 = floatx80_default_nan(&env->fp_status);
57
} else if (floatx80_is_any_nan(ST0)) {
58
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
59
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
60
float_raise(float_flag_invalid, &env->fp_status);
61
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
62
- } else if (floatx80_invalid_encoding(ST0) ||
63
- floatx80_invalid_encoding(ST1)) {
64
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
65
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
66
float_raise(float_flag_invalid, &env->fp_status);
67
ST1 = floatx80_default_nan(&env->fp_status);
68
} else if (floatx80_is_any_nan(ST0)) {
69
@@ -XXX,XX +XXX,XX @@ void helper_fxtract(CPUX86State *env)
70
&env->fp_status);
71
fpush(env);
72
ST0 = temp.d;
73
- } else if (floatx80_invalid_encoding(ST0)) {
74
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
75
float_raise(float_flag_invalid, &env->fp_status);
76
ST0 = floatx80_default_nan(&env->fp_status);
77
fpush(env);
78
@@ -XXX,XX +XXX,XX @@ static void helper_fprem_common(CPUX86State *env, bool mod)
79
env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
80
if (floatx80_is_zero(ST0) || floatx80_is_zero(ST1) ||
81
exp0 == 0x7fff || exp1 == 0x7fff ||
82
- floatx80_invalid_encoding(ST0) || floatx80_invalid_encoding(ST1)) {
83
+ floatx80_invalid_encoding(ST0, &env->fp_status) ||
84
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
85
ST0 = floatx80_modrem(ST0, ST1, mod, &quotient, &env->fp_status);
86
} else {
87
if (exp0 == 0) {
88
@@ -XXX,XX +XXX,XX @@ void helper_fyl2xp1(CPUX86State *env)
89
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
90
float_raise(float_flag_invalid, &env->fp_status);
91
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
92
- } else if (floatx80_invalid_encoding(ST0) ||
93
- floatx80_invalid_encoding(ST1)) {
94
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
95
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
96
float_raise(float_flag_invalid, &env->fp_status);
97
ST1 = floatx80_default_nan(&env->fp_status);
98
} else if (floatx80_is_any_nan(ST0)) {
99
@@ -XXX,XX +XXX,XX @@ void helper_fyl2x(CPUX86State *env)
100
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
101
float_raise(float_flag_invalid, &env->fp_status);
102
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
103
- } else if (floatx80_invalid_encoding(ST0) ||
104
- floatx80_invalid_encoding(ST1)) {
105
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
106
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
107
float_raise(float_flag_invalid, &env->fp_status);
108
ST1 = floatx80_default_nan(&env->fp_status);
109
} else if (floatx80_is_any_nan(ST0)) {
110
@@ -XXX,XX +XXX,XX @@ void helper_frndint(CPUX86State *env)
111
void helper_fscale(CPUX86State *env)
112
{
113
uint8_t old_flags = save_exception_flags(env);
114
- if (floatx80_invalid_encoding(ST1) || floatx80_invalid_encoding(ST0)) {
115
+ if (floatx80_invalid_encoding(ST1, &env->fp_status) ||
116
+ floatx80_invalid_encoding(ST0, &env->fp_status)) {
117
float_raise(float_flag_invalid, &env->fp_status);
118
ST0 = floatx80_default_nan(&env->fp_status);
119
} else if (floatx80_is_any_nan(ST1)) {
120
@@ -XXX,XX +XXX,XX @@ void helper_fscale(CPUX86State *env)
121
ST0 = floatx80_silence_nan(ST0, &env->fp_status);
122
}
123
} else if (floatx80_is_infinity(ST1, &env->fp_status) &&
124
- !floatx80_invalid_encoding(ST0) &&
125
+ !floatx80_invalid_encoding(ST0, &env->fp_status) &&
126
!floatx80_is_any_nan(ST0)) {
127
if (floatx80_is_neg(ST1)) {
128
if (floatx80_is_infinity(ST0, &env->fp_status)) {
44
--
129
--
45
2.20.1
130
2.43.0
46
131
47
132
diff view generated by jsdifflib
1
The MPS2 board has 2 LEDs, but the MPS3 board has 10 LEDs. The
1
Because floatx80 has an explicit integer bit, this permits some
2
FPGAIO device is similar on both sets of boards, but the LED0
2
odd encodings where the integer bit is not set correctly for the
3
register has correspondingly more bits that have an effect. Add a
3
floating point value type. In In Intel terminology the
4
device property for number of LEDs.
4
categories are:
5
exp == 0, int = 0, mantissa == 0 : zeroes
6
exp == 0, int = 0, mantissa != 0 : denormals
7
exp == 0, int = 1 : pseudo-denormals
8
0 < exp < 0x7fff, int = 0 : unnormals
9
0 < exp < 0x7fff, int = 1 : normals
10
exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
11
exp == 0x7fff, int = 1, mantissa == 0 : infinities
12
exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
13
exp == 0x7fff, int = 1, mantissa == 0 : NaNs
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.
5
27
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210215115138.20465-6-peter.maydell@linaro.org
30
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
31
Message-id: 20250224111524.1101196-8-peter.maydell@linaro.org
32
Message-id: 20250217125055.160887-6-peter.maydell@linaro.org
10
---
33
---
11
include/hw/misc/mps2-fpgaio.h | 5 ++++-
34
include/fpu/softfloat-types.h | 14 ++++++++
12
hw/misc/mps2-fpgaio.c | 31 +++++++++++++++++++++++--------
35
include/fpu/softfloat.h | 68 ++++++++++++++++++-----------------
13
2 files changed, 27 insertions(+), 9 deletions(-)
36
target/m68k/cpu.c | 28 ++++++++++++++-
37
3 files changed, 77 insertions(+), 33 deletions(-)
14
38
15
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
39
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
16
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/mps2-fpgaio.h
41
--- a/include/fpu/softfloat-types.h
18
+++ b/include/hw/misc/mps2-fpgaio.h
42
+++ b/include/fpu/softfloat-types.h
19
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
20
#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
44
/*
21
OBJECT_DECLARE_SIMPLE_TYPE(MPS2FPGAIO, MPS2_FPGAIO)
45
* Are Pseudo-infinities (Inf with the Integer bit zero) valid?
22
46
* If so, floatx80_is_infinity() will return true for them.
23
+#define MPS2FPGAIO_MAX_LEDS 32
47
+ * If not, floatx80_invalid_encoding will return false for them,
24
+
48
+ * and using them as inputs to a float op will raise Invalid.
25
struct MPS2FPGAIO {
49
*/
26
/*< private >*/
50
floatx80_pseudo_inf_valid = 2,
27
SysBusDevice parent_obj;
51
+ /*
28
52
+ * Are Pseudo-NaNs (NaNs where the Integer bit is zero) valid?
29
/*< public >*/
53
+ * If not, floatx80_invalid_encoding() will return false for them,
30
MemoryRegion iomem;
54
+ * and using them as inputs to a float op will raise Invalid.
31
- LEDState *led[2];
55
+ */
32
+ LEDState *led[MPS2FPGAIO_MAX_LEDS];
56
+ floatx80_pseudo_nan_valid = 4,
33
+ uint32_t num_leds;
57
+ /*
34
58
+ * Are Unnormals (0 < exp < 0x7fff, Integer bit zero) valid?
35
uint32_t led0;
59
+ * If not, floatx80_invalid_encoding() will return false for them,
36
uint32_t prescale;
60
+ * and using them as inputs to a float op will raise Invalid.
37
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
61
+ */
62
+ floatx80_unnormal_valid = 8,
63
} FloatX80Behaviour;
64
65
/*
66
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
38
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/misc/mps2-fpgaio.c
68
--- a/include/fpu/softfloat.h
40
+++ b/hw/misc/mps2-fpgaio.c
69
+++ b/include/fpu/softfloat.h
41
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
70
@@ -XXX,XX +XXX,XX @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
42
71
43
switch (offset) {
72
/*----------------------------------------------------------------------------
44
case A_LED0:
73
| Return whether the given value is an invalid floatx80 encoding.
45
- s->led0 = value & 0x3;
74
-| Invalid floatx80 encodings arise when the integer bit is not set, but
46
- led_set_state(s->led[0], value & 0x01);
75
-| the exponent is not zero. The only times the integer bit is permitted to
47
- led_set_state(s->led[1], value & 0x02);
76
-| be zero is in subnormal numbers and the value zero.
48
+ if (s->num_leds != 0) {
77
-| This includes what the Intel software developer's manual calls pseudo-NaNs,
49
+ uint32_t i;
78
-| pseudo-infinities and un-normal numbers. It does not include
50
+
79
-| pseudo-denormals, which must still be correctly handled as inputs even
51
+ s->led0 = value & MAKE_64BIT_MASK(0, s->num_leds);
80
-| if they are never generated as outputs.
52
+ for (i = 0; i < s->num_leds; i++) {
81
+| Invalid floatx80 encodings may arise when the integer bit is not set
53
+ led_set_state(s->led[i], value & (1 << i));
82
+| correctly; this is target-specific. In Intel terminology the
54
+ }
83
+| categories are:
55
+ }
84
+| exp == 0, int = 0, mantissa == 0 : zeroes
56
break;
85
+| exp == 0, int = 0, mantissa != 0 : denormals
57
case A_PRESCALE:
86
+| exp == 0, int = 1 : pseudo-denormals
58
resync_counter(s);
87
+| 0 < exp < 0x7fff, int = 0 : unnormals
59
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_reset(DeviceState *dev)
88
+| 0 < exp < 0x7fff, int = 1 : normals
60
s->pscntr = 0;
89
+| exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
61
s->pscntr_sync_ticks = now;
90
+| exp == 0x7fff, int = 1, mantissa == 0 : infinities
62
91
+| exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
63
- for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) {
92
+| exp == 0x7fff, int = 1, mantissa == 0 : NaNs
64
+ for (size_t i = 0; i < s->num_leds; i++) {
93
+|
65
device_cold_reset(DEVICE(s->led[i]));
94
+| The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
66
}
95
+| x87 permits as input also pseudo-denormals.
67
}
96
+| m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
68
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_init(Object *obj)
97
+|
69
static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
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)
70
{
105
{
71
MPS2FPGAIO *s = MPS2_FPGAIO(dev);
106
-#if defined(TARGET_M68K)
72
+ uint32_t i;
107
- /*-------------------------------------------------------------------------
73
108
- | With m68k, the explicit integer bit can be zero in the case of:
74
- s->led[0] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
109
- | - zeros (exp == 0, mantissa == 0)
75
- LED_COLOR_GREEN, "USERLED0");
110
- | - denormalized numbers (exp == 0, mantissa != 0)
76
- s->led[1] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
111
- | - unnormalized numbers (exp != 0, exp < 0x7FFF)
77
- LED_COLOR_GREEN, "USERLED1");
112
- | - infinities (exp == 0x7FFF, mantissa == 0)
78
+ if (s->num_leds > MPS2FPGAIO_MAX_LEDS) {
113
- | - not-a-numbers (exp == 0x7FFF, mantissa != 0)
79
+ error_setg(errp, "num-leds cannot be greater than %d",
114
- |
80
+ MPS2FPGAIO_MAX_LEDS);
115
- | For infinities and NaNs, the explicit integer bit can be either one or
81
+ return;
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;
82
+ }
134
+ }
83
+
135
+
84
+ for (i = 0; i < s->num_leds; i++) {
136
+ if ((a.high & 0x7fff) == 0x7fff) {
85
+ g_autofree char *ledname = g_strdup_printf("USERLED%d", i);
137
+ if (a.low) {
86
+ s->led[i] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
138
+ return !(s->floatx80_behaviour & floatx80_pseudo_nan_valid);
87
+ LED_COLOR_GREEN, ledname);
139
+ } else {
140
+ return !(s->floatx80_behaviour & floatx80_pseudo_inf_valid);
141
+ }
142
+ } else {
143
+ return !(s->floatx80_behaviour & floatx80_unnormal_valid);
88
+ }
144
+ }
89
}
145
}
90
146
91
static bool mps2_fpgaio_counters_needed(void *opaque)
147
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
92
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_fpgaio_vmstate = {
148
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
93
static Property mps2_fpgaio_properties[] = {
149
index XXXXXXX..XXXXXXX 100644
94
/* Frequency of the prescale counter */
150
--- a/target/m68k/cpu.c
95
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
151
+++ b/target/m68k/cpu.c
96
+ /* Number of LEDs controlled by LED0 register */
152
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
97
+ DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
153
* m68k-specific floatx80 behaviour:
98
DEFINE_PROP_END_OF_LIST(),
154
* * default Infinity values have a zero Integer bit
99
};
155
* * input Infinities may have the Integer bit either 0 or 1
100
156
+ * * pseudo-denormals supported for input and output
157
+ * * don't raise Invalid for pseudo-NaN/pseudo-Inf/Unnormal
158
+ *
159
+ * With m68k, the explicit integer bit can be zero in the case of:
160
+ * - zeros (exp == 0, mantissa == 0)
161
+ * - denormalized numbers (exp == 0, mantissa != 0)
162
+ * - unnormalized numbers (exp != 0, exp < 0x7FFF)
163
+ * - infinities (exp == 0x7FFF, mantissa == 0)
164
+ * - not-a-numbers (exp == 0x7FFF, mantissa != 0)
165
+ *
166
+ * For infinities and NaNs, the explicit integer bit can be either one or
167
+ * zero.
168
+ *
169
+ * The IEEE 754 standard does not define a zero integer bit. Such a number
170
+ * is an unnormalized number. Hardware does not directly support
171
+ * denormalized and unnormalized numbers, but implicitly supports them by
172
+ * trapping them as unimplemented data types, allowing efficient conversion
173
+ * in software.
174
+ *
175
+ * See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL",
176
+ * "1.6 FLOATING-POINT DATA TYPES"
177
+ *
178
+ * Note though that QEMU's fp emulation does directly handle both
179
+ * denormal and unnormal values, and does not trap to guest software.
180
*/
181
set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
182
- floatx80_pseudo_inf_valid,
183
+ floatx80_pseudo_inf_valid |
184
+ floatx80_pseudo_nan_valid |
185
+ floatx80_unnormal_valid,
186
&env->fp_status);
187
188
nan = floatx80_default_nan(&env->fp_status);
101
--
189
--
102
2.20.1
190
2.43.0
103
191
104
192
diff view generated by jsdifflib
1
On the MPS2 boards, the first 32 interrupt lines are entirely
1
Currently we compile-time set an 'm68k_denormal' flag in the FloatFmt
2
internal to the SSE; interrupt lines for devices outside the SSE
2
for floatx80 for m68k. This controls our handling of what the Intel
3
start at 32. In the application notes that document each FPGA image,
3
documentation calls a "pseudo-denormal": a value where the exponent
4
the interrupt wiring is documented from the point of view of the CPU,
4
field is zero and the explicit integer bit is set.
5
so '0' is the first of the SSE's interrupts and the devices in the
6
FPGA image itself are '32' and up: so the UART 0 Receive interrupt is
7
32, the SPI #0 interrupt is 51, and so on.
8
5
9
Within our implementation, because the external interrupts must be
6
For x86, the x87 FPU is supposed to accept a pseudo-denormal as
10
connected to the EXP_IRQ[0...n] lines of the SSE object, we made the
7
input, but never generate one on output. For m68k, these values are
11
get_sse_irq_in() function take an irqno whose values start at 0 for
8
permitted on input and may be produced on output.
12
the first FPGA device interrupt. In this numbering scheme the UART 0
13
Receive interrupt is 0, the SPI #0 interrupt is 19, and so on.
14
9
15
The result of these two different numbering schemes has been that
10
Replace the flag in the FloatFmt with a flag indicating whether the
16
half of the devices were wired up to the wrong IRQs: the UART IRQs
11
float format has an explicit bit (which will be true for floatx80 for
17
are wired up correctly, but the DMA and SPI devices were passing
12
all targets, and false for every other float type). Then we can gate
18
start-at-32 values to get_sse_irq_in() and so being mis-connected.
13
the handling of these pseudo-denormals on the setting of a
14
floatx80_behaviour flag.
19
15
20
Fix the bug by making get_sse_irq_in() take values specified with the
16
As far as I can see from the code we don't actually handle the
21
same scheme that the hardware manuals use, to avoid confusion.
17
x86-mandated "accept on input but don't generate" behaviour, because
18
the handling in partsN(canonicalize) looked at fmt->m68k_denormal.
19
So I have added TODO comments to that effect.
20
21
This commit doesn't change any behaviour for any target.
22
22
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20210215115138.20465-12-peter.maydell@linaro.org
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
26
Message-id: 20250224111524.1101196-9-peter.maydell@linaro.org
27
Message-id: 20250217125055.160887-7-peter.maydell@linaro.org
26
---
28
---
27
hw/arm/mps2-tz.c | 24 +++++++++++++++++-------
29
include/fpu/softfloat-types.h | 19 +++++++++++++++++++
28
1 file changed, 17 insertions(+), 7 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(-)
29
34
30
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
35
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
31
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/mps2-tz.c
37
--- a/include/fpu/softfloat-types.h
33
+++ b/hw/arm/mps2-tz.c
38
+++ b/include/fpu/softfloat-types.h
34
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
39
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
35
40
* and using them as inputs to a float op will raise Invalid.
36
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
41
*/
37
{
42
floatx80_unnormal_valid = 8,
38
- /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
39
+ /*
40
+ * Return a qemu_irq which will signal IRQ n to all CPUs in the
41
+ * SSE. The irqno should be as the CPU sees it, so the first
42
+ * external-to-the-SSE interrupt is 32.
43
+ */
44
MachineClass *mc = MACHINE_GET_CLASS(mms);
45
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
46
47
- assert(irqno < mmc->numirq);
48
+ assert(irqno >= 32 && irqno < (mmc->numirq + 32));
49
+
43
+
50
+ /*
44
+ /*
51
+ * Convert from "CPU irq number" (as listed in the FPGA image
45
+ * If the exponent is 0 and the Integer bit is set, Intel call
52
+ * documentation) to the SSE external-interrupt number.
46
+ * this a "pseudo-denormal"; x86 supports that only on input
47
+ * (treating them as denormals by ignoring the Integer bit).
48
+ * For m68k, the integer bit is considered validly part of the
49
+ * input value when the exponent is 0, and may be 0 or 1,
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.
53
+ */
60
+ */
54
+ irqno -= 32;
61
+ floatx80_pseudo_denormal_valid = 16,
55
62
} FloatX80Behaviour;
56
if (mc->max_cpus > 1) {
63
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
64
/*
58
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
65
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
59
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
66
index XXXXXXX..XXXXXXX 100644
60
CMSDKAPBUART *uart = opaque;
67
--- a/fpu/softfloat.c
61
int i = uart - &mms->uart[0];
68
+++ b/fpu/softfloat.c
62
- int rxirqno = i * 2;
69
@@ -XXX,XX +XXX,XX @@ typedef struct {
63
- int txirqno = i * 2 + 1;
70
* round_mask: bits below lsb which must be rounded
64
- int combirqno = i + 10;
71
* The following optional modifiers are available:
65
+ int rxirqno = i * 2 + 32;
72
* arm_althp: handle ARM Alternative Half Precision
66
+ int txirqno = i * 2 + 33;
73
- * m68k_denormal: explicit integer bit for extended precision may be 1
67
+ int combirqno = i + 42;
74
+ * has_explicit_bit: has an explicit integer bit; this affects whether
68
SysBusDevice *s;
75
+ * the float_status floatx80_behaviour handling applies
69
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
76
*/
70
77
typedef struct {
71
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
78
int exp_size;
72
79
@@ -XXX,XX +XXX,XX @@ typedef struct {
73
s = SYS_BUS_DEVICE(mms->lan9118);
80
int frac_size;
74
sysbus_realize_and_unref(s, &error_fatal);
81
int frac_shift;
75
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16));
82
bool arm_althp;
76
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
83
- bool m68k_denormal;
77
return sysbus_mmio_get_region(s, 0);
84
+ bool has_explicit_bit;
78
}
85
uint64_t round_mask;
79
86
} FloatFmt;
80
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
87
81
&error_fatal);
88
@@ -XXX,XX +XXX,XX @@ static const FloatFmt floatx80_params[3] = {
82
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
89
[floatx80_precision_d] = { FLOATX80_PARAMS(52) },
83
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
90
[floatx80_precision_x] = {
84
- get_sse_irq_in(mms, 15));
91
FLOATX80_PARAMS(64),
85
+ get_sse_irq_in(mms, 47));
92
-#ifdef TARGET_M68K
86
93
- .m68k_denormal = true,
87
/* Most of the devices in the FPGA are behind Peripheral Protection
94
-#endif
88
* Controllers. The required order for initializing things is:
95
+ .has_explicit_bit = true,
96
},
97
};
98
99
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/m68k/cpu.c
102
+++ b/target/m68k/cpu.c
103
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
104
set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
105
floatx80_pseudo_inf_valid |
106
floatx80_pseudo_nan_valid |
107
- floatx80_unnormal_valid,
108
+ floatx80_unnormal_valid |
109
+ floatx80_pseudo_denormal_valid,
110
&env->fp_status);
111
112
nan = floatx80_default_nan(&env->fp_status);
113
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
114
index XXXXXXX..XXXXXXX 100644
115
--- a/fpu/softfloat-parts.c.inc
116
+++ b/fpu/softfloat-parts.c.inc
117
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
118
static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
119
const FloatFmt *fmt)
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);
139
+
140
if (unlikely(p->exp == 0)) {
141
if (likely(frac_eqz(p))) {
142
p->cls = float_class_zero;
143
@@ -XXX,XX +XXX,XX @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
144
int shift = frac_normalize(p);
145
p->cls = float_class_denormal;
146
p->exp = fmt->frac_shift - fmt->exp_bias
147
- - shift + !fmt->m68k_denormal;
148
+ - shift + !has_pseudo_denormals;
149
}
150
} else if (likely(p->exp < fmt->exp_max) || fmt->arm_althp) {
151
p->cls = float_class_normal;
152
@@ -XXX,XX +XXX,XX @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
153
frac_clear(p);
154
} else {
155
bool is_tiny = s->tininess_before_rounding || exp < 0;
156
+ bool has_pseudo_denormals = fmt->has_explicit_bit &&
157
+ (s->floatx80_behaviour & floatx80_pseudo_denormal_valid);
158
159
if (!is_tiny) {
160
FloatPartsN discard;
161
is_tiny = !frac_addi(&discard, p, inc);
162
}
163
164
- frac_shrjam(p, !fmt->m68k_denormal - exp);
165
+ frac_shrjam(p, !has_pseudo_denormals - exp);
166
167
if (p->frac_lo & round_mask) {
168
/* Need to recompute round-to-even/round-to-odd. */
169
@@ -XXX,XX +XXX,XX @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
170
p->frac_lo &= ~round_mask;
171
}
172
173
- exp = (p->frac_hi & DECOMPOSED_IMPLICIT_BIT) && !fmt->m68k_denormal;
174
+ exp = (p->frac_hi & DECOMPOSED_IMPLICIT_BIT) && !has_pseudo_denormals;
175
frac_shr(p, frac_shift);
176
177
if (is_tiny) {
89
--
178
--
90
2.20.1
179
2.43.0
91
180
92
181
diff view generated by jsdifflib
1
The AN524 has more interrupt lines than the AN505 and AN521; make
1
Currently we have a compile-time shortcut where we
2
numirq board-specific rather than a compile-time constant.
2
return false from no_signaling_nans() on everything except
3
Xtensa, because we know that's the only target that
4
might ever set status->no_signaling_nans.
3
5
4
Since the difference is small (92 on the current boards and 95 on the
6
Remove the ifdef, so we always look at the status flag;
5
new one) we don't dynamically allocate the cpu_irq_splitter[] array
7
this has no behavioural change, but will be necessary
6
but leave it as a fixed length array whose size is the maximum needed
8
if we want to build softfloat once for all targets.
7
for any of the boards.
8
9
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210215115138.20465-10-peter.maydell@linaro.org
13
Message-id: 20250224111524.1101196-10-peter.maydell@linaro.org
14
Message-id: 20250217125055.160887-8-peter.maydell@linaro.org
13
---
15
---
14
hw/arm/mps2-tz.c | 15 ++++++++++-----
16
fpu/softfloat-specialize.c.inc | 4 ----
15
1 file changed, 10 insertions(+), 5 deletions(-)
17
1 file changed, 4 deletions(-)
16
18
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
19
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2-tz.c
21
--- a/fpu/softfloat-specialize.c.inc
20
+++ b/hw/arm/mps2-tz.c
22
+++ b/fpu/softfloat-specialize.c.inc
21
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ this code that are retained.
22
#include "hw/qdev-clock.h"
24
*/
23
#include "qom/object.h"
25
static inline bool no_signaling_nans(float_status *status)
24
25
-#define MPS2TZ_NUMIRQ 92
26
+#define MPS2TZ_NUMIRQ_MAX 92
27
28
typedef enum MPS2TZFPGAType {
29
FPGA_AN505,
30
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
31
const uint32_t *oscclk;
32
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
33
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
34
+ int numirq; /* Number of external interrupts */
35
const char *armsse_type;
36
};
37
38
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
39
SplitIRQ sec_resp_splitter;
40
qemu_or_irq uart_irq_orgate;
41
DeviceState *lan9118;
42
- SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
43
+ SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX];
44
Clock *sysclk;
45
Clock *s32kclk;
46
};
47
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
48
{
26
{
49
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
27
-#if defined(TARGET_XTENSA)
50
MachineClass *mc = MACHINE_GET_CLASS(mms);
28
return status->no_signaling_nans;
51
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
29
-#else
52
30
- return false;
53
- assert(irqno < MPS2TZ_NUMIRQ);
31
-#endif
54
+ assert(irqno < mmc->numirq);
55
56
if (mc->max_cpus > 1) {
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
59
iotkitdev = DEVICE(&mms->iotkit);
60
object_property_set_link(OBJECT(&mms->iotkit), "memory",
61
OBJECT(system_memory), &error_abort);
62
- qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
63
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
64
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
65
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
66
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
67
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
68
* board. If there is only one CPU, we can just wire the device IRQ
69
* directly to the SSE's IRQ input.
70
*/
71
+ assert(mmc->numirq <= MPS2TZ_NUMIRQ_MAX);
72
if (mc->max_cpus > 1) {
73
- for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
74
+ for (i = 0; i < mmc->numirq; i++) {
75
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
76
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
77
78
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
79
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
80
mmc->fpgaio_num_leds = 2;
81
mmc->fpgaio_has_switches = false;
82
+ mmc->numirq = 92;
83
mmc->armsse_type = TYPE_IOTKIT;
84
}
32
}
85
33
86
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
34
/* Define how the architecture discriminates signaling NaNs.
87
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
88
mmc->fpgaio_num_leds = 2;
89
mmc->fpgaio_has_switches = false;
90
+ mmc->numirq = 92;
91
mmc->armsse_type = TYPE_SSE200;
92
}
93
94
--
35
--
95
2.20.1
36
2.43.0
96
37
97
38
diff view generated by jsdifflib
1
The function tc6393xb_draw_graphic32() is called in exactly one place,
1
Currently we have a compile-time shortcut where we return a hardcode
2
so just inline the function body at its callsite. This allows us to
2
value from snan_bit_is_one() on everything except MIPS, because we
3
drop the template header entirely.
3
know that's the only target that needs to change
4
status->no_signaling_nans at runtime.
4
5
5
The code move includes a single added space after 'for' to fix
6
Remove the ifdef, so we always look at the status flag. This means
6
the coding style.
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.
7
12
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20250224111524.1101196-11-peter.maydell@linaro.org
11
Message-id: 20210215103215.4944-5-peter.maydell@linaro.org
17
Message-id: 20250217125055.160887-9-peter.maydell@linaro.org
12
---
18
---
13
hw/display/tc6393xb_template.h | 45 ----------------------------------
19
target/hppa/fpu_helper.c | 1 +
14
hw/display/tc6393xb.c | 23 ++++++++++++++---
20
target/sh4/cpu.c | 1 +
15
2 files changed, 19 insertions(+), 49 deletions(-)
21
fpu/softfloat-specialize.c.inc | 7 -------
16
delete mode 100644 hw/display/tc6393xb_template.h
22
3 files changed, 2 insertions(+), 7 deletions(-)
17
23
18
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
24
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
19
deleted file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- a/hw/display/tc6393xb_template.h
22
+++ /dev/null
23
@@ -XXX,XX +XXX,XX @@
24
-/*
25
- * Toshiba TC6393XB I/O Controller.
26
- * Found in Sharp Zaurus SL-6000 (tosa) or some
27
- * Toshiba e-Series PDAs.
28
- *
29
- * FB support code. Based on G364 fb emulator
30
- *
31
- * Copyright (c) 2007 Hervé Poussineau
32
- *
33
- * This program is free software; you can redistribute it and/or
34
- * modify it under the terms of the GNU General Public License as
35
- * published by the Free Software Foundation; either version 2 of
36
- * the License, or (at your option) any later version.
37
- *
38
- * This program is distributed in the hope that it will be useful,
39
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
40
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
- * GNU General Public License for more details.
42
- *
43
- * You should have received a copy of the GNU General Public License along
44
- * with this program; if not, see <http://www.gnu.org/licenses/>.
45
- */
46
-
47
-static void tc6393xb_draw_graphic32(TC6393xbState *s)
48
-{
49
- DisplaySurface *surface = qemu_console_surface(s->con);
50
- int i;
51
- uint16_t *data_buffer;
52
- uint8_t *data_display;
53
-
54
- data_buffer = s->vram_ptr;
55
- data_display = surface_data(surface);
56
- for(i = 0; i < s->scr_height; i++) {
57
- int j;
58
- for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
59
- uint16_t color = *data_buffer;
60
- uint32_t dest_color = rgb_to_pixel32(
61
- ((color & 0xf800) * 0x108) >> 11,
62
- ((color & 0x7e0) * 0x41) >> 9,
63
- ((color & 0x1f) * 0x21) >> 2
64
- );
65
- *(uint32_t *)data_display = dest_color;
66
- }
67
- }
68
-}
69
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
70
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
71
--- a/hw/display/tc6393xb.c
26
--- a/target/hppa/fpu_helper.c
72
+++ b/hw/display/tc6393xb.c
27
+++ b/target/hppa/fpu_helper.c
73
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
28
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
74
(uint32_t) addr, value & 0xff);
29
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
30
/* Default NaN: sign bit clear, msb-1 frac bit set */
31
set_float_default_nan_pattern(0b00100000, &env->fp_status);
32
+ set_snan_bit_is_one(true, &env->fp_status);
33
/*
34
* "PA-RISC 2.0 Architecture" says it is IMPDEF whether the flushing
35
* enabled by FPSR.D happens before or after rounding. We pick "before"
36
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/sh4/cpu.c
39
+++ b/target/sh4/cpu.c
40
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
41
set_flush_to_zero(1, &env->fp_status);
42
#endif
43
set_default_nan_mode(1, &env->fp_status);
44
+ set_snan_bit_is_one(true, &env->fp_status);
45
/* sign bit clear, set all frac bits other than msb */
46
set_float_default_nan_pattern(0b00111111, &env->fp_status);
47
/*
48
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
49
index XXXXXXX..XXXXXXX 100644
50
--- a/fpu/softfloat-specialize.c.inc
51
+++ b/fpu/softfloat-specialize.c.inc
52
@@ -XXX,XX +XXX,XX @@ static inline bool no_signaling_nans(float_status *status)
53
* In IEEE 754-1985 this was implementation defined, but in IEEE 754-2008
54
* the msb must be zero. MIPS is (so far) unique in supporting both the
55
* 2008 revision and backward compatibility with their original choice.
56
- * Thus for MIPS we must make the choice at runtime.
57
*/
58
static inline bool snan_bit_is_one(float_status *status)
59
{
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
75
}
67
}
76
68
77
-#define BITS 32
69
/*----------------------------------------------------------------------------
78
-#include "tc6393xb_template.h"
79
-
80
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
81
{
82
- tc6393xb_draw_graphic32(s);
83
+ DisplaySurface *surface = qemu_console_surface(s->con);
84
+ int i;
85
+ uint16_t *data_buffer;
86
+ uint8_t *data_display;
87
+
88
+ data_buffer = s->vram_ptr;
89
+ data_display = surface_data(surface);
90
+ for (i = 0; i < s->scr_height; i++) {
91
+ int j;
92
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
93
+ uint16_t color = *data_buffer;
94
+ uint32_t dest_color = rgb_to_pixel32(
95
+ ((color & 0xf800) * 0x108) >> 11,
96
+ ((color & 0x7e0) * 0x41) >> 9,
97
+ ((color & 0x1f) * 0x21) >> 2
98
+ );
99
+ *(uint32_t *)data_display = dest_color;
100
+ }
101
+ }
102
dpy_gfx_update_full(s->con);
103
}
104
105
--
70
--
106
2.20.1
71
2.43.0
107
72
108
73
diff view generated by jsdifflib
1
The AN524 version of the SCC interface has different behaviour for
1
We happen to know that for the PPC target the FP status flags (and in
2
some of the CFG registers; implement it.
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.
3
6
4
Each board in this family can have minor differences in the meaning
7
We would like to build softfloat once for all targets; that means
5
of the CFG registers, so rather than trying to specify all the
8
removing target-specific ifdefs. Remove the check for TARGET_PPC;
6
possible semantics via individual device properties, we make the
9
this won't change behaviour because can_use_fpu() will see that
7
behaviour conditional on the part-number field of the SCC_ID register
10
float_flag_inexact is clear and take the softfloat path anyway.
8
which the board code already passes us.
9
10
For the AN524, the differences are:
11
* CFG3 is reserved rather than being board switches
12
* CFG5 is a new register ("ACLK Frequency in Hz")
13
* CFG6 is a new register ("Clock divider for BRAM")
14
15
We implement both of the new registers as reads-as-written.
16
11
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20210215115138.20465-11-peter.maydell@linaro.org
14
Message-id: 20250224111524.1101196-12-peter.maydell@linaro.org
15
Message-id: 20250217125055.160887-10-peter.maydell@linaro.org
20
---
16
---
21
include/hw/misc/mps2-scc.h | 3 ++
17
fpu/softfloat.c | 2 --
22
hw/misc/mps2-scc.c | 71 ++++++++++++++++++++++++++++++++++++--
18
1 file changed, 2 deletions(-)
23
2 files changed, 72 insertions(+), 2 deletions(-)
24
19
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
20
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
26
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/misc/mps2-scc.h
22
--- a/fpu/softfloat.c
28
+++ b/include/hw/misc/mps2-scc.h
23
+++ b/fpu/softfloat.c
29
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
24
@@ -XXX,XX +XXX,XX @@ GEN_INPUT_FLUSH3(float64_input_flush3, float64)
30
25
* the use of hardfloat, since hardfloat relies on the inexact flag being
31
uint32_t cfg0;
26
* already set.
32
uint32_t cfg1;
33
+ uint32_t cfg2;
34
uint32_t cfg4;
35
+ uint32_t cfg5;
36
+ uint32_t cfg6;
37
uint32_t cfgdata_rtn;
38
uint32_t cfgdata_out;
39
uint32_t cfgctrl;
40
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/misc/mps2-scc.c
43
+++ b/hw/misc/mps2-scc.c
44
@@ -XXX,XX +XXX,XX @@
45
46
REG32(CFG0, 0)
47
REG32(CFG1, 4)
48
+REG32(CFG2, 8)
49
REG32(CFG3, 0xc)
50
REG32(CFG4, 0x10)
51
+REG32(CFG5, 0x14)
52
+REG32(CFG6, 0x18)
53
REG32(CFGDATA_RTN, 0xa0)
54
REG32(CFGDATA_OUT, 0xa4)
55
REG32(CFGCTRL, 0xa8)
56
@@ -XXX,XX +XXX,XX @@ REG32(DLL, 0x100)
57
REG32(AID, 0xFF8)
58
REG32(ID, 0xFFC)
59
60
+static int scc_partno(MPS2SCC *s)
61
+{
62
+ /* Return the partno field of the SCC_ID (0x524, 0x511, etc) */
63
+ return extract32(s->id, 4, 8);
64
+}
65
+
66
/* Handle a write via the SYS_CFG channel to the specified function/device.
67
* Return false on error (reported to guest via SYS_CFGCTRL ERROR bit).
68
*/
27
*/
69
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
28
-#if defined(TARGET_PPC) || defined(__FAST_MATH__)
70
case A_CFG1:
29
# if defined(__FAST_MATH__)
71
r = s->cfg1;
30
# warning disabling hardfloat due to -ffast-math: hardfloat requires an exact \
72
break;
31
IEEE implementation
73
+ case A_CFG2:
32
-# endif
74
+ if (scc_partno(s) != 0x524) {
33
# define QEMU_NO_HARDFLOAT 1
75
+ /* CFG2 reserved on other boards */
34
# define QEMU_SOFTFLOAT_ATTR QEMU_FLATTEN
76
+ goto bad_offset;
35
#else
77
+ }
78
+ r = s->cfg2;
79
+ break;
80
case A_CFG3:
81
+ if (scc_partno(s) == 0x524) {
82
+ /* CFG3 reserved on AN524 */
83
+ goto bad_offset;
84
+ }
85
/* These are user-settable DIP switches on the board. We don't
86
* model that, so just return zeroes.
87
*/
88
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
89
case A_CFG4:
90
r = s->cfg4;
91
break;
92
+ case A_CFG5:
93
+ if (scc_partno(s) != 0x524) {
94
+ /* CFG5 reserved on other boards */
95
+ goto bad_offset;
96
+ }
97
+ r = s->cfg5;
98
+ break;
99
+ case A_CFG6:
100
+ if (scc_partno(s) != 0x524) {
101
+ /* CFG6 reserved on other boards */
102
+ goto bad_offset;
103
+ }
104
+ r = s->cfg6;
105
+ break;
106
case A_CFGDATA_RTN:
107
r = s->cfgdata_rtn;
108
break;
109
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
110
r = s->id;
111
break;
112
default:
113
+ bad_offset:
114
qemu_log_mask(LOG_GUEST_ERROR,
115
"MPS2 SCC read: bad offset %x\n", (int) offset);
116
r = 0;
117
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
118
led_set_state(s->led[i], extract32(value, i, 1));
119
}
120
break;
121
+ case A_CFG2:
122
+ if (scc_partno(s) != 0x524) {
123
+ /* CFG2 reserved on other boards */
124
+ goto bad_offset;
125
+ }
126
+ /* AN524: QSPI Select signal */
127
+ s->cfg2 = value;
128
+ break;
129
+ case A_CFG5:
130
+ if (scc_partno(s) != 0x524) {
131
+ /* CFG5 reserved on other boards */
132
+ goto bad_offset;
133
+ }
134
+ /* AN524: ACLK frequency in Hz */
135
+ s->cfg5 = value;
136
+ break;
137
+ case A_CFG6:
138
+ if (scc_partno(s) != 0x524) {
139
+ /* CFG6 reserved on other boards */
140
+ goto bad_offset;
141
+ }
142
+ /* AN524: Clock divider for BRAM */
143
+ s->cfg6 = value;
144
+ break;
145
case A_CFGDATA_OUT:
146
s->cfgdata_out = value;
147
break;
148
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
149
s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8));
150
break;
151
default:
152
+ bad_offset:
153
qemu_log_mask(LOG_GUEST_ERROR,
154
"MPS2 SCC write: bad offset 0x%x\n", (int) offset);
155
break;
156
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
157
trace_mps2_scc_reset();
158
s->cfg0 = 0;
159
s->cfg1 = 0;
160
+ s->cfg2 = 0;
161
+ s->cfg5 = 0;
162
+ s->cfg6 = 0;
163
s->cfgdata_rtn = 0;
164
s->cfgdata_out = 0;
165
s->cfgctrl = 0x100000;
166
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
167
168
static const VMStateDescription mps2_scc_vmstate = {
169
.name = "mps2-scc",
170
- .version_id = 2,
171
- .minimum_version_id = 2,
172
+ .version_id = 3,
173
+ .minimum_version_id = 3,
174
.fields = (VMStateField[]) {
175
VMSTATE_UINT32(cfg0, MPS2SCC),
176
VMSTATE_UINT32(cfg1, MPS2SCC),
177
+ VMSTATE_UINT32(cfg2, MPS2SCC),
178
+ /* cfg3, cfg4 are read-only so need not be migrated */
179
+ VMSTATE_UINT32(cfg5, MPS2SCC),
180
+ VMSTATE_UINT32(cfg6, MPS2SCC),
181
VMSTATE_UINT32(cfgdata_rtn, MPS2SCC),
182
VMSTATE_UINT32(cfgdata_out, MPS2SCC),
183
VMSTATE_UINT32(cfgctrl, MPS2SCC),
184
--
36
--
185
2.20.1
37
2.43.0
186
187
diff view generated by jsdifflib
1
Now the template header is included only for BITS==32, expand
1
Now we have removed all the target-specifics from the softfloat code,
2
out all the macros that depended on the BITS setting.
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>
6
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215103215.4944-4-peter.maydell@linaro.org
8
Message-id: 20250224111524.1101196-13-peter.maydell@linaro.org
9
Message-id: 20250217125055.160887-11-peter.maydell@linaro.org
7
---
10
---
8
hw/display/tc6393xb_template.h | 35 ++++------------------------------
11
fpu/softfloat.c | 3 ---
9
1 file changed, 4 insertions(+), 31 deletions(-)
12
fpu/meson.build | 2 +-
13
2 files changed, 1 insertion(+), 4 deletions(-)
10
14
11
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/tc6393xb_template.h
17
--- a/fpu/softfloat.c
14
+++ b/hw/display/tc6393xb_template.h
18
+++ b/fpu/softfloat.c
15
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ this code that are retained.
16
* with this program; if not, see <http://www.gnu.org/licenses/>.
20
* version 2 or later. See the COPYING file in the top-level directory.
17
*/
21
*/
18
22
19
-#if BITS == 8
23
-/* softfloat (and in particular the code in softfloat-specialize.h) is
20
-# define SET_PIXEL(addr, color) (*(uint8_t *)addr = color)
24
- * target-dependent and needs the TARGET_* macros.
21
-#elif BITS == 15 || BITS == 16
25
- */
22
-# define SET_PIXEL(addr, color) (*(uint16_t *)addr = color)
26
#include "qemu/osdep.h"
23
-#elif BITS == 24
27
#include <math.h>
24
-# define SET_PIXEL(addr, color) \
28
#include "qemu/bitops.h"
25
- do { \
29
diff --git a/fpu/meson.build b/fpu/meson.build
26
- addr[0] = color; \
30
index XXXXXXX..XXXXXXX 100644
27
- addr[1] = (color) >> 8; \
31
--- a/fpu/meson.build
28
- addr[2] = (color) >> 16; \
32
+++ b/fpu/meson.build
29
- } while (0)
33
@@ -1 +1 @@
30
-#elif BITS == 32
34
-specific_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
31
-# define SET_PIXEL(addr, color) (*(uint32_t *)addr = color)
35
+common_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
32
-#else
33
-# error unknown bit depth
34
-#endif
35
-
36
-
37
-static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
38
+static void tc6393xb_draw_graphic32(TC6393xbState *s)
39
{
40
DisplaySurface *surface = qemu_console_surface(s->con);
41
int i;
42
@@ -XXX,XX +XXX,XX @@ static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
43
data_buffer = s->vram_ptr;
44
data_display = surface_data(surface);
45
for(i = 0; i < s->scr_height; i++) {
46
-#if (BITS == 16)
47
- memcpy(data_display, data_buffer, s->scr_width * 2);
48
- data_buffer += s->scr_width;
49
- data_display += surface_stride(surface);
50
-#else
51
int j;
52
- for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) {
53
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
54
uint16_t color = *data_buffer;
55
- uint32_t dest_color = glue(rgb_to_pixel, BITS)(
56
+ uint32_t dest_color = rgb_to_pixel32(
57
((color & 0xf800) * 0x108) >> 11,
58
((color & 0x7e0) * 0x41) >> 9,
59
((color & 0x1f) * 0x21) >> 2
60
);
61
- SET_PIXEL(data_display, dest_color);
62
+ *(uint32_t *)data_display = dest_color;
63
}
64
-#endif
65
}
66
}
67
-
68
-#undef BITS
69
-#undef SET_PIXEL
70
--
36
--
71
2.20.1
37
2.43.0
72
38
73
39
diff view generated by jsdifflib
1
We only include the template header once, so just inline it into the
1
Most of the target/arm/vfp_helper.c file is purely TCG helper code,
2
source file for the device.
2
guarded by #ifdef CONFIG_TCG. Move this into a new file in
3
target/arm/tcg/.
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.
3
12
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20250221190957.811948-2-peter.maydell@linaro.org
7
Message-id: 20210215103215.4944-9-peter.maydell@linaro.org
8
---
16
---
9
hw/display/omap_lcd_template.h | 154 ---------------------------------
17
target/arm/{ => tcg}/vfp_helper.c | 399 +----------
10
hw/display/omap_lcdc.c | 127 ++++++++++++++++++++++++++-
18
target/arm/vfp_helper.c | 1109 -----------------------------
11
2 files changed, 125 insertions(+), 156 deletions(-)
19
target/arm/tcg/meson.build | 1 +
12
delete mode 100644 hw/display/omap_lcd_template.h
20
3 files changed, 4 insertions(+), 1505 deletions(-)
21
copy target/arm/{ => tcg}/vfp_helper.c (71%)
13
22
14
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
23
diff --git a/target/arm/vfp_helper.c b/target/arm/tcg/vfp_helper.c
15
deleted file mode 100644
24
similarity index 71%
16
index XXXXXXX..XXXXXXX
25
copy from target/arm/vfp_helper.c
17
--- a/hw/display/omap_lcd_template.h
26
copy to target/arm/tcg/vfp_helper.c
18
+++ /dev/null
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/vfp_helper.c
29
+++ b/target/arm/tcg/vfp_helper.c
19
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@
31
#include "internals.h"
32
#include "cpu-features.h"
33
#include "fpu/softfloat.h"
34
-#ifdef CONFIG_TCG
35
#include "qemu/log.h"
36
-#endif
37
-
38
-/* VFP support. We follow the convention used for VFP instructions:
39
- Single precision routines have a "s" suffix, double precision a
40
- "d" suffix. */
41
42
/*
43
- * Set the float_status behaviour to match the Arm defaults:
44
- * * tininess-before-rounding
45
- * * 2-input NaN propagation prefers SNaN over QNaN, and then
46
- * operand A over operand B (see FPProcessNaNs() pseudocode)
47
- * * 3-input NaN propagation prefers SNaN over QNaN, and then
48
- * operand C over A over B (see FPProcessNaNs3() pseudocode,
49
- * but note that for QEMU muladd is a * b + c, whereas for
50
- * the pseudocode function the arguments are in the order c, a, b.
51
- * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
52
- * and the input NaN if it is signalling
53
- * * Default NaN has sign bit clear, msb frac bit set
54
+ * VFP support. We follow the convention used for VFP instructions:
55
+ * Single precision routines have a "s" suffix, double precision a
56
+ * "d" suffix.
57
*/
58
-void arm_set_default_fp_behaviours(float_status *s)
59
-{
60
- set_float_detect_tininess(float_tininess_before_rounding, s);
61
- set_float_ftz_detection(float_ftz_before_rounding, s);
62
- set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
63
- set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
64
- set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
65
- set_float_default_nan_pattern(0b01000000, s);
66
-}
67
-
20
-/*
68
-/*
21
- * QEMU OMAP LCD Emulator templates
69
- * Set the float_status behaviour to match the FEAT_AFP
70
- * FPCR.AH=1 requirements:
71
- * * tininess-after-rounding
72
- * * 2-input NaN propagation prefers the first NaN
73
- * * 3-input NaN propagation prefers a over b over c
74
- * * 0 * Inf + NaN always returns the input NaN and doesn't
75
- * set Invalid for a QNaN
76
- * * default NaN has sign bit set, msb frac bit set
77
- */
78
-void arm_set_ah_fp_behaviours(float_status *s)
79
-{
80
- set_float_detect_tininess(float_tininess_after_rounding, s);
81
- set_float_ftz_detection(float_ftz_after_rounding, s);
82
- set_float_2nan_prop_rule(float_2nan_prop_ab, s);
83
- set_float_3nan_prop_rule(float_3nan_prop_abc, s);
84
- set_float_infzeronan_rule(float_infzeronan_dnan_never |
85
- float_infzeronan_suppress_invalid, s);
86
- set_float_default_nan_pattern(0b11000000, s);
87
-}
88
-
89
-#ifdef CONFIG_TCG
90
-
91
-/* Convert host exception flags to vfp form. */
92
-static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
93
-{
94
- uint32_t target_bits = 0;
95
-
96
- if (host_bits & float_flag_invalid) {
97
- target_bits |= FPSR_IOC;
98
- }
99
- if (host_bits & float_flag_divbyzero) {
100
- target_bits |= FPSR_DZC;
101
- }
102
- if (host_bits & float_flag_overflow) {
103
- target_bits |= FPSR_OFC;
104
- }
105
- if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
106
- target_bits |= FPSR_UFC;
107
- }
108
- if (host_bits & float_flag_inexact) {
109
- target_bits |= FPSR_IXC;
110
- }
111
- if (host_bits & float_flag_input_denormal_flushed) {
112
- target_bits |= FPSR_IDC;
113
- }
114
- /*
115
- * With FPCR.AH, IDC is set when an input denormal is used,
116
- * and flushing an output denormal to zero sets both IXC and UFC.
117
- */
118
- if (ah && (host_bits & float_flag_input_denormal_used)) {
119
- target_bits |= FPSR_IDC;
120
- }
121
- if (ah && (host_bits & float_flag_output_denormal_flushed)) {
122
- target_bits |= FPSR_IXC;
123
- }
124
- return target_bits;
125
-}
126
-
127
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
128
-{
129
- uint32_t a32_flags = 0, a64_flags = 0;
130
-
131
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
132
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
133
- /* FZ16 does not generate an input denormal exception. */
134
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
135
- & ~float_flag_input_denormal_flushed);
136
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
137
- & ~float_flag_input_denormal_flushed);
138
-
139
- a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
140
- a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
141
- & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
142
- /*
143
- * We do not merge in flags from FPST_AH or FPST_AH_F16, because
144
- * they are used for insns that must not set the cumulative exception bits.
145
- */
146
-
147
- /*
148
- * Flushing an input denormal *only* because FPCR.FIZ == 1 does
149
- * not set FPSR.IDC; if FPCR.FZ is also set then this takes
150
- * precedence and IDC is set (see the FPUnpackBase pseudocode).
151
- * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
152
- * We only do this for the a64 flags because FIZ has no effect
153
- * on AArch32 even if it is set.
154
- */
155
- if ((env->vfp.fpcr & (FPCR_FZ | FPCR_AH)) != FPCR_FZ) {
156
- a64_flags &= ~float_flag_input_denormal_flushed;
157
- }
158
- return vfp_exceptbits_from_host(a64_flags, env->vfp.fpcr & FPCR_AH) |
159
- vfp_exceptbits_from_host(a32_flags, false);
160
-}
161
-
162
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
163
-{
164
- /*
165
- * Clear out all the exception-flag information in the float_status
166
- * values. The caller should have arranged for env->vfp.fpsr to
167
- * be the architecturally up-to-date exception flag information first.
168
- */
169
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32]);
170
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64]);
171
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32_F16]);
172
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64_F16]);
173
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD]);
174
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD_F16]);
175
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH]);
176
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH_F16]);
177
-}
178
-
179
-static void vfp_sync_and_clear_float_status_exc_flags(CPUARMState *env)
180
-{
181
- /*
182
- * Synchronize any pending exception-flag information in the
183
- * float_status values into env->vfp.fpsr, and then clear out
184
- * the float_status data.
185
- */
186
- env->vfp.fpsr |= vfp_get_fpsr_from_host(env);
187
- vfp_clear_float_status_exc_flags(env);
188
-}
189
-
190
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
191
-{
192
- uint64_t changed = env->vfp.fpcr;
193
-
194
- changed ^= val;
195
- changed &= mask;
196
- if (changed & (3 << 22)) {
197
- int i = (val >> 22) & 3;
198
- switch (i) {
199
- case FPROUNDING_TIEEVEN:
200
- i = float_round_nearest_even;
201
- break;
202
- case FPROUNDING_POSINF:
203
- i = float_round_up;
204
- break;
205
- case FPROUNDING_NEGINF:
206
- i = float_round_down;
207
- break;
208
- case FPROUNDING_ZERO:
209
- i = float_round_to_zero;
210
- break;
211
- }
212
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
213
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64]);
214
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32_F16]);
215
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64_F16]);
216
- }
217
- if (changed & FPCR_FZ16) {
218
- bool ftz_enabled = val & FPCR_FZ16;
219
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
220
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
221
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
222
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
223
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
224
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
225
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
226
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
227
- }
228
- if (changed & FPCR_FZ) {
229
- bool ftz_enabled = val & FPCR_FZ;
230
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
231
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64]);
232
- /* FIZ is A64 only so FZ always makes A32 code flush inputs to zero */
233
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
234
- }
235
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
236
- /*
237
- * A64: Flush denormalized inputs to zero if FPCR.FIZ = 1, or
238
- * both FPCR.AH = 0 and FPCR.FZ = 1.
239
- */
240
- bool fitz_enabled = (val & FPCR_FIZ) ||
241
- (val & (FPCR_FZ | FPCR_AH)) == FPCR_FZ;
242
- set_flush_inputs_to_zero(fitz_enabled, &env->vfp.fp_status[FPST_A64]);
243
- }
244
- if (changed & FPCR_DN) {
245
- bool dnan_enabled = val & FPCR_DN;
246
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
247
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
248
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
249
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
250
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
251
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
252
- }
253
- if (changed & FPCR_AH) {
254
- bool ah_enabled = val & FPCR_AH;
255
-
256
- if (ah_enabled) {
257
- /* Change behaviours for A64 FP operations */
258
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
259
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
260
- } else {
261
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
262
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
263
- }
264
- }
265
- /*
266
- * If any bits changed that we look at in vfp_get_fpsr_from_host(),
267
- * we must sync the float_status flags into vfp.fpsr now (under the
268
- * old regime) before we update vfp.fpcr.
269
- */
270
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
271
- vfp_sync_and_clear_float_status_exc_flags(env);
272
- }
273
-}
274
-
275
-#else
276
-
277
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
278
-{
279
- return 0;
280
-}
281
-
282
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
283
-{
284
-}
285
-
286
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
287
-{
288
-}
289
-
290
-#endif
291
-
292
-uint32_t vfp_get_fpcr(CPUARMState *env)
293
-{
294
- uint32_t fpcr = env->vfp.fpcr
295
- | (env->vfp.vec_len << 16)
296
- | (env->vfp.vec_stride << 20);
297
-
298
- /*
299
- * M-profile LTPSIZE is the same bits [18:16] as A-profile Len; whichever
300
- * of the two is not applicable to this CPU will always be zero.
301
- */
302
- fpcr |= env->v7m.ltpsize << 16;
303
-
304
- return fpcr;
305
-}
306
-
307
-uint32_t vfp_get_fpsr(CPUARMState *env)
308
-{
309
- uint32_t fpsr = env->vfp.fpsr;
310
- uint32_t i;
311
-
312
- fpsr |= vfp_get_fpsr_from_host(env);
313
-
314
- i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
315
- fpsr |= i ? FPSR_QC : 0;
316
- return fpsr;
317
-}
318
-
319
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
320
-{
321
- return (vfp_get_fpcr(env) & FPSCR_FPCR_MASK) |
322
- (vfp_get_fpsr(env) & FPSCR_FPSR_MASK);
323
-}
324
-
325
-uint32_t vfp_get_fpscr(CPUARMState *env)
326
-{
327
- return HELPER(vfp_get_fpscr)(env);
328
-}
329
-
330
-void vfp_set_fpsr(CPUARMState *env, uint32_t val)
331
-{
332
- ARMCPU *cpu = env_archcpu(env);
333
-
334
- if (arm_feature(env, ARM_FEATURE_NEON) ||
335
- cpu_isar_feature(aa32_mve, cpu)) {
336
- /*
337
- * The bit we set within vfp.qc[] is arbitrary; the array as a
338
- * whole being zero/non-zero is what counts.
339
- */
340
- env->vfp.qc[0] = val & FPSR_QC;
341
- env->vfp.qc[1] = 0;
342
- env->vfp.qc[2] = 0;
343
- env->vfp.qc[3] = 0;
344
- }
345
-
346
- /*
347
- * NZCV lives only in env->vfp.fpsr. The cumulative exception flags
348
- * IOC|DZC|OFC|UFC|IXC|IDC also live in env->vfp.fpsr, with possible
349
- * extra pending exception information that hasn't yet been folded in
350
- * living in the float_status values (for TCG).
351
- * Since this FPSR write gives us the up to date values of the exception
352
- * flags, we want to store into vfp.fpsr the NZCV and CEXC bits, zeroing
353
- * anything else. We also need to clear out the float_status exception
354
- * information so that the next vfp_get_fpsr does not fold in stale data.
355
- */
356
- val &= FPSR_NZCV_MASK | FPSR_CEXC_MASK;
357
- env->vfp.fpsr = val;
358
- vfp_clear_float_status_exc_flags(env);
359
-}
360
-
361
-static void vfp_set_fpcr_masked(CPUARMState *env, uint32_t val, uint32_t mask)
362
-{
363
- /*
364
- * We only set FPCR bits defined by mask, and leave the others alone.
365
- * We assume the mask is sensible (e.g. doesn't try to set only
366
- * part of a field)
367
- */
368
- ARMCPU *cpu = env_archcpu(env);
369
-
370
- /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
371
- if (!cpu_isar_feature(any_fp16, cpu)) {
372
- val &= ~FPCR_FZ16;
373
- }
374
- if (!cpu_isar_feature(aa64_afp, cpu)) {
375
- val &= ~(FPCR_FIZ | FPCR_AH | FPCR_NEP);
376
- }
377
-
378
- if (!cpu_isar_feature(aa64_ebf16, cpu)) {
379
- val &= ~FPCR_EBF;
380
- }
381
-
382
- vfp_set_fpcr_to_host(env, val, mask);
383
-
384
- if (mask & (FPCR_LEN_MASK | FPCR_STRIDE_MASK)) {
385
- if (!arm_feature(env, ARM_FEATURE_M)) {
386
- /*
387
- * Short-vector length and stride; on M-profile these bits
388
- * are used for different purposes.
389
- * We can't make this conditional be "if MVFR0.FPShVec != 0",
390
- * because in v7A no-short-vector-support cores still had to
391
- * allow Stride/Len to be written with the only effect that
392
- * some insns are required to UNDEF if the guest sets them.
393
- */
394
- env->vfp.vec_len = extract32(val, 16, 3);
395
- env->vfp.vec_stride = extract32(val, 20, 2);
396
- } else if (cpu_isar_feature(aa32_mve, cpu)) {
397
- env->v7m.ltpsize = extract32(val, FPCR_LTPSIZE_SHIFT,
398
- FPCR_LTPSIZE_LENGTH);
399
- }
400
- }
401
-
402
- /*
403
- * We don't implement trapped exception handling, so the
404
- * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
405
- *
406
- * The FPCR bits we keep in vfp.fpcr are AHP, DN, FZ, RMode, EBF, FZ16,
407
- * FIZ, AH, and NEP.
408
- * Len, Stride and LTPSIZE we just handled. Store those bits
409
- * there, and zero any of the other FPCR bits and the RES0 and RAZ/WI
410
- * bits.
411
- */
412
- val &= FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK | FPCR_FZ16 |
413
- FPCR_EBF | FPCR_FIZ | FPCR_AH | FPCR_NEP;
414
- env->vfp.fpcr &= ~mask;
415
- env->vfp.fpcr |= val;
416
-}
417
-
418
-void vfp_set_fpcr(CPUARMState *env, uint32_t val)
419
-{
420
- vfp_set_fpcr_masked(env, val, MAKE_64BIT_MASK(0, 32));
421
-}
422
-
423
-void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
424
-{
425
- vfp_set_fpcr_masked(env, val, FPSCR_FPCR_MASK);
426
- vfp_set_fpsr(env, val & FPSCR_FPSR_MASK);
427
-}
428
-
429
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
430
-{
431
- HELPER(vfp_set_fpscr)(env, val);
432
-}
433
-
434
-#ifdef CONFIG_TCG
435
436
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
437
438
@@ -XXX,XX +XXX,XX @@ void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg)
439
440
raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
441
}
442
-
443
-#endif
444
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
445
index XXXXXXX..XXXXXXX 100644
446
--- a/target/arm/vfp_helper.c
447
+++ b/target/arm/vfp_helper.c
448
@@ -XXX,XX +XXX,XX @@
449
#include "internals.h"
450
#include "cpu-features.h"
451
#include "fpu/softfloat.h"
452
-#ifdef CONFIG_TCG
453
-#include "qemu/log.h"
454
-#endif
455
-
456
-/* VFP support. We follow the convention used for VFP instructions:
457
- Single precision routines have a "s" suffix, double precision a
458
- "d" suffix. */
459
460
/*
461
* Set the float_status behaviour to match the Arm defaults:
462
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val)
463
{
464
HELPER(vfp_set_fpscr)(env, val);
465
}
466
-
467
-#ifdef CONFIG_TCG
468
-
469
-#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
470
-
471
-#define VFP_BINOP(name) \
472
-dh_ctype_f16 VFP_HELPER(name, h)(dh_ctype_f16 a, dh_ctype_f16 b, float_status *fpst) \
473
-{ \
474
- return float16_ ## name(a, b, fpst); \
475
-} \
476
-float32 VFP_HELPER(name, s)(float32 a, float32 b, float_status *fpst) \
477
-{ \
478
- return float32_ ## name(a, b, fpst); \
479
-} \
480
-float64 VFP_HELPER(name, d)(float64 a, float64 b, float_status *fpst) \
481
-{ \
482
- return float64_ ## name(a, b, fpst); \
483
-}
484
-VFP_BINOP(add)
485
-VFP_BINOP(sub)
486
-VFP_BINOP(mul)
487
-VFP_BINOP(div)
488
-VFP_BINOP(min)
489
-VFP_BINOP(max)
490
-VFP_BINOP(minnum)
491
-VFP_BINOP(maxnum)
492
-#undef VFP_BINOP
493
-
494
-dh_ctype_f16 VFP_HELPER(sqrt, h)(dh_ctype_f16 a, float_status *fpst)
495
-{
496
- return float16_sqrt(a, fpst);
497
-}
498
-
499
-float32 VFP_HELPER(sqrt, s)(float32 a, float_status *fpst)
500
-{
501
- return float32_sqrt(a, fpst);
502
-}
503
-
504
-float64 VFP_HELPER(sqrt, d)(float64 a, float_status *fpst)
505
-{
506
- return float64_sqrt(a, fpst);
507
-}
508
-
509
-static void softfloat_to_vfp_compare(CPUARMState *env, FloatRelation cmp)
510
-{
511
- uint32_t flags;
512
- switch (cmp) {
513
- case float_relation_equal:
514
- flags = 0x6;
515
- break;
516
- case float_relation_less:
517
- flags = 0x8;
518
- break;
519
- case float_relation_greater:
520
- flags = 0x2;
521
- break;
522
- case float_relation_unordered:
523
- flags = 0x3;
524
- break;
525
- default:
526
- g_assert_not_reached();
527
- }
528
- env->vfp.fpsr = deposit64(env->vfp.fpsr, 28, 4, flags); /* NZCV */
529
-}
530
-
531
-/* XXX: check quiet/signaling case */
532
-#define DO_VFP_cmp(P, FLOATTYPE, ARGTYPE, FPST) \
533
-void VFP_HELPER(cmp, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
534
-{ \
535
- softfloat_to_vfp_compare(env, \
536
- FLOATTYPE ## _compare_quiet(a, b, &env->vfp.fp_status[FPST])); \
537
-} \
538
-void VFP_HELPER(cmpe, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
539
-{ \
540
- softfloat_to_vfp_compare(env, \
541
- FLOATTYPE ## _compare(a, b, &env->vfp.fp_status[FPST])); \
542
-}
543
-DO_VFP_cmp(h, float16, dh_ctype_f16, FPST_A32_F16)
544
-DO_VFP_cmp(s, float32, float32, FPST_A32)
545
-DO_VFP_cmp(d, float64, float64, FPST_A32)
546
-#undef DO_VFP_cmp
547
-
548
-/* Integer to float and float to integer conversions */
549
-
550
-#define CONV_ITOF(name, ftype, fsz, sign) \
551
-ftype HELPER(name)(uint32_t x, float_status *fpst) \
552
-{ \
553
- return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
554
-}
555
-
556
-#define CONV_FTOI(name, ftype, fsz, sign, round) \
557
-sign##int32_t HELPER(name)(ftype x, float_status *fpst) \
558
-{ \
559
- if (float##fsz##_is_any_nan(x)) { \
560
- float_raise(float_flag_invalid, fpst); \
561
- return 0; \
562
- } \
563
- return float##fsz##_to_##sign##int32##round(x, fpst); \
564
-}
565
-
566
-#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
567
- CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
568
- CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
569
- CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
570
-
571
-FLOAT_CONVS(si, h, uint32_t, 16, )
572
-FLOAT_CONVS(si, s, float32, 32, )
573
-FLOAT_CONVS(si, d, float64, 64, )
574
-FLOAT_CONVS(ui, h, uint32_t, 16, u)
575
-FLOAT_CONVS(ui, s, float32, 32, u)
576
-FLOAT_CONVS(ui, d, float64, 64, u)
577
-
578
-#undef CONV_ITOF
579
-#undef CONV_FTOI
580
-#undef FLOAT_CONVS
581
-
582
-/* floating point conversion */
583
-float64 VFP_HELPER(fcvtd, s)(float32 x, float_status *status)
584
-{
585
- return float32_to_float64(x, status);
586
-}
587
-
588
-float32 VFP_HELPER(fcvts, d)(float64 x, float_status *status)
589
-{
590
- return float64_to_float32(x, status);
591
-}
592
-
593
-uint32_t HELPER(bfcvt)(float32 x, float_status *status)
594
-{
595
- return float32_to_bfloat16(x, status);
596
-}
597
-
598
-uint32_t HELPER(bfcvt_pair)(uint64_t pair, float_status *status)
599
-{
600
- bfloat16 lo = float32_to_bfloat16(extract64(pair, 0, 32), status);
601
- bfloat16 hi = float32_to_bfloat16(extract64(pair, 32, 32), status);
602
- return deposit32(lo, 16, 16, hi);
603
-}
604
-
605
-/*
606
- * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
607
- * must always round-to-nearest; the AArch64 ones honour the FPSCR
608
- * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
609
- * round-to-nearest so either helper will work.) AArch32 float-to-fix
610
- * must round-to-zero.
611
- */
612
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
613
-ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
614
- float_status *fpst) \
615
-{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpst); }
616
-
617
-#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
618
- ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
619
- uint32_t shift, \
620
- float_status *fpst) \
621
- { \
622
- ftype ret; \
623
- FloatRoundMode oldmode = fpst->float_rounding_mode; \
624
- fpst->float_rounding_mode = float_round_nearest_even; \
625
- ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpst); \
626
- fpst->float_rounding_mode = oldmode; \
627
- return ret; \
628
- }
629
-
630
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
631
-uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
632
- float_status *fpst) \
633
-{ \
634
- if (unlikely(float##fsz##_is_any_nan(x))) { \
635
- float_raise(float_flag_invalid, fpst); \
636
- return 0; \
637
- } \
638
- return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
639
-}
640
-
641
-#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
642
-VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
643
-VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
644
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
645
- float_round_to_zero, _round_to_zero) \
646
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
647
- get_float_rounding_mode(fpst), )
648
-
649
-#define VFP_CONV_FIX_A64(name, p, fsz, ftype, isz, itype) \
650
-VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
651
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
652
- get_float_rounding_mode(fpst), )
653
-
654
-VFP_CONV_FIX(sh, d, 64, float64, 64, int16)
655
-VFP_CONV_FIX(sl, d, 64, float64, 64, int32)
656
-VFP_CONV_FIX_A64(sq, d, 64, float64, 64, int64)
657
-VFP_CONV_FIX(uh, d, 64, float64, 64, uint16)
658
-VFP_CONV_FIX(ul, d, 64, float64, 64, uint32)
659
-VFP_CONV_FIX_A64(uq, d, 64, float64, 64, uint64)
660
-VFP_CONV_FIX(sh, s, 32, float32, 32, int16)
661
-VFP_CONV_FIX(sl, s, 32, float32, 32, int32)
662
-VFP_CONV_FIX_A64(sq, s, 32, float32, 64, int64)
663
-VFP_CONV_FIX(uh, s, 32, float32, 32, uint16)
664
-VFP_CONV_FIX(ul, s, 32, float32, 32, uint32)
665
-VFP_CONV_FIX_A64(uq, s, 32, float32, 64, uint64)
666
-VFP_CONV_FIX(sh, h, 16, dh_ctype_f16, 32, int16)
667
-VFP_CONV_FIX(sl, h, 16, dh_ctype_f16, 32, int32)
668
-VFP_CONV_FIX_A64(sq, h, 16, dh_ctype_f16, 64, int64)
669
-VFP_CONV_FIX(uh, h, 16, dh_ctype_f16, 32, uint16)
670
-VFP_CONV_FIX(ul, h, 16, dh_ctype_f16, 32, uint32)
671
-VFP_CONV_FIX_A64(uq, h, 16, dh_ctype_f16, 64, uint64)
672
-VFP_CONV_FLOAT_FIX_ROUND(sq, d, 64, float64, 64, int64,
673
- float_round_to_zero, _round_to_zero)
674
-VFP_CONV_FLOAT_FIX_ROUND(uq, d, 64, float64, 64, uint64,
675
- float_round_to_zero, _round_to_zero)
676
-
677
-#undef VFP_CONV_FIX
678
-#undef VFP_CONV_FIX_FLOAT
679
-#undef VFP_CONV_FLOAT_FIX_ROUND
680
-#undef VFP_CONV_FIX_A64
681
-
682
-/* Set the current fp rounding mode and return the old one.
683
- * The argument is a softfloat float_round_ value.
684
- */
685
-uint32_t HELPER(set_rmode)(uint32_t rmode, float_status *fp_status)
686
-{
687
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
688
- set_float_rounding_mode(rmode, fp_status);
689
-
690
- return prev_rmode;
691
-}
692
-
693
-/* Half precision conversions. */
694
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, float_status *fpst,
695
- uint32_t ahp_mode)
696
-{
697
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
698
- * it would affect flushing input denormals.
699
- */
700
- bool save = get_flush_inputs_to_zero(fpst);
701
- set_flush_inputs_to_zero(false, fpst);
702
- float32 r = float16_to_float32(a, !ahp_mode, fpst);
703
- set_flush_inputs_to_zero(save, fpst);
704
- return r;
705
-}
706
-
707
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, float_status *fpst,
708
- uint32_t ahp_mode)
709
-{
710
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
711
- * it would affect flushing output denormals.
712
- */
713
- bool save = get_flush_to_zero(fpst);
714
- set_flush_to_zero(false, fpst);
715
- float16 r = float32_to_float16(a, !ahp_mode, fpst);
716
- set_flush_to_zero(save, fpst);
717
- return r;
718
-}
719
-
720
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, float_status *fpst,
721
- uint32_t ahp_mode)
722
-{
723
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
724
- * it would affect flushing input denormals.
725
- */
726
- bool save = get_flush_inputs_to_zero(fpst);
727
- set_flush_inputs_to_zero(false, fpst);
728
- float64 r = float16_to_float64(a, !ahp_mode, fpst);
729
- set_flush_inputs_to_zero(save, fpst);
730
- return r;
731
-}
732
-
733
-uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, float_status *fpst,
734
- uint32_t ahp_mode)
735
-{
736
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
737
- * it would affect flushing output denormals.
738
- */
739
- bool save = get_flush_to_zero(fpst);
740
- set_flush_to_zero(false, fpst);
741
- float16 r = float64_to_float16(a, !ahp_mode, fpst);
742
- set_flush_to_zero(save, fpst);
743
- return r;
744
-}
745
-
746
-/* NEON helpers. */
747
-
748
-/* Constants 256 and 512 are used in some helpers; we avoid relying on
749
- * int->float conversions at run-time. */
750
-#define float64_256 make_float64(0x4070000000000000LL)
751
-#define float64_512 make_float64(0x4080000000000000LL)
752
-#define float16_maxnorm make_float16(0x7bff)
753
-#define float32_maxnorm make_float32(0x7f7fffff)
754
-#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
755
-
756
-/* Reciprocal functions
22
- *
757
- *
23
- * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
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()
24
- *
763
- *
25
- * Redistribution and use in source and binary forms, with or without
764
- * input is a 9 bit fixed point number
26
- * modification, are permitted provided that the following conditions
765
- * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
27
- * are met:
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
28
- *
809
- *
29
- * 1. Redistributions of source code must retain the above copyright
810
- * The parameters are exponent and 64 bit fraction (without implicit
30
- * notice, this list of conditions and the following disclaimer.
811
- * bit) where the binary point is nominally at bit 52. Returns a
31
- * 2. Redistributions in binary form must reproduce the above copyright
812
- * float64 which can then be rounded to the appropriate size by the
32
- * notice, this list of conditions and the following disclaimer in
813
- * callee.
33
- * the documentation and/or other materials provided with the
34
- * distribution.
35
- *
36
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
37
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
38
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
40
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
41
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
42
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
- */
814
- */
48
-
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
-
49
-/*
926
-/*
50
- * 2-bit colour
927
- * FEAT_RPRES means the f32 FRECPE has an "increased precision" variant
928
- * which is used when FPCR.AH == 1.
51
- */
929
- */
52
-static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
930
-static float32 do_recpe_f32(float32 input, float_status *fpst, bool rpres)
53
- int width, int deststep)
931
-{
54
-{
932
- float32 f32 = float32_squash_input_denormal(input, fpst);
55
- uint16_t *pal = opaque;
933
- uint32_t f32_val = float32_val(f32);
56
- uint8_t v, r, g, b;
934
- bool f32_sign = float32_is_neg(f32);
57
-
935
- int f32_exp = extract32(f32_val, 23, 8);
58
- do {
936
- uint32_t f32_frac = extract32(f32_val, 0, 23);
59
- v = ldub_p((void *) s);
937
- uint64_t f64_frac;
60
- r = (pal[v & 3] >> 4) & 0xf0;
938
-
61
- g = pal[v & 3] & 0xf0;
939
- if (float32_is_any_nan(f32)) {
62
- b = (pal[v & 3] << 4) & 0xf0;
940
- float32 nan = f32;
63
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
941
- if (float32_is_signaling_nan(f32, fpst)) {
64
- d += 4;
942
- float_raise(float_flag_invalid, fpst);
65
- v >>= 2;
943
- if (!fpst->default_nan_mode) {
66
- r = (pal[v & 3] >> 4) & 0xf0;
944
- nan = float32_silence_nan(f32, fpst);
67
- g = pal[v & 3] & 0xf0;
945
- }
68
- b = (pal[v & 3] << 4) & 0xf0;
946
- }
69
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
947
- if (fpst->default_nan_mode) {
70
- d += 4;
948
- nan = float32_default_nan(fpst);
71
- v >>= 2;
949
- }
72
- r = (pal[v & 3] >> 4) & 0xf0;
950
- return nan;
73
- g = pal[v & 3] & 0xf0;
951
- } else if (float32_is_infinity(f32)) {
74
- b = (pal[v & 3] << 4) & 0xf0;
952
- return float32_set_sign(float32_zero, float32_is_neg(f32));
75
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
953
- } else if (float32_is_zero(f32)) {
76
- d += 4;
954
- float_raise(float_flag_divbyzero, fpst);
77
- v >>= 2;
955
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
78
- r = (pal[v & 3] >> 4) & 0xf0;
956
- } else if (float32_abs(f32) < (1ULL << 21)) {
79
- g = pal[v & 3] & 0xf0;
957
- /* Abs(value) < 2.0^-128 */
80
- b = (pal[v & 3] << 4) & 0xf0;
958
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
81
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
959
- if (round_to_inf(fpst, f32_sign)) {
82
- d += 4;
960
- return float32_set_sign(float32_infinity, f32_sign);
83
- s++;
961
- } else {
84
- width -= 4;
962
- return float32_set_sign(float32_maxnorm, f32_sign);
85
- } while (width > 0);
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);
86
-}
1175
-}
87
-
1176
-
88
-/*
1177
-/*
89
- * 4-bit colour
1178
- * FEAT_RPRES means the f32 FRSQRTE has an "increased precision" variant
1179
- * which is used when FPCR.AH == 1.
90
- */
1180
- */
91
-static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
1181
-static float32 do_rsqrte_f32(float32 input, float_status *s, bool rpres)
92
- int width, int deststep)
1182
-{
93
-{
1183
- float32 f32 = float32_squash_input_denormal(input, s);
94
- uint16_t *pal = opaque;
1184
- uint32_t val = float32_val(f32);
95
- uint8_t v, r, g, b;
1185
- uint32_t f32_sign = float32_is_neg(f32);
96
-
1186
- int f32_exp = extract32(val, 23, 8);
97
- do {
1187
- uint32_t f32_frac = extract32(val, 0, 23);
98
- v = ldub_p((void *) s);
1188
- uint64_t f64_frac;
99
- r = (pal[v & 0xf] >> 4) & 0xf0;
1189
-
100
- g = pal[v & 0xf] & 0xf0;
1190
- if (float32_is_any_nan(f32)) {
101
- b = (pal[v & 0xf] << 4) & 0xf0;
1191
- float32 nan = f32;
102
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
1192
- if (float32_is_signaling_nan(f32, s)) {
103
- d += 4;
1193
- float_raise(float_flag_invalid, s);
104
- v >>= 4;
1194
- if (!s->default_nan_mode) {
105
- r = (pal[v & 0xf] >> 4) & 0xf0;
1195
- nan = float32_silence_nan(f32, s);
106
- g = pal[v & 0xf] & 0xf0;
1196
- }
107
- b = (pal[v & 0xf] << 4) & 0xf0;
1197
- }
108
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
1198
- if (s->default_nan_mode) {
109
- d += 4;
1199
- nan = float32_default_nan(s);
110
- s++;
1200
- }
111
- width -= 2;
1201
- return nan;
112
- } while (width > 0);
1202
- } else if (float32_is_zero(f32)) {
113
-}
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
-};
114
-
1402
-
115
-/*
1403
-/*
116
- * 8-bit colour
1404
- * Implement float64 to int32_t conversion without saturation;
1405
- * the result is supplied modulo 2^32.
117
- */
1406
- */
118
-static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
1407
-uint64_t HELPER(fjcvtzs)(float64 value, float_status *status)
119
- int width, int deststep)
1408
-{
120
-{
1409
- uint32_t frac, e_old, e_new;
121
- uint16_t *pal = opaque;
1410
- bool inexact;
122
- uint8_t v, r, g, b;
1411
-
123
-
1412
- e_old = get_float_exception_flags(status);
124
- do {
1413
- set_float_exception_flags(0, status);
125
- v = ldub_p((void *) s);
1414
- frac = float64_to_int32_modulo(value, float_round_to_zero, status);
126
- r = (pal[v] >> 4) & 0xf0;
1415
- e_new = get_float_exception_flags(status);
127
- g = pal[v] & 0xf0;
1416
- set_float_exception_flags(e_old | e_new, status);
128
- b = (pal[v] << 4) & 0xf0;
1417
-
129
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
1418
- /* Normal inexact, denormal with flush-to-zero, or overflow or NaN */
130
- s++;
1419
- inexact = e_new & (float_flag_inexact |
131
- d += 4;
1420
- float_flag_input_denormal_flushed |
132
- } while (-- width != 0);
1421
- float_flag_invalid);
133
-}
1422
-
134
-
1423
- /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */
135
-/*
1424
- inexact |= value == float64_chs(float64_zero);
136
- * 12-bit colour
1425
-
137
- */
1426
- /* Pack the result and the env->ZF representation of Z together. */
138
-static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
1427
- return deposit64(frac, 32, 32, inexact);
139
- int width, int deststep)
1428
-}
140
-{
1429
-
141
- uint16_t v;
1430
-uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
142
- uint8_t r, g, b;
1431
-{
143
-
1432
- uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status[FPST_A32]);
144
- do {
1433
- uint32_t result = pair;
145
- v = lduw_le_p((void *) s);
1434
- uint32_t z = (pair >> 32) == 0;
146
- r = (v >> 4) & 0xf0;
1435
-
147
- g = v & 0xf0;
1436
- /* Store Z, clear NCV, in FPSCR.NZCV. */
148
- b = (v << 4) & 0xf0;
1437
- env->vfp.fpsr = (env->vfp.fpsr & ~FPSR_NZCV_MASK) | (z * FPSR_Z);
149
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
1438
-
150
- s += 2;
1439
- return result;
151
- d += 4;
1440
-}
152
- } while (-- width != 0);
1441
-
153
-}
1442
-/* Round a float32 to an integer that fits in int32_t or int64_t. */
154
-
1443
-static float32 frint_s(float32 f, float_status *fpst, int intsize)
155
-/*
1444
-{
156
- * 16-bit colour
1445
- int old_flags = get_float_exception_flags(fpst);
157
- */
1446
- uint32_t exp = extract32(f, 23, 8);
158
-static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
1447
-
159
- int width, int deststep)
1448
- if (unlikely(exp == 0xff)) {
160
-{
1449
- /* NaN or Inf. */
161
- uint16_t v;
1450
- goto overflow;
162
- uint8_t r, g, b;
1451
- }
163
-
1452
-
164
- do {
1453
- /* Round and re-extract the exponent. */
165
- v = lduw_le_p((void *) s);
1454
- f = float32_round_to_int(f, fpst);
166
- r = (v >> 8) & 0xf8;
1455
- exp = extract32(f, 23, 8);
167
- g = (v >> 3) & 0xfc;
1456
-
168
- b = (v << 3) & 0xf8;
1457
- /* Validate the range of the result. */
169
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
1458
- if (exp < 126 + intsize) {
170
- s += 2;
1459
- /* abs(F) <= INT{N}_MAX */
171
- d += 4;
1460
- return f;
172
- } while (-- width != 0);
1461
- }
173
-}
1462
- if (exp == 126 + intsize) {
174
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
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
175
index XXXXXXX..XXXXXXX 100644
1569
index XXXXXXX..XXXXXXX 100644
176
--- a/hw/display/omap_lcdc.c
1570
--- a/target/arm/tcg/meson.build
177
+++ b/hw/display/omap_lcdc.c
1571
+++ b/target/arm/tcg/meson.build
178
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
1572
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
179
1573
'vec_helper.c',
180
#define draw_line_func drawfn
1574
'tlb-insns.c',
181
1575
'arith_helper.c',
182
-#define DEPTH 32
1576
+ 'vfp_helper.c',
183
-#include "omap_lcd_template.h"
1577
))
184
+/*
1578
185
+ * 2-bit colour
1579
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
186
+ */
187
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
188
+ int width, int deststep)
189
+{
190
+ uint16_t *pal = opaque;
191
+ uint8_t v, r, g, b;
192
+
193
+ do {
194
+ v = ldub_p((void *) s);
195
+ r = (pal[v & 3] >> 4) & 0xf0;
196
+ g = pal[v & 3] & 0xf0;
197
+ b = (pal[v & 3] << 4) & 0xf0;
198
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
199
+ d += 4;
200
+ v >>= 2;
201
+ r = (pal[v & 3] >> 4) & 0xf0;
202
+ g = pal[v & 3] & 0xf0;
203
+ b = (pal[v & 3] << 4) & 0xf0;
204
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
205
+ d += 4;
206
+ v >>= 2;
207
+ r = (pal[v & 3] >> 4) & 0xf0;
208
+ g = pal[v & 3] & 0xf0;
209
+ b = (pal[v & 3] << 4) & 0xf0;
210
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
211
+ d += 4;
212
+ v >>= 2;
213
+ r = (pal[v & 3] >> 4) & 0xf0;
214
+ g = pal[v & 3] & 0xf0;
215
+ b = (pal[v & 3] << 4) & 0xf0;
216
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
217
+ d += 4;
218
+ s++;
219
+ width -= 4;
220
+ } while (width > 0);
221
+}
222
+
223
+/*
224
+ * 4-bit colour
225
+ */
226
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
227
+ int width, int deststep)
228
+{
229
+ uint16_t *pal = opaque;
230
+ uint8_t v, r, g, b;
231
+
232
+ do {
233
+ v = ldub_p((void *) s);
234
+ r = (pal[v & 0xf] >> 4) & 0xf0;
235
+ g = pal[v & 0xf] & 0xf0;
236
+ b = (pal[v & 0xf] << 4) & 0xf0;
237
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
238
+ d += 4;
239
+ v >>= 4;
240
+ r = (pal[v & 0xf] >> 4) & 0xf0;
241
+ g = pal[v & 0xf] & 0xf0;
242
+ b = (pal[v & 0xf] << 4) & 0xf0;
243
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
244
+ d += 4;
245
+ s++;
246
+ width -= 2;
247
+ } while (width > 0);
248
+}
249
+
250
+/*
251
+ * 8-bit colour
252
+ */
253
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
254
+ int width, int deststep)
255
+{
256
+ uint16_t *pal = opaque;
257
+ uint8_t v, r, g, b;
258
+
259
+ do {
260
+ v = ldub_p((void *) s);
261
+ r = (pal[v] >> 4) & 0xf0;
262
+ g = pal[v] & 0xf0;
263
+ b = (pal[v] << 4) & 0xf0;
264
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
265
+ s++;
266
+ d += 4;
267
+ } while (-- width != 0);
268
+}
269
+
270
+/*
271
+ * 12-bit colour
272
+ */
273
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
274
+ int width, int deststep)
275
+{
276
+ uint16_t v;
277
+ uint8_t r, g, b;
278
+
279
+ do {
280
+ v = lduw_le_p((void *) s);
281
+ r = (v >> 4) & 0xf0;
282
+ g = v & 0xf0;
283
+ b = (v << 4) & 0xf0;
284
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
285
+ s += 2;
286
+ d += 4;
287
+ } while (-- width != 0);
288
+}
289
+
290
+/*
291
+ * 16-bit colour
292
+ */
293
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
294
+ int width, int deststep)
295
+{
296
+ uint16_t v;
297
+ uint8_t r, g, b;
298
+
299
+ do {
300
+ v = lduw_le_p((void *) s);
301
+ r = (v >> 8) & 0xf8;
302
+ g = (v >> 3) & 0xfc;
303
+ b = (v << 3) & 0xf8;
304
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
305
+ s += 2;
306
+ d += 4;
307
+ } while (-- width != 0);
308
+}
309
310
static void omap_update_display(void *opaque)
311
{
312
--
1580
--
313
2.20.1
1581
2.43.0
314
315
diff view generated by jsdifflib
1
Instead of hardcoding the MachineClass default_ram_size and
1
Currently the helper_vfp_get_fpscr() and helper_vfp_set_fpscr()
2
default_ram_id fields, set them on class creation by finding the
2
functions do the actual work of updating the FPSCR, and we have
3
entry in the RAMInfo array which is marked as being the QEMU system
3
wrappers vfp_get_fpscr() and vfp_set_fpscr() which we use for calls
4
RAM.
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.
5
13
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-18-peter.maydell@linaro.org
16
Message-id: 20250221190957.811948-3-peter.maydell@linaro.org
9
---
17
---
10
hw/arm/mps2-tz.c | 24 ++++++++++++++++++++++--
18
target/arm/tcg/vfp_helper.c | 10 ++++++++++
11
1 file changed, 22 insertions(+), 2 deletions(-)
19
target/arm/vfp_helper.c | 15 ++-------------
20
2 files changed, 12 insertions(+), 13 deletions(-)
12
21
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
22
diff --git a/target/arm/tcg/vfp_helper.c b/target/arm/tcg/vfp_helper.c
14
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
24
--- a/target/arm/tcg/vfp_helper.c
16
+++ b/hw/arm/mps2-tz.c
25
+++ b/target/arm/tcg/vfp_helper.c
17
@@ -XXX,XX +XXX,XX @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
26
@@ -XXX,XX +XXX,XX @@ void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg)
18
27
19
mc->init = mps2tz_common_init;
28
raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
20
iic->check = mps2_tz_idau_check;
29
}
21
- mc->default_ram_size = 16 * MiB;
30
+
22
- mc->default_ram_id = "mps.ram";
31
+uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
32
+{
33
+ return vfp_get_fpscr(env);
23
+}
34
+}
24
+
35
+
25
+static void mps2tz_set_default_ram_info(MPS2TZMachineClass *mmc)
36
+void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
26
+{
37
+{
27
+ /*
38
+ vfp_set_fpscr(env, val);
28
+ * Set mc->default_ram_size and default_ram_id from the
39
+}
29
+ * information in mmc->raminfo.
40
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
30
+ */
41
index XXXXXXX..XXXXXXX 100644
31
+ MachineClass *mc = MACHINE_CLASS(mmc);
42
--- a/target/arm/vfp_helper.c
32
+ const RAMInfo *p;
43
+++ b/target/arm/vfp_helper.c
33
+
44
@@ -XXX,XX +XXX,XX @@
34
+ for (p = mmc->raminfo; p->name; p++) {
45
35
+ if (p->mrindex < 0) {
46
#include "qemu/osdep.h"
36
+ /* Found the entry for "system memory" */
47
#include "cpu.h"
37
+ mc->default_ram_size = p->size;
48
-#include "exec/helper-proto.h"
38
+ mc->default_ram_id = p->name;
49
#include "internals.h"
39
+ return;
50
#include "cpu-features.h"
40
+ }
51
#include "fpu/softfloat.h"
41
+ }
52
@@ -XXX,XX +XXX,XX @@ uint32_t vfp_get_fpsr(CPUARMState *env)
42
+ g_assert_not_reached();
53
return fpsr;
43
}
54
}
44
55
45
static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
56
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
46
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
57
+uint32_t vfp_get_fpscr(CPUARMState *env)
47
mmc->numirq = 92;
58
{
48
mmc->raminfo = an505_raminfo;
59
return (vfp_get_fpcr(env) & FPSCR_FPCR_MASK) |
49
mmc->armsse_type = TYPE_IOTKIT;
60
(vfp_get_fpsr(env) & FPSCR_FPSR_MASK);
50
+ mps2tz_set_default_ram_info(mmc);
51
}
61
}
52
62
53
static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
63
-uint32_t vfp_get_fpscr(CPUARMState *env)
54
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
64
-{
55
mmc->numirq = 92;
65
- return HELPER(vfp_get_fpscr)(env);
56
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
66
-}
57
mmc->armsse_type = TYPE_SSE200;
67
-
58
+ mps2tz_set_default_ram_info(mmc);
68
void vfp_set_fpsr(CPUARMState *env, uint32_t val)
69
{
70
ARMCPU *cpu = env_archcpu(env);
71
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpcr(CPUARMState *env, uint32_t val)
72
vfp_set_fpcr_masked(env, val, MAKE_64BIT_MASK(0, 32));
59
}
73
}
60
74
61
static const TypeInfo mps2tz_info = {
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
-}
62
--
86
--
63
2.20.1
87
2.43.0
64
65
diff view generated by jsdifflib
1
For a long time now the UI layer has guaranteed that the console
1
The softfloat (i.e. TCG) specific handling for the FPCR
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
2
and FPSR is abstracted behind five functions:
3
code from the tc6393xb display device which was handling the
3
arm_set_default_fp_behaviours
4
possibility that the console surface was some other format.
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.
5
20
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215103215.4944-3-peter.maydell@linaro.org
23
Message-id: 20250221190957.811948-4-peter.maydell@linaro.org
9
---
24
---
10
include/ui/console.h | 10 ----------
25
target/arm/internals.h | 9 ++
11
hw/display/tc6393xb.c | 33 +--------------------------------
26
target/arm/tcg-stubs.c | 22 ++++
12
2 files changed, 1 insertion(+), 42 deletions(-)
27
target/arm/tcg/vfp_helper.c | 228 +++++++++++++++++++++++++++++++++
28
target/arm/vfp_helper.c | 248 ------------------------------------
29
4 files changed, 259 insertions(+), 248 deletions(-)
13
30
14
diff --git a/include/ui/console.h b/include/ui/console.h
31
diff --git a/target/arm/internals.h b/target/arm/internals.h
15
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
16
--- a/include/ui/console.h
33
--- a/target/arm/internals.h
17
+++ b/include/ui/console.h
34
+++ b/target/arm/internals.h
18
@@ -XXX,XX +XXX,XX @@ PixelFormat qemu_default_pixelformat(int bpp);
35
@@ -XXX,XX +XXX,XX @@ int alle1_tlbmask(CPUARMState *env);
19
DisplaySurface *qemu_create_displaysurface(int width, int height);
36
void arm_set_default_fp_behaviours(float_status *s);
20
void qemu_free_displaysurface(DisplaySurface *surface);
37
/* Set the float_status behaviour to match Arm FPCR.AH=1 behaviour */
21
38
void arm_set_ah_fp_behaviours(float_status *s);
22
-static inline int is_surface_bgr(DisplaySurface *surface)
39
+/* Read the float_status info and return the appropriate FPSR value */
23
-{
40
+uint32_t vfp_get_fpsr_from_host(CPUARMState *env);
24
- if (PIXMAN_FORMAT_BPP(surface->format) == 32 &&
41
+/* Clear the exception status flags from all float_status fields */
25
- PIXMAN_FORMAT_TYPE(surface->format) == PIXMAN_TYPE_ABGR) {
42
+void vfp_clear_float_status_exc_flags(CPUARMState *env);
26
- return 1;
43
+/*
27
- } else {
44
+ * Update float_status fields to handle the bits of the FPCR
28
- return 0;
45
+ * specified by mask changing to the values in val.
29
- }
46
+ */
30
-}
47
+void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask);
31
-
48
32
static inline int is_buffer_shared(DisplaySurface *surface)
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)
33
{
56
{
34
return !(surface->flags & QEMU_ALLOCATED_FLAG);
57
}
35
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
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
36
index XXXXXXX..XXXXXXX 100644
81
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/display/tc6393xb.c
82
--- a/target/arm/tcg/vfp_helper.c
38
+++ b/hw/display/tc6393xb.c
83
+++ b/target/arm/tcg/vfp_helper.c
39
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
84
@@ -XXX,XX +XXX,XX @@
40
(uint32_t) addr, value & 0xff);
85
#include "fpu/softfloat.h"
41
}
86
#include "qemu/log.h"
42
87
43
-#define BITS 8
88
+/*
44
-#include "tc6393xb_template.h"
89
+ * Set the float_status behaviour to match the Arm defaults:
45
-#define BITS 15
90
+ * * tininess-before-rounding
46
-#include "tc6393xb_template.h"
91
+ * * 2-input NaN propagation prefers SNaN over QNaN, and then
47
-#define BITS 16
92
+ * operand A over operand B (see FPProcessNaNs() pseudocode)
48
-#include "tc6393xb_template.h"
93
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
49
-#define BITS 24
94
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
50
-#include "tc6393xb_template.h"
95
+ * but note that for QEMU muladd is a * b + c, whereas for
51
#define BITS 32
96
+ * the pseudocode function the arguments are in the order c, a, b.
52
#include "tc6393xb_template.h"
97
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
53
98
+ * and the input NaN if it is signalling
54
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
99
+ * * Default NaN has sign bit clear, msb frac bit set
100
+ */
101
+void arm_set_default_fp_behaviours(float_status *s)
102
+{
103
+ set_float_detect_tininess(float_tininess_before_rounding, s);
104
+ set_float_ftz_detection(float_ftz_before_rounding, s);
105
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
106
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
107
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
108
+ set_float_default_nan_pattern(0b01000000, s);
109
+}
110
+
111
+/*
112
+ * Set the float_status behaviour to match the FEAT_AFP
113
+ * FPCR.AH=1 requirements:
114
+ * * tininess-after-rounding
115
+ * * 2-input NaN propagation prefers the first NaN
116
+ * * 3-input NaN propagation prefers a over b over c
117
+ * * 0 * Inf + NaN always returns the input NaN and doesn't
118
+ * set Invalid for a QNaN
119
+ * * default NaN has sign bit set, msb frac bit set
120
+ */
121
+void arm_set_ah_fp_behaviours(float_status *s)
122
+{
123
+ set_float_detect_tininess(float_tininess_after_rounding, s);
124
+ set_float_ftz_detection(float_ftz_after_rounding, s);
125
+ set_float_2nan_prop_rule(float_2nan_prop_ab, s);
126
+ set_float_3nan_prop_rule(float_3nan_prop_abc, s);
127
+ set_float_infzeronan_rule(float_infzeronan_dnan_never |
128
+ float_infzeronan_suppress_invalid, s);
129
+ set_float_default_nan_pattern(0b11000000, s);
130
+}
131
+
132
+/* Convert host exception flags to vfp form. */
133
+static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
134
+{
135
+ uint32_t target_bits = 0;
136
+
137
+ if (host_bits & float_flag_invalid) {
138
+ target_bits |= FPSR_IOC;
139
+ }
140
+ if (host_bits & float_flag_divbyzero) {
141
+ target_bits |= FPSR_DZC;
142
+ }
143
+ if (host_bits & float_flag_overflow) {
144
+ target_bits |= FPSR_OFC;
145
+ }
146
+ if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
147
+ target_bits |= FPSR_UFC;
148
+ }
149
+ if (host_bits & float_flag_inexact) {
150
+ target_bits |= FPSR_IXC;
151
+ }
152
+ if (host_bits & float_flag_input_denormal_flushed) {
153
+ target_bits |= FPSR_IDC;
154
+ }
155
+ /*
156
+ * With FPCR.AH, IDC is set when an input denormal is used,
157
+ * and flushing an output denormal to zero sets both IXC and UFC.
158
+ */
159
+ if (ah && (host_bits & float_flag_input_denormal_used)) {
160
+ target_bits |= FPSR_IDC;
161
+ }
162
+ if (ah && (host_bits & float_flag_output_denormal_flushed)) {
163
+ target_bits |= FPSR_IXC;
164
+ }
165
+ return target_bits;
166
+}
167
+
168
+uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
169
+{
170
+ uint32_t a32_flags = 0, a64_flags = 0;
171
+
172
+ a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
173
+ a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
174
+ /* FZ16 does not generate an input denormal exception. */
175
+ a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
176
+ & ~float_flag_input_denormal_flushed);
177
+ a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
178
+ & ~float_flag_input_denormal_flushed);
179
+
180
+ a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
181
+ a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
182
+ & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
183
+ /*
184
+ * We do not merge in flags from FPST_AH or FPST_AH_F16, because
185
+ * they are used for insns that must not set the cumulative exception bits.
186
+ */
187
+
188
+ /*
189
+ * Flushing an input denormal *only* because FPCR.FIZ == 1 does
190
+ * not set FPSR.IDC; if FPCR.FZ is also set then this takes
191
+ * precedence and IDC is set (see the FPUnpackBase pseudocode).
192
+ * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
193
+ * We only do this for the a64 flags because FIZ has no effect
194
+ * on AArch32 even if it is set.
195
+ */
196
+ if ((env->vfp.fpcr & (FPCR_FZ | FPCR_AH)) != FPCR_FZ) {
197
+ a64_flags &= ~float_flag_input_denormal_flushed;
198
+ }
199
+ return vfp_exceptbits_from_host(a64_flags, env->vfp.fpcr & FPCR_AH) |
200
+ vfp_exceptbits_from_host(a32_flags, false);
201
+}
202
+
203
+void vfp_clear_float_status_exc_flags(CPUARMState *env)
204
+{
205
+ /*
206
+ * Clear out all the exception-flag information in the float_status
207
+ * values. The caller should have arranged for env->vfp.fpsr to
208
+ * be the architecturally up-to-date exception flag information first.
209
+ */
210
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32]);
211
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64]);
212
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32_F16]);
213
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64_F16]);
214
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD]);
215
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD_F16]);
216
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH]);
217
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH_F16]);
218
+}
219
+
220
+static void vfp_sync_and_clear_float_status_exc_flags(CPUARMState *env)
221
+{
222
+ /*
223
+ * Synchronize any pending exception-flag information in the
224
+ * float_status values into env->vfp.fpsr, and then clear out
225
+ * the float_status data.
226
+ */
227
+ env->vfp.fpsr |= vfp_get_fpsr_from_host(env);
228
+ vfp_clear_float_status_exc_flags(env);
229
+}
230
+
231
+void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
232
+{
233
+ uint64_t changed = env->vfp.fpcr;
234
+
235
+ changed ^= val;
236
+ changed &= mask;
237
+ if (changed & (3 << 22)) {
238
+ int i = (val >> 22) & 3;
239
+ switch (i) {
240
+ case FPROUNDING_TIEEVEN:
241
+ i = float_round_nearest_even;
242
+ break;
243
+ case FPROUNDING_POSINF:
244
+ i = float_round_up;
245
+ break;
246
+ case FPROUNDING_NEGINF:
247
+ i = float_round_down;
248
+ break;
249
+ case FPROUNDING_ZERO:
250
+ i = float_round_to_zero;
251
+ break;
252
+ }
253
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
254
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64]);
255
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32_F16]);
256
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64_F16]);
257
+ }
258
+ if (changed & FPCR_FZ16) {
259
+ bool ftz_enabled = val & FPCR_FZ16;
260
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
261
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
262
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
263
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
264
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
265
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
266
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
267
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
268
+ }
269
+ if (changed & FPCR_FZ) {
270
+ bool ftz_enabled = val & FPCR_FZ;
271
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
272
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64]);
273
+ /* FIZ is A64 only so FZ always makes A32 code flush inputs to zero */
274
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
275
+ }
276
+ if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
277
+ /*
278
+ * A64: Flush denormalized inputs to zero if FPCR.FIZ = 1, or
279
+ * both FPCR.AH = 0 and FPCR.FZ = 1.
280
+ */
281
+ bool fitz_enabled = (val & FPCR_FIZ) ||
282
+ (val & (FPCR_FZ | FPCR_AH)) == FPCR_FZ;
283
+ set_flush_inputs_to_zero(fitz_enabled, &env->vfp.fp_status[FPST_A64]);
284
+ }
285
+ if (changed & FPCR_DN) {
286
+ bool dnan_enabled = val & FPCR_DN;
287
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
288
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
289
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
290
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
291
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
292
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
293
+ }
294
+ if (changed & FPCR_AH) {
295
+ bool ah_enabled = val & FPCR_AH;
296
+
297
+ if (ah_enabled) {
298
+ /* Change behaviours for A64 FP operations */
299
+ arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
300
+ arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
301
+ } else {
302
+ arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
303
+ arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
304
+ }
305
+ }
306
+ /*
307
+ * If any bits changed that we look at in vfp_get_fpsr_from_host(),
308
+ * we must sync the float_status flags into vfp.fpsr now (under the
309
+ * old regime) before we update vfp.fpcr.
310
+ */
311
+ if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
312
+ vfp_sync_and_clear_float_status_exc_flags(env);
313
+ }
314
+}
315
+
316
/*
317
* VFP support. We follow the convention used for VFP instructions:
318
* Single precision routines have a "s" suffix, double precision a
319
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
320
index XXXXXXX..XXXXXXX 100644
321
--- a/target/arm/vfp_helper.c
322
+++ b/target/arm/vfp_helper.c
323
@@ -XXX,XX +XXX,XX @@
324
#include "cpu.h"
325
#include "internals.h"
326
#include "cpu-features.h"
327
-#include "fpu/softfloat.h"
328
-
329
-/*
330
- * Set the float_status behaviour to match the Arm defaults:
331
- * * tininess-before-rounding
332
- * * 2-input NaN propagation prefers SNaN over QNaN, and then
333
- * operand A over operand B (see FPProcessNaNs() pseudocode)
334
- * * 3-input NaN propagation prefers SNaN over QNaN, and then
335
- * operand C over A over B (see FPProcessNaNs3() pseudocode,
336
- * but note that for QEMU muladd is a * b + c, whereas for
337
- * the pseudocode function the arguments are in the order c, a, b.
338
- * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
339
- * and the input NaN if it is signalling
340
- * * Default NaN has sign bit clear, msb frac bit set
341
- */
342
-void arm_set_default_fp_behaviours(float_status *s)
343
-{
344
- set_float_detect_tininess(float_tininess_before_rounding, s);
345
- set_float_ftz_detection(float_ftz_before_rounding, s);
346
- set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
347
- set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
348
- set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
349
- set_float_default_nan_pattern(0b01000000, s);
350
-}
351
-
352
-/*
353
- * Set the float_status behaviour to match the FEAT_AFP
354
- * FPCR.AH=1 requirements:
355
- * * tininess-after-rounding
356
- * * 2-input NaN propagation prefers the first NaN
357
- * * 3-input NaN propagation prefers a over b over c
358
- * * 0 * Inf + NaN always returns the input NaN and doesn't
359
- * set Invalid for a QNaN
360
- * * default NaN has sign bit set, msb frac bit set
361
- */
362
-void arm_set_ah_fp_behaviours(float_status *s)
363
-{
364
- set_float_detect_tininess(float_tininess_after_rounding, s);
365
- set_float_ftz_detection(float_ftz_after_rounding, s);
366
- set_float_2nan_prop_rule(float_2nan_prop_ab, s);
367
- set_float_3nan_prop_rule(float_3nan_prop_abc, s);
368
- set_float_infzeronan_rule(float_infzeronan_dnan_never |
369
- float_infzeronan_suppress_invalid, s);
370
- set_float_default_nan_pattern(0b11000000, s);
371
-}
372
-
373
-#ifdef CONFIG_TCG
374
-
375
-/* Convert host exception flags to vfp form. */
376
-static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
377
-{
378
- uint32_t target_bits = 0;
379
-
380
- if (host_bits & float_flag_invalid) {
381
- target_bits |= FPSR_IOC;
382
- }
383
- if (host_bits & float_flag_divbyzero) {
384
- target_bits |= FPSR_DZC;
385
- }
386
- if (host_bits & float_flag_overflow) {
387
- target_bits |= FPSR_OFC;
388
- }
389
- if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
390
- target_bits |= FPSR_UFC;
391
- }
392
- if (host_bits & float_flag_inexact) {
393
- target_bits |= FPSR_IXC;
394
- }
395
- if (host_bits & float_flag_input_denormal_flushed) {
396
- target_bits |= FPSR_IDC;
397
- }
398
- /*
399
- * With FPCR.AH, IDC is set when an input denormal is used,
400
- * and flushing an output denormal to zero sets both IXC and UFC.
401
- */
402
- if (ah && (host_bits & float_flag_input_denormal_used)) {
403
- target_bits |= FPSR_IDC;
404
- }
405
- if (ah && (host_bits & float_flag_output_denormal_flushed)) {
406
- target_bits |= FPSR_IXC;
407
- }
408
- return target_bits;
409
-}
410
-
411
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
412
-{
413
- uint32_t a32_flags = 0, a64_flags = 0;
414
-
415
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
416
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
417
- /* FZ16 does not generate an input denormal exception. */
418
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
419
- & ~float_flag_input_denormal_flushed);
420
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
421
- & ~float_flag_input_denormal_flushed);
422
-
423
- a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
424
- a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
425
- & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
426
- /*
427
- * We do not merge in flags from FPST_AH or FPST_AH_F16, because
428
- * they are used for insns that must not set the cumulative exception bits.
429
- */
430
-
431
- /*
432
- * Flushing an input denormal *only* because FPCR.FIZ == 1 does
433
- * not set FPSR.IDC; if FPCR.FZ is also set then this takes
434
- * precedence and IDC is set (see the FPUnpackBase pseudocode).
435
- * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
436
- * We only do this for the a64 flags because FIZ has no effect
437
- * on AArch32 even if it is set.
438
- */
439
- if ((env->vfp.fpcr & (FPCR_FZ | FPCR_AH)) != FPCR_FZ) {
440
- a64_flags &= ~float_flag_input_denormal_flushed;
441
- }
442
- return vfp_exceptbits_from_host(a64_flags, env->vfp.fpcr & FPCR_AH) |
443
- vfp_exceptbits_from_host(a32_flags, false);
444
-}
445
-
446
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
447
-{
448
- /*
449
- * Clear out all the exception-flag information in the float_status
450
- * values. The caller should have arranged for env->vfp.fpsr to
451
- * be the architecturally up-to-date exception flag information first.
452
- */
453
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32]);
454
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64]);
455
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32_F16]);
456
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64_F16]);
457
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD]);
458
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD_F16]);
459
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH]);
460
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH_F16]);
461
-}
462
-
463
-static void vfp_sync_and_clear_float_status_exc_flags(CPUARMState *env)
464
-{
465
- /*
466
- * Synchronize any pending exception-flag information in the
467
- * float_status values into env->vfp.fpsr, and then clear out
468
- * the float_status data.
469
- */
470
- env->vfp.fpsr |= vfp_get_fpsr_from_host(env);
471
- vfp_clear_float_status_exc_flags(env);
472
-}
473
-
474
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
475
-{
476
- uint64_t changed = env->vfp.fpcr;
477
-
478
- changed ^= val;
479
- changed &= mask;
480
- if (changed & (3 << 22)) {
481
- int i = (val >> 22) & 3;
482
- switch (i) {
483
- case FPROUNDING_TIEEVEN:
484
- i = float_round_nearest_even;
485
- break;
486
- case FPROUNDING_POSINF:
487
- i = float_round_up;
488
- break;
489
- case FPROUNDING_NEGINF:
490
- i = float_round_down;
491
- break;
492
- case FPROUNDING_ZERO:
493
- i = float_round_to_zero;
494
- break;
495
- }
496
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
497
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64]);
498
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32_F16]);
499
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64_F16]);
500
- }
501
- if (changed & FPCR_FZ16) {
502
- bool ftz_enabled = val & FPCR_FZ16;
503
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
504
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
505
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
506
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
507
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
508
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
509
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
510
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
511
- }
512
- if (changed & FPCR_FZ) {
513
- bool ftz_enabled = val & FPCR_FZ;
514
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
515
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64]);
516
- /* FIZ is A64 only so FZ always makes A32 code flush inputs to zero */
517
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
518
- }
519
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
520
- /*
521
- * A64: Flush denormalized inputs to zero if FPCR.FIZ = 1, or
522
- * both FPCR.AH = 0 and FPCR.FZ = 1.
523
- */
524
- bool fitz_enabled = (val & FPCR_FIZ) ||
525
- (val & (FPCR_FZ | FPCR_AH)) == FPCR_FZ;
526
- set_flush_inputs_to_zero(fitz_enabled, &env->vfp.fp_status[FPST_A64]);
527
- }
528
- if (changed & FPCR_DN) {
529
- bool dnan_enabled = val & FPCR_DN;
530
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
531
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
532
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
533
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
534
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
535
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
536
- }
537
- if (changed & FPCR_AH) {
538
- bool ah_enabled = val & FPCR_AH;
539
-
540
- if (ah_enabled) {
541
- /* Change behaviours for A64 FP operations */
542
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
543
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
544
- } else {
545
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
546
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
547
- }
548
- }
549
- /*
550
- * If any bits changed that we look at in vfp_get_fpsr_from_host(),
551
- * we must sync the float_status flags into vfp.fpsr now (under the
552
- * old regime) before we update vfp.fpcr.
553
- */
554
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
555
- vfp_sync_and_clear_float_status_exc_flags(env);
556
- }
557
-}
558
-
559
-#else
560
-
561
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
562
-{
563
- return 0;
564
-}
565
-
566
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
567
-{
568
-}
569
-
570
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
571
-{
572
-}
573
-
574
-#endif
575
576
uint32_t vfp_get_fpcr(CPUARMState *env)
55
{
577
{
56
- DisplaySurface *surface = qemu_console_surface(s->con);
57
-
58
- switch (surface_bits_per_pixel(surface)) {
59
- case 8:
60
- tc6393xb_draw_graphic8(s);
61
- break;
62
- case 15:
63
- tc6393xb_draw_graphic15(s);
64
- break;
65
- case 16:
66
- tc6393xb_draw_graphic16(s);
67
- break;
68
- case 24:
69
- tc6393xb_draw_graphic24(s);
70
- break;
71
- case 32:
72
- tc6393xb_draw_graphic32(s);
73
- break;
74
- default:
75
- printf("tc6393xb: unknown depth %d\n",
76
- surface_bits_per_pixel(surface));
77
- return;
78
- }
79
-
80
+ tc6393xb_draw_graphic32(s);
81
dpy_gfx_update_full(s->con);
82
}
83
84
--
578
--
85
2.20.1
579
2.43.0
86
87
diff view generated by jsdifflib
1
Update old infocenter.arm.com URLs to the equivalent developer.arm.com
1
The vfp_helper.c in the target/arm directory now only has
2
ones (the old URLs should redirect, but we might as well avoid the
2
code for handling FPSCR/FPCR/FPSR in it, and no helper
3
redirection notice, and the new URLs are pleasantly shorter).
3
functions. Rename it to vfp_fpscr.c; this helps keep it
4
4
distinct from tcg/vfp_helper.c.
5
This commit covers the links to the MPS2 board TRM, the various
6
Application Notes, the IoTKit and SSE-200 documents.
7
5
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210215115138.20465-25-peter.maydell@linaro.org
8
Message-id: 20250221190957.811948-5-peter.maydell@linaro.org
11
---
9
---
12
include/hw/arm/armsse.h | 4 ++--
10
target/arm/{vfp_helper.c => vfp_fpscr.c} | 2 +-
13
include/hw/misc/armsse-cpuid.h | 2 +-
11
target/arm/meson.build | 2 +-
14
include/hw/misc/armsse-mhu.h | 2 +-
12
2 files changed, 2 insertions(+), 2 deletions(-)
15
include/hw/misc/iotkit-secctl.h | 2 +-
13
rename target/arm/{vfp_helper.c => vfp_fpscr.c} (98%)
16
include/hw/misc/iotkit-sysctl.h | 2 +-
17
include/hw/misc/iotkit-sysinfo.h | 2 +-
18
include/hw/misc/mps2-fpgaio.h | 2 +-
19
hw/arm/mps2-tz.c | 11 +++++------
20
hw/misc/armsse-cpuid.c | 2 +-
21
hw/misc/armsse-mhu.c | 2 +-
22
hw/misc/iotkit-sysctl.c | 2 +-
23
hw/misc/iotkit-sysinfo.c | 2 +-
24
hw/misc/mps2-fpgaio.c | 2 +-
25
hw/misc/mps2-scc.c | 2 +-
26
14 files changed, 19 insertions(+), 20 deletions(-)
27
14
28
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
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
29
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/armsse.h
20
--- a/target/arm/vfp_helper.c
31
+++ b/include/hw/arm/armsse.h
21
+++ b/target/arm/vfp_fpscr.c
32
@@ -XXX,XX +XXX,XX @@
33
* hardware, which include the IoT Kit and the SSE-050, SSE-100 and
34
* SSE-200. Currently we model:
35
* - the Arm IoT Kit which is documented in
36
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
37
+ * https://developer.arm.com/documentation/ecm0601256/latest
38
* - the SSE-200 which is documented in
39
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
40
+ * https://developer.arm.com/documentation/101104/latest/
41
*
42
* The IoTKit contains:
43
* a Cortex-M33
44
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/misc/armsse-cpuid.h
47
+++ b/include/hw/misc/armsse-cpuid.h
48
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
49
/*
23
/*
50
* This is a model of the "CPU_IDENTITY" register block which is part of the
24
- * ARM VFP floating-point operations
51
* Arm SSE-200 and documented in
25
+ * ARM VFP floating-point: handling of FPSCR/FPCR/FPSR
52
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
53
+ * https://developer.arm.com/documentation/101104/latest/
54
*
26
*
55
* QEMU interface:
27
* Copyright (c) 2003 Fabrice Bellard
56
* + QOM property "CPUID": the value to use for the CPUID register
28
*
57
diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h
29
diff --git a/target/arm/meson.build b/target/arm/meson.build
58
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
59
--- a/include/hw/misc/armsse-mhu.h
31
--- a/target/arm/meson.build
60
+++ b/include/hw/misc/armsse-mhu.h
32
+++ b/target/arm/meson.build
61
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
62
/*
34
'debug_helper.c',
63
* This is a model of the Message Handling Unit (MHU) which is part of the
35
'gdbstub.c',
64
* Arm SSE-200 and documented in
36
'helper.c',
65
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
37
- 'vfp_helper.c',
66
+ * https://developer.arm.com/documentation/101104/latest/
38
+ 'vfp_fpscr.c',
67
*
39
))
68
* QEMU interface:
40
arm_ss.add(zlib)
69
* + sysbus MMIO region 0: the system information register bank
70
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/include/hw/misc/iotkit-secctl.h
73
+++ b/include/hw/misc/iotkit-secctl.h
74
@@ -XXX,XX +XXX,XX @@
75
76
/* This is a model of the security controller which is part of the
77
* Arm IoT Kit and documented in
78
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
79
+ * https://developer.arm.com/documentation/ecm0601256/latest
80
*
81
* QEMU interface:
82
* + sysbus MMIO region 0 is the "secure privilege control block" registers
83
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
84
index XXXXXXX..XXXXXXX 100644
85
--- a/include/hw/misc/iotkit-sysctl.h
86
+++ b/include/hw/misc/iotkit-sysctl.h
87
@@ -XXX,XX +XXX,XX @@
88
/*
89
* This is a model of the "system control element" which is part of the
90
* Arm IoTKit and documented in
91
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
92
+ * https://developer.arm.com/documentation/ecm0601256/latest
93
* Specifically, it implements the "system information block" and
94
* "system control register" blocks.
95
*
96
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
97
index XXXXXXX..XXXXXXX 100644
98
--- a/include/hw/misc/iotkit-sysinfo.h
99
+++ b/include/hw/misc/iotkit-sysinfo.h
100
@@ -XXX,XX +XXX,XX @@
101
/*
102
* This is a model of the "system information block" which is part of the
103
* Arm IoTKit and documented in
104
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
105
+ * https://developer.arm.com/documentation/ecm0601256/latest
106
* QEMU interface:
107
* + QOM property "SYS_VERSION": value to use for SYS_VERSION register
108
* + QOM property "SYS_CONFIG": value to use for SYS_CONFIG register
109
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
110
index XXXXXXX..XXXXXXX 100644
111
--- a/include/hw/misc/mps2-fpgaio.h
112
+++ b/include/hw/misc/mps2-fpgaio.h
113
@@ -XXX,XX +XXX,XX @@
114
/* This is a model of the FPGAIO register block in the AN505
115
* FPGA image for the MPS2 dev board; it is documented in the
116
* application note:
117
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
118
+ * https://developer.arm.com/documentation/dai0505/latest/
119
*
120
* QEMU interface:
121
* + sysbus MMIO region 0: the register bank
122
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hw/arm/mps2-tz.c
125
+++ b/hw/arm/mps2-tz.c
126
@@ -XXX,XX +XXX,XX @@
127
* https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
128
*
129
* Board TRM:
130
- * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
131
+ * https://developer.arm.com/documentation/100112/latest/
132
* Application Note AN505:
133
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
134
+ * https://developer.arm.com/documentation/dai0505/latest/
135
* Application Note AN521:
136
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
137
+ * https://developer.arm.com/documentation/dai0521/latest/
138
* Application Note AN524:
139
* https://developer.arm.com/documentation/dai0524/latest/
140
*
141
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
142
* (ARM ECM0601256) for the details of some of the device layout:
143
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
144
+ * https://developer.arm.com/documentation/ecm0601256/latest
145
* Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
146
* most of the device layout:
147
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
148
- *
149
+ * https://developer.arm.com/documentation/101104/latest/
150
*/
151
152
#include "qemu/osdep.h"
153
diff --git a/hw/misc/armsse-cpuid.c b/hw/misc/armsse-cpuid.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/misc/armsse-cpuid.c
156
+++ b/hw/misc/armsse-cpuid.c
157
@@ -XXX,XX +XXX,XX @@
158
/*
159
* This is a model of the "CPU_IDENTITY" register block which is part of the
160
* Arm SSE-200 and documented in
161
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
162
+ * https://developer.arm.com/documentation/101104/latest/
163
*
164
* It consists of one read-only CPUID register (set by QOM property), plus the
165
* usual ID registers.
166
diff --git a/hw/misc/armsse-mhu.c b/hw/misc/armsse-mhu.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/misc/armsse-mhu.c
169
+++ b/hw/misc/armsse-mhu.c
170
@@ -XXX,XX +XXX,XX @@
171
/*
172
* This is a model of the Message Handling Unit (MHU) which is part of the
173
* Arm SSE-200 and documented in
174
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
175
+ * https://developer.arm.com/documentation/101104/latest/
176
*/
177
178
#include "qemu/osdep.h"
179
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/misc/iotkit-sysctl.c
182
+++ b/hw/misc/iotkit-sysctl.c
183
@@ -XXX,XX +XXX,XX @@
184
/*
185
* This is a model of the "system control element" which is part of the
186
* Arm IoTKit and documented in
187
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
188
+ * https://developer.arm.com/documentation/ecm0601256/latest
189
* Specifically, it implements the "system control register" blocks.
190
*/
191
192
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/hw/misc/iotkit-sysinfo.c
195
+++ b/hw/misc/iotkit-sysinfo.c
196
@@ -XXX,XX +XXX,XX @@
197
/*
198
* This is a model of the "system information block" which is part of the
199
* Arm IoTKit and documented in
200
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
201
+ * https://developer.arm.com/documentation/ecm0601256/latest
202
* It consists of 2 read-only version/config registers, plus the
203
* usual ID registers.
204
*/
205
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
206
index XXXXXXX..XXXXXXX 100644
207
--- a/hw/misc/mps2-fpgaio.c
208
+++ b/hw/misc/mps2-fpgaio.c
209
@@ -XXX,XX +XXX,XX @@
210
/* This is a model of the "FPGA system control and I/O" block found
211
* in the AN505 FPGA image for the MPS2 devboard.
212
* It is documented in AN505:
213
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
214
+ * https://developer.arm.com/documentation/dai0505/latest/
215
*/
216
217
#include "qemu/osdep.h"
218
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
219
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/misc/mps2-scc.c
221
+++ b/hw/misc/mps2-scc.c
222
@@ -XXX,XX +XXX,XX @@
223
* found in the FPGA images of MPS2 development boards.
224
*
225
* Documentation of it can be found in the MPS2 TRM:
226
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100112_0100_03_en/index.html
227
+ * https://developer.arm.com/documentation/100112/latest/
228
* and also in the Application Notes documenting individual FPGA images.
229
*/
230
41
231
--
42
--
232
2.20.1
43
2.43.0
233
234
diff view generated by jsdifflib
1
In the mps2-tz board code, we handle devices whose interrupt lines
1
From: Joelle van Dyne <j@getutm.app>
2
must be wired to all CPUs by creating IRQ splitter devices for the
3
AN521, because it has 2 CPUs, but wiring the device IRQ directly to
4
the SSE/IoTKit input for the AN505, which has only 1 CPU.
5
2
6
We can avoid making an explicit check on the board type constant by
3
macOS 15.2's Hypervisor.framework exposes SME feature on M4 Macs.
7
instead creating and using the IRQ splitters for any board with more
4
However, QEMU's hvf accelerator code does not properly support it
8
than 1 CPU. This avoids having to add extra cases to the
5
yet, causing QEMU to fail to start when hvf accelerator is used on
9
conditionals every time we add new boards.
6
these systems, with the error message:
10
7
8
qemu-aarch64-softmmu: cannot disable sme4224
9
All SME vector lengths are disabled.
10
With SME enabled, at least one vector length must be enabled.
11
12
Ideally we would have SME support on these hosts; however, until that
13
point, we must suppress the SME feature in the ID registers, so that
14
users can at least run non-SME guests.
15
16
Cc: qemu-stable@nongnu.org
17
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2665
18
Signed-off-by: Joelle van Dyne <j@getutm.app>
19
Message-id: 20250224165735.36792-1-j@getutm.app
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
[PMM: expanded commit message, comment]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20210215115138.20465-9-peter.maydell@linaro.org
15
---
23
---
16
hw/arm/mps2-tz.c | 19 +++++++++----------
24
target/arm/hvf/hvf.c | 12 ++++++++++++
17
1 file changed, 9 insertions(+), 10 deletions(-)
25
1 file changed, 12 insertions(+)
18
26
19
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
27
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
20
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/mps2-tz.c
29
--- a/target/arm/hvf/hvf.c
22
+++ b/hw/arm/mps2-tz.c
30
+++ b/target/arm/hvf/hvf.c
23
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
31
@@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
24
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
32
25
{
33
clamp_id_aa64mmfr0_parange_to_ipa_size(&host_isar.id_aa64mmfr0);
26
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
34
27
- MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
35
+ /*
28
+ MachineClass *mc = MACHINE_GET_CLASS(mms);
36
+ * Disable SME, which is not properly handled by QEMU hvf yet.
29
37
+ * To allow this through we would need to:
30
assert(irqno < MPS2TZ_NUMIRQ);
38
+ * - make sure that the SME state is correctly handled in the
31
39
+ * get_registers/put_registers functions
32
- switch (mmc->fpga_type) {
40
+ * - get the SME-specific CPU properties to work with accelerators
33
- case FPGA_AN505:
41
+ * other than TCG
34
- return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
42
+ * - fix any assumptions we made that SME implies SVE (since
35
- case FPGA_AN521:
43
+ * on the M4 there is SME but not SVE)
36
+ if (mc->max_cpus > 1) {
44
+ */
37
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
45
+ host_isar.id_aa64pfr1 &= ~R_ID_AA64PFR1_SME_MASK;
38
- default:
46
+
39
- g_assert_not_reached();
47
ahcf->isar = host_isar;
40
+ } else {
41
+ return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
42
}
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
46
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
47
48
48
/*
49
/*
49
- * The AN521 needs us to create splitters to feed the IRQ inputs
50
- * for each CPU in the SSE-200 from each device in the board.
51
+ * If this board has more than one CPU, then we need to create splitters
52
+ * to feed the IRQ inputs for each CPU in the SSE from each device in the
53
+ * board. If there is only one CPU, we can just wire the device IRQ
54
+ * directly to the SSE's IRQ input.
55
*/
56
- if (mmc->fpga_type == FPGA_AN521) {
57
+ if (mc->max_cpus > 1) {
58
for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
59
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
60
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
61
--
50
--
62
2.20.1
51
2.43.0
63
64
diff view generated by jsdifflib
1
From: Peter Collingbourne <pcc@google.com>
1
From: Joelle van Dyne <j@getutm.app>
2
2
3
Section D6.7 of the ARM ARM states:
3
In the syndrome value for a data abort, bit 21 is SSE, which is
4
set to indicate that the abort was on a sign-extending load. When
5
we handle the data abort from the guest via address_space_read(),
6
we forgot to handle this and so would return the wrong value if
7
the guest did a sign-extending load to an MMIO region. Add the
8
sign-extension of the returned data.
4
9
5
For the purpose of determining Tag Check Fault handling, unprivileged
10
Cc: qemu-stable@nongnu.org
6
load and store instructions are treated as if executed at EL0 when
11
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
executed at either:
12
Message-id: 20250224184123.50780-1-j@getutm.app
8
- EL1, when the Effective value of PSTATE.UAO is 0.
13
[PMM: Drop an unnecessary check on 'len'; expand commit message]
9
- EL2, when both the Effective value of HCR_EL2.{E2H, TGE} is {1, 1}
10
and the Effective value of PSTATE.UAO is 0.
11
12
ARM has confirmed a defect in the pseudocode function
13
AArch64.TagCheckFault that makes it inconsistent with the above
14
wording. The remedy is to adjust references to PSTATE.EL in that
15
function to instead refer to AArch64.AccessUsesEL(acctype), so
16
that unprivileged instructions use SCTLR_EL1.TCF0 and TFSRE0_EL1.
17
The exception type for synchronous tag check faults remains unchanged.
18
19
This patch implements the described change by partially reverting
20
commits 50244cc76abc and cc97b0019bb5.
21
22
Signed-off-by: Peter Collingbourne <pcc@google.com>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20210219201820.2672077-1-pcc@google.com
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
---
16
---
28
target/arm/helper.c | 2 +-
17
target/arm/hvf/hvf.c | 4 ++++
29
target/arm/mte_helper.c | 13 +++++++++----
18
1 file changed, 4 insertions(+)
30
2 files changed, 10 insertions(+), 5 deletions(-)
31
19
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
33
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
22
--- a/target/arm/hvf/hvf.c
35
+++ b/target/arm/helper.c
23
+++ b/target/arm/hvf/hvf.c
36
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
24
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
37
if (FIELD_EX32(flags, TBFLAG_A64, UNPRIV)
25
bool isv = syndrome & ARM_EL_ISV;
38
&& tbid
26
bool iswrite = (syndrome >> 6) & 1;
39
&& !(env->pstate & PSTATE_TCO)
27
bool s1ptw = (syndrome >> 7) & 1;
40
- && (sctlr & SCTLR_TCF)
28
+ bool sse = (syndrome >> 21) & 1;
41
+ && (sctlr & SCTLR_TCF0)
29
uint32_t sas = (syndrome >> 22) & 3;
42
&& allocation_tag_access_enabled(env, 0, sctlr)) {
30
uint32_t len = 1 << sas;
43
flags = FIELD_DP32(flags, TBFLAG_A64, MTE0_ACTIVE, 1);
31
uint32_t srt = (syndrome >> 16) & 0x1f;
32
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
33
address_space_read(&address_space_memory,
34
hvf_exit->exception.physical_address,
35
MEMTXATTRS_UNSPECIFIED, &val, len);
36
+ if (sse) {
37
+ val = sextract64(val, 0, len * 8);
38
+ }
39
hvf_set_reg(cpu, srt, val);
44
}
40
}
45
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/mte_helper.c
48
+++ b/target/arm/mte_helper.c
49
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
50
reg_el = regime_el(env, arm_mmu_idx);
51
sctlr = env->cp15.sctlr_el[reg_el];
52
53
- el = arm_current_el(env);
54
- if (el == 0) {
55
+ switch (arm_mmu_idx) {
56
+ case ARMMMUIdx_E10_0:
57
+ case ARMMMUIdx_E20_0:
58
+ el = 0;
59
tcf = extract64(sctlr, 38, 2);
60
- } else {
61
+ break;
62
+ default:
63
+ el = reg_el;
64
tcf = extract64(sctlr, 40, 2);
65
}
66
67
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
68
env->exception.vaddress = dirty_ptr;
69
70
is_write = FIELD_EX32(desc, MTEDESC, WRITE);
71
- syn = syn_data_abort_no_iss(el != 0, 0, 0, 0, 0, is_write, 0x11);
72
+ syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0,
73
+ is_write, 0x11);
74
raise_exception(env, EXCP_DATA_ABORT, syn, exception_target_el(env));
75
/* noreturn, but fall through to the assert anyway */
76
41
77
--
42
--
78
2.20.1
43
2.43.0
79
80
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
2
2
3
The STATUS register will be reset to IDLE in
3
Regression introduced by cf76c4
4
cnpcm7xx_smbus_enter_reset(), no need to preset
4
(hw/misc: Add nr_regs and cold_reset_values to NPCM CLK)
5
it in instance_init().
6
5
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
cold_reset_values has a different size, depending on device used
7
(NPCM7xx vs NPCM8xx). However, s->regs has a fixed size, which matches
8
NPCM8xx. Thus, when initializing a NPCM7xx, we go past cold_reset_values
9
ending.
10
11
Report by asan:
12
==2066==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55d68a3e97f0 at pc 0x7fcaf2b2d14b bp 0x7ffff0cc3890 sp 0x7ffff0cc3040
13
READ of size 196 at 0x55d68a3e97f0 thread T0
14
#0 0x7fcaf2b2d14a in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
15
#1 0x55d688447e0d in memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:29
16
#2 0x55d688447e0d in npcm_clk_enter_reset ../hw/misc/npcm_clk.c:968
17
#3 0x55d6899b7213 in resettable_phase_enter ../hw/core/resettable.c:136
18
#4 0x55d6899a1ef7 in bus_reset_child_foreach ../hw/core/bus.c:97
19
#5 0x55d6899b717d in resettable_child_foreach ../hw/core/resettable.c:92
20
#6 0x55d6899b717d in resettable_phase_enter ../hw/core/resettable.c:129
21
#7 0x55d6899b4ead in resettable_container_child_foreach ../hw/core/resetcontainer.c:54
22
#8 0x55d6899b717d in resettable_child_foreach ../hw/core/resettable.c:92
23
#9 0x55d6899b717d in resettable_phase_enter ../hw/core/resettable.c:129
24
#10 0x55d6899b7bfa in resettable_assert_reset ../hw/core/resettable.c:55
25
#11 0x55d6899b8666 in resettable_reset ../hw/core/resettable.c:45
26
#12 0x55d688d15cd2 in qemu_system_reset ../system/runstate.c:527
27
#13 0x55d687fc5edd in qdev_machine_creation_done ../hw/core/machine.c:1738
28
#14 0x55d688d209bd in qemu_machine_creation_done ../system/vl.c:2779
29
#15 0x55d688d209bd in qmp_x_exit_preconfig ../system/vl.c:2807
30
#16 0x55d688d281fb in qemu_init ../system/vl.c:3838
31
#17 0x55d687ceab12 in main ../system/main.c:68
32
#18 0x7fcaef006249 (/lib/x86_64-linux-gnu/libc.so.6+0x27249)
33
#19 0x7fcaef006304 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x27304)
34
#20 0x55d687cf0010 in _start (/home/runner/work/qemu-ci/qemu-ci/build/qemu-system-arm+0x371c010)
35
36
0x55d68a3e97f0 is located 0 bytes to the right of global variable 'npcm7xx_cold_reset_values' defined in '../hw/misc/npcm_clk.c:134:23' (0x55d68a3e9780) of size 112
37
38
Impacted tests:
39
Summary of Failures:
40
41
check:
42
2/747 qemu:qtest+qtest-aarch64 / qtest-aarch64/qom-test ERROR 9.28s killed by signal 6 SIGABRT
43
4/747 qemu:qtest+qtest-arm / qtest-arm/qom-test ERROR 7.82s killed by signal 6 SIGABRT
44
32/747 qemu:qtest+qtest-aarch64 / qtest-aarch64/device-introspect-test ERROR 10.91s killed by signal 6 SIGABRT
45
35/747 qemu:qtest+qtest-arm / qtest-arm/device-introspect-test ERROR 11.33s killed by signal 6 SIGABRT
46
114/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_pwm-test ERROR 0.98s killed by signal 6 SIGABRT
47
115/747 qemu:qtest+qtest-aarch64 / qtest-aarch64/test-hmp ERROR 2.95s killed by signal 6 SIGABRT
48
117/747 qemu:qtest+qtest-arm / qtest-arm/test-hmp ERROR 2.54s killed by signal 6 SIGABRT
49
151/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_watchdog_timer-test ERROR 0.96s killed by signal 6 SIGABRT
50
247/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_adc-test ERROR 0.96s killed by signal 6 SIGABRT
51
248/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_gpio-test ERROR 1.05s killed by signal 6 SIGABRT
52
249/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_rng-test ERROR 0.97s killed by signal 6 SIGABRT
53
250/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_sdhci-test ERROR 0.97s killed by signal 6 SIGABRT
54
251/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_smbus-test ERROR 0.89s killed by signal 6 SIGABRT
55
252/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_timer-test ERROR 1.09s killed by signal 6 SIGABRT
56
253/747 qemu:qtest+qtest-arm / qtest-arm/npcm_gmac-test ERROR 1.12s killed by signal 6 SIGABRT
57
255/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_emc-test ERROR 1.05s killed by signal 6 SIGABRT
58
59
check-functional:
60
22/203 qemu:func-thorough+func-arm-thorough+thorough / func-arm-arm_quanta_gsj ERROR 0.79s exit status 1
61
38/203 qemu:func-quick+func-aarch64 / func-aarch64-migration ERROR 1.97s exit status 1
62
45/203 qemu:func-quick+func-arm / func-arm-migration ERROR 1.90s exit status 1
63
64
Fixes: cf76c4e174e1 ("hw/misc: Add nr_regs and cold_reset_values to NPCM CLK")
65
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
66
Reviewed-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210228224813.312532-1-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
67
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
68
---
12
hw/i2c/npcm7xx_smbus.c | 1 -
69
hw/misc/npcm_clk.c | 5 +++--
13
1 file changed, 1 deletion(-)
70
1 file changed, 3 insertions(+), 2 deletions(-)
14
71
15
diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c
72
diff --git a/hw/misc/npcm_clk.c b/hw/misc/npcm_clk.c
16
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/i2c/npcm7xx_smbus.c
74
--- a/hw/misc/npcm_clk.c
18
+++ b/hw/i2c/npcm7xx_smbus.c
75
+++ b/hw/misc/npcm_clk.c
19
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_smbus_init(Object *obj)
76
@@ -XXX,XX +XXX,XX @@ static void npcm_clk_enter_reset(Object *obj, ResetType type)
20
sysbus_init_mmio(sbd, &s->iomem);
77
NPCMCLKState *s = NPCM_CLK(obj);
21
78
NPCMCLKClass *c = NPCM_CLK_GET_CLASS(s);
22
s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
79
23
- s->status = NPCM7XX_SMBUS_STATUS_IDLE;
80
- g_assert(sizeof(s->regs) >= c->nr_regs * sizeof(uint32_t));
24
}
81
- memcpy(s->regs, c->cold_reset_values, sizeof(s->regs));
25
82
+ size_t sizeof_regs = c->nr_regs * sizeof(uint32_t);
26
static const VMStateDescription vmstate_npcm7xx_smbus = {
83
+ g_assert(sizeof(s->regs) >= sizeof_regs);
84
+ memcpy(s->regs, c->cold_reset_values, sizeof_regs);
85
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
86
npcm7xx_clk_update_all_clocks(s);
87
/*
27
--
88
--
28
2.20.1
89
2.43.0
29
30
diff view generated by jsdifflib
1
MPS3 boards have an extra SWITCH register in the FPGAIO block which
1
From: Bernhard Beschow <shentey@gmail.com>
2
reports the value of some switches. Implement this, governed by a
3
property the board code can use to specify whether whether it exists.
4
2
3
While at it add missing GUSB2RHBCTL register as found in i.MX 8M Plus reference
4
manual.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Message-id: 20250223114708.1780-2-shentey@gmail.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-7-peter.maydell@linaro.org
9
---
10
---
10
include/hw/misc/mps2-fpgaio.h | 1 +
11
include/hw/usb/hcd-dwc3.h | 2 +-
11
hw/misc/mps2-fpgaio.c | 10 ++++++++++
12
hw/usb/hcd-dwc3.c | 5 +++++
12
2 files changed, 11 insertions(+)
13
2 files changed, 6 insertions(+), 1 deletion(-)
13
14
14
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
15
diff --git a/include/hw/usb/hcd-dwc3.h b/include/hw/usb/hcd-dwc3.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/mps2-fpgaio.h
17
--- a/include/hw/usb/hcd-dwc3.h
17
+++ b/include/hw/misc/mps2-fpgaio.h
18
+++ b/include/hw/usb/hcd-dwc3.h
18
@@ -XXX,XX +XXX,XX @@ struct MPS2FPGAIO {
19
@@ -XXX,XX +XXX,XX @@
19
MemoryRegion iomem;
20
#define USB_DWC3(obj) \
20
LEDState *led[MPS2FPGAIO_MAX_LEDS];
21
OBJECT_CHECK(USBDWC3, (obj), TYPE_USB_DWC3)
21
uint32_t num_leds;
22
22
+ bool has_switches;
23
-#define USB_DWC3_R_MAX ((0x530 / 4) + 1)
23
24
+#define USB_DWC3_R_MAX (0x600 / 4)
24
uint32_t led0;
25
#define DWC3_SIZE 0x10000
25
uint32_t prescale;
26
26
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
27
typedef struct USBDWC3 {
28
diff --git a/hw/usb/hcd-dwc3.c b/hw/usb/hcd-dwc3.c
27
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/mps2-fpgaio.c
30
--- a/hw/usb/hcd-dwc3.c
29
+++ b/hw/misc/mps2-fpgaio.c
31
+++ b/hw/usb/hcd-dwc3.c
30
@@ -XXX,XX +XXX,XX @@ REG32(CLK100HZ, 0x14)
32
@@ -XXX,XX +XXX,XX @@ REG32(GFLADJ, 0x530)
31
REG32(COUNTER, 0x18)
33
FIELD(GFLADJ, GFLADJ_REFCLK_FLADJ, 8, 14)
32
REG32(PRESCALE, 0x1c)
34
FIELD(GFLADJ, GFLADJ_30MHZ_SDBND_SEL, 7, 1)
33
REG32(PSCNTR, 0x20)
35
FIELD(GFLADJ, GFLADJ_30MHZ, 0, 6)
34
+REG32(SWITCH, 0x28)
36
+REG32(GUSB2RHBCTL, 0x540)
35
REG32(MISC, 0x4c)
37
+ FIELD(GUSB2RHBCTL, OVRD_L1TIMEOUT, 0, 4)
36
38
37
static uint32_t counter_from_tickoff(int64_t now, int64_t tick_offset, int frq)
39
#define DWC3_GLOBAL_OFFSET 0xC100
38
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
40
static void reset_csr(USBDWC3 * s)
39
resync_counter(s);
41
@@ -XXX,XX +XXX,XX @@ static const RegisterAccessInfo usb_dwc3_regs_info[] = {
40
r = s->pscntr;
42
.rsvd = 0x40,
41
break;
43
.ro = 0x400040,
42
+ case A_SWITCH:
44
.unimp = 0xffffffff,
43
+ if (!s->has_switches) {
45
+ },{ .name = "GUSB2RHBCTL", .addr = A_GUSB2RHBCTL,
44
+ goto bad_offset;
46
+ .rsvd = 0xfffffff0,
45
+ }
47
+ .unimp = 0xffffffff,
46
+ /* User-togglable board switches. We don't model that, so report 0. */
48
}
47
+ r = 0;
48
+ break;
49
default:
50
+ bad_offset:
51
qemu_log_mask(LOG_GUEST_ERROR,
52
"MPS2 FPGAIO read: bad offset %x\n", (int) offset);
53
r = 0;
54
@@ -XXX,XX +XXX,XX @@ static Property mps2_fpgaio_properties[] = {
55
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
56
/* Number of LEDs controlled by LED0 register */
57
DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
58
+ DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
59
DEFINE_PROP_END_OF_LIST(),
60
};
49
};
61
50
62
--
51
--
63
2.20.1
52
2.43.0
64
65
diff view generated by jsdifflib
1
The AN524 has a USB controller (an ISP1763); we don't have a model of
1
From: Bernhard Beschow <shentey@gmail.com>
2
it but we should provide a stub "unimplemented-device" for it. This
3
is slightly complicated because the USB controller shares a PPC port
4
with the ethernet controller.
5
2
6
Implement a make_* function which provides creates a container
3
On the real device, the PCIe root bus is only connected to a PCIe bridge and
7
MemoryRegion with both the ethernet controller and an
4
does not allow for direct attachment of devices. Doing so in QEMU results in no
8
unimplemented-device stub for the USB controller.
5
PCI devices being detected by Linux. Instead, PCI devices should plug into the
6
secondary PCIe bus spawned by the internal PCIe bridge.
9
7
8
Unfortunately, QEMU defaults to plugging devices into the PCIe root bus. To work
9
around this, every PCI device created on the command line needs an extra
10
`bus=dw-pcie` option which is error prone. Fix that by marking the PCIe root bus
11
as full which makes QEMU decend into the child PCIe bus.
12
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Message-id: 20250223114708.1780-3-shentey@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210215115138.20465-22-peter.maydell@linaro.org
14
---
17
---
15
hw/arm/mps2-tz.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
18
include/hw/pci-host/designware.h | 7 +++++++
16
1 file changed, 47 insertions(+), 1 deletion(-)
19
hw/pci-host/designware.c | 18 +++++++++++++++++-
20
2 files changed, 24 insertions(+), 1 deletion(-)
17
21
18
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
22
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
19
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/mps2-tz.c
24
--- a/include/hw/pci-host/designware.h
21
+++ b/hw/arm/mps2-tz.c
25
+++ b/include/hw/pci-host/designware.h
22
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
26
@@ -XXX,XX +XXX,XX @@
23
27
#include "hw/pci/pci_bridge.h"
24
ARMSSE iotkit;
28
#include "qom/object.h"
25
MemoryRegion ram[MPS2TZ_RAM_MAX];
29
26
+ MemoryRegion eth_usb_container;
30
+#define TYPE_DESIGNWARE_PCIE_ROOT_BUS "designware-pcie-root-BUS"
31
+OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERootBus, DESIGNWARE_PCIE_ROOT_BUS)
27
+
32
+
28
MPS2SCC scc;
33
#define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host"
29
MPS2FPGAIO fpgaio;
34
OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST)
30
TZPPC ppc[5];
35
31
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
36
#define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
32
UnimplementedDeviceState gfx;
37
OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT)
33
UnimplementedDeviceState cldc;
38
34
UnimplementedDeviceState rtc;
39
+struct DesignwarePCIERootBus {
35
+ UnimplementedDeviceState usb;
40
+ PCIBus parent;
36
PL080State dma[4];
41
+};
37
TZMSC msc[4];
42
+
38
CMSDKAPBUART uart[6];
43
typedef struct DesignwarePCIEViewport {
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
44
DesignwarePCIERoot *root;
40
return sysbus_mmio_get_region(s, 0);
45
41
}
46
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
42
47
index XXXXXXX..XXXXXXX 100644
43
+static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
48
--- a/hw/pci-host/designware.c
44
+ const char *name, hwaddr size,
49
+++ b/hw/pci-host/designware.c
45
+ const int *irqs)
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)
46
+{
55
+{
47
+ /*
56
+ BusClass *k = BUS_CLASS(klass);
48
+ * The AN524 makes the ethernet and USB share a PPC port.
49
+ * irqs[] is the ethernet IRQ.
50
+ */
51
+ SysBusDevice *s;
52
+ NICInfo *nd = &nd_table[0];
53
+
54
+ memory_region_init(&mms->eth_usb_container, OBJECT(mms),
55
+ "mps2-tz-eth-usb-container", 0x200000);
56
+
57
+
57
+ /*
58
+ /*
58
+ * In hardware this is a LAN9220; the LAN9118 is software compatible
59
+ * Designware has only a single root complex. Enforce the limit on the
59
+ * except that it doesn't support the checksum-offload feature.
60
+ * parent bus
60
+ */
61
+ */
61
+ qemu_check_nic_model(nd, "lan9118");
62
+ k->max_dev = 1;
62
+ mms->lan9118 = qdev_new(TYPE_LAN9118);
63
+ qdev_set_nic_properties(mms->lan9118, nd);
64
+
65
+ s = SYS_BUS_DEVICE(mms->lan9118);
66
+ sysbus_realize_and_unref(s, &error_fatal);
67
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
68
+
69
+ memory_region_add_subregion(&mms->eth_usb_container,
70
+ 0, sysbus_mmio_get_region(s, 0));
71
+
72
+ /* The USB OTG controller is an ISP1763; we don't have a model of it. */
73
+ object_initialize_child(OBJECT(mms), "usb-otg",
74
+ &mms->usb, TYPE_UNIMPLEMENTED_DEVICE);
75
+ qdev_prop_set_string(DEVICE(&mms->usb), "name", "usb-otg");
76
+ qdev_prop_set_uint64(DEVICE(&mms->usb), "size", 0x100000);
77
+ s = SYS_BUS_DEVICE(&mms->usb);
78
+ sysbus_realize(s, &error_fatal);
79
+
80
+ memory_region_add_subregion(&mms->eth_usb_container,
81
+ 0x100000, sysbus_mmio_get_region(s, 0));
82
+
83
+ return &mms->eth_usb_container;
84
+}
63
+}
85
+
64
+
86
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
65
static DesignwarePCIEHost *
87
const char *name, hwaddr size,
66
designware_pcie_root_to_host(DesignwarePCIERoot *root)
88
const int *irqs)
67
{
89
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
68
@@ -XXX,XX +XXX,XX @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
90
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
69
&s->pci.memory,
91
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
70
&s->pci.io,
92
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
71
0, 4,
93
- { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
72
- TYPE_PCIE_BUS);
94
+ { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 48 } },
73
+ TYPE_DESIGNWARE_PCIE_ROOT_BUS);
95
},
74
pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
96
},
75
97
};
76
memory_region_init(&s->pci.address_space_root,
77
@@ -XXX,XX +XXX,XX @@ static void designware_pcie_host_init(Object *obj)
78
79
static const TypeInfo designware_pcie_types[] = {
80
{
81
+ .name = TYPE_DESIGNWARE_PCIE_ROOT_BUS,
82
+ .parent = TYPE_PCIE_BUS,
83
+ .instance_size = sizeof(DesignwarePCIERootBus),
84
+ .class_init = designware_pcie_root_bus_class_init,
85
+ }, {
86
.name = TYPE_DESIGNWARE_PCIE_HOST,
87
.parent = TYPE_PCI_HOST_BRIDGE,
88
.instance_size = sizeof(DesignwarePCIEHost),
98
--
89
--
99
2.20.1
90
2.43.0
100
101
diff view generated by jsdifflib
1
From: schspa <schspa@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
At the moment the following QEMU command line triggers an assertion
3
The move of the Kconfig bits to hw/gpio is fixing a bug in 6328d8ffa6cb9d
4
failure On xlnx-versal SOC:
4
("misc/pca955*: Move models under hw/gpio"), which moved the code but forgot to
5
qemu-system-aarch64 \
5
move the Kconfig sections.
6
-machine xlnx-versal-virt -nographic -smp 2 -m 128 \
7
-fsdev local,id=shareid,path=${HOME}/work,security_model=none \
8
-device virtio-9p-device,fsdev=shareid,mount_tag=share \
9
-fsdev local,id=shareid1,path=${HOME}/Music,security_model=none \
10
-device virtio-9p-device,fsdev=shareid1,mount_tag=share1
11
6
12
qemu-system-aarch64: ../migration/savevm.c:860:
7
Fixes: 6328d8ffa6cb9d "misc/pca955*: Move models under hw/gpio"
13
vmstate_register_with_alias_id:
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
14
Assertion `!se->compat || se->instance_id == 0' failed.
9
Message-id: 20250223114708.1780-4-shentey@gmail.com
15
16
This problem was fixed on arm virt platform in commit f58b39d2d5b
17
("virtio-mmio: format transport base address in BusClass.get_dev_path")
18
19
It works perfectly on arm virt platform. but there is still there on
20
xlnx-versal SOC.
21
22
The main difference between arm virt and xlnx-versal is they use
23
different way to create virtio-mmio qdev. on arm virt, it calls
24
sysbus_create_simple("virtio-mmio", base, pic[irq]); which will call
25
sysbus_mmio_map internally and assign base address to subsys device
26
mmio correctly. but xlnx-versal's implements won't do this.
27
28
However, xlnx-versal can't switch to sysbus_create_simple() to create
29
virtio-mmio device. It's because xlnx-versal's cpu use
30
VersalVirt.soc.fpd.apu.mr as it's memory. which is subregion of
31
system_memory. sysbus_create_simple will add virtio to system_memory,
32
which can't be accessed by cpu.
33
34
Besides, xlnx-versal can't add sysbus_mmio_map api call too, because
35
this will add memory region to system_memory, and it can't be added
36
to VersalVirt.soc.fpd.apu.mr again.
37
38
We can solve this by assign correct base address offset on dev_path.
39
40
This path was test on aarch64 virt & xlnx-versal platform.
41
42
Signed-off-by: schspa <schspa@gmail.com>
43
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
44
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
45
---
12
---
46
hw/virtio/virtio-mmio.c | 13 +++++++------
13
hw/gpio/Kconfig | 8 ++++++++
47
1 file changed, 7 insertions(+), 6 deletions(-)
14
hw/misc/Kconfig | 8 --------
15
2 files changed, 8 insertions(+), 8 deletions(-)
48
16
49
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
17
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
50
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/virtio/virtio-mmio.c
19
--- a/hw/gpio/Kconfig
52
+++ b/hw/virtio/virtio-mmio.c
20
+++ b/hw/gpio/Kconfig
53
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
21
@@ -XXX,XX +XXX,XX @@ config SIFIVE_GPIO
54
BusState *virtio_mmio_bus;
22
config STM32L4X5_GPIO
55
VirtIOMMIOProxy *virtio_mmio_proxy;
23
bool
56
char *proxy_path;
24
57
- SysBusDevice *proxy_sbd;
25
+config PCA9552
58
char *path;
26
+ bool
59
+ MemoryRegionSection section;
27
+ depends on I2C
60
61
virtio_mmio_bus = qdev_get_parent_bus(dev);
62
virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
63
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
64
}
65
66
/* Otherwise, we append the base address of the transport. */
67
- proxy_sbd = SYS_BUS_DEVICE(virtio_mmio_proxy);
68
- assert(proxy_sbd->num_mmio == 1);
69
- assert(proxy_sbd->mmio[0].memory == &virtio_mmio_proxy->iomem);
70
+ section = memory_region_find(&virtio_mmio_proxy->iomem, 0, 0x200);
71
+ assert(section.mr);
72
73
if (proxy_path) {
74
path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path,
75
- proxy_sbd->mmio[0].addr);
76
+ section.offset_within_address_space);
77
} else {
78
path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx,
79
- proxy_sbd->mmio[0].addr);
80
+ section.offset_within_address_space);
81
}
82
+ memory_region_unref(section.mr);
83
+
28
+
84
g_free(proxy_path);
29
+config PCA9554
85
return path;
30
+ bool
86
}
31
+ depends on I2C
32
+
33
config PCF8574
34
bool
35
depends on I2C
36
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/misc/Kconfig
39
+++ b/hw/misc/Kconfig
40
@@ -XXX,XX +XXX,XX @@ config EDU
41
default y if TEST_DEVICES
42
depends on PCI && MSI_NONBROKEN
43
44
-config PCA9552
45
- bool
46
- depends on I2C
47
-
48
-config PCA9554
49
- bool
50
- depends on I2C
51
-
52
config I2C_ECHO
53
bool
54
default y if TEST_DEVICES
87
--
55
--
88
2.20.1
56
2.43.0
89
90
diff view generated by jsdifflib
1
Add support for the mps3-an524 board; this is an SSE-200 based FPGA
1
From: Bernhard Beschow <shentey@gmail.com>
2
image, like the existing mps2-an521. It has a usefully larger amount
3
of RAM, and a PL031 RTC, as well as some more minor differences.
4
2
5
In real hardware this image runs on a newer generation of the FPGA
3
As a first step, implement the bare minimum: CPUs, RAM, interrupt controller,
6
board, the MPS3 rather than the older MPS2. Architecturally the two
4
serial. All other devices of the A53 memory map are represented as
7
boards are similar, so we implement the MPS3 boards in the mps2-tz.c
5
TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows
8
file as variations of the existing MPS2 boards.
6
for running Linux without it crashing due to invalid memory accesses.
9
7
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 20250223114708.1780-5-shentey@gmail.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: drop 'static const' from serial_table[] definition to avoid
12
compile failure on GCC 7.5]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210215115138.20465-21-peter.maydell@linaro.org
13
---
14
---
14
hw/arm/mps2-tz.c | 139 +++++++++++++++++++++++++++++++++++++++++++++--
15
MAINTAINERS | 9 +
15
1 file changed, 135 insertions(+), 4 deletions(-)
16
docs/system/arm/imx8mp-evk.rst | 54 +++++
17
docs/system/target-arm.rst | 1 +
18
include/hw/arm/fsl-imx8mp.h | 189 +++++++++++++++++
19
hw/arm/fsl-imx8mp.c | 367 +++++++++++++++++++++++++++++++++
20
hw/arm/imx8mp-evk.c | 55 +++++
21
hw/arm/Kconfig | 12 ++
22
hw/arm/meson.build | 2 +
23
8 files changed, 689 insertions(+)
24
create mode 100644 docs/system/arm/imx8mp-evk.rst
25
create mode 100644 include/hw/arm/fsl-imx8mp.h
26
create mode 100644 hw/arm/fsl-imx8mp.c
27
create mode 100644 hw/arm/imx8mp-evk.c
16
28
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
29
diff --git a/MAINTAINERS b/MAINTAINERS
18
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2-tz.c
31
--- a/MAINTAINERS
20
+++ b/hw/arm/mps2-tz.c
32
+++ b/MAINTAINERS
33
@@ -XXX,XX +XXX,XX @@ F: hw/pci-host/designware.c
34
F: include/hw/pci-host/designware.h
35
F: docs/system/arm/mcimx7d-sabre.rst
36
37
+MCIMX8MP-EVK / i.MX8MP
38
+M: Bernhard Beschow <shentey@gmail.com>
39
+L: qemu-arm@nongnu.org
40
+S: Maintained
41
+F: hw/arm/imx8mp-evk.c
42
+F: hw/arm/fsl-imx8mp.c
43
+F: include/hw/arm/fsl-imx8mp.h
44
+F: docs/system/arm/imx8mp-evk.rst
45
+
46
MPS2 / MPS3
47
M: Peter Maydell <peter.maydell@linaro.org>
48
L: qemu-arm@nongnu.org
49
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
50
new file mode 100644
51
index XXXXXXX..XXXXXXX
52
--- /dev/null
53
+++ b/docs/system/arm/imx8mp-evk.rst
21
@@ -XXX,XX +XXX,XX @@
54
@@ -XXX,XX +XXX,XX @@
22
* This source file covers the following FPGA images, for TrustZone cores:
55
+NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
23
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
56
+================================================
24
* "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
57
+
25
+ * "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
58
+The ``imx8mp-evk`` machine models the i.MX 8M Plus Evaluation Kit, based on an
26
*
59
+i.MX 8M Plus SoC.
27
* Links to the TRM for the board itself and to the various Application
60
+
28
* Notes which document the FPGA images can be found here:
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
29
@@ -XXX,XX +XXX,XX @@
126
@@ -XXX,XX +XXX,XX @@
30
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
127
+/*
31
* Application Note AN521:
128
+ * i.MX 8M Plus SoC Definitions
32
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
129
+ *
33
+ * Application Note AN524:
130
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
34
+ * https://developer.arm.com/documentation/dai0524/latest/
131
+ *
35
*
132
+ * SPDX-License-Identifier: GPL-2.0-or-later
36
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
133
+ */
37
* (ARM ECM0601256) for the details of some of the device layout:
134
+
38
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
135
+#ifndef FSL_IMX8MP_H
39
- * Similarly, the AN521 uses the SSE-200, and the SSE-200 TRM defines
136
+#define FSL_IMX8MP_H
40
+ * Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
137
+
41
* most of the device layout:
138
+#include "cpu.h"
42
* http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
139
+#include "hw/char/imx_serial.h"
43
*
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
44
@@ -XXX,XX +XXX,XX @@
321
@@ -XXX,XX +XXX,XX @@
45
#include "hw/qdev-clock.h"
322
+/*
46
#include "qom/object.h"
323
+ * i.MX 8M Plus SoC Implementation
47
324
+ *
48
-#define MPS2TZ_NUMIRQ_MAX 92
325
+ * Based on hw/arm/fsl-imx6.c
49
+#define MPS2TZ_NUMIRQ_MAX 95
326
+ *
50
#define MPS2TZ_RAM_MAX 4
327
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
51
328
+ *
52
typedef enum MPS2TZFPGAType {
329
+ * SPDX-License-Identifier: GPL-2.0-or-later
53
FPGA_AN505,
330
+ */
54
FPGA_AN521,
331
+
55
+ FPGA_AN524,
332
+#include "qemu/osdep.h"
56
} MPS2TZFPGAType;
333
+#include "exec/address-spaces.h"
57
334
+#include "hw/arm/bsa.h"
58
/*
335
+#include "hw/arm/fsl-imx8mp.h"
59
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
336
+#include "hw/intc/arm_gicv3.h"
60
TZPPC ppc[5];
337
+#include "hw/misc/unimp.h"
61
TZMPC mpc[3];
338
+#include "hw/boards.h"
62
PL022State spi[5];
339
+#include "system/system.h"
63
- ArmSbconI2CState i2c[4];
340
+#include "target/arm/cpu-qom.h"
64
+ ArmSbconI2CState i2c[5];
341
+#include "qapi/error.h"
65
UnimplementedDeviceState i2s_audio;
342
+#include "qobject/qlist.h"
66
UnimplementedDeviceState gpio[4];
343
+
67
UnimplementedDeviceState gfx;
344
+static const struct {
68
+ UnimplementedDeviceState cldc;
345
+ hwaddr addr;
69
+ UnimplementedDeviceState rtc;
346
+ size_t size;
70
PL080State dma[4];
347
+ const char *name;
71
TZMSC msc[4];
348
+} fsl_imx8mp_memmap[] = {
72
- CMSDKAPBUART uart[5];
349
+ [FSL_IMX8MP_RAM] = { FSL_IMX8MP_RAM_START, FSL_IMX8MP_RAM_SIZE_MAX, "ram" },
73
+ CMSDKAPBUART uart[6];
350
+ [FSL_IMX8MP_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
74
SplitIRQ sec_resp_splitter;
351
+ [FSL_IMX8MP_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
75
qemu_or_irq uart_irq_orgate;
352
+ [FSL_IMX8MP_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
76
DeviceState *lan9118;
353
+ [FSL_IMX8MP_DDR_BLK_CTRL] = { 0x3d000000, 1 * MiB, "ddr_blk_ctrl" },
77
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
354
+ [FSL_IMX8MP_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
78
#define TYPE_MPS2TZ_MACHINE "mps2tz"
355
+ [FSL_IMX8MP_AUDIO_DSP] = { 0x3b000000, 16 * MiB, "audio_dsp" },
79
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
356
+ [FSL_IMX8MP_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
80
#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
357
+ [FSL_IMX8MP_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
81
+#define TYPE_MPS3TZ_AN524_MACHINE MACHINE_TYPE_NAME("mps3-an524")
358
+ [FSL_IMX8MP_NPU] = { 0x38500000, 2 * MiB, "npu" },
82
359
+ [FSL_IMX8MP_VPU] = { 0x38340000, 2 * MiB, "vpu" },
83
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
360
+ [FSL_IMX8MP_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
84
361
+ [FSL_IMX8MP_VPU_VC8000E_ENCODER] = { 0x38320000, 2 * MiB, "vpu_vc8000e_encoder" },
85
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
362
+ [FSL_IMX8MP_VPU_G2_DECODER] = { 0x38310000, 2 * MiB, "vpu_g2_decoder" },
86
25000000,
363
+ [FSL_IMX8MP_VPU_G1_DECODER] = { 0x38300000, 2 * MiB, "vpu_g1_decoder" },
87
};
364
+ [FSL_IMX8MP_USB2] = { 0x38200000, 1 * MiB, "usb2" },
88
365
+ [FSL_IMX8MP_USB1] = { 0x38100000, 1 * MiB, "usb1" },
89
+static const uint32_t an524_oscclk[] = {
366
+ [FSL_IMX8MP_GPU2D] = { 0x38008000, 32 * KiB, "gpu2d" },
90
+ 24000000,
367
+ [FSL_IMX8MP_GPU3D] = { 0x38000000, 32 * KiB, "gpu3d" },
91
+ 32000000,
368
+ [FSL_IMX8MP_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
92
+ 50000000,
369
+ [FSL_IMX8MP_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
93
+ 50000000,
370
+ [FSL_IMX8MP_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
94
+ 24576000,
371
+ [FSL_IMX8MP_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
95
+ 23750000,
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" },
96
+};
505
+};
97
+
506
+
98
static const RAMInfo an505_raminfo[] = { {
507
+static void fsl_imx8mp_init(Object *obj)
99
.name = "ssram-0",
508
+{
100
.base = 0x00000000,
509
+ MachineState *ms = MACHINE(qdev_get_machine());
101
@@ -XXX,XX +XXX,XX @@ static const RAMInfo an505_raminfo[] = { {
510
+ FslImx8mpState *s = FSL_IMX8MP(obj);
102
},
511
+ int i;
103
};
512
+
104
513
+ for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MP_NUM_CPUS); i++) {
105
+static const RAMInfo an524_raminfo[] = { {
514
+ g_autofree char *name = g_strdup_printf("cpu%d", i);
106
+ .name = "bram",
515
+ object_initialize_child(obj, name, &s->cpu[i],
107
+ .base = 0x00000000,
516
+ ARM_CPU_TYPE_NAME("cortex-a53"));
108
+ .size = 512 * KiB,
517
+ }
109
+ .mpc = 0,
518
+
110
+ .mrindex = 0,
519
+ object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
111
+ }, {
520
+
112
+ .name = "sram",
521
+ for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
113
+ .base = 0x20000000,
522
+ g_autofree char *name = g_strdup_printf("uart%d", i + 1);
114
+ .size = 32 * 4 * KiB,
523
+ object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
115
+ .mpc = 1,
524
+ }
116
+ .mrindex = 1,
525
+}
117
+ }, {
526
+
118
+ /* We don't model QSPI flash yet; for now expose it as simple ROM */
527
+static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
119
+ .name = "QSPI",
528
+{
120
+ .base = 0x28000000,
529
+ MachineState *ms = MACHINE(qdev_get_machine());
121
+ .size = 8 * MiB,
530
+ FslImx8mpState *s = FSL_IMX8MP(dev);
122
+ .mpc = 1,
531
+ DeviceState *gicdev = DEVICE(&s->gic);
123
+ .mrindex = 2,
532
+ int i;
124
+ .flags = IS_ROM,
533
+
125
+ }, {
534
+ if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) {
126
+ .name = "DDR",
535
+ error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
127
+ .base = 0x60000000,
536
+ TYPE_FSL_IMX8MP, FSL_IMX8MP_NUM_CPUS, ms->smp.cpus);
128
+ .size = 2 * GiB,
537
+ return;
129
+ .mpc = 2,
538
+ }
130
+ .mrindex = -1,
539
+
131
+ }, {
540
+ /* CPUs */
132
+ .name = NULL,
541
+ for (i = 0; i < ms->smp.cpus; i++) {
542
+ /* On uniprocessor, the CBAR is set to 0 */
543
+ if (ms->smp.cpus > 1) {
544
+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
545
+ fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr,
546
+ &error_abort);
547
+ }
548
+
549
+ /*
550
+ * CNTFID0 base frequency in Hz of system counter
551
+ */
552
+ object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
553
+ &error_abort);
554
+
555
+ if (i) {
556
+ /*
557
+ * Secondary CPUs start in powered-down state (and can be
558
+ * powered up via the SRC system reset controller)
559
+ */
560
+ object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
561
+ true, &error_abort);
562
+ }
563
+
564
+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
565
+ return;
566
+ }
567
+ }
568
+
569
+ /* GIC */
570
+ {
571
+ SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
572
+ QList *redist_region_count;
573
+
574
+ qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
575
+ qdev_prop_set_uint32(gicdev, "num-irq",
576
+ FSL_IMX8MP_NUM_IRQS + GIC_INTERNAL);
577
+ redist_region_count = qlist_new();
578
+ qlist_append_int(redist_region_count, ms->smp.cpus);
579
+ qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
580
+ object_property_set_link(OBJECT(&s->gic), "sysmem",
581
+ OBJECT(get_system_memory()), &error_fatal);
582
+ if (!sysbus_realize(gicsbd, errp)) {
583
+ return;
584
+ }
585
+ sysbus_mmio_map(gicsbd, 0, fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr);
586
+ sysbus_mmio_map(gicsbd, 1, fsl_imx8mp_memmap[FSL_IMX8MP_GIC_REDIST].addr);
587
+
588
+ /*
589
+ * Wire the outputs from each CPU's generic timer and the GICv3
590
+ * maintenance interrupt signal to the appropriate GIC PPI inputs, and
591
+ * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
592
+ */
593
+ for (i = 0; i < ms->smp.cpus; i++) {
594
+ DeviceState *cpudev = DEVICE(&s->cpu[i]);
595
+ int intidbase = FSL_IMX8MP_NUM_IRQS + i * GIC_INTERNAL;
596
+ qemu_irq irq;
597
+
598
+ /*
599
+ * Mapping from the output timer irq lines from the CPU to the
600
+ * GIC PPI inputs.
601
+ */
602
+ static const int timer_irqs[] = {
603
+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
604
+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
605
+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
606
+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
607
+ };
608
+
609
+ for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
610
+ irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
611
+ qdev_connect_gpio_out(cpudev, j, irq);
612
+ }
613
+
614
+ irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
615
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
616
+ 0, irq);
617
+
618
+ irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
619
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, irq);
620
+
621
+ sysbus_connect_irq(gicsbd, i,
622
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
623
+ sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
624
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
625
+ }
626
+ }
627
+
628
+ /* UARTs */
629
+ for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
630
+ struct {
631
+ hwaddr addr;
632
+ unsigned int irq;
633
+ } serial_table[FSL_IMX8MP_NUM_UARTS] = {
634
+ { fsl_imx8mp_memmap[FSL_IMX8MP_UART1].addr, FSL_IMX8MP_UART1_IRQ },
635
+ { fsl_imx8mp_memmap[FSL_IMX8MP_UART2].addr, FSL_IMX8MP_UART2_IRQ },
636
+ { fsl_imx8mp_memmap[FSL_IMX8MP_UART3].addr, FSL_IMX8MP_UART3_IRQ },
637
+ { fsl_imx8mp_memmap[FSL_IMX8MP_UART4].addr, FSL_IMX8MP_UART4_IRQ },
638
+ };
639
+
640
+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
641
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
642
+ return;
643
+ }
644
+
645
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
646
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
647
+ qdev_get_gpio_in(gicdev, serial_table[i].irq));
648
+ }
649
+
650
+ /* Unimplemented devices */
651
+ for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
652
+ switch (i) {
653
+ case FSL_IMX8MP_GIC_DIST:
654
+ case FSL_IMX8MP_GIC_REDIST:
655
+ case FSL_IMX8MP_RAM:
656
+ case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
657
+ /* device implemented and treated above */
658
+ break;
659
+
660
+ default:
661
+ create_unimplemented_device(fsl_imx8mp_memmap[i].name,
662
+ fsl_imx8mp_memmap[i].addr,
663
+ fsl_imx8mp_memmap[i].size);
664
+ break;
665
+ }
666
+ }
667
+}
668
+
669
+static void fsl_imx8mp_class_init(ObjectClass *oc, void *data)
670
+{
671
+ DeviceClass *dc = DEVICE_CLASS(oc);
672
+
673
+ dc->realize = fsl_imx8mp_realize;
674
+
675
+ dc->desc = "i.MX 8M Plus SoC";
676
+}
677
+
678
+static const TypeInfo fsl_imx8mp_types[] = {
679
+ {
680
+ .name = TYPE_FSL_IMX8MP,
681
+ .parent = TYPE_DEVICE,
682
+ .instance_size = sizeof(FslImx8mpState),
683
+ .instance_init = fsl_imx8mp_init,
684
+ .class_init = fsl_imx8mp_class_init,
133
+ },
685
+ },
134
+};
686
+};
135
+
687
+
136
static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
688
+DEFINE_TYPES(fsl_imx8mp_types)
137
{
689
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
138
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
690
new file mode 100644
139
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
691
index XXXXXXX..XXXXXXX
140
},
692
--- /dev/null
141
};
693
+++ b/hw/arm/imx8mp-evk.c
142
694
@@ -XXX,XX +XXX,XX @@
143
+ const PPCInfo an524_ppcs[] = { {
695
+/*
144
+ .name = "apb_ppcexp0",
696
+ * NXP i.MX 8M Plus Evaluation Kit System Emulation
145
+ .ports = {
697
+ *
146
+ { "bram-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
698
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
147
+ { "qspi-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
699
+ *
148
+ { "ddr-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
700
+ * SPDX-License-Identifier: GPL-2.0-or-later
149
+ },
701
+ */
150
+ }, {
702
+
151
+ .name = "apb_ppcexp1",
703
+#include "qemu/osdep.h"
152
+ .ports = {
704
+#include "exec/address-spaces.h"
153
+ { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000 },
705
+#include "hw/arm/boot.h"
154
+ { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000 },
706
+#include "hw/arm/fsl-imx8mp.h"
155
+ { "spi0", make_spi, &mms->spi[0], 0x41202000, 0x1000, { 52 } },
707
+#include "hw/boards.h"
156
+ { "spi1", make_spi, &mms->spi[1], 0x41203000, 0x1000, { 53 } },
708
+#include "system/qtest.h"
157
+ { "spi2", make_spi, &mms->spi[2], 0x41204000, 0x1000, { 54 } },
709
+#include "qemu/error-report.h"
158
+ { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000 },
710
+#include "qapi/error.h"
159
+ { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000 },
711
+
160
+ { /* port 7 reserved */ },
712
+static void imx8mp_evk_init(MachineState *machine)
161
+ { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000 },
713
+{
162
+ },
714
+ static struct arm_boot_info boot_info;
163
+ }, {
715
+ FslImx8mpState *s;
164
+ .name = "apb_ppcexp2",
716
+
165
+ .ports = {
717
+ if (machine->ram_size > FSL_IMX8MP_RAM_SIZE_MAX) {
166
+ { "scc", make_scc, &mms->scc, 0x41300000, 0x1000 },
718
+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
167
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
719
+ machine->ram_size, FSL_IMX8MP_RAM_SIZE_MAX);
168
+ 0x41301000, 0x1000 },
720
+ exit(1);
169
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x41302000, 0x1000 },
721
+ }
170
+ { "uart0", make_uart, &mms->uart[0], 0x41303000, 0x1000, { 32, 33, 42 } },
722
+
171
+ { "uart1", make_uart, &mms->uart[1], 0x41304000, 0x1000, { 34, 35, 43 } },
723
+ boot_info = (struct arm_boot_info) {
172
+ { "uart2", make_uart, &mms->uart[2], 0x41305000, 0x1000, { 36, 37, 44 } },
724
+ .loader_start = FSL_IMX8MP_RAM_START,
173
+ { "uart3", make_uart, &mms->uart[3], 0x41306000, 0x1000, { 38, 39, 45 } },
725
+ .board_id = -1,
174
+ { "uart4", make_uart, &mms->uart[4], 0x41307000, 0x1000, { 40, 41, 46 } },
726
+ .ram_size = machine->ram_size,
175
+ { "uart5", make_uart, &mms->uart[5], 0x41308000, 0x1000, { 124, 125, 126 } },
727
+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
176
+
177
+ { /* port 9 reserved */ },
178
+ { "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
179
+ { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
180
+ },
181
+ }, {
182
+ .name = "ahb_ppcexp0",
183
+ .ports = {
184
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
185
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
186
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
187
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
188
+ { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
189
+ },
190
+ },
191
+ };
728
+ };
192
+
729
+
193
switch (mmc->fpga_type) {
730
+ s = FSL_IMX8MP(object_new(TYPE_FSL_IMX8MP));
194
case FPGA_AN505:
731
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
195
case FPGA_AN521:
732
+ qdev_realize(DEVICE(s), NULL, &error_fatal);
196
ppcs = an505_ppcs;
733
+
197
num_ppcs = ARRAY_SIZE(an505_ppcs);
734
+ memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
198
break;
735
+ machine->ram);
199
+ case FPGA_AN524:
736
+
200
+ ppcs = an524_ppcs;
737
+ if (!qtest_enabled()) {
201
+ num_ppcs = ARRAY_SIZE(an524_ppcs);
738
+ arm_load_kernel(&s->cpu[0], machine, &boot_info);
202
+ break;
739
+ }
203
default:
740
+}
204
g_assert_not_reached();
741
+
205
}
742
+static void imx8mp_evk_machine_init(MachineClass *mc)
206
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
207
mps2tz_set_default_ram_info(mmc);
208
}
209
210
+static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
211
+{
743
+{
212
+ MachineClass *mc = MACHINE_CLASS(oc);
744
+ mc->desc = "NXP i.MX 8M Plus EVK Board";
213
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
745
+ mc->init = imx8mp_evk_init;
214
+
746
+ mc->max_cpus = FSL_IMX8MP_NUM_CPUS;
215
+ mc->desc = "ARM MPS3 with AN524 FPGA image for dual Cortex-M33";
747
+ mc->default_ram_id = "imx8mp-evk.ram";
216
+ mc->default_cpus = 2;
217
+ mc->min_cpus = mc->default_cpus;
218
+ mc->max_cpus = mc->default_cpus;
219
+ mmc->fpga_type = FPGA_AN524;
220
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
221
+ mmc->scc_id = 0x41045240;
222
+ mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
223
+ mmc->oscclk = an524_oscclk;
224
+ mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
225
+ mmc->fpgaio_num_leds = 10;
226
+ mmc->fpgaio_has_switches = true;
227
+ mmc->numirq = 95;
228
+ mmc->raminfo = an524_raminfo;
229
+ mmc->armsse_type = TYPE_SSE200;
230
+ mps2tz_set_default_ram_info(mmc);
231
+}
748
+}
232
+
749
+DEFINE_MACHINE("imx8mp-evk", imx8mp_evk_machine_init)
233
static const TypeInfo mps2tz_info = {
750
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
234
.name = TYPE_MPS2TZ_MACHINE,
751
index XXXXXXX..XXXXXXX 100644
235
.parent = TYPE_MACHINE,
752
--- a/hw/arm/Kconfig
236
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2tz_an521_info = {
753
+++ b/hw/arm/Kconfig
237
.class_init = mps2tz_an521_class_init,
754
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
238
};
755
select UNIMP
239
756
select USB_CHIPIDEA
240
+static const TypeInfo mps3tz_an524_info = {
757
241
+ .name = TYPE_MPS3TZ_AN524_MACHINE,
758
+config FSL_IMX8MP
242
+ .parent = TYPE_MPS2TZ_MACHINE,
759
+ bool
243
+ .class_init = mps3tz_an524_class_init,
760
+ select ARM_GIC
244
+};
761
+ select IMX
245
+
762
+ select UNIMP
246
static void mps2tz_machine_init(void)
763
+
247
{
764
+config FSL_IMX8MP_EVK
248
type_register_static(&mps2tz_info);
765
+ bool
249
type_register_static(&mps2tz_an505_info);
766
+ default y
250
type_register_static(&mps2tz_an521_info);
767
+ depends on TCG && AARCH64
251
+ type_register_static(&mps3tz_an524_info);
768
+ select FSL_IMX8MP
252
}
769
+
253
770
config ARM_SMMUV3
254
type_init(mps2tz_machine_init);
771
bool
772
773
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
774
index XXXXXXX..XXXXXXX 100644
775
--- a/hw/arm/meson.build
776
+++ b/hw/arm/meson.build
777
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c'))
778
arm_ss.add(when: 'CONFIG_MUSCA', if_true: files('musca.c'))
779
arm_ss.add(when: 'CONFIG_ARMSSE', if_true: files('armsse.c'))
780
arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.c'))
781
+arm_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true: files('fsl-imx8mp.c'))
782
+arm_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true: files('imx8mp-evk.c'))
783
arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
784
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
785
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
255
--
786
--
256
2.20.1
787
2.43.0
257
258
diff view generated by jsdifflib
1
From: Doug Evans <dje@google.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
This is a 10/100 ethernet device that has several features.
3
Fixes quite a few stack traces during the Linux boot process. Also provides the
4
Only the ones needed by the Linux driver have been implemented.
4
clocks for devices added later, e.g. enet1.
5
See npcm7xx_emc.c for a list of unimplemented features.
6
5
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
7
Message-id: 20250223114708.1780-6-shentey@gmail.com
9
Signed-off-by: Doug Evans <dje@google.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20210218212453.831406-2-dje@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
include/hw/net/npcm7xx_emc.h | 286 ++++++++++++
11
MAINTAINERS | 2 +
14
hw/net/npcm7xx_emc.c | 857 +++++++++++++++++++++++++++++++++++
12
docs/system/arm/imx8mp-evk.rst | 1 +
15
hw/net/meson.build | 1 +
13
include/hw/arm/fsl-imx8mp.h | 4 +
16
hw/net/trace-events | 17 +
14
include/hw/misc/imx8mp_analog.h | 81 +++++++++++++++
17
4 files changed, 1161 insertions(+)
15
include/hw/misc/imx8mp_ccm.h | 30 ++++++
18
create mode 100644 include/hw/net/npcm7xx_emc.h
16
hw/arm/fsl-imx8mp.c | 20 ++++
19
create mode 100644 hw/net/npcm7xx_emc.c
17
hw/misc/imx8mp_analog.c | 160 +++++++++++++++++++++++++++++
18
hw/misc/imx8mp_ccm.c | 175 ++++++++++++++++++++++++++++++++
19
hw/arm/Kconfig | 2 +
20
hw/misc/Kconfig | 6 ++
21
hw/misc/meson.build | 2 +
22
11 files changed, 483 insertions(+)
23
create mode 100644 include/hw/misc/imx8mp_analog.h
24
create mode 100644 include/hw/misc/imx8mp_ccm.h
25
create mode 100644 hw/misc/imx8mp_analog.c
26
create mode 100644 hw/misc/imx8mp_ccm.c
20
27
21
diff --git a/include/hw/net/npcm7xx_emc.h b/include/hw/net/npcm7xx_emc.h
28
diff --git a/MAINTAINERS b/MAINTAINERS
29
index XXXXXXX..XXXXXXX 100644
30
--- a/MAINTAINERS
31
+++ b/MAINTAINERS
32
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
33
S: Maintained
34
F: hw/arm/imx8mp-evk.c
35
F: hw/arm/fsl-imx8mp.c
36
+F: hw/misc/imx8mp_*.c
37
F: include/hw/arm/fsl-imx8mp.h
38
+F: include/hw/misc/imx8mp_*.h
39
F: docs/system/arm/imx8mp-evk.rst
40
41
MPS2 / MPS3
42
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
43
index XXXXXXX..XXXXXXX 100644
44
--- a/docs/system/arm/imx8mp-evk.rst
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
58
@@ -XXX,XX +XXX,XX @@
59
#include "cpu.h"
60
#include "hw/char/imx_serial.h"
61
#include "hw/intc/arm_gicv3_common.h"
62
+#include "hw/misc/imx8mp_analog.h"
63
+#include "hw/misc/imx8mp_ccm.h"
64
#include "qom/object.h"
65
#include "qemu/units.h"
66
67
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
68
69
ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
70
GICv3State gic;
71
+ IMX8MPCCMState ccm;
72
+ IMX8MPAnalogState analog;
73
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
74
};
75
76
diff --git a/include/hw/misc/imx8mp_analog.h b/include/hw/misc/imx8mp_analog.h
22
new file mode 100644
77
new file mode 100644
23
index XXXXXXX..XXXXXXX
78
index XXXXXXX..XXXXXXX
24
--- /dev/null
79
--- /dev/null
25
+++ b/include/hw/net/npcm7xx_emc.h
80
+++ b/include/hw/misc/imx8mp_analog.h
26
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
27
+/*
82
+/*
28
+ * Nuvoton NPCM7xx EMC Module
83
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
29
+ *
84
+ *
30
+ * Copyright 2020 Google LLC
85
+ * i.MX8MP ANALOG IP block emulation code
31
+ *
86
+ *
32
+ * This program is free software; you can redistribute it and/or modify it
87
+ * SPDX-License-Identifier: GPL-2.0-or-later
33
+ * under the terms of the GNU General Public License as published by the
34
+ * Free Software Foundation; either version 2 of the License, or
35
+ * (at your option) any later version.
36
+ *
37
+ * This program is distributed in the hope that it will be useful, but WITHOUT
38
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
39
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40
+ * for more details.
41
+ */
88
+ */
42
+
89
+
43
+#ifndef NPCM7XX_EMC_H
90
+#ifndef IMX8MP_ANALOG_H
44
+#define NPCM7XX_EMC_H
91
+#define IMX8MP_ANALOG_H
45
+
92
+
46
+#include "hw/irq.h"
93
+#include "qom/object.h"
47
+#include "hw/sysbus.h"
94
+#include "hw/sysbus.h"
48
+#include "net/net.h"
95
+
49
+
96
+enum IMX8MPAnalogRegisters {
50
+/* 32-bit register indices. */
97
+ ANALOG_AUDIO_PLL1_GEN_CTRL = 0x000 / 4,
51
+enum NPCM7xxPWMRegister {
98
+ ANALOG_AUDIO_PLL1_FDIV_CTL0 = 0x004 / 4,
52
+ /* Control registers. */
99
+ ANALOG_AUDIO_PLL1_FDIV_CTL1 = 0x008 / 4,
53
+ REG_CAMCMR,
100
+ ANALOG_AUDIO_PLL1_SSCG_CTRL = 0x00c / 4,
54
+ REG_CAMEN,
101
+ ANALOG_AUDIO_PLL1_MNIT_CTRL = 0x010 / 4,
55
+
102
+ ANALOG_AUDIO_PLL2_GEN_CTRL = 0x014 / 4,
56
+ /* There are 16 CAMn[ML] registers. */
103
+ ANALOG_AUDIO_PLL2_FDIV_CTL0 = 0x018 / 4,
57
+ REG_CAMM_BASE,
104
+ ANALOG_AUDIO_PLL2_FDIV_CTL1 = 0x01c / 4,
58
+ REG_CAML_BASE,
105
+ ANALOG_AUDIO_PLL2_SSCG_CTRL = 0x020 / 4,
59
+ REG_CAMML_LAST = 0x21,
106
+ ANALOG_AUDIO_PLL2_MNIT_CTRL = 0x024 / 4,
60
+
107
+ ANALOG_VIDEO_PLL1_GEN_CTRL = 0x028 / 4,
61
+ REG_TXDLSA = 0x22,
108
+ ANALOG_VIDEO_PLL1_FDIV_CTL0 = 0x02c / 4,
62
+ REG_RXDLSA,
109
+ ANALOG_VIDEO_PLL1_FDIV_CTL1 = 0x030 / 4,
63
+ REG_MCMDR,
110
+ ANALOG_VIDEO_PLL1_SSCG_CTRL = 0x034 / 4,
64
+ REG_MIID,
111
+ ANALOG_VIDEO_PLL1_MNIT_CTRL = 0x038 / 4,
65
+ REG_MIIDA,
112
+ ANALOG_DRAM_PLL_GEN_CTRL = 0x050 / 4,
66
+ REG_FFTCR,
113
+ ANALOG_DRAM_PLL_FDIV_CTL0 = 0x054 / 4,
67
+ REG_TSDR,
114
+ ANALOG_DRAM_PLL_FDIV_CTL1 = 0x058 / 4,
68
+ REG_RSDR,
115
+ ANALOG_DRAM_PLL_SSCG_CTRL = 0x05c / 4,
69
+ REG_DMARFC,
116
+ ANALOG_DRAM_PLL_MNIT_CTRL = 0x060 / 4,
70
+ REG_MIEN,
117
+ ANALOG_GPU_PLL_GEN_CTRL = 0x064 / 4,
71
+
118
+ ANALOG_GPU_PLL_FDIV_CTL0 = 0x068 / 4,
72
+ /* Status registers. */
119
+ ANALOG_GPU_PLL_LOCKD_CTRL = 0x06c / 4,
73
+ REG_MISTA,
120
+ ANALOG_GPU_PLL_MNIT_CTRL = 0x070 / 4,
74
+ REG_MGSTA,
121
+ ANALOG_VPU_PLL_GEN_CTRL = 0x074 / 4,
75
+ REG_MPCNT,
122
+ ANALOG_VPU_PLL_FDIV_CTL0 = 0x078 / 4,
76
+ REG_MRPC,
123
+ ANALOG_VPU_PLL_LOCKD_CTRL = 0x07c / 4,
77
+ REG_MRPCC,
124
+ ANALOG_VPU_PLL_MNIT_CTRL = 0x080 / 4,
78
+ REG_MREPC,
125
+ ANALOG_ARM_PLL_GEN_CTRL = 0x084 / 4,
79
+ REG_DMARFS,
126
+ ANALOG_ARM_PLL_FDIV_CTL0 = 0x088 / 4,
80
+ REG_CTXDSA,
127
+ ANALOG_ARM_PLL_LOCKD_CTRL = 0x08c / 4,
81
+ REG_CTXBSA,
128
+ ANALOG_ARM_PLL_MNIT_CTRL = 0x090 / 4,
82
+ REG_CRXDSA,
129
+ ANALOG_SYS_PLL1_GEN_CTRL = 0x094 / 4,
83
+ REG_CRXBSA,
130
+ ANALOG_SYS_PLL1_FDIV_CTL0 = 0x098 / 4,
84
+
131
+ ANALOG_SYS_PLL1_LOCKD_CTRL = 0x09c / 4,
85
+ NPCM7XX_NUM_EMC_REGS,
132
+ ANALOG_SYS_PLL1_MNIT_CTRL = 0x100 / 4,
86
+};
133
+ ANALOG_SYS_PLL2_GEN_CTRL = 0x104 / 4,
87
+
134
+ ANALOG_SYS_PLL2_FDIV_CTL0 = 0x108 / 4,
88
+/* REG_CAMCMR fields */
135
+ ANALOG_SYS_PLL2_LOCKD_CTRL = 0x10c / 4,
89
+/* Enable CAM Compare */
136
+ ANALOG_SYS_PLL2_MNIT_CTRL = 0x110 / 4,
90
+#define REG_CAMCMR_ECMP (1 << 4)
137
+ ANALOG_SYS_PLL3_GEN_CTRL = 0x114 / 4,
91
+/* Complement CAM Compare */
138
+ ANALOG_SYS_PLL3_FDIV_CTL0 = 0x118 / 4,
92
+#define REG_CAMCMR_CCAM (1 << 3)
139
+ ANALOG_SYS_PLL3_LOCKD_CTRL = 0x11c / 4,
93
+/* Accept Broadcast Packet */
140
+ ANALOG_SYS_PLL3_MNIT_CTRL = 0x120 / 4,
94
+#define REG_CAMCMR_ABP (1 << 2)
141
+ ANALOG_OSC_MISC_CFG = 0x124 / 4,
95
+/* Accept Multicast Packet */
142
+ ANALOG_ANAMIX_PLL_MNIT_CTL = 0x128 / 4,
96
+#define REG_CAMCMR_AMP (1 << 1)
143
+
97
+/* Accept Unicast Packet */
144
+ ANALOG_DIGPROG = 0x800 / 4,
98
+#define REG_CAMCMR_AUP (1 << 0)
145
+ ANALOG_MAX,
99
+
146
+};
100
+/* REG_MCMDR fields */
147
+
101
+/* Software Reset */
148
+#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
102
+#define REG_MCMDR_SWR (1 << 24)
149
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
103
+/* Internal Loopback Select */
150
+
104
+#define REG_MCMDR_LBK (1 << 21)
151
+struct IMX8MPAnalogState {
105
+/* Operation Mode Select */
152
+ SysBusDevice parent_obj;
106
+#define REG_MCMDR_OPMOD (1 << 20)
153
+
107
+/* Enable MDC Clock Generation */
154
+ struct {
108
+#define REG_MCMDR_ENMDC (1 << 19)
155
+ MemoryRegion container;
109
+/* Full-Duplex Mode Select */
156
+ MemoryRegion analog;
110
+#define REG_MCMDR_FDUP (1 << 18)
157
+ } mmio;
111
+/* Enable SQE Checking */
158
+
112
+#define REG_MCMDR_ENSEQ (1 << 17)
159
+ uint32_t analog[ANALOG_MAX];
113
+/* Send PAUSE Frame */
160
+};
114
+#define REG_MCMDR_SDPZ (1 << 16)
161
+
115
+/* No Defer */
162
+#endif /* IMX8MP_ANALOG_H */
116
+#define REG_MCMDR_NDEF (1 << 9)
163
diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h
117
+/* Frame Transmission On */
118
+#define REG_MCMDR_TXON (1 << 8)
119
+/* Strip CRC Checksum */
120
+#define REG_MCMDR_SPCRC (1 << 5)
121
+/* Accept CRC Error Packet */
122
+#define REG_MCMDR_AEP (1 << 4)
123
+/* Accept Control Packet */
124
+#define REG_MCMDR_ACP (1 << 3)
125
+/* Accept Runt Packet */
126
+#define REG_MCMDR_ARP (1 << 2)
127
+/* Accept Long Packet */
128
+#define REG_MCMDR_ALP (1 << 1)
129
+/* Frame Reception On */
130
+#define REG_MCMDR_RXON (1 << 0)
131
+
132
+/* REG_MIEN fields */
133
+/* Enable Transmit Descriptor Unavailable Interrupt */
134
+#define REG_MIEN_ENTDU (1 << 23)
135
+/* Enable Transmit Completion Interrupt */
136
+#define REG_MIEN_ENTXCP (1 << 18)
137
+/* Enable Transmit Interrupt */
138
+#define REG_MIEN_ENTXINTR (1 << 16)
139
+/* Enable Receive Descriptor Unavailable Interrupt */
140
+#define REG_MIEN_ENRDU (1 << 10)
141
+/* Enable Receive Good Interrupt */
142
+#define REG_MIEN_ENRXGD (1 << 4)
143
+/* Enable Receive Interrupt */
144
+#define REG_MIEN_ENRXINTR (1 << 0)
145
+
146
+/* REG_MISTA fields */
147
+/* TODO: Add error fields and support simulated errors? */
148
+/* Transmit Bus Error Interrupt */
149
+#define REG_MISTA_TXBERR (1 << 24)
150
+/* Transmit Descriptor Unavailable Interrupt */
151
+#define REG_MISTA_TDU (1 << 23)
152
+/* Transmit Completion Interrupt */
153
+#define REG_MISTA_TXCP (1 << 18)
154
+/* Transmit Interrupt */
155
+#define REG_MISTA_TXINTR (1 << 16)
156
+/* Receive Bus Error Interrupt */
157
+#define REG_MISTA_RXBERR (1 << 11)
158
+/* Receive Descriptor Unavailable Interrupt */
159
+#define REG_MISTA_RDU (1 << 10)
160
+/* DMA Early Notification Interrupt */
161
+#define REG_MISTA_DENI (1 << 9)
162
+/* Maximum Frame Length Interrupt */
163
+#define REG_MISTA_DFOI (1 << 8)
164
+/* Receive Good Interrupt */
165
+#define REG_MISTA_RXGD (1 << 4)
166
+/* Packet Too Long Interrupt */
167
+#define REG_MISTA_PTLE (1 << 3)
168
+/* Receive Interrupt */
169
+#define REG_MISTA_RXINTR (1 << 0)
170
+
171
+/* REG_MGSTA fields */
172
+/* Transmission Halted */
173
+#define REG_MGSTA_TXHA (1 << 11)
174
+/* Receive Halted */
175
+#define REG_MGSTA_RXHA (1 << 11)
176
+
177
+/* REG_DMARFC fields */
178
+/* Maximum Receive Frame Length */
179
+#define REG_DMARFC_RXMS(word) extract32((word), 0, 16)
180
+
181
+/* REG MIIDA fields */
182
+/* Busy Bit */
183
+#define REG_MIIDA_BUSY (1 << 17)
184
+
185
+/* Transmit and receive descriptors */
186
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
187
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
188
+
189
+struct NPCM7xxEMCTxDesc {
190
+ uint32_t flags;
191
+ uint32_t txbsa;
192
+ uint32_t status_and_length;
193
+ uint32_t ntxdsa;
194
+};
195
+
196
+struct NPCM7xxEMCRxDesc {
197
+ uint32_t status_and_length;
198
+ uint32_t rxbsa;
199
+ uint32_t reserved;
200
+ uint32_t nrxdsa;
201
+};
202
+
203
+/* NPCM7xxEMCTxDesc.flags values */
204
+/* Owner: 0 = cpu, 1 = emc */
205
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
206
+/* Transmit interrupt enable */
207
+#define TX_DESC_FLAG_INTEN (1 << 2)
208
+/* CRC append */
209
+#define TX_DESC_FLAG_CRCAPP (1 << 1)
210
+/* Padding enable */
211
+#define TX_DESC_FLAG_PADEN (1 << 0)
212
+
213
+/* NPCM7xxEMCTxDesc.status_and_length values */
214
+/* Collision count */
215
+#define TX_DESC_STATUS_CCNT_SHIFT 28
216
+#define TX_DESC_STATUS_CCNT_BITSIZE 4
217
+/* SQE error */
218
+#define TX_DESC_STATUS_SQE (1 << 26)
219
+/* Transmission paused */
220
+#define TX_DESC_STATUS_PAU (1 << 25)
221
+/* P transmission halted */
222
+#define TX_DESC_STATUS_TXHA (1 << 24)
223
+/* Late collision */
224
+#define TX_DESC_STATUS_LC (1 << 23)
225
+/* Transmission abort */
226
+#define TX_DESC_STATUS_TXABT (1 << 22)
227
+/* No carrier sense */
228
+#define TX_DESC_STATUS_NCS (1 << 21)
229
+/* Defer exceed */
230
+#define TX_DESC_STATUS_EXDEF (1 << 20)
231
+/* Transmission complete */
232
+#define TX_DESC_STATUS_TXCP (1 << 19)
233
+/* Transmission deferred */
234
+#define TX_DESC_STATUS_DEF (1 << 17)
235
+/* Transmit interrupt */
236
+#define TX_DESC_STATUS_TXINTR (1 << 16)
237
+
238
+#define TX_DESC_PKT_LEN(word) extract32((word), 0, 16)
239
+
240
+/* Transmit buffer start address */
241
+#define TX_DESC_TXBSA(word) ((uint32_t) (word) & ~3u)
242
+
243
+/* Next transmit descriptor start address */
244
+#define TX_DESC_NTXDSA(word) ((uint32_t) (word) & ~3u)
245
+
246
+/* NPCM7xxEMCRxDesc.status_and_length values */
247
+/* Owner: 0b00 = cpu, 0b01 = undefined, 0b10 = emc, 0b11 = undefined */
248
+#define RX_DESC_STATUS_OWNER_SHIFT 30
249
+#define RX_DESC_STATUS_OWNER_BITSIZE 2
250
+#define RX_DESC_STATUS_OWNER_MASK (3 << RX_DESC_STATUS_OWNER_SHIFT)
251
+/* Runt packet */
252
+#define RX_DESC_STATUS_RP (1 << 22)
253
+/* Alignment error */
254
+#define RX_DESC_STATUS_ALIE (1 << 21)
255
+/* Frame reception complete */
256
+#define RX_DESC_STATUS_RXGD (1 << 20)
257
+/* Packet too long */
258
+#define RX_DESC_STATUS_PTLE (1 << 19)
259
+/* CRC error */
260
+#define RX_DESC_STATUS_CRCE (1 << 17)
261
+/* Receive interrupt */
262
+#define RX_DESC_STATUS_RXINTR (1 << 16)
263
+
264
+#define RX_DESC_PKT_LEN(word) extract32((word), 0, 16)
265
+
266
+/* Receive buffer start address */
267
+#define RX_DESC_RXBSA(word) ((uint32_t) (word) & ~3u)
268
+
269
+/* Next receive descriptor start address */
270
+#define RX_DESC_NRXDSA(word) ((uint32_t) (word) & ~3u)
271
+
272
+/* Minimum packet length, when TX_DESC_FLAG_PADEN is set. */
273
+#define MIN_PACKET_LENGTH 64
274
+
275
+struct NPCM7xxEMCState {
276
+ /*< private >*/
277
+ SysBusDevice parent;
278
+ /*< public >*/
279
+
280
+ MemoryRegion iomem;
281
+
282
+ qemu_irq tx_irq;
283
+ qemu_irq rx_irq;
284
+
285
+ NICState *nic;
286
+ NICConf conf;
287
+
288
+ /* 0 or 1, for log messages */
289
+ uint8_t emc_num;
290
+
291
+ uint32_t regs[NPCM7XX_NUM_EMC_REGS];
292
+
293
+ /*
294
+ * tx is active. Set to true by TSDR and then switches off when out of
295
+ * descriptors. If the TXON bit in REG_MCMDR is off then this is off.
296
+ */
297
+ bool tx_active;
298
+
299
+ /*
300
+ * rx is active. Set to true by RSDR and then switches off when out of
301
+ * descriptors. If the RXON bit in REG_MCMDR is off then this is off.
302
+ */
303
+ bool rx_active;
304
+};
305
+
306
+typedef struct NPCM7xxEMCState NPCM7xxEMCState;
307
+
308
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
309
+#define NPCM7XX_EMC(obj) \
310
+ OBJECT_CHECK(NPCM7xxEMCState, (obj), TYPE_NPCM7XX_EMC)
311
+
312
+#endif /* NPCM7XX_EMC_H */
313
diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c
314
new file mode 100644
164
new file mode 100644
315
index XXXXXXX..XXXXXXX
165
index XXXXXXX..XXXXXXX
316
--- /dev/null
166
--- /dev/null
317
+++ b/hw/net/npcm7xx_emc.c
167
+++ b/include/hw/misc/imx8mp_ccm.h
318
@@ -XXX,XX +XXX,XX @@
168
@@ -XXX,XX +XXX,XX @@
319
+/*
169
+/*
320
+ * Nuvoton NPCM7xx EMC Module
170
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
321
+ *
171
+ *
322
+ * Copyright 2020 Google LLC
172
+ * i.MX 8M Plus CCM IP block emulation code
323
+ *
173
+ *
324
+ * This program is free software; you can redistribute it and/or modify it
174
+ * SPDX-License-Identifier: GPL-2.0-or-later
325
+ * under the terms of the GNU General Public License as published by the
326
+ * Free Software Foundation; either version 2 of the License, or
327
+ * (at your option) any later version.
328
+ *
329
+ * This program is distributed in the hope that it will be useful, but WITHOUT
330
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
331
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
332
+ * for more details.
333
+ *
334
+ * Unsupported/unimplemented features:
335
+ * - MCMDR.FDUP (full duplex) is ignored, half duplex is not supported
336
+ * - Only CAM0 is supported, CAM[1-15] are not
337
+ * - writes to CAMEN.[1-15] are ignored, these bits always read as zeroes
338
+ * - MII is not implemented, MIIDA.BUSY and MIID always return zero
339
+ * - MCMDR.LBK is not implemented
340
+ * - MCMDR.{OPMOD,ENSQE,AEP,ARP} are not supported
341
+ * - H/W FIFOs are not supported, MCMDR.FFTCR is ignored
342
+ * - MGSTA.SQE is not supported
343
+ * - pause and control frames are not implemented
344
+ * - MGSTA.CCNT is not supported
345
+ * - MPCNT, DMARFS are not implemented
346
+ */
175
+ */
347
+
176
+
348
+#include "qemu/osdep.h"
177
+#ifndef IMX8MP_CCM_H
349
+
178
+#define IMX8MP_CCM_H
350
+/* For crc32 */
179
+
351
+#include <zlib.h>
180
+#include "hw/misc/imx_ccm.h"
352
+
181
+#include "qom/object.h"
353
+#include "qemu-common.h"
182
+
354
+#include "hw/irq.h"
183
+enum IMX8MPCCMRegisters {
355
+#include "hw/qdev-clock.h"
184
+ CCM_MAX = 0xc6fc / sizeof(uint32_t) + 1,
356
+#include "hw/qdev-properties.h"
185
+};
357
+#include "hw/net/npcm7xx_emc.h"
186
+
358
+#include "net/eth.h"
187
+#define TYPE_IMX8MP_CCM "imx8mp.ccm"
359
+#include "migration/vmstate.h"
188
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPCCMState, IMX8MP_CCM)
360
+#include "qemu/bitops.h"
189
+
361
+#include "qemu/error-report.h"
190
+struct IMX8MPCCMState {
362
+#include "qemu/log.h"
191
+ IMXCCMState parent_obj;
363
+#include "qemu/module.h"
192
+
364
+#include "qemu/units.h"
193
+ MemoryRegion iomem;
365
+#include "sysemu/dma.h"
194
+
366
+#include "trace.h"
195
+ uint32_t ccm[CCM_MAX];
367
+
196
+};
368
+#define CRC_LENGTH 4
197
+
369
+
198
+#endif /* IMX8MP_CCM_H */
370
+/*
199
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
371
+ * The maximum size of a (layer 2) ethernet frame as defined by 802.3.
200
index XXXXXXX..XXXXXXX 100644
372
+ * 1518 = 6(dest macaddr) + 6(src macaddr) + 2(proto) + 4(crc) + 1500(payload)
201
--- a/hw/arm/fsl-imx8mp.c
373
+ * This does not include an additional 4 for the vlan field (802.1q).
202
+++ b/hw/arm/fsl-imx8mp.c
374
+ */
203
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
375
+#define MAX_ETH_FRAME_SIZE 1518
204
376
+
205
object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
377
+static const char *emc_reg_name(int regno)
206
378
+{
207
+ object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
379
+#define REG(name) case REG_ ## name: return #name;
208
+
380
+ switch (regno) {
209
+ object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
381
+ REG(CAMCMR)
210
+
382
+ REG(CAMEN)
211
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
383
+ REG(TXDLSA)
212
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
384
+ REG(RXDLSA)
213
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
385
+ REG(MCMDR)
214
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
386
+ REG(MIID)
215
}
387
+ REG(MIIDA)
216
}
388
+ REG(FFTCR)
217
389
+ REG(TSDR)
218
+ /* CCM */
390
+ REG(RSDR)
219
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
391
+ REG(DMARFC)
392
+ REG(MIEN)
393
+ REG(MISTA)
394
+ REG(MGSTA)
395
+ REG(MPCNT)
396
+ REG(MRPC)
397
+ REG(MRPCC)
398
+ REG(MREPC)
399
+ REG(DMARFS)
400
+ REG(CTXDSA)
401
+ REG(CTXBSA)
402
+ REG(CRXDSA)
403
+ REG(CRXBSA)
404
+ case REG_CAMM_BASE + 0: return "CAM0M";
405
+ case REG_CAML_BASE + 0: return "CAM0L";
406
+ case REG_CAMM_BASE + 2 ... REG_CAMML_LAST:
407
+ /* Only CAM0 is supported, fold the others into something simple. */
408
+ if (regno & 1) {
409
+ return "CAM<n>L";
410
+ } else {
411
+ return "CAM<n>M";
412
+ }
413
+ default: return "UNKNOWN";
414
+ }
415
+#undef REG
416
+}
417
+
418
+static void emc_reset(NPCM7xxEMCState *emc)
419
+{
420
+ trace_npcm7xx_emc_reset(emc->emc_num);
421
+
422
+ memset(&emc->regs[0], 0, sizeof(emc->regs));
423
+
424
+ /* These regs have non-zero reset values. */
425
+ emc->regs[REG_TXDLSA] = 0xfffffffc;
426
+ emc->regs[REG_RXDLSA] = 0xfffffffc;
427
+ emc->regs[REG_MIIDA] = 0x00900000;
428
+ emc->regs[REG_FFTCR] = 0x0101;
429
+ emc->regs[REG_DMARFC] = 0x0800;
430
+ emc->regs[REG_MPCNT] = 0x7fff;
431
+
432
+ emc->tx_active = false;
433
+ emc->rx_active = false;
434
+}
435
+
436
+static void npcm7xx_emc_reset(DeviceState *dev)
437
+{
438
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
439
+ emc_reset(emc);
440
+}
441
+
442
+static void emc_soft_reset(NPCM7xxEMCState *emc)
443
+{
444
+ /*
445
+ * The docs say at least MCMDR.{LBK,OPMOD} bits are not changed during a
446
+ * soft reset, but does not go into further detail. For now, KISS.
447
+ */
448
+ uint32_t mcmdr = emc->regs[REG_MCMDR];
449
+ emc_reset(emc);
450
+ emc->regs[REG_MCMDR] = mcmdr & (REG_MCMDR_LBK | REG_MCMDR_OPMOD);
451
+
452
+ qemu_set_irq(emc->tx_irq, 0);
453
+ qemu_set_irq(emc->rx_irq, 0);
454
+}
455
+
456
+static void emc_set_link(NetClientState *nc)
457
+{
458
+ /* Nothing to do yet. */
459
+}
460
+
461
+/* MISTA.TXINTR is the union of the individual bits with their enables. */
462
+static void emc_update_mista_txintr(NPCM7xxEMCState *emc)
463
+{
464
+ /* Only look at the bits we support. */
465
+ uint32_t mask = (REG_MISTA_TXBERR |
466
+ REG_MISTA_TDU |
467
+ REG_MISTA_TXCP);
468
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
469
+ emc->regs[REG_MISTA] |= REG_MISTA_TXINTR;
470
+ } else {
471
+ emc->regs[REG_MISTA] &= ~REG_MISTA_TXINTR;
472
+ }
473
+}
474
+
475
+/* MISTA.RXINTR is the union of the individual bits with their enables. */
476
+static void emc_update_mista_rxintr(NPCM7xxEMCState *emc)
477
+{
478
+ /* Only look at the bits we support. */
479
+ uint32_t mask = (REG_MISTA_RXBERR |
480
+ REG_MISTA_RDU |
481
+ REG_MISTA_RXGD);
482
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
483
+ emc->regs[REG_MISTA] |= REG_MISTA_RXINTR;
484
+ } else {
485
+ emc->regs[REG_MISTA] &= ~REG_MISTA_RXINTR;
486
+ }
487
+}
488
+
489
+/* N.B. emc_update_mista_txintr must have already been called. */
490
+static void emc_update_tx_irq(NPCM7xxEMCState *emc)
491
+{
492
+ int level = !!(emc->regs[REG_MISTA] &
493
+ emc->regs[REG_MIEN] &
494
+ REG_MISTA_TXINTR);
495
+ trace_npcm7xx_emc_update_tx_irq(level);
496
+ qemu_set_irq(emc->tx_irq, level);
497
+}
498
+
499
+/* N.B. emc_update_mista_rxintr must have already been called. */
500
+static void emc_update_rx_irq(NPCM7xxEMCState *emc)
501
+{
502
+ int level = !!(emc->regs[REG_MISTA] &
503
+ emc->regs[REG_MIEN] &
504
+ REG_MISTA_RXINTR);
505
+ trace_npcm7xx_emc_update_rx_irq(level);
506
+ qemu_set_irq(emc->rx_irq, level);
507
+}
508
+
509
+/* Update IRQ states due to changes in MIEN,MISTA. */
510
+static void emc_update_irq_from_reg_change(NPCM7xxEMCState *emc)
511
+{
512
+ emc_update_mista_txintr(emc);
513
+ emc_update_tx_irq(emc);
514
+
515
+ emc_update_mista_rxintr(emc);
516
+ emc_update_rx_irq(emc);
517
+}
518
+
519
+static int emc_read_tx_desc(dma_addr_t addr, NPCM7xxEMCTxDesc *desc)
520
+{
521
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
522
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
523
+ HWADDR_PRIx "\n", __func__, addr);
524
+ return -1;
525
+ }
526
+ desc->flags = le32_to_cpu(desc->flags);
527
+ desc->txbsa = le32_to_cpu(desc->txbsa);
528
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
529
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
530
+ return 0;
531
+}
532
+
533
+static int emc_write_tx_desc(const NPCM7xxEMCTxDesc *desc, dma_addr_t addr)
534
+{
535
+ NPCM7xxEMCTxDesc le_desc;
536
+
537
+ le_desc.flags = cpu_to_le32(desc->flags);
538
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
539
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
540
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
541
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
542
+ sizeof(le_desc))) {
543
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
544
+ HWADDR_PRIx "\n", __func__, addr);
545
+ return -1;
546
+ }
547
+ return 0;
548
+}
549
+
550
+static int emc_read_rx_desc(dma_addr_t addr, NPCM7xxEMCRxDesc *desc)
551
+{
552
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
553
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
554
+ HWADDR_PRIx "\n", __func__, addr);
555
+ return -1;
556
+ }
557
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
558
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
559
+ desc->reserved = le32_to_cpu(desc->reserved);
560
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
561
+ return 0;
562
+}
563
+
564
+static int emc_write_rx_desc(const NPCM7xxEMCRxDesc *desc, dma_addr_t addr)
565
+{
566
+ NPCM7xxEMCRxDesc le_desc;
567
+
568
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
569
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
570
+ le_desc.reserved = cpu_to_le32(desc->reserved);
571
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
572
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
573
+ sizeof(le_desc))) {
574
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
575
+ HWADDR_PRIx "\n", __func__, addr);
576
+ return -1;
577
+ }
578
+ return 0;
579
+}
580
+
581
+static void emc_set_mista(NPCM7xxEMCState *emc, uint32_t flags)
582
+{
583
+ trace_npcm7xx_emc_set_mista(flags);
584
+ emc->regs[REG_MISTA] |= flags;
585
+ if (extract32(flags, 16, 16)) {
586
+ emc_update_mista_txintr(emc);
587
+ }
588
+ if (extract32(flags, 0, 16)) {
589
+ emc_update_mista_rxintr(emc);
590
+ }
591
+}
592
+
593
+static void emc_halt_tx(NPCM7xxEMCState *emc, uint32_t mista_flag)
594
+{
595
+ emc->tx_active = false;
596
+ emc_set_mista(emc, mista_flag);
597
+}
598
+
599
+static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag)
600
+{
601
+ emc->rx_active = false;
602
+ emc_set_mista(emc, mista_flag);
603
+}
604
+
605
+static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc,
606
+ const NPCM7xxEMCTxDesc *tx_desc,
607
+ uint32_t desc_addr)
608
+{
609
+ /* Update the current descriptor, if only to reset the owner flag. */
610
+ if (emc_write_tx_desc(tx_desc, desc_addr)) {
611
+ /*
612
+ * We just read it so this shouldn't generally happen.
613
+ * Error already reported.
614
+ */
615
+ emc_set_mista(emc, REG_MISTA_TXBERR);
616
+ }
617
+ emc->regs[REG_CTXDSA] = TX_DESC_NTXDSA(tx_desc->ntxdsa);
618
+}
619
+
620
+static void emc_set_next_rx_descriptor(NPCM7xxEMCState *emc,
621
+ const NPCM7xxEMCRxDesc *rx_desc,
622
+ uint32_t desc_addr)
623
+{
624
+ /* Update the current descriptor, if only to reset the owner flag. */
625
+ if (emc_write_rx_desc(rx_desc, desc_addr)) {
626
+ /*
627
+ * We just read it so this shouldn't generally happen.
628
+ * Error already reported.
629
+ */
630
+ emc_set_mista(emc, REG_MISTA_RXBERR);
631
+ }
632
+ emc->regs[REG_CRXDSA] = RX_DESC_NRXDSA(rx_desc->nrxdsa);
633
+}
634
+
635
+static void emc_try_send_next_packet(NPCM7xxEMCState *emc)
636
+{
637
+ /* Working buffer for sending out packets. Most packets fit in this. */
638
+#define TX_BUFFER_SIZE 2048
639
+ uint8_t tx_send_buffer[TX_BUFFER_SIZE];
640
+ uint32_t desc_addr = TX_DESC_NTXDSA(emc->regs[REG_CTXDSA]);
641
+ NPCM7xxEMCTxDesc tx_desc;
642
+ uint32_t next_buf_addr, length;
643
+ uint8_t *buf;
644
+ g_autofree uint8_t *malloced_buf = NULL;
645
+
646
+ if (emc_read_tx_desc(desc_addr, &tx_desc)) {
647
+ /* Error reading descriptor, already reported. */
648
+ emc_halt_tx(emc, REG_MISTA_TXBERR);
649
+ emc_update_tx_irq(emc);
650
+ return;
220
+ return;
651
+ }
221
+ }
652
+
222
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0,
653
+ /* Nothing we can do if we don't own the descriptor. */
223
+ fsl_imx8mp_memmap[FSL_IMX8MP_CCM].addr);
654
+ if (!(tx_desc.flags & TX_DESC_FLAG_OWNER_MASK)) {
224
+
655
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
225
+ /* Analog */
656
+ emc_halt_tx(emc, REG_MISTA_TDU);
226
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->analog), errp)) {
657
+ emc_update_tx_irq(emc);
658
+ return;
659
+ }
660
+
661
+ /* Give the descriptor back regardless of what happens. */
662
+ tx_desc.flags &= ~TX_DESC_FLAG_OWNER_MASK;
663
+ tx_desc.status_and_length &= 0xffff;
664
+
665
+ /*
666
+ * Despite the h/w documentation saying the tx buffer is word aligned,
667
+ * the linux driver does not word align the buffer. There is value in not
668
+ * aligning the buffer: See the description of NET_IP_ALIGN in linux
669
+ * kernel sources.
670
+ */
671
+ next_buf_addr = tx_desc.txbsa;
672
+ emc->regs[REG_CTXBSA] = next_buf_addr;
673
+ length = TX_DESC_PKT_LEN(tx_desc.status_and_length);
674
+ buf = &tx_send_buffer[0];
675
+
676
+ if (length > sizeof(tx_send_buffer)) {
677
+ malloced_buf = g_malloc(length);
678
+ buf = malloced_buf;
679
+ }
680
+
681
+ if (dma_memory_read(&address_space_memory, next_buf_addr, buf, length)) {
682
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n",
683
+ __func__, next_buf_addr);
684
+ emc_set_mista(emc, REG_MISTA_TXBERR);
685
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
686
+ emc_update_tx_irq(emc);
687
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
688
+ return;
227
+ return;
689
+ }
228
+ }
690
+
229
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0,
691
+ if ((tx_desc.flags & TX_DESC_FLAG_PADEN) && (length < MIN_PACKET_LENGTH)) {
230
+ fsl_imx8mp_memmap[FSL_IMX8MP_ANA_PLL].addr);
692
+ memset(buf + length, 0, MIN_PACKET_LENGTH - length);
231
+
693
+ length = MIN_PACKET_LENGTH;
232
/* UARTs */
233
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
234
struct {
235
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
236
/* Unimplemented devices */
237
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
238
switch (i) {
239
+ case FSL_IMX8MP_ANA_PLL:
240
+ case FSL_IMX8MP_CCM:
241
case FSL_IMX8MP_GIC_DIST:
242
case FSL_IMX8MP_GIC_REDIST:
243
case FSL_IMX8MP_RAM:
244
diff --git a/hw/misc/imx8mp_analog.c b/hw/misc/imx8mp_analog.c
245
new file mode 100644
246
index XXXXXXX..XXXXXXX
247
--- /dev/null
248
+++ b/hw/misc/imx8mp_analog.c
249
@@ -XXX,XX +XXX,XX @@
250
+/*
251
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
252
+ *
253
+ * i.MX 8M Plus ANALOG IP block emulation code
254
+ *
255
+ * Based on hw/misc/imx7_ccm.c
256
+ *
257
+ * SPDX-License-Identifier: GPL-2.0-or-later
258
+ */
259
+
260
+#include "qemu/osdep.h"
261
+#include "qemu/log.h"
262
+
263
+#include "hw/misc/imx8mp_analog.h"
264
+#include "migration/vmstate.h"
265
+
266
+#define ANALOG_PLL_LOCK BIT(31)
267
+
268
+static void imx8mp_analog_reset(DeviceState *dev)
269
+{
270
+ IMX8MPAnalogState *s = IMX8MP_ANALOG(dev);
271
+
272
+ memset(s->analog, 0, sizeof(s->analog));
273
+
274
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] = 0x00002010;
275
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL0] = 0x00145032;
276
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL1] = 0x00000000;
277
+ s->analog[ANALOG_AUDIO_PLL1_SSCG_CTRL] = 0x00000000;
278
+ s->analog[ANALOG_AUDIO_PLL1_MNIT_CTRL] = 0x00100103;
279
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] = 0x00002010;
280
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL0] = 0x00145032;
281
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL1] = 0x00000000;
282
+ s->analog[ANALOG_AUDIO_PLL2_SSCG_CTRL] = 0x00000000;
283
+ s->analog[ANALOG_AUDIO_PLL2_MNIT_CTRL] = 0x00100103;
284
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] = 0x00002010;
285
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL0] = 0x00145032;
286
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL1] = 0x00000000;
287
+ s->analog[ANALOG_VIDEO_PLL1_SSCG_CTRL] = 0x00000000;
288
+ s->analog[ANALOG_VIDEO_PLL1_MNIT_CTRL] = 0x00100103;
289
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] = 0x00002010;
290
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL0] = 0x0012c032;
291
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL1] = 0x00000000;
292
+ s->analog[ANALOG_DRAM_PLL_SSCG_CTRL] = 0x00000000;
293
+ s->analog[ANALOG_DRAM_PLL_MNIT_CTRL] = 0x00100103;
294
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] = 0x00000810;
295
+ s->analog[ANALOG_GPU_PLL_FDIV_CTL0] = 0x000c8031;
296
+ s->analog[ANALOG_GPU_PLL_LOCKD_CTRL] = 0x0010003f;
297
+ s->analog[ANALOG_GPU_PLL_MNIT_CTRL] = 0x00280081;
298
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] = 0x00000810;
299
+ s->analog[ANALOG_VPU_PLL_FDIV_CTL0] = 0x0012c032;
300
+ s->analog[ANALOG_VPU_PLL_LOCKD_CTRL] = 0x0010003f;
301
+ s->analog[ANALOG_VPU_PLL_MNIT_CTRL] = 0x00280081;
302
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] = 0x00000810;
303
+ s->analog[ANALOG_ARM_PLL_FDIV_CTL0] = 0x000fa031;
304
+ s->analog[ANALOG_ARM_PLL_LOCKD_CTRL] = 0x0010003f;
305
+ s->analog[ANALOG_ARM_PLL_MNIT_CTRL] = 0x00280081;
306
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] = 0x0aaaa810;
307
+ s->analog[ANALOG_SYS_PLL1_FDIV_CTL0] = 0x00190032;
308
+ s->analog[ANALOG_SYS_PLL1_LOCKD_CTRL] = 0x0010003f;
309
+ s->analog[ANALOG_SYS_PLL1_MNIT_CTRL] = 0x00280081;
310
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] = 0x0aaaa810;
311
+ s->analog[ANALOG_SYS_PLL2_FDIV_CTL0] = 0x000fa031;
312
+ s->analog[ANALOG_SYS_PLL2_LOCKD_CTRL] = 0x0010003f;
313
+ s->analog[ANALOG_SYS_PLL2_MNIT_CTRL] = 0x00280081;
314
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] = 0x00000810;
315
+ s->analog[ANALOG_SYS_PLL3_FDIV_CTL0] = 0x000fa031;
316
+ s->analog[ANALOG_SYS_PLL3_LOCKD_CTRL] = 0x0010003f;
317
+ s->analog[ANALOG_SYS_PLL3_MNIT_CTRL] = 0x00280081;
318
+ s->analog[ANALOG_OSC_MISC_CFG] = 0x00000000;
319
+ s->analog[ANALOG_ANAMIX_PLL_MNIT_CTL] = 0x00000000;
320
+ s->analog[ANALOG_DIGPROG] = 0x00824010;
321
+
322
+ /* all PLLs need to be locked */
323
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
324
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
325
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
326
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
327
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
328
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
329
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
330
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
331
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
332
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] |= ANALOG_PLL_LOCK;
333
+}
334
+
335
+static uint64_t imx8mp_analog_read(void *opaque, hwaddr offset, unsigned size)
336
+{
337
+ IMX8MPAnalogState *s = opaque;
338
+
339
+ return s->analog[offset >> 2];
340
+}
341
+
342
+static void imx8mp_analog_write(void *opaque, hwaddr offset,
343
+ uint64_t value, unsigned size)
344
+{
345
+ IMX8MPAnalogState *s = opaque;
346
+
347
+ if (offset >> 2 == ANALOG_DIGPROG) {
348
+ qemu_log_mask(LOG_GUEST_ERROR,
349
+ "Guest write to read-only ANALOG_DIGPROG register\n");
350
+ } else {
351
+ s->analog[offset >> 2] = value;
694
+ }
352
+ }
695
+
353
+}
696
+ /* N.B. emc_receive can get called here. */
354
+
697
+ qemu_send_packet(qemu_get_queue(emc->nic), buf, length);
355
+static const struct MemoryRegionOps imx8mp_analog_ops = {
698
+ trace_npcm7xx_emc_sent_packet(length);
356
+ .read = imx8mp_analog_read,
699
+
357
+ .write = imx8mp_analog_write,
700
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXCP;
358
+ .endianness = DEVICE_NATIVE_ENDIAN,
701
+ if (tx_desc.flags & TX_DESC_FLAG_INTEN) {
359
+ .impl = {
702
+ emc_set_mista(emc, REG_MISTA_TXCP);
703
+ }
704
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_TXINTR) {
705
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXINTR;
706
+ }
707
+
708
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
709
+ emc_update_tx_irq(emc);
710
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
711
+}
712
+
713
+static bool emc_can_receive(NetClientState *nc)
714
+{
715
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
716
+
717
+ bool can_receive = emc->rx_active;
718
+ trace_npcm7xx_emc_can_receive(can_receive);
719
+ return can_receive;
720
+}
721
+
722
+/* If result is false then *fail_reason contains the reason. */
723
+static bool emc_receive_filter1(NPCM7xxEMCState *emc, const uint8_t *buf,
724
+ size_t len, const char **fail_reason)
725
+{
726
+ eth_pkt_types_e pkt_type = get_eth_packet_type(PKT_GET_ETH_HDR(buf));
727
+
728
+ switch (pkt_type) {
729
+ case ETH_PKT_BCAST:
730
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
731
+ return true;
732
+ } else {
733
+ *fail_reason = "Broadcast packet disabled";
734
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_ABP);
735
+ }
736
+ case ETH_PKT_MCAST:
737
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
738
+ return true;
739
+ } else {
740
+ *fail_reason = "Multicast packet disabled";
741
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_AMP);
742
+ }
743
+ case ETH_PKT_UCAST: {
744
+ bool matches;
745
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_AUP) {
746
+ return true;
747
+ }
748
+ matches = ((emc->regs[REG_CAMCMR] & REG_CAMCMR_ECMP) &&
749
+ /* We only support one CAM register, CAM0. */
750
+ (emc->regs[REG_CAMEN] & (1 << 0)) &&
751
+ memcmp(buf, emc->conf.macaddr.a, ETH_ALEN) == 0);
752
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
753
+ *fail_reason = "MACADDR matched, comparison complemented";
754
+ return !matches;
755
+ } else {
756
+ *fail_reason = "MACADDR didn't match";
757
+ return matches;
758
+ }
759
+ }
760
+ default:
761
+ g_assert_not_reached();
762
+ }
763
+}
764
+
765
+static bool emc_receive_filter(NPCM7xxEMCState *emc, const uint8_t *buf,
766
+ size_t len)
767
+{
768
+ const char *fail_reason = NULL;
769
+ bool ok = emc_receive_filter1(emc, buf, len, &fail_reason);
770
+ if (!ok) {
771
+ trace_npcm7xx_emc_packet_filtered_out(fail_reason);
772
+ }
773
+ return ok;
774
+}
775
+
776
+static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1)
777
+{
778
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
779
+ const uint32_t len = len1;
780
+ size_t max_frame_len;
781
+ bool long_frame;
782
+ uint32_t desc_addr;
783
+ NPCM7xxEMCRxDesc rx_desc;
784
+ uint32_t crc;
785
+ uint8_t *crc_ptr;
786
+ uint32_t buf_addr;
787
+
788
+ trace_npcm7xx_emc_receiving_packet(len);
789
+
790
+ if (!emc_can_receive(nc)) {
791
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__);
792
+ return -1;
793
+ }
794
+
795
+ if (len < ETH_HLEN ||
796
+ /* Defensive programming: drop unsupportable large packets. */
797
+ len > 0xffff - CRC_LENGTH) {
798
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Dropped frame of %u bytes\n",
799
+ __func__, len);
800
+ return len;
801
+ }
802
+
803
+ /*
804
+ * DENI is set if EMC received the Length/Type field of the incoming
805
+ * packet, so it will be set regardless of what happens next.
806
+ */
807
+ emc_set_mista(emc, REG_MISTA_DENI);
808
+
809
+ if (!emc_receive_filter(emc, buf, len)) {
810
+ emc_update_rx_irq(emc);
811
+ return len;
812
+ }
813
+
814
+ /* Huge frames (> DMARFC) are dropped. */
815
+ max_frame_len = REG_DMARFC_RXMS(emc->regs[REG_DMARFC]);
816
+ if (len + CRC_LENGTH > max_frame_len) {
817
+ trace_npcm7xx_emc_packet_dropped(len);
818
+ emc_set_mista(emc, REG_MISTA_DFOI);
819
+ emc_update_rx_irq(emc);
820
+ return len;
821
+ }
822
+
823
+ /*
824
+ * Long Frames (> MAX_ETH_FRAME_SIZE) are also dropped, unless MCMDR.ALP
825
+ * is set.
826
+ */
827
+ long_frame = false;
828
+ if (len + CRC_LENGTH > MAX_ETH_FRAME_SIZE) {
829
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_ALP) {
830
+ long_frame = true;
831
+ } else {
832
+ trace_npcm7xx_emc_packet_dropped(len);
833
+ emc_set_mista(emc, REG_MISTA_PTLE);
834
+ emc_update_rx_irq(emc);
835
+ return len;
836
+ }
837
+ }
838
+
839
+ desc_addr = RX_DESC_NRXDSA(emc->regs[REG_CRXDSA]);
840
+ if (emc_read_rx_desc(desc_addr, &rx_desc)) {
841
+ /* Error reading descriptor, already reported. */
842
+ emc_halt_rx(emc, REG_MISTA_RXBERR);
843
+ emc_update_rx_irq(emc);
844
+ return len;
845
+ }
846
+
847
+ /* Nothing we can do if we don't own the descriptor. */
848
+ if (!(rx_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK)) {
849
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
850
+ emc_halt_rx(emc, REG_MISTA_RDU);
851
+ emc_update_rx_irq(emc);
852
+ return len;
853
+ }
854
+
855
+ crc = 0;
856
+ crc_ptr = (uint8_t *) &crc;
857
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
858
+ crc = cpu_to_be32(crc32(~0, buf, len));
859
+ }
860
+
861
+ /* Give the descriptor back regardless of what happens. */
862
+ rx_desc.status_and_length &= ~RX_DESC_STATUS_OWNER_MASK;
863
+
864
+ buf_addr = rx_desc.rxbsa;
865
+ emc->regs[REG_CRXBSA] = buf_addr;
866
+ if (dma_memory_write(&address_space_memory, buf_addr, buf, len) ||
867
+ (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC) &&
868
+ dma_memory_write(&address_space_memory, buf_addr + len, crc_ptr,
869
+ 4))) {
870
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bus error writing packet\n",
871
+ __func__);
872
+ emc_set_mista(emc, REG_MISTA_RXBERR);
873
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
874
+ emc_update_rx_irq(emc);
875
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
876
+ return len;
877
+ }
878
+
879
+ trace_npcm7xx_emc_received_packet(len);
880
+
881
+ /* Note: We've already verified len+4 <= 0xffff. */
882
+ rx_desc.status_and_length = len;
883
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
884
+ rx_desc.status_and_length += 4;
885
+ }
886
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXGD;
887
+ emc_set_mista(emc, REG_MISTA_RXGD);
888
+
889
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_RXINTR) {
890
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXINTR;
891
+ }
892
+ if (long_frame) {
893
+ rx_desc.status_and_length |= RX_DESC_STATUS_PTLE;
894
+ }
895
+
896
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
897
+ emc_update_rx_irq(emc);
898
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
899
+ return len;
900
+}
901
+
902
+static void emc_try_receive_next_packet(NPCM7xxEMCState *emc)
903
+{
904
+ if (emc_can_receive(qemu_get_queue(emc->nic))) {
905
+ qemu_flush_queued_packets(qemu_get_queue(emc->nic));
906
+ }
907
+}
908
+
909
+static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size)
910
+{
911
+ NPCM7xxEMCState *emc = opaque;
912
+ uint32_t reg = offset / sizeof(uint32_t);
913
+ uint32_t result;
914
+
915
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
916
+ qemu_log_mask(LOG_GUEST_ERROR,
917
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
918
+ __func__, offset);
919
+ return 0;
920
+ }
921
+
922
+ switch (reg) {
923
+ case REG_MIID:
924
+ /*
925
+ * We don't implement MII. For determinism, always return zero as
926
+ * writes record the last value written for debugging purposes.
927
+ */
928
+ qemu_log_mask(LOG_UNIMP, "%s: Read of MIID, returning 0\n", __func__);
929
+ result = 0;
930
+ break;
931
+ case REG_TSDR:
932
+ case REG_RSDR:
933
+ qemu_log_mask(LOG_GUEST_ERROR,
934
+ "%s: Read of write-only reg, %s/%d\n",
935
+ __func__, emc_reg_name(reg), reg);
936
+ return 0;
937
+ default:
938
+ result = emc->regs[reg];
939
+ break;
940
+ }
941
+
942
+ trace_npcm7xx_emc_reg_read(emc->emc_num, result, emc_reg_name(reg), reg);
943
+ return result;
944
+}
945
+
946
+static void npcm7xx_emc_write(void *opaque, hwaddr offset,
947
+ uint64_t v, unsigned size)
948
+{
949
+ NPCM7xxEMCState *emc = opaque;
950
+ uint32_t reg = offset / sizeof(uint32_t);
951
+ uint32_t value = v;
952
+
953
+ g_assert(size == sizeof(uint32_t));
954
+
955
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
956
+ qemu_log_mask(LOG_GUEST_ERROR,
957
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
958
+ __func__, offset);
959
+ return;
960
+ }
961
+
962
+ trace_npcm7xx_emc_reg_write(emc->emc_num, emc_reg_name(reg), reg, value);
963
+
964
+ switch (reg) {
965
+ case REG_CAMCMR:
966
+ emc->regs[reg] = value;
967
+ break;
968
+ case REG_CAMEN:
969
+ /* Only CAM0 is supported, don't pretend otherwise. */
970
+ if (value & ~1) {
971
+ qemu_log_mask(LOG_GUEST_ERROR,
972
+ "%s: Only CAM0 is supported, cannot enable others"
973
+ ": 0x%x\n",
974
+ __func__, value);
975
+ }
976
+ emc->regs[reg] = value & 1;
977
+ break;
978
+ case REG_CAMM_BASE + 0:
979
+ emc->regs[reg] = value;
980
+ emc->conf.macaddr.a[0] = value >> 24;
981
+ emc->conf.macaddr.a[1] = value >> 16;
982
+ emc->conf.macaddr.a[2] = value >> 8;
983
+ emc->conf.macaddr.a[3] = value >> 0;
984
+ break;
985
+ case REG_CAML_BASE + 0:
986
+ emc->regs[reg] = value;
987
+ emc->conf.macaddr.a[4] = value >> 24;
988
+ emc->conf.macaddr.a[5] = value >> 16;
989
+ break;
990
+ case REG_MCMDR: {
991
+ uint32_t prev;
992
+ if (value & REG_MCMDR_SWR) {
993
+ emc_soft_reset(emc);
994
+ /* On h/w the reset happens over multiple cycles. For now KISS. */
995
+ break;
996
+ }
997
+ prev = emc->regs[reg];
998
+ emc->regs[reg] = value;
999
+ /* Update tx state. */
1000
+ if (!(prev & REG_MCMDR_TXON) &&
1001
+ (value & REG_MCMDR_TXON)) {
1002
+ emc->regs[REG_CTXDSA] = emc->regs[REG_TXDLSA];
1003
+ /*
1004
+ * Linux kernel turns TX on with CPU still holding descriptor,
1005
+ * which suggests we should wait for a write to TSDR before trying
1006
+ * to send a packet: so we don't send one here.
1007
+ */
1008
+ } else if ((prev & REG_MCMDR_TXON) &&
1009
+ !(value & REG_MCMDR_TXON)) {
1010
+ emc->regs[REG_MGSTA] |= REG_MGSTA_TXHA;
1011
+ }
1012
+ if (!(value & REG_MCMDR_TXON)) {
1013
+ emc_halt_tx(emc, 0);
1014
+ }
1015
+ /* Update rx state. */
1016
+ if (!(prev & REG_MCMDR_RXON) &&
1017
+ (value & REG_MCMDR_RXON)) {
1018
+ emc->regs[REG_CRXDSA] = emc->regs[REG_RXDLSA];
1019
+ } else if ((prev & REG_MCMDR_RXON) &&
1020
+ !(value & REG_MCMDR_RXON)) {
1021
+ emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
1022
+ }
1023
+ if (!(value & REG_MCMDR_RXON)) {
1024
+ emc_halt_rx(emc, 0);
1025
+ }
1026
+ break;
1027
+ }
1028
+ case REG_TXDLSA:
1029
+ case REG_RXDLSA:
1030
+ case REG_DMARFC:
1031
+ case REG_MIID:
1032
+ emc->regs[reg] = value;
1033
+ break;
1034
+ case REG_MIEN:
1035
+ emc->regs[reg] = value;
1036
+ emc_update_irq_from_reg_change(emc);
1037
+ break;
1038
+ case REG_MISTA:
1039
+ /* Clear the bits that have 1 in "value". */
1040
+ emc->regs[reg] &= ~value;
1041
+ emc_update_irq_from_reg_change(emc);
1042
+ break;
1043
+ case REG_MGSTA:
1044
+ /* Clear the bits that have 1 in "value". */
1045
+ emc->regs[reg] &= ~value;
1046
+ break;
1047
+ case REG_TSDR:
1048
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_TXON) {
1049
+ emc->tx_active = true;
1050
+ /* Keep trying to send packets until we run out. */
1051
+ while (emc->tx_active) {
1052
+ emc_try_send_next_packet(emc);
1053
+ }
1054
+ }
1055
+ break;
1056
+ case REG_RSDR:
1057
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
1058
+ emc->rx_active = true;
1059
+ emc_try_receive_next_packet(emc);
1060
+ }
1061
+ break;
1062
+ case REG_MIIDA:
1063
+ emc->regs[reg] = value & ~REG_MIIDA_BUSY;
1064
+ break;
1065
+ case REG_MRPC:
1066
+ case REG_MRPCC:
1067
+ case REG_MREPC:
1068
+ case REG_CTXDSA:
1069
+ case REG_CTXBSA:
1070
+ case REG_CRXDSA:
1071
+ case REG_CRXBSA:
1072
+ qemu_log_mask(LOG_GUEST_ERROR,
1073
+ "%s: Write to read-only reg %s/%d\n",
1074
+ __func__, emc_reg_name(reg), reg);
1075
+ break;
1076
+ default:
1077
+ qemu_log_mask(LOG_UNIMP, "%s: Write to unimplemented reg %s/%d\n",
1078
+ __func__, emc_reg_name(reg), reg);
1079
+ break;
1080
+ }
1081
+}
1082
+
1083
+static const struct MemoryRegionOps npcm7xx_emc_ops = {
1084
+ .read = npcm7xx_emc_read,
1085
+ .write = npcm7xx_emc_write,
1086
+ .endianness = DEVICE_LITTLE_ENDIAN,
1087
+ .valid = {
1088
+ .min_access_size = 4,
360
+ .min_access_size = 4,
1089
+ .max_access_size = 4,
361
+ .max_access_size = 4,
1090
+ .unaligned = false,
362
+ .unaligned = false,
1091
+ },
363
+ },
1092
+};
364
+};
1093
+
365
+
1094
+static void emc_cleanup(NetClientState *nc)
366
+static void imx8mp_analog_init(Object *obj)
1095
+{
367
+{
1096
+ /* Nothing to do yet. */
368
+ IMX8MPAnalogState *s = IMX8MP_ANALOG(obj);
1097
+}
369
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
1098
+
370
+
1099
+static NetClientInfo net_npcm7xx_emc_info = {
371
+ memory_region_init(&s->mmio.container, obj, TYPE_IMX8MP_ANALOG, 0x10000);
1100
+ .type = NET_CLIENT_DRIVER_NIC,
372
+
1101
+ .size = sizeof(NICState),
373
+ memory_region_init_io(&s->mmio.analog, obj, &imx8mp_analog_ops, s,
1102
+ .can_receive = emc_can_receive,
374
+ TYPE_IMX8MP_ANALOG, sizeof(s->analog));
1103
+ .receive = emc_receive,
375
+ memory_region_add_subregion(&s->mmio.container, 0, &s->mmio.analog);
1104
+ .cleanup = emc_cleanup,
376
+
1105
+ .link_status_changed = emc_set_link,
377
+ sysbus_init_mmio(sd, &s->mmio.container);
1106
+};
378
+}
1107
+
379
+
1108
+static void npcm7xx_emc_realize(DeviceState *dev, Error **errp)
380
+static const VMStateDescription imx8mp_analog_vmstate = {
1109
+{
381
+ .name = TYPE_IMX8MP_ANALOG,
1110
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
382
+ .version_id = 1,
1111
+ SysBusDevice *sbd = SYS_BUS_DEVICE(emc);
383
+ .minimum_version_id = 1,
1112
+
384
+ .fields = (const VMStateField[]) {
1113
+ memory_region_init_io(&emc->iomem, OBJECT(emc), &npcm7xx_emc_ops, emc,
385
+ VMSTATE_UINT32_ARRAY(analog, IMX8MPAnalogState, ANALOG_MAX),
1114
+ TYPE_NPCM7XX_EMC, 4 * KiB);
386
+ VMSTATE_END_OF_LIST()
1115
+ sysbus_init_mmio(sbd, &emc->iomem);
1116
+ sysbus_init_irq(sbd, &emc->tx_irq);
1117
+ sysbus_init_irq(sbd, &emc->rx_irq);
1118
+
1119
+ qemu_macaddr_default_if_unset(&emc->conf.macaddr);
1120
+ emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf,
1121
+ object_get_typename(OBJECT(dev)), dev->id, emc);
1122
+ qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a);
1123
+}
1124
+
1125
+static void npcm7xx_emc_unrealize(DeviceState *dev)
1126
+{
1127
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
1128
+
1129
+ qemu_del_nic(emc->nic);
1130
+}
1131
+
1132
+static const VMStateDescription vmstate_npcm7xx_emc = {
1133
+ .name = TYPE_NPCM7XX_EMC,
1134
+ .version_id = 0,
1135
+ .minimum_version_id = 0,
1136
+ .fields = (VMStateField[]) {
1137
+ VMSTATE_UINT8(emc_num, NPCM7xxEMCState),
1138
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxEMCState, NPCM7XX_NUM_EMC_REGS),
1139
+ VMSTATE_BOOL(tx_active, NPCM7xxEMCState),
1140
+ VMSTATE_BOOL(rx_active, NPCM7xxEMCState),
1141
+ VMSTATE_END_OF_LIST(),
1142
+ },
387
+ },
1143
+};
388
+};
1144
+
389
+
1145
+static Property npcm7xx_emc_properties[] = {
390
+static void imx8mp_analog_class_init(ObjectClass *klass, void *data)
1146
+ DEFINE_NIC_PROPERTIES(NPCM7xxEMCState, conf),
1147
+ DEFINE_PROP_END_OF_LIST(),
1148
+};
1149
+
1150
+static void npcm7xx_emc_class_init(ObjectClass *klass, void *data)
1151
+{
391
+{
1152
+ DeviceClass *dc = DEVICE_CLASS(klass);
392
+ DeviceClass *dc = DEVICE_CLASS(klass);
1153
+
393
+
1154
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
394
+ device_class_set_legacy_reset(dc, imx8mp_analog_reset);
1155
+ dc->desc = "NPCM7xx EMC Controller";
395
+ dc->vmsd = &imx8mp_analog_vmstate;
1156
+ dc->realize = npcm7xx_emc_realize;
396
+ dc->desc = "i.MX 8M Plus Analog Module";
1157
+ dc->unrealize = npcm7xx_emc_unrealize;
397
+}
1158
+ dc->reset = npcm7xx_emc_reset;
398
+
1159
+ dc->vmsd = &vmstate_npcm7xx_emc;
399
+static const TypeInfo imx8mp_analog_types[] = {
1160
+ device_class_set_props(dc, npcm7xx_emc_properties);
400
+ {
1161
+}
401
+ .name = TYPE_IMX8MP_ANALOG,
1162
+
402
+ .parent = TYPE_SYS_BUS_DEVICE,
1163
+static const TypeInfo npcm7xx_emc_info = {
403
+ .instance_size = sizeof(IMX8MPAnalogState),
1164
+ .name = TYPE_NPCM7XX_EMC,
404
+ .instance_init = imx8mp_analog_init,
1165
+ .parent = TYPE_SYS_BUS_DEVICE,
405
+ .class_init = imx8mp_analog_class_init,
1166
+ .instance_size = sizeof(NPCM7xxEMCState),
406
+ }
1167
+ .class_init = npcm7xx_emc_class_init,
407
+};
1168
+};
408
+
1169
+
409
+DEFINE_TYPES(imx8mp_analog_types);
1170
+static void npcm7xx_emc_register_type(void)
410
diff --git a/hw/misc/imx8mp_ccm.c b/hw/misc/imx8mp_ccm.c
1171
+{
411
new file mode 100644
1172
+ type_register_static(&npcm7xx_emc_info);
412
index XXXXXXX..XXXXXXX
1173
+}
413
--- /dev/null
1174
+
414
+++ b/hw/misc/imx8mp_ccm.c
1175
+type_init(npcm7xx_emc_register_type)
415
@@ -XXX,XX +XXX,XX @@
1176
diff --git a/hw/net/meson.build b/hw/net/meson.build
416
+/*
417
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
418
+ *
419
+ * i.MX 8M Plus CCM IP block emulation code
420
+ *
421
+ * Based on hw/misc/imx7_ccm.c
422
+ *
423
+ * SPDX-License-Identifier: GPL-2.0-or-later
424
+ */
425
+
426
+#include "qemu/osdep.h"
427
+#include "qemu/log.h"
428
+
429
+#include "hw/misc/imx8mp_ccm.h"
430
+#include "migration/vmstate.h"
431
+
432
+#include "trace.h"
433
+
434
+#define CKIH_FREQ 16000000 /* 16MHz crystal input */
435
+
436
+static void imx8mp_ccm_reset(DeviceState *dev)
437
+{
438
+ IMX8MPCCMState *s = IMX8MP_CCM(dev);
439
+
440
+ memset(s->ccm, 0, sizeof(s->ccm));
441
+}
442
+
443
+#define CCM_INDEX(offset) (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
444
+#define CCM_BITOP(offset) ((offset) & (hwaddr)0xF)
445
+
446
+enum {
447
+ CCM_BITOP_NONE = 0x00,
448
+ CCM_BITOP_SET = 0x04,
449
+ CCM_BITOP_CLR = 0x08,
450
+ CCM_BITOP_TOG = 0x0C,
451
+};
452
+
453
+static uint64_t imx8mp_set_clr_tog_read(void *opaque, hwaddr offset,
454
+ unsigned size)
455
+{
456
+ const uint32_t *mmio = opaque;
457
+
458
+ return mmio[CCM_INDEX(offset)];
459
+}
460
+
461
+static void imx8mp_set_clr_tog_write(void *opaque, hwaddr offset,
462
+ uint64_t value, unsigned size)
463
+{
464
+ const uint8_t bitop = CCM_BITOP(offset);
465
+ const uint32_t index = CCM_INDEX(offset);
466
+ uint32_t *mmio = opaque;
467
+
468
+ switch (bitop) {
469
+ case CCM_BITOP_NONE:
470
+ mmio[index] = value;
471
+ break;
472
+ case CCM_BITOP_SET:
473
+ mmio[index] |= value;
474
+ break;
475
+ case CCM_BITOP_CLR:
476
+ mmio[index] &= ~value;
477
+ break;
478
+ case CCM_BITOP_TOG:
479
+ mmio[index] ^= value;
480
+ break;
481
+ };
482
+}
483
+
484
+static const struct MemoryRegionOps imx8mp_set_clr_tog_ops = {
485
+ .read = imx8mp_set_clr_tog_read,
486
+ .write = imx8mp_set_clr_tog_write,
487
+ .endianness = DEVICE_NATIVE_ENDIAN,
488
+ .impl = {
489
+ /*
490
+ * Our device would not work correctly if the guest was doing
491
+ * unaligned access. This might not be a limitation on the real
492
+ * device but in practice there is no reason for a guest to access
493
+ * this device unaligned.
494
+ */
495
+ .min_access_size = 4,
496
+ .max_access_size = 4,
497
+ .unaligned = false,
498
+ },
499
+};
500
+
501
+static void imx8mp_ccm_init(Object *obj)
502
+{
503
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
504
+ IMX8MPCCMState *s = IMX8MP_CCM(obj);
505
+
506
+ memory_region_init_io(&s->iomem,
507
+ obj,
508
+ &imx8mp_set_clr_tog_ops,
509
+ s->ccm,
510
+ TYPE_IMX8MP_CCM ".ccm",
511
+ sizeof(s->ccm));
512
+
513
+ sysbus_init_mmio(sd, &s->iomem);
514
+}
515
+
516
+static const VMStateDescription imx8mp_ccm_vmstate = {
517
+ .name = TYPE_IMX8MP_CCM,
518
+ .version_id = 1,
519
+ .minimum_version_id = 1,
520
+ .fields = (const VMStateField[]) {
521
+ VMSTATE_UINT32_ARRAY(ccm, IMX8MPCCMState, CCM_MAX),
522
+ VMSTATE_END_OF_LIST()
523
+ },
524
+};
525
+
526
+static uint32_t imx8mp_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
527
+{
528
+ /*
529
+ * This function is "consumed" by GPT emulation code. Some clocks
530
+ * have fixed frequencies and we can provide requested frequency
531
+ * easily. However for CCM provided clocks (like IPG) each GPT
532
+ * timer can have its own clock root.
533
+ * This means we need additional information when calling this
534
+ * function to know the requester's identity.
535
+ */
536
+ uint32_t freq = 0;
537
+
538
+ switch (clock) {
539
+ case CLK_NONE:
540
+ break;
541
+ case CLK_32k:
542
+ freq = CKIL_FREQ;
543
+ break;
544
+ case CLK_HIGH:
545
+ freq = CKIH_FREQ;
546
+ break;
547
+ case CLK_IPG:
548
+ case CLK_IPG_HIGH:
549
+ /*
550
+ * For now we don't have a way to figure out the device this
551
+ * function is called for. Until then the IPG derived clocks
552
+ * are left unimplemented.
553
+ */
554
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Clock %d Not implemented\n",
555
+ TYPE_IMX8MP_CCM, __func__, clock);
556
+ break;
557
+ default:
558
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
559
+ TYPE_IMX8MP_CCM, __func__, clock);
560
+ break;
561
+ }
562
+
563
+ trace_ccm_clock_freq(clock, freq);
564
+
565
+ return freq;
566
+}
567
+
568
+static void imx8mp_ccm_class_init(ObjectClass *klass, void *data)
569
+{
570
+ DeviceClass *dc = DEVICE_CLASS(klass);
571
+ IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
572
+
573
+ device_class_set_legacy_reset(dc, imx8mp_ccm_reset);
574
+ dc->vmsd = &imx8mp_ccm_vmstate;
575
+ dc->desc = "i.MX 8M Plus Clock Control Module";
576
+
577
+ ccm->get_clock_frequency = imx8mp_ccm_get_clock_frequency;
578
+}
579
+
580
+static const TypeInfo imx8mp_ccm_types[] = {
581
+ {
582
+ .name = TYPE_IMX8MP_CCM,
583
+ .parent = TYPE_IMX_CCM,
584
+ .instance_size = sizeof(IMX8MPCCMState),
585
+ .instance_init = imx8mp_ccm_init,
586
+ .class_init = imx8mp_ccm_class_init,
587
+ },
588
+};
589
+
590
+DEFINE_TYPES(imx8mp_ccm_types);
591
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
1177
index XXXXXXX..XXXXXXX 100644
592
index XXXXXXX..XXXXXXX 100644
1178
--- a/hw/net/meson.build
593
--- a/hw/arm/Kconfig
1179
+++ b/hw/net/meson.build
594
+++ b/hw/arm/Kconfig
1180
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c'))
595
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
1181
softmmu_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c'))
596
config FSL_IMX8MP
1182
softmmu_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
597
bool
1183
softmmu_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c'))
598
select ARM_GIC
1184
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c'))
599
+ select FSL_IMX8MP_ANALOG
1185
600
+ select FSL_IMX8MP_CCM
1186
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
601
select IMX
1187
softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
602
select UNIMP
1188
diff --git a/hw/net/trace-events b/hw/net/trace-events
603
604
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
1189
index XXXXXXX..XXXXXXX 100644
605
index XXXXXXX..XXXXXXX 100644
1190
--- a/hw/net/trace-events
606
--- a/hw/misc/Kconfig
1191
+++ b/hw/net/trace-events
607
+++ b/hw/misc/Kconfig
1192
@@ -XXX,XX +XXX,XX @@ imx_fec_receive_last(int last) "rx frame flags 0x%04x"
608
@@ -XXX,XX +XXX,XX @@ config IMX
1193
imx_enet_receive(size_t size) "len %zu"
609
select SSI
1194
imx_enet_receive_len(uint64_t addr, int len) "rx_bd 0x%"PRIx64" length %d"
610
select USB_EHCI_SYSBUS
1195
imx_enet_receive_last(int last) "rx frame flags 0x%04x"
611
1196
+
612
+config FSL_IMX8MP_ANALOG
1197
+# npcm7xx_emc.c
613
+ bool
1198
+npcm7xx_emc_reset(int emc_num) "Resetting emc%d"
614
+
1199
+npcm7xx_emc_update_tx_irq(int level) "Setting tx irq to %d"
615
+config FSL_IMX8MP_CCM
1200
+npcm7xx_emc_update_rx_irq(int level) "Setting rx irq to %d"
616
+ bool
1201
+npcm7xx_emc_set_mista(uint32_t flags) "ORing 0x%x into MISTA"
617
+
1202
+npcm7xx_emc_cpu_owned_desc(uint32_t addr) "Can't process cpu-owned descriptor @0x%x"
618
config STM32_RCC
1203
+npcm7xx_emc_sent_packet(uint32_t len) "Sent %u byte packet"
619
bool
1204
+npcm7xx_emc_tx_done(uint32_t ctxdsa) "TX done, CTXDSA=0x%x"
620
1205
+npcm7xx_emc_can_receive(int can_receive) "Can receive: %d"
621
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
1206
+npcm7xx_emc_packet_filtered_out(const char* fail_reason) "Packet filtered out: %s"
622
index XXXXXXX..XXXXXXX 100644
1207
+npcm7xx_emc_packet_dropped(uint32_t len) "%u byte packet dropped"
623
--- a/hw/misc/meson.build
1208
+npcm7xx_emc_receiving_packet(uint32_t len) "Receiving %u byte packet"
624
+++ b/hw/misc/meson.build
1209
+npcm7xx_emc_received_packet(uint32_t len) "Received %u byte packet"
625
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_AXP2XX_PMU', if_true: files('axp2xx.c'))
1210
+npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=0x%x"
626
system_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
1211
+npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int regno) "emc%d: 0x%x = reg[%s/%d]"
627
system_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
1212
+npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t value) "emc%d: reg[%s/%d] = 0x%x"
628
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pmu.c', 'exynos4210_clk.c', 'exynos4210_rng.c'))
629
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_analog.c'))
630
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_CCM', if_true: files('imx8mp_ccm.c'))
631
system_ss.add(when: 'CONFIG_IMX', if_true: files(
632
'imx25_ccm.c',
633
'imx31_ccm.c',
1213
--
634
--
1214
2.20.1
635
2.43.0
1215
1216
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Cortex-A53 supports 40bits of address space. sbsa-ref's memory starts
3
SNVS contains an RTC which allows Linux to deal correctly with time. This is
4
above this limit.
4
particularly useful when handling persistent storage which will be done in the
5
next patch.
5
6
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Acked-by: Leif Lindholm <leif@nuviainc.com>
9
Message-id: 20250223114708.1780-7-shentey@gmail.com
9
Message-id: 20210216150122.3830863-2-marcin.juszkiewicz@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
hw/arm/sbsa-ref.c | 1 -
12
docs/system/arm/imx8mp-evk.rst | 1 +
13
1 file changed, 1 deletion(-)
13
include/hw/arm/fsl-imx8mp.h | 2 ++
14
hw/arm/fsl-imx8mp.c | 10 ++++++++++
15
3 files changed, 13 insertions(+)
14
16
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
17
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/sbsa-ref.c
19
--- a/docs/system/arm/imx8mp-evk.rst
18
+++ b/hw/arm/sbsa-ref.c
20
+++ b/docs/system/arm/imx8mp-evk.rst
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
21
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
22
* Up to 4 Cortex-A53 cores
23
* Generic Interrupt Controller (GICv3)
24
* 4 UARTs
25
+ * Secure Non-Volatile Storage (SNVS) including an RTC
26
* Clock Tree
27
28
Boot options
29
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/arm/fsl-imx8mp.h
32
+++ b/include/hw/arm/fsl-imx8mp.h
33
@@ -XXX,XX +XXX,XX @@
34
#include "cpu.h"
35
#include "hw/char/imx_serial.h"
36
#include "hw/intc/arm_gicv3_common.h"
37
+#include "hw/misc/imx7_snvs.h"
38
#include "hw/misc/imx8mp_analog.h"
39
#include "hw/misc/imx8mp_ccm.h"
40
#include "qom/object.h"
41
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
42
GICv3State gic;
43
IMX8MPCCMState ccm;
44
IMX8MPAnalogState analog;
45
+ IMX7SNVSState snvs;
46
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
20
};
47
};
21
48
22
static const char * const valid_cpus[] = {
49
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
23
- ARM_CPU_TYPE_NAME("cortex-a53"),
50
index XXXXXXX..XXXXXXX 100644
24
ARM_CPU_TYPE_NAME("cortex-a57"),
51
--- a/hw/arm/fsl-imx8mp.c
25
ARM_CPU_TYPE_NAME("cortex-a72"),
52
+++ b/hw/arm/fsl-imx8mp.c
26
};
53
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
54
55
object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
56
57
+ object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
58
+
59
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
60
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
61
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
62
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
63
qdev_get_gpio_in(gicdev, serial_table[i].irq));
64
}
65
66
+ /* SNVS */
67
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
68
+ return;
69
+ }
70
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
71
+ fsl_imx8mp_memmap[FSL_IMX8MP_SNVS_HP].addr);
72
+
73
/* Unimplemented devices */
74
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
75
switch (i) {
76
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
77
case FSL_IMX8MP_GIC_DIST:
78
case FSL_IMX8MP_GIC_REDIST:
79
case FSL_IMX8MP_RAM:
80
+ case FSL_IMX8MP_SNVS_HP:
81
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
82
/* device implemented and treated above */
83
break;
27
--
84
--
28
2.20.1
85
2.43.0
29
30
diff view generated by jsdifflib
1
From: Doug Evans <dje@google.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
This is a 10/100 ethernet device that has several features.
3
The USDHC emulation allows for running real-world images such as those generated
4
Only the ones needed by the Linux driver have been implemented.
4
by Buildroot. Convert the board documentation accordingly instead of running a
5
See npcm7xx_emc.c for a list of unimplemented features.
5
Linux kernel with ephemeral storage.
6
6
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Doug Evans <dje@google.com>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
11
Message-id: 20210218212453.831406-3-dje@google.com
9
Message-id: 20250223114708.1780-8-shentey@gmail.com
10
[PMM: drop 'static const' from usdhc_table[] for GCC 7.5]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
12
---
14
docs/system/arm/nuvoton.rst | 3 ++-
13
docs/system/arm/imx8mp-evk.rst | 18 ++++++++++++------
15
include/hw/arm/npcm7xx.h | 2 ++
14
include/hw/arm/fsl-imx8mp.h | 7 +++++++
16
hw/arm/npcm7xx.c | 50 +++++++++++++++++++++++++++++++++++--
15
hw/arm/fsl-imx8mp.c | 28 ++++++++++++++++++++++++++++
17
3 files changed, 52 insertions(+), 3 deletions(-)
16
hw/arm/imx8mp-evk.c | 18 ++++++++++++++++++
17
hw/arm/Kconfig | 1 +
18
5 files changed, 66 insertions(+), 6 deletions(-)
18
19
19
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
20
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
20
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/arm/nuvoton.rst
22
--- a/docs/system/arm/imx8mp-evk.rst
22
+++ b/docs/system/arm/nuvoton.rst
23
+++ b/docs/system/arm/imx8mp-evk.rst
23
@@ -XXX,XX +XXX,XX @@ Supported devices
24
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
24
* Analog to Digital Converter (ADC)
25
* Up to 4 Cortex-A53 cores
25
* Pulse Width Modulation (PWM)
26
* Generic Interrupt Controller (GICv3)
26
* SMBus controller (SMBF)
27
* 4 UARTs
27
+ * Ethernet controller (EMC)
28
+ * 3 USDHC Storage Controllers
28
29
* Secure Non-Volatile Storage (SNVS) including an RTC
29
Missing devices
30
* Clock Tree
30
---------------
31
31
@@ -XXX,XX +XXX,XX @@ Missing devices
32
@@ -XXX,XX +XXX,XX @@ Direct Linux Kernel Boot
32
* Shared memory (SHM)
33
33
* eSPI slave interface
34
Probably the easiest way to get started with a whole Linux system on the machine
34
35
is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
35
- * Ethernet controllers (GMAC and EMC)
36
-of writing and involves two steps. First run the following commands in the
36
+ * Ethernet controller (GMAC)
37
+of writing and involves three steps. First run the following commands in the
37
* USB device (USBD)
38
toplevel directory of the Buildroot source tree:
38
* Peripheral SPI controller (PSPI)
39
39
* SD/MMC host
40
.. code-block:: bash
40
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
41
41
index XXXXXXX..XXXXXXX 100644
42
- $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
42
--- a/include/hw/arm/npcm7xx.h
43
$ make freescale_imx8mpevk_defconfig
43
+++ b/include/hw/arm/npcm7xx.h
44
$ make
45
46
Once finished successfully there is an ``output/image`` subfolder. Navigate into
47
-it and patch the device tree with the following commands which will remove the
48
-``cpu-idle-states`` properties from CPU nodes:
49
+it and resize the SD card image to a power of two:
50
+
51
+.. code-block:: bash
52
+
53
+ $ qemu-img resize sdcard.img 256M
54
+
55
+Finally, the device tree needs to be patched with the following commands which
56
+will remove the ``cpu-idle-states`` properties from CPU nodes:
57
58
.. code-block:: bash
59
60
@@ -XXX,XX +XXX,XX @@ Now that everything is prepared the machine can be started as follows:
61
-display none -serial null -serial stdio \
62
-kernel Image \
63
-dtb imx8mp-evk-patched.dtb \
64
- -initrd rootfs.cpio \
65
- -append "root=/dev/ram"
66
+ -append "root=/dev/mmcblk2p2" \
67
+ -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
68
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/hw/arm/fsl-imx8mp.h
71
+++ b/include/hw/arm/fsl-imx8mp.h
44
@@ -XXX,XX +XXX,XX @@
72
@@ -XXX,XX +XXX,XX @@
45
#include "hw/misc/npcm7xx_gcr.h"
73
#include "hw/misc/imx7_snvs.h"
46
#include "hw/misc/npcm7xx_pwm.h"
74
#include "hw/misc/imx8mp_analog.h"
47
#include "hw/misc/npcm7xx_rng.h"
75
#include "hw/misc/imx8mp_ccm.h"
48
+#include "hw/net/npcm7xx_emc.h"
76
+#include "hw/sd/sdhci.h"
49
#include "hw/nvram/npcm7xx_otp.h"
77
#include "qom/object.h"
50
#include "hw/timer/npcm7xx_timer.h"
78
#include "qemu/units.h"
51
#include "hw/ssi/npcm7xx_fiu.h"
79
52
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
80
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpConfiguration {
53
EHCISysBusState ehci;
81
FSL_IMX8MP_NUM_CPUS = 4,
54
OHCISysBusState ohci;
82
FSL_IMX8MP_NUM_IRQS = 160,
55
NPCM7xxFIUState fiu[2];
83
FSL_IMX8MP_NUM_UARTS = 4,
56
+ NPCM7xxEMCState emc[2];
84
+ FSL_IMX8MP_NUM_USDHCS = 3,
57
} NPCM7xxState;
58
59
#define TYPE_NPCM7XX "npcm7xx"
60
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/npcm7xx.c
63
+++ b/hw/arm/npcm7xx.c
64
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
65
NPCM7XX_UART1_IRQ,
66
NPCM7XX_UART2_IRQ,
67
NPCM7XX_UART3_IRQ,
68
+ NPCM7XX_EMC1RX_IRQ = 15,
69
+ NPCM7XX_EMC1TX_IRQ,
70
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
71
NPCM7XX_TIMER1_IRQ,
72
NPCM7XX_TIMER2_IRQ,
73
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
74
NPCM7XX_SMBUS15_IRQ,
75
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
76
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
77
+ NPCM7XX_EMC2RX_IRQ = 114,
78
+ NPCM7XX_EMC2TX_IRQ,
79
NPCM7XX_GPIO0_IRQ = 116,
80
NPCM7XX_GPIO1_IRQ,
81
NPCM7XX_GPIO2_IRQ,
82
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_smbus_addr[] = {
83
0xf008f000,
84
};
85
};
85
86
86
+/* Register base address for each EMC Module */
87
struct FslImx8mpState {
87
+static const hwaddr npcm7xx_emc_addr[] = {
88
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
88
+ 0xf0825000,
89
IMX8MPAnalogState analog;
89
+ 0xf0826000,
90
IMX7SNVSState snvs;
90
+};
91
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
91
+
92
+ SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
92
static const struct {
93
};
93
hwaddr regs_addr;
94
94
uint32_t unconnected_pins;
95
enum FslImx8mpMemoryRegions {
95
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
96
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpMemoryRegions {
96
for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
97
};
97
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
98
99
enum FslImx8mpIrqs {
100
+ FSL_IMX8MP_USDHC1_IRQ = 22,
101
+ FSL_IMX8MP_USDHC2_IRQ = 23,
102
+ FSL_IMX8MP_USDHC3_IRQ = 24,
103
+
104
FSL_IMX8MP_UART1_IRQ = 26,
105
FSL_IMX8MP_UART2_IRQ = 27,
106
FSL_IMX8MP_UART3_IRQ = 28,
107
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/hw/arm/fsl-imx8mp.c
110
+++ b/hw/arm/fsl-imx8mp.c
111
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
112
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
113
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
98
}
114
}
99
+
115
+
100
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
116
+ for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
101
+ object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
117
+ g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
118
+ object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
102
+ }
119
+ }
103
}
120
}
104
121
105
static void npcm7xx_realize(DeviceState *dev, Error **errp)
122
static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
123
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
107
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
124
qdev_get_gpio_in(gicdev, serial_table[i].irq));
108
}
125
}
109
126
110
+ /*
127
+ /* USDHCs */
111
+ * EMC Modules. Cannot fail.
128
+ for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
112
+ * The mapping of the device to its netdev backend works as follows:
129
+ struct {
113
+ * emc[i] = nd_table[i]
130
+ hwaddr addr;
114
+ * This works around the inability to specify the netdev property for the
131
+ unsigned int irq;
115
+ * emc device: it's not pluggable and thus the -device option can't be
132
+ } usdhc_table[FSL_IMX8MP_NUM_USDHCS] = {
116
+ * used.
133
+ { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC1].addr, FSL_IMX8MP_USDHC1_IRQ },
117
+ */
134
+ { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC2].addr, FSL_IMX8MP_USDHC2_IRQ },
118
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
135
+ { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC3].addr, FSL_IMX8MP_USDHC3_IRQ },
119
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
136
+ };
120
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
137
+
121
+ s->emc[i].emc_num = i;
138
+ object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
122
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->emc[i]);
139
+ SDHCI_VENDOR_IMX, &error_abort);
123
+ if (nd_table[i].used) {
140
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), errp)) {
124
+ qemu_check_nic_model(&nd_table[i], TYPE_NPCM7XX_EMC);
141
+ return;
125
+ qdev_set_nic_properties(DEVICE(sbd), &nd_table[i]);
126
+ }
142
+ }
127
+ /*
143
+
128
+ * The device exists regardless of whether it's connected to a QEMU
144
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, usdhc_table[i].addr);
129
+ * netdev backend. So always instantiate it even if there is no
145
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
130
+ * backend.
146
+ qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
131
+ */
132
+ sysbus_realize(sbd, &error_abort);
133
+ sysbus_mmio_map(sbd, 0, npcm7xx_emc_addr[i]);
134
+ int tx_irq = i == 0 ? NPCM7XX_EMC1TX_IRQ : NPCM7XX_EMC2TX_IRQ;
135
+ int rx_irq = i == 0 ? NPCM7XX_EMC1RX_IRQ : NPCM7XX_EMC2RX_IRQ;
136
+ /*
137
+ * N.B. The values for the second argument sysbus_connect_irq are
138
+ * chosen to match the registration order in npcm7xx_emc_realize.
139
+ */
140
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, tx_irq));
141
+ sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
142
+ }
147
+ }
143
+
148
+
144
/*
149
/* SNVS */
145
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
150
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
146
* specified, but this is a programming error.
151
return;
147
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
152
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
148
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
153
case FSL_IMX8MP_RAM:
149
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
154
case FSL_IMX8MP_SNVS_HP:
150
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
155
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
151
- create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
156
+ case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
152
- create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
157
/* device implemented and treated above */
153
create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
158
break;
154
create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
159
155
create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
160
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/hw/arm/imx8mp-evk.c
163
+++ b/hw/arm/imx8mp-evk.c
164
@@ -XXX,XX +XXX,XX @@
165
#include "hw/arm/boot.h"
166
#include "hw/arm/fsl-imx8mp.h"
167
#include "hw/boards.h"
168
+#include "hw/qdev-properties.h"
169
#include "system/qtest.h"
170
#include "qemu/error-report.h"
171
#include "qapi/error.h"
172
@@ -XXX,XX +XXX,XX @@ static void imx8mp_evk_init(MachineState *machine)
173
memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
174
machine->ram);
175
176
+ for (int i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
177
+ BusState *bus;
178
+ DeviceState *carddev;
179
+ BlockBackend *blk;
180
+ DriveInfo *di = drive_get(IF_SD, i, 0);
181
+
182
+ if (!di) {
183
+ continue;
184
+ }
185
+
186
+ blk = blk_by_legacy_dinfo(di);
187
+ bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
188
+ carddev = qdev_new(TYPE_SD_CARD);
189
+ qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
190
+ qdev_realize_and_unref(carddev, bus, &error_fatal);
191
+ }
192
+
193
if (!qtest_enabled()) {
194
arm_load_kernel(&s->cpu[0], machine, &boot_info);
195
}
196
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
197
index XXXXXXX..XXXXXXX 100644
198
--- a/hw/arm/Kconfig
199
+++ b/hw/arm/Kconfig
200
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
201
select FSL_IMX8MP_ANALOG
202
select FSL_IMX8MP_CCM
203
select IMX
204
+ select SDHCI
205
select UNIMP
206
207
config FSL_IMX8MP_EVK
156
--
208
--
157
2.20.1
209
2.43.0
158
159
diff view generated by jsdifflib
1
From: Doug Evans <dje@google.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Reviewed-by: Hao Wu <wuhaotsh@google.com>
3
Linux checks for the PLLs in the PHY to be locked, so implement a model
4
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
4
emulating that.
5
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Message-id: 20250223114708.1780-9-shentey@gmail.com
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Doug Evans <dje@google.com>
7
Message-id: 20210218212453.831406-4-dje@google.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++
11
MAINTAINERS | 2 +
11
tests/qtest/meson.build | 3 +-
12
docs/system/arm/imx8mp-evk.rst | 1 +
12
2 files changed, 864 insertions(+), 1 deletion(-)
13
include/hw/arm/fsl-imx8mp.h | 10 +++
13
create mode 100644 tests/qtest/npcm7xx_emc-test.c
14
include/hw/pci-host/fsl_imx8m_phy.h | 28 +++++++++
15
hw/arm/fsl-imx8mp.c | 30 +++++++++
16
hw/pci-host/fsl_imx8m_phy.c | 98 +++++++++++++++++++++++++++++
17
hw/arm/Kconfig | 3 +
18
hw/pci-host/Kconfig | 3 +
19
hw/pci-host/meson.build | 1 +
20
9 files changed, 176 insertions(+)
21
create mode 100644 include/hw/pci-host/fsl_imx8m_phy.h
22
create mode 100644 hw/pci-host/fsl_imx8m_phy.c
14
23
15
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
24
diff --git a/MAINTAINERS b/MAINTAINERS
25
index XXXXXXX..XXXXXXX 100644
26
--- a/MAINTAINERS
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
55
@@ -XXX,XX +XXX,XX @@
56
#include "hw/misc/imx7_snvs.h"
57
#include "hw/misc/imx8mp_analog.h"
58
#include "hw/misc/imx8mp_ccm.h"
59
+#include "hw/pci-host/designware.h"
60
+#include "hw/pci-host/fsl_imx8m_phy.h"
61
#include "hw/sd/sdhci.h"
62
#include "qom/object.h"
63
#include "qemu/units.h"
64
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
65
IMX7SNVSState snvs;
66
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
67
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
68
+ DesignwarePCIEHost pcie;
69
+ FslImx8mPciePhyState pcie_phy;
70
};
71
72
enum FslImx8mpMemoryRegions {
73
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
74
FSL_IMX8MP_UART4_IRQ = 29,
75
FSL_IMX8MP_UART5_IRQ = 30,
76
FSL_IMX8MP_UART6_IRQ = 16,
77
+
78
+ FSL_IMX8MP_PCI_INTA_IRQ = 126,
79
+ FSL_IMX8MP_PCI_INTB_IRQ = 125,
80
+ FSL_IMX8MP_PCI_INTC_IRQ = 124,
81
+ FSL_IMX8MP_PCI_INTD_IRQ = 123,
82
+ FSL_IMX8MP_PCI_MSI_IRQ = 140,
83
};
84
85
#endif /* FSL_IMX8MP_H */
86
diff --git a/include/hw/pci-host/fsl_imx8m_phy.h b/include/hw/pci-host/fsl_imx8m_phy.h
16
new file mode 100644
87
new file mode 100644
17
index XXXXXXX..XXXXXXX
88
index XXXXXXX..XXXXXXX
18
--- /dev/null
89
--- /dev/null
19
+++ b/tests/qtest/npcm7xx_emc-test.c
90
+++ b/include/hw/pci-host/fsl_imx8m_phy.h
20
@@ -XXX,XX +XXX,XX @@
91
@@ -XXX,XX +XXX,XX @@
21
+/*
92
+/*
22
+ * QTests for Nuvoton NPCM7xx EMC Modules.
93
+ * i.MX8 PCIe PHY emulation
23
+ *
94
+ *
24
+ * Copyright 2020 Google LLC
95
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
25
+ *
96
+ *
26
+ * This program is free software; you can redistribute it and/or modify it
97
+ * SPDX-License-Identifier: GPL-2.0-or-later
27
+ * under the terms of the GNU General Public License as published by the
98
+ */
28
+ * Free Software Foundation; either version 2 of the License, or
99
+
29
+ * (at your option) any later version.
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
30
+ *
183
+ *
31
+ * This program is distributed in the hope that it will be useful, but WITHOUT
184
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
32
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
185
+ *
33
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
186
+ * SPDX-License-Identifier: GPL-2.0-or-later
34
+ * for more details.
35
+ */
187
+ */
36
+
188
+
37
+#include "qemu/osdep.h"
189
+#include "qemu/osdep.h"
38
+#include "qemu-common.h"
190
+#include "hw/pci-host/fsl_imx8m_phy.h"
39
+#include "libqos/libqos.h"
191
+#include "hw/resettable.h"
40
+#include "qapi/qmp/qdict.h"
192
+#include "migration/vmstate.h"
41
+#include "qapi/qmp/qnum.h"
193
+
42
+#include "qemu/bitops.h"
194
+#define CMN_REG075 0x1d4
43
+#include "qemu/iov.h"
195
+#define ANA_PLL_LOCK_DONE BIT(1)
44
+
196
+#define ANA_PLL_AFC_DONE BIT(0)
45
+/* Name of the emc device. */
197
+
46
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
198
+static uint64_t fsl_imx8m_pcie_phy_read(void *opaque, hwaddr offset,
47
+
199
+ unsigned size)
48
+/* Timeout for various operations, in seconds. */
200
+{
49
+#define TIMEOUT_SECONDS 10
201
+ FslImx8mPciePhyState *s = opaque;
50
+
202
+
51
+/* Address in memory of the descriptor. */
203
+ if (offset == CMN_REG075) {
52
+#define DESC_ADDR (1 << 20) /* 1 MiB */
204
+ return s->data[offset] | ANA_PLL_LOCK_DONE | ANA_PLL_AFC_DONE;
53
+
205
+ }
54
+/* Address in memory of the data packet. */
206
+
55
+#define DATA_ADDR (DESC_ADDR + 4096)
207
+ return s->data[offset];
56
+
208
+}
57
+#define CRC_LENGTH 4
209
+
58
+
210
+static void fsl_imx8m_pcie_phy_write(void *opaque, hwaddr offset,
59
+#define NUM_TX_DESCRIPTORS 3
211
+ uint64_t value, unsigned size)
60
+#define NUM_RX_DESCRIPTORS 2
212
+{
61
+
213
+ FslImx8mPciePhyState *s = opaque;
62
+/* Size of tx,rx test buffers. */
214
+
63
+#define TX_DATA_LEN 64
215
+ s->data[offset] = value;
64
+#define RX_DATA_LEN 64
216
+}
65
+
217
+
66
+#define TX_STEP_COUNT 10000
218
+static const MemoryRegionOps fsl_imx8m_pcie_phy_ops = {
67
+#define RX_STEP_COUNT 10000
219
+ .read = fsl_imx8m_pcie_phy_read,
68
+
220
+ .write = fsl_imx8m_pcie_phy_write,
69
+/* 32-bit register indices. */
221
+ .impl = {
70
+typedef enum NPCM7xxPWMRegister {
222
+ .min_access_size = 1,
71
+ /* Control registers. */
223
+ .max_access_size = 1,
72
+ REG_CAMCMR,
224
+ },
73
+ REG_CAMEN,
225
+ .valid = {
74
+
226
+ .min_access_size = 1,
75
+ /* There are 16 CAMn[ML] registers. */
227
+ .max_access_size = 8,
76
+ REG_CAMM_BASE,
228
+ },
77
+ REG_CAML_BASE,
229
+ .endianness = DEVICE_LITTLE_ENDIAN,
78
+
79
+ REG_TXDLSA = 0x22,
80
+ REG_RXDLSA,
81
+ REG_MCMDR,
82
+ REG_MIID,
83
+ REG_MIIDA,
84
+ REG_FFTCR,
85
+ REG_TSDR,
86
+ REG_RSDR,
87
+ REG_DMARFC,
88
+ REG_MIEN,
89
+
90
+ /* Status registers. */
91
+ REG_MISTA,
92
+ REG_MGSTA,
93
+ REG_MPCNT,
94
+ REG_MRPC,
95
+ REG_MRPCC,
96
+ REG_MREPC,
97
+ REG_DMARFS,
98
+ REG_CTXDSA,
99
+ REG_CTXBSA,
100
+ REG_CRXDSA,
101
+ REG_CRXBSA,
102
+
103
+ NPCM7XX_NUM_EMC_REGS,
104
+} NPCM7xxPWMRegister;
105
+
106
+enum { NUM_CAMML_REGS = 16 };
107
+
108
+/* REG_CAMCMR fields */
109
+/* Enable CAM Compare */
110
+#define REG_CAMCMR_ECMP (1 << 4)
111
+/* Accept Unicast Packet */
112
+#define REG_CAMCMR_AUP (1 << 0)
113
+
114
+/* REG_MCMDR fields */
115
+/* Software Reset */
116
+#define REG_MCMDR_SWR (1 << 24)
117
+/* Frame Transmission On */
118
+#define REG_MCMDR_TXON (1 << 8)
119
+/* Accept Long Packet */
120
+#define REG_MCMDR_ALP (1 << 1)
121
+/* Frame Reception On */
122
+#define REG_MCMDR_RXON (1 << 0)
123
+
124
+/* REG_MIEN fields */
125
+/* Enable Transmit Completion Interrupt */
126
+#define REG_MIEN_ENTXCP (1 << 18)
127
+/* Enable Transmit Interrupt */
128
+#define REG_MIEN_ENTXINTR (1 << 16)
129
+/* Enable Receive Good Interrupt */
130
+#define REG_MIEN_ENRXGD (1 << 4)
131
+/* ENable Receive Interrupt */
132
+#define REG_MIEN_ENRXINTR (1 << 0)
133
+
134
+/* REG_MISTA fields */
135
+/* Transmit Bus Error Interrupt */
136
+#define REG_MISTA_TXBERR (1 << 24)
137
+/* Transmit Descriptor Unavailable Interrupt */
138
+#define REG_MISTA_TDU (1 << 23)
139
+/* Transmit Completion Interrupt */
140
+#define REG_MISTA_TXCP (1 << 18)
141
+/* Transmit Interrupt */
142
+#define REG_MISTA_TXINTR (1 << 16)
143
+/* Receive Bus Error Interrupt */
144
+#define REG_MISTA_RXBERR (1 << 11)
145
+/* Receive Descriptor Unavailable Interrupt */
146
+#define REG_MISTA_RDU (1 << 10)
147
+/* DMA Early Notification Interrupt */
148
+#define REG_MISTA_DENI (1 << 9)
149
+/* Maximum Frame Length Interrupt */
150
+#define REG_MISTA_DFOI (1 << 8)
151
+/* Receive Good Interrupt */
152
+#define REG_MISTA_RXGD (1 << 4)
153
+/* Packet Too Long Interrupt */
154
+#define REG_MISTA_PTLE (1 << 3)
155
+/* Receive Interrupt */
156
+#define REG_MISTA_RXINTR (1 << 0)
157
+
158
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
159
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
160
+
161
+struct NPCM7xxEMCTxDesc {
162
+ uint32_t flags;
163
+ uint32_t txbsa;
164
+ uint32_t status_and_length;
165
+ uint32_t ntxdsa;
166
+};
230
+};
167
+
231
+
168
+struct NPCM7xxEMCRxDesc {
232
+static void fsl_imx8m_pcie_phy_realize(DeviceState *dev, Error **errp)
169
+ uint32_t status_and_length;
233
+{
170
+ uint32_t rxbsa;
234
+ FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(dev);
171
+ uint32_t reserved;
235
+
172
+ uint32_t nrxdsa;
236
+ memory_region_init_io(&s->iomem, OBJECT(s), &fsl_imx8m_pcie_phy_ops, s,
237
+ TYPE_FSL_IMX8M_PCIE_PHY, ARRAY_SIZE(s->data));
238
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
239
+}
240
+
241
+static void fsl_imx8m_pcie_phy_reset_hold(Object *obj, ResetType type)
242
+{
243
+ FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(obj);
244
+
245
+ memset(s->data, 0, sizeof(s->data));
246
+}
247
+
248
+static const VMStateDescription fsl_imx8m_pcie_phy_vmstate = {
249
+ .name = "fsl-imx8m-pcie-phy",
250
+ .version_id = 1,
251
+ .minimum_version_id = 1,
252
+ .fields = (const VMStateField[]) {
253
+ VMSTATE_UINT8_ARRAY(data, FslImx8mPciePhyState,
254
+ FSL_IMX8M_PCIE_PHY_DATA_SIZE),
255
+ VMSTATE_END_OF_LIST()
256
+ }
173
+};
257
+};
174
+
258
+
175
+/* NPCM7xxEMCTxDesc.flags values */
259
+static void fsl_imx8m_pcie_phy_class_init(ObjectClass *klass, void *data)
176
+/* Owner: 0 = cpu, 1 = emc */
260
+{
177
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
261
+ DeviceClass *dc = DEVICE_CLASS(klass);
178
+/* Transmit interrupt enable */
262
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
179
+#define TX_DESC_FLAG_INTEN (1 << 2)
263
+
180
+
264
+ dc->realize = fsl_imx8m_pcie_phy_realize;
181
+/* NPCM7xxEMCTxDesc.status_and_length values */
265
+ dc->vmsd = &fsl_imx8m_pcie_phy_vmstate;
182
+/* Transmission complete */
266
+ rc->phases.hold = fsl_imx8m_pcie_phy_reset_hold;
183
+#define TX_DESC_STATUS_TXCP (1 << 19)
267
+}
184
+/* Transmit interrupt */
268
+
185
+#define TX_DESC_STATUS_TXINTR (1 << 16)
269
+static const TypeInfo fsl_imx8m_pcie_phy_types[] = {
186
+
187
+/* NPCM7xxEMCRxDesc.status_and_length values */
188
+/* Owner: 0b00 = cpu, 0b10 = emc */
189
+#define RX_DESC_STATUS_OWNER_SHIFT 30
190
+#define RX_DESC_STATUS_OWNER_MASK 0xc0000000
191
+/* Frame Reception Complete */
192
+#define RX_DESC_STATUS_RXGD (1 << 20)
193
+/* Packet too long */
194
+#define RX_DESC_STATUS_PTLE (1 << 19)
195
+/* Receive Interrupt */
196
+#define RX_DESC_STATUS_RXINTR (1 << 16)
197
+
198
+#define RX_DESC_PKT_LEN(word) ((uint32_t) (word) & 0xffff)
199
+
200
+typedef struct EMCModule {
201
+ int rx_irq;
202
+ int tx_irq;
203
+ uint64_t base_addr;
204
+} EMCModule;
205
+
206
+typedef struct TestData {
207
+ const EMCModule *module;
208
+} TestData;
209
+
210
+static const EMCModule emc_module_list[] = {
211
+ {
270
+ {
212
+ .rx_irq = 15,
271
+ .name = TYPE_FSL_IMX8M_PCIE_PHY,
213
+ .tx_irq = 16,
272
+ .parent = TYPE_SYS_BUS_DEVICE,
214
+ .base_addr = 0xf0825000
273
+ .instance_size = sizeof(FslImx8mPciePhyState),
215
+ },
274
+ .class_init = fsl_imx8m_pcie_phy_class_init,
216
+ {
217
+ .rx_irq = 114,
218
+ .tx_irq = 115,
219
+ .base_addr = 0xf0826000
220
+ }
275
+ }
221
+};
276
+};
222
+
277
+
223
+/* Returns the index of the EMC module. */
278
+DEFINE_TYPES(fsl_imx8m_pcie_phy_types)
224
+static int emc_module_index(const EMCModule *mod)
279
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
225
+{
280
index XXXXXXX..XXXXXXX 100644
226
+ ptrdiff_t diff = mod - emc_module_list;
281
--- a/hw/arm/Kconfig
227
+
282
+++ b/hw/arm/Kconfig
228
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(emc_module_list));
283
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
229
+
284
230
+ return diff;
285
config FSL_IMX8MP
231
+}
286
bool
232
+
287
+ imply PCI_DEVICES
233
+static void packet_test_clear(void *sockets)
288
select ARM_GIC
234
+{
289
select FSL_IMX8MP_ANALOG
235
+ int *test_sockets = sockets;
290
select FSL_IMX8MP_CCM
236
+
291
select IMX
237
+ close(test_sockets[0]);
292
+ select PCI_EXPRESS_DESIGNWARE
238
+ g_free(test_sockets);
293
+ select PCI_EXPRESS_FSL_IMX8M_PHY
239
+}
294
select SDHCI
240
+
295
select UNIMP
241
+static int *packet_test_init(int module_num, GString *cmd_line)
296
242
+{
297
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
243
+ int *test_sockets = g_new(int, 2);
298
index XXXXXXX..XXXXXXX 100644
244
+ int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets);
299
--- a/hw/pci-host/Kconfig
245
+ g_assert_cmpint(ret, != , -1);
300
+++ b/hw/pci-host/Kconfig
246
+
301
@@ -XXX,XX +XXX,XX @@ config ASTRO
247
+ /*
302
bool
248
+ * KISS and use -nic. We specify two nics (both emc{0,1}) because there's
303
select PCI
249
+ * currently no way to specify only emc1: The driver implicitly relies on
304
250
+ * emc[i] == nd_table[i].
305
+config PCI_EXPRESS_FSL_IMX8M_PHY
251
+ */
306
+ bool
252
+ if (module_num == 0) {
307
+
253
+ g_string_append_printf(cmd_line,
308
config GT64120
254
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " "
309
bool
255
+ " -nic user,model=" TYPE_NPCM7XX_EMC " ",
310
select PCI
256
+ test_sockets[1]);
311
diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build
257
+ } else {
312
index XXXXXXX..XXXXXXX 100644
258
+ g_string_append_printf(cmd_line,
313
--- a/hw/pci-host/meson.build
259
+ " -nic user,model=" TYPE_NPCM7XX_EMC " "
314
+++ b/hw/pci-host/meson.build
260
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " ",
315
@@ -XXX,XX +XXX,XX @@ pci_ss.add(when: 'CONFIG_ARTICIA', if_true: files('articia.c'))
261
+ test_sockets[1]);
316
pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c'))
262
+ }
317
263
+
318
# ARM devices
264
+ g_test_queue_destroy(packet_test_clear, test_sockets);
319
+pci_ss.add(when: 'CONFIG_PCI_EXPRESS_FSL_IMX8M_PHY', if_true: files('fsl_imx8m_phy.c'))
265
+ return test_sockets;
320
pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
266
+}
321
267
+
322
# HPPA devices
268
+static uint32_t emc_read(QTestState *qts, const EMCModule *mod,
269
+ NPCM7xxPWMRegister regno)
270
+{
271
+ return qtest_readl(qts, mod->base_addr + regno * sizeof(uint32_t));
272
+}
273
+
274
+static void emc_write(QTestState *qts, const EMCModule *mod,
275
+ NPCM7xxPWMRegister regno, uint32_t value)
276
+{
277
+ qtest_writel(qts, mod->base_addr + regno * sizeof(uint32_t), value);
278
+}
279
+
280
+static void emc_read_tx_desc(QTestState *qts, uint32_t addr,
281
+ NPCM7xxEMCTxDesc *desc)
282
+{
283
+ qtest_memread(qts, addr, desc, sizeof(*desc));
284
+ desc->flags = le32_to_cpu(desc->flags);
285
+ desc->txbsa = le32_to_cpu(desc->txbsa);
286
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
287
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
288
+}
289
+
290
+static void emc_write_tx_desc(QTestState *qts, const NPCM7xxEMCTxDesc *desc,
291
+ uint32_t addr)
292
+{
293
+ NPCM7xxEMCTxDesc le_desc;
294
+
295
+ le_desc.flags = cpu_to_le32(desc->flags);
296
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
297
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
298
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
299
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
300
+}
301
+
302
+static void emc_read_rx_desc(QTestState *qts, uint32_t addr,
303
+ NPCM7xxEMCRxDesc *desc)
304
+{
305
+ qtest_memread(qts, addr, desc, sizeof(*desc));
306
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
307
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
308
+ desc->reserved = le32_to_cpu(desc->reserved);
309
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
310
+}
311
+
312
+static void emc_write_rx_desc(QTestState *qts, const NPCM7xxEMCRxDesc *desc,
313
+ uint32_t addr)
314
+{
315
+ NPCM7xxEMCRxDesc le_desc;
316
+
317
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
318
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
319
+ le_desc.reserved = cpu_to_le32(desc->reserved);
320
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
321
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
322
+}
323
+
324
+/*
325
+ * Reset the EMC module.
326
+ * The module must be reset before, e.g., TXDLSA,RXDLSA are changed.
327
+ */
328
+static bool emc_soft_reset(QTestState *qts, const EMCModule *mod)
329
+{
330
+ uint32_t val;
331
+ uint64_t end_time;
332
+
333
+ emc_write(qts, mod, REG_MCMDR, REG_MCMDR_SWR);
334
+
335
+ /*
336
+ * Wait for device to reset as the linux driver does.
337
+ * During reset the AHB reads 0 for all registers. So first wait for
338
+ * something that resets to non-zero, and then wait for SWR becoming 0.
339
+ */
340
+ end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
341
+
342
+ do {
343
+ qtest_clock_step(qts, 100);
344
+ val = emc_read(qts, mod, REG_FFTCR);
345
+ } while (val == 0 && g_get_monotonic_time() < end_time);
346
+ if (val != 0) {
347
+ do {
348
+ qtest_clock_step(qts, 100);
349
+ val = emc_read(qts, mod, REG_MCMDR);
350
+ if ((val & REG_MCMDR_SWR) == 0) {
351
+ /*
352
+ * N.B. The CAMs have been reset here, so macaddr matching of
353
+ * incoming packets will not work.
354
+ */
355
+ return true;
356
+ }
357
+ } while (g_get_monotonic_time() < end_time);
358
+ }
359
+
360
+ g_message("%s: Timeout expired", __func__);
361
+ return false;
362
+}
363
+
364
+/* Check emc registers are reset to default value. */
365
+static void test_init(gconstpointer test_data)
366
+{
367
+ const TestData *td = test_data;
368
+ const EMCModule *mod = td->module;
369
+ QTestState *qts = qtest_init("-machine quanta-gsj");
370
+ int i;
371
+
372
+#define CHECK_REG(regno, value) \
373
+ do { \
374
+ g_assert_cmphex(emc_read(qts, mod, (regno)), ==, (value)); \
375
+ } while (0)
376
+
377
+ CHECK_REG(REG_CAMCMR, 0);
378
+ CHECK_REG(REG_CAMEN, 0);
379
+ CHECK_REG(REG_TXDLSA, 0xfffffffc);
380
+ CHECK_REG(REG_RXDLSA, 0xfffffffc);
381
+ CHECK_REG(REG_MCMDR, 0);
382
+ CHECK_REG(REG_MIID, 0);
383
+ CHECK_REG(REG_MIIDA, 0x00900000);
384
+ CHECK_REG(REG_FFTCR, 0x0101);
385
+ CHECK_REG(REG_DMARFC, 0x0800);
386
+ CHECK_REG(REG_MIEN, 0);
387
+ CHECK_REG(REG_MISTA, 0);
388
+ CHECK_REG(REG_MGSTA, 0);
389
+ CHECK_REG(REG_MPCNT, 0x7fff);
390
+ CHECK_REG(REG_MRPC, 0);
391
+ CHECK_REG(REG_MRPCC, 0);
392
+ CHECK_REG(REG_MREPC, 0);
393
+ CHECK_REG(REG_DMARFS, 0);
394
+ CHECK_REG(REG_CTXDSA, 0);
395
+ CHECK_REG(REG_CTXBSA, 0);
396
+ CHECK_REG(REG_CRXDSA, 0);
397
+ CHECK_REG(REG_CRXBSA, 0);
398
+
399
+#undef CHECK_REG
400
+
401
+ for (i = 0; i < NUM_CAMML_REGS; ++i) {
402
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAMM_BASE + i * 2), ==,
403
+ 0);
404
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAML_BASE + i * 2), ==,
405
+ 0);
406
+ }
407
+
408
+ qtest_quit(qts);
409
+}
410
+
411
+static bool emc_wait_irq(QTestState *qts, const EMCModule *mod, int step,
412
+ bool is_tx)
413
+{
414
+ uint64_t end_time =
415
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
416
+
417
+ do {
418
+ if (qtest_get_irq(qts, is_tx ? mod->tx_irq : mod->rx_irq)) {
419
+ return true;
420
+ }
421
+ qtest_clock_step(qts, step);
422
+ } while (g_get_monotonic_time() < end_time);
423
+
424
+ g_message("%s: Timeout expired", __func__);
425
+ return false;
426
+}
427
+
428
+static bool emc_wait_mista(QTestState *qts, const EMCModule *mod, int step,
429
+ uint32_t flag)
430
+{
431
+ uint64_t end_time =
432
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
433
+
434
+ do {
435
+ uint32_t mista = emc_read(qts, mod, REG_MISTA);
436
+ if (mista & flag) {
437
+ return true;
438
+ }
439
+ qtest_clock_step(qts, step);
440
+ } while (g_get_monotonic_time() < end_time);
441
+
442
+ g_message("%s: Timeout expired", __func__);
443
+ return false;
444
+}
445
+
446
+static bool wait_socket_readable(int fd)
447
+{
448
+ fd_set read_fds;
449
+ struct timeval tv;
450
+ int rv;
451
+
452
+ FD_ZERO(&read_fds);
453
+ FD_SET(fd, &read_fds);
454
+ tv.tv_sec = TIMEOUT_SECONDS;
455
+ tv.tv_usec = 0;
456
+ rv = select(fd + 1, &read_fds, NULL, NULL, &tv);
457
+ if (rv == -1) {
458
+ perror("select");
459
+ } else if (rv == 0) {
460
+ g_message("%s: Timeout expired", __func__);
461
+ }
462
+ return rv == 1;
463
+}
464
+
465
+/* Initialize *desc (in host endian format). */
466
+static void init_tx_desc(NPCM7xxEMCTxDesc *desc, size_t count,
467
+ uint32_t desc_addr)
468
+{
469
+ g_assert(count >= 2);
470
+ memset(&desc[0], 0, sizeof(*desc) * count);
471
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
472
+ for (size_t i = 0; i < count - 1; ++i) {
473
+ desc[i].flags =
474
+ (TX_DESC_FLAG_OWNER_MASK | /* owner = 1: emc */
475
+ TX_DESC_FLAG_INTEN |
476
+ 0 | /* crc append = 0 */
477
+ 0 /* padding enable = 0 */);
478
+ desc[i].status_and_length =
479
+ (0 | /* collision count = 0 */
480
+ 0 | /* SQE = 0 */
481
+ 0 | /* PAU = 0 */
482
+ 0 | /* TXHA = 0 */
483
+ 0 | /* LC = 0 */
484
+ 0 | /* TXABT = 0 */
485
+ 0 | /* NCS = 0 */
486
+ 0 | /* EXDEF = 0 */
487
+ 0 | /* TXCP = 0 */
488
+ 0 | /* DEF = 0 */
489
+ 0 | /* TXINTR = 0 */
490
+ 0 /* length filled in later */);
491
+ desc[i].ntxdsa = desc_addr + (i + 1) * sizeof(*desc);
492
+ }
493
+}
494
+
495
+static void enable_tx(QTestState *qts, const EMCModule *mod,
496
+ const NPCM7xxEMCTxDesc *desc, size_t count,
497
+ uint32_t desc_addr, uint32_t mien_flags)
498
+{
499
+ /* Write the descriptors to guest memory. */
500
+ for (size_t i = 0; i < count; ++i) {
501
+ emc_write_tx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
502
+ }
503
+
504
+ /* Trigger sending the packet. */
505
+ /* The module must be reset before changing TXDLSA. */
506
+ g_assert(emc_soft_reset(qts, mod));
507
+ emc_write(qts, mod, REG_TXDLSA, desc_addr);
508
+ emc_write(qts, mod, REG_CTXDSA, ~0);
509
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENTXCP | mien_flags);
510
+ {
511
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
512
+ mcmdr |= REG_MCMDR_TXON;
513
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
514
+ }
515
+
516
+ /* Prod the device to send the packet. */
517
+ emc_write(qts, mod, REG_TSDR, 1);
518
+}
519
+
520
+static void emc_send_verify1(QTestState *qts, const EMCModule *mod, int fd,
521
+ bool with_irq, uint32_t desc_addr,
522
+ uint32_t next_desc_addr,
523
+ const char *test_data, int test_size)
524
+{
525
+ NPCM7xxEMCTxDesc result_desc;
526
+ uint32_t expected_mask, expected_value, recv_len;
527
+ int ret;
528
+ char buffer[TX_DATA_LEN];
529
+
530
+ g_assert(wait_socket_readable(fd));
531
+
532
+ /* Read the descriptor back. */
533
+ emc_read_tx_desc(qts, desc_addr, &result_desc);
534
+ /* Descriptor should be owned by cpu now. */
535
+ g_assert((result_desc.flags & TX_DESC_FLAG_OWNER_MASK) == 0);
536
+ /* Test the status bits, ignoring the length field. */
537
+ expected_mask = 0xffff << 16;
538
+ expected_value = TX_DESC_STATUS_TXCP;
539
+ if (with_irq) {
540
+ expected_value |= TX_DESC_STATUS_TXINTR;
541
+ }
542
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
543
+ expected_value);
544
+
545
+ /* Check data sent to the backend. */
546
+ recv_len = ~0;
547
+ ret = qemu_recv(fd, &recv_len, sizeof(recv_len), MSG_DONTWAIT);
548
+ g_assert_cmpint(ret, == , sizeof(recv_len));
549
+
550
+ g_assert(wait_socket_readable(fd));
551
+ memset(buffer, 0xff, sizeof(buffer));
552
+ ret = qemu_recv(fd, buffer, test_size, MSG_DONTWAIT);
553
+ g_assert_cmpmem(buffer, ret, test_data, test_size);
554
+}
555
+
556
+static void emc_send_verify(QTestState *qts, const EMCModule *mod, int fd,
557
+ bool with_irq)
558
+{
559
+ NPCM7xxEMCTxDesc desc[NUM_TX_DESCRIPTORS];
560
+ uint32_t desc_addr = DESC_ADDR;
561
+ static const char test1_data[] = "TEST1";
562
+ static const char test2_data[] = "Testing 1 2 3 ...";
563
+ uint32_t data1_addr = DATA_ADDR;
564
+ uint32_t data2_addr = data1_addr + sizeof(test1_data);
565
+ bool got_tdu;
566
+ uint32_t end_desc_addr;
567
+
568
+ /* Prepare test data buffer. */
569
+ qtest_memwrite(qts, data1_addr, test1_data, sizeof(test1_data));
570
+ qtest_memwrite(qts, data2_addr, test2_data, sizeof(test2_data));
571
+
572
+ init_tx_desc(&desc[0], NUM_TX_DESCRIPTORS, desc_addr);
573
+ desc[0].txbsa = data1_addr;
574
+ desc[0].status_and_length |= sizeof(test1_data);
575
+ desc[1].txbsa = data2_addr;
576
+ desc[1].status_and_length |= sizeof(test2_data);
577
+
578
+ enable_tx(qts, mod, &desc[0], NUM_TX_DESCRIPTORS, desc_addr,
579
+ with_irq ? REG_MIEN_ENTXINTR : 0);
580
+
581
+ /*
582
+ * It's problematic to observe the interrupt for each packet.
583
+ * Instead just wait until all the packets go out.
584
+ */
585
+ got_tdu = false;
586
+ while (!got_tdu) {
587
+ if (with_irq) {
588
+ g_assert_true(emc_wait_irq(qts, mod, TX_STEP_COUNT,
589
+ /*is_tx=*/true));
590
+ } else {
591
+ g_assert_true(emc_wait_mista(qts, mod, TX_STEP_COUNT,
592
+ REG_MISTA_TXINTR));
593
+ }
594
+ got_tdu = !!(emc_read(qts, mod, REG_MISTA) & REG_MISTA_TDU);
595
+ /* If we don't have TDU yet, reset the interrupt. */
596
+ if (!got_tdu) {
597
+ emc_write(qts, mod, REG_MISTA,
598
+ emc_read(qts, mod, REG_MISTA) & 0xffff0000);
599
+ }
600
+ }
601
+
602
+ end_desc_addr = desc_addr + 2 * sizeof(desc[0]);
603
+ g_assert_cmphex(emc_read(qts, mod, REG_CTXDSA), ==, end_desc_addr);
604
+ g_assert_cmphex(emc_read(qts, mod, REG_MISTA), ==,
605
+ REG_MISTA_TXCP | REG_MISTA_TXINTR | REG_MISTA_TDU);
606
+
607
+ emc_send_verify1(qts, mod, fd, with_irq,
608
+ desc_addr, end_desc_addr,
609
+ test1_data, sizeof(test1_data));
610
+ emc_send_verify1(qts, mod, fd, with_irq,
611
+ desc_addr + sizeof(desc[0]), end_desc_addr,
612
+ test2_data, sizeof(test2_data));
613
+}
614
+
615
+/* Initialize *desc (in host endian format). */
616
+static void init_rx_desc(NPCM7xxEMCRxDesc *desc, size_t count,
617
+ uint32_t desc_addr, uint32_t data_addr)
618
+{
619
+ g_assert_true(count >= 2);
620
+ memset(desc, 0, sizeof(*desc) * count);
621
+ desc[0].rxbsa = data_addr;
622
+ desc[0].status_and_length =
623
+ (0b10 << RX_DESC_STATUS_OWNER_SHIFT | /* owner = 10: emc */
624
+ 0 | /* RP = 0 */
625
+ 0 | /* ALIE = 0 */
626
+ 0 | /* RXGD = 0 */
627
+ 0 | /* PTLE = 0 */
628
+ 0 | /* CRCE = 0 */
629
+ 0 | /* RXINTR = 0 */
630
+ 0 /* length (filled in later) */);
631
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
632
+ desc[0].nrxdsa = desc_addr + sizeof(*desc);
633
+}
634
+
635
+static void enable_rx(QTestState *qts, const EMCModule *mod,
636
+ const NPCM7xxEMCRxDesc *desc, size_t count,
637
+ uint32_t desc_addr, uint32_t mien_flags,
638
+ uint32_t mcmdr_flags)
639
+{
640
+ /*
641
+ * Write the descriptor to guest memory.
642
+ * FWIW, IWBN if the docs said the buffer needs to be at least DMARFC
643
+ * bytes.
644
+ */
645
+ for (size_t i = 0; i < count; ++i) {
646
+ emc_write_rx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
647
+ }
648
+
649
+ /* Trigger receiving the packet. */
650
+ /* The module must be reset before changing RXDLSA. */
651
+ g_assert(emc_soft_reset(qts, mod));
652
+ emc_write(qts, mod, REG_RXDLSA, desc_addr);
653
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENRXGD | mien_flags);
654
+
655
+ /*
656
+ * We don't know what the device's macaddr is, so just accept all
657
+ * unicast packets (AUP).
658
+ */
659
+ emc_write(qts, mod, REG_CAMCMR, REG_CAMCMR_AUP);
660
+ emc_write(qts, mod, REG_CAMEN, 1 << 0);
661
+ {
662
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
663
+ mcmdr |= REG_MCMDR_RXON | mcmdr_flags;
664
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
665
+ }
666
+
667
+ /* Prod the device to accept a packet. */
668
+ emc_write(qts, mod, REG_RSDR, 1);
669
+}
670
+
671
+static void emc_recv_verify(QTestState *qts, const EMCModule *mod, int fd,
672
+ bool with_irq)
673
+{
674
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
675
+ uint32_t desc_addr = DESC_ADDR;
676
+ uint32_t data_addr = DATA_ADDR;
677
+ int ret;
678
+ uint32_t expected_mask, expected_value;
679
+ NPCM7xxEMCRxDesc result_desc;
680
+
681
+ /* Prepare test data buffer. */
682
+ const char test[RX_DATA_LEN] = "TEST";
683
+ int len = htonl(sizeof(test));
684
+ const struct iovec iov[] = {
685
+ {
686
+ .iov_base = &len,
687
+ .iov_len = sizeof(len),
688
+ },{
689
+ .iov_base = (char *) test,
690
+ .iov_len = sizeof(test),
691
+ },
692
+ };
693
+
694
+ /*
695
+ * Reset the device BEFORE sending a test packet, otherwise the packet
696
+ * may get swallowed by an active device of an earlier test.
697
+ */
698
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
699
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
700
+ with_irq ? REG_MIEN_ENRXINTR : 0, 0);
701
+
702
+ /* Send test packet to device's socket. */
703
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test));
704
+ g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
705
+
706
+ /* Wait for RX interrupt. */
707
+ if (with_irq) {
708
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
709
+ } else {
710
+ g_assert_true(emc_wait_mista(qts, mod, RX_STEP_COUNT, REG_MISTA_RXGD));
711
+ }
712
+
713
+ g_assert_cmphex(emc_read(qts, mod, REG_CRXDSA), ==,
714
+ desc_addr + sizeof(desc[0]));
715
+
716
+ expected_mask = 0xffff;
717
+ expected_value = (REG_MISTA_DENI |
718
+ REG_MISTA_RXGD |
719
+ REG_MISTA_RXINTR);
720
+ g_assert_cmphex((emc_read(qts, mod, REG_MISTA) & expected_mask),
721
+ ==, expected_value);
722
+
723
+ /* Read the descriptor back. */
724
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
725
+ /* Descriptor should be owned by cpu now. */
726
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
727
+ /* Test the status bits, ignoring the length field. */
728
+ expected_mask = 0xffff << 16;
729
+ expected_value = RX_DESC_STATUS_RXGD;
730
+ if (with_irq) {
731
+ expected_value |= RX_DESC_STATUS_RXINTR;
732
+ }
733
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
734
+ expected_value);
735
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
736
+ RX_DATA_LEN + CRC_LENGTH);
737
+
738
+ {
739
+ char buffer[RX_DATA_LEN];
740
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
741
+ g_assert_cmpstr(buffer, == , "TEST");
742
+ }
743
+}
744
+
745
+static void emc_test_ptle(QTestState *qts, const EMCModule *mod, int fd)
746
+{
747
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
748
+ uint32_t desc_addr = DESC_ADDR;
749
+ uint32_t data_addr = DATA_ADDR;
750
+ int ret;
751
+ NPCM7xxEMCRxDesc result_desc;
752
+ uint32_t expected_mask, expected_value;
753
+
754
+ /* Prepare test data buffer. */
755
+#define PTLE_DATA_LEN 1600
756
+ char test_data[PTLE_DATA_LEN];
757
+ int len = htonl(sizeof(test_data));
758
+ const struct iovec iov[] = {
759
+ {
760
+ .iov_base = &len,
761
+ .iov_len = sizeof(len),
762
+ },{
763
+ .iov_base = (char *) test_data,
764
+ .iov_len = sizeof(test_data),
765
+ },
766
+ };
767
+ memset(test_data, 42, sizeof(test_data));
768
+
769
+ /*
770
+ * Reset the device BEFORE sending a test packet, otherwise the packet
771
+ * may get swallowed by an active device of an earlier test.
772
+ */
773
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
774
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
775
+ REG_MIEN_ENRXINTR, REG_MCMDR_ALP);
776
+
777
+ /* Send test packet to device's socket. */
778
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test_data));
779
+ g_assert_cmpint(ret, == , sizeof(test_data) + sizeof(len));
780
+
781
+ /* Wait for RX interrupt. */
782
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
783
+
784
+ /* Read the descriptor back. */
785
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
786
+ /* Descriptor should be owned by cpu now. */
787
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
788
+ /* Test the status bits, ignoring the length field. */
789
+ expected_mask = 0xffff << 16;
790
+ expected_value = (RX_DESC_STATUS_RXGD |
791
+ RX_DESC_STATUS_PTLE |
792
+ RX_DESC_STATUS_RXINTR);
793
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
794
+ expected_value);
795
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
796
+ PTLE_DATA_LEN + CRC_LENGTH);
797
+
798
+ {
799
+ char buffer[PTLE_DATA_LEN];
800
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
801
+ g_assert(memcmp(buffer, test_data, PTLE_DATA_LEN) == 0);
802
+ }
803
+}
804
+
805
+static void test_tx(gconstpointer test_data)
806
+{
807
+ const TestData *td = test_data;
808
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
809
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
810
+ cmd_line);
811
+ QTestState *qts = qtest_init(cmd_line->str);
812
+
813
+ /*
814
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
815
+ * the fork and before the exec, but that will require some harness
816
+ * improvements.
817
+ */
818
+ close(test_sockets[1]);
819
+ /* Defensive programming */
820
+ test_sockets[1] = -1;
821
+
822
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
823
+
824
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
825
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
826
+
827
+ qtest_quit(qts);
828
+}
829
+
830
+static void test_rx(gconstpointer test_data)
831
+{
832
+ const TestData *td = test_data;
833
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
834
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
835
+ cmd_line);
836
+ QTestState *qts = qtest_init(cmd_line->str);
837
+
838
+ /*
839
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
840
+ * the fork and before the exec, but that will require some harness
841
+ * improvements.
842
+ */
843
+ close(test_sockets[1]);
844
+ /* Defensive programming */
845
+ test_sockets[1] = -1;
846
+
847
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
848
+
849
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
850
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
851
+ emc_test_ptle(qts, td->module, test_sockets[0]);
852
+
853
+ qtest_quit(qts);
854
+}
855
+
856
+static void emc_add_test(const char *name, const TestData* td,
857
+ GTestDataFunc fn)
858
+{
859
+ g_autofree char *full_name = g_strdup_printf(
860
+ "npcm7xx_emc/emc[%d]/%s", emc_module_index(td->module), name);
861
+ qtest_add_data_func(full_name, td, fn);
862
+}
863
+#define add_test(name, td) emc_add_test(#name, td, test_##name)
864
+
865
+int main(int argc, char **argv)
866
+{
867
+ TestData test_data_list[ARRAY_SIZE(emc_module_list)];
868
+
869
+ g_test_init(&argc, &argv, NULL);
870
+
871
+ for (int i = 0; i < ARRAY_SIZE(emc_module_list); ++i) {
872
+ TestData *td = &test_data_list[i];
873
+
874
+ td->module = &emc_module_list[i];
875
+
876
+ add_test(init, td);
877
+ add_test(tx, td);
878
+ add_test(rx, td);
879
+ }
880
+
881
+ return g_test_run();
882
+}
883
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
884
index XXXXXXX..XXXXXXX 100644
885
--- a/tests/qtest/meson.build
886
+++ b/tests/qtest/meson.build
887
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
888
'npcm7xx_rng-test',
889
'npcm7xx_smbus-test',
890
'npcm7xx_timer-test',
891
- 'npcm7xx_watchdog_timer-test']
892
+ 'npcm7xx_watchdog_timer-test'] + \
893
+ (slirp.found() ? ['npcm7xx_emc-test'] : [])
894
qtests_arm = \
895
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
896
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
897
--
323
--
898
2.20.1
324
2.43.0
899
900
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Always perform one call instead of two for 16-byte operands.
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Use byte loads/stores directly into the vector register file
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
instead of extractions and deposits to a 64-bit local variable.
5
Message-id: 20250223114708.1780-10-shentey@gmail.com
6
6
[PMM: drop static const from gpio_table for GCC 7.5]
7
In order to easily receive pointers into the vector register file,
8
convert the helper to the gvec out-of-line signature. Move the
9
helper into vec_helper.c, where it can make use of H1 and clear_tail.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Tested-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 20210224230532.276878-1-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
8
---
17
target/arm/helper-a64.h | 2 +-
9
docs/system/arm/imx8mp-evk.rst | 1 +
18
target/arm/helper-a64.c | 32 ---------------------
10
include/hw/arm/fsl-imx8mp.h | 14 +++++++++
19
target/arm/translate-a64.c | 58 +++++---------------------------------
11
hw/arm/fsl-imx8mp.c | 55 ++++++++++++++++++++++++++++++++++
20
target/arm/vec_helper.c | 48 +++++++++++++++++++++++++++++++
12
3 files changed, 70 insertions(+)
21
4 files changed, 56 insertions(+), 84 deletions(-)
22
13
23
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
14
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
24
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/helper-a64.h
16
--- a/docs/system/arm/imx8mp-evk.rst
26
+++ b/target/arm/helper-a64.h
17
+++ b/docs/system/arm/imx8mp-evk.rst
27
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
18
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
28
DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
19
* 4 UARTs
29
DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
20
* 3 USDHC Storage Controllers
30
DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr)
21
* 1 Designware PCI Express Controller
31
-DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32)
22
+ * 5 GPIO Controllers
32
+DEF_HELPER_FLAGS_4(simd_tblx, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
* Secure Non-Volatile Storage (SNVS) including an RTC
33
DEF_HELPER_FLAGS_3(vfp_mulxs, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
24
* Clock Tree
34
DEF_HELPER_FLAGS_3(vfp_mulxd, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
25
35
DEF_HELPER_FLAGS_3(neon_ceq_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr)
26
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
36
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
37
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/helper-a64.c
28
--- a/include/hw/arm/fsl-imx8mp.h
39
+++ b/target/arm/helper-a64.c
29
+++ b/include/hw/arm/fsl-imx8mp.h
40
@@ -XXX,XX +XXX,XX @@ float64 HELPER(vfp_mulxd)(float64 a, float64 b, void *fpstp)
30
@@ -XXX,XX +XXX,XX @@
41
return float64_mul(a, b, fpst);
31
42
}
32
#include "cpu.h"
43
33
#include "hw/char/imx_serial.h"
44
-uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
34
+#include "hw/gpio/imx_gpio.h"
45
- uint32_t rn, uint32_t numregs)
35
#include "hw/intc/arm_gicv3_common.h"
46
-{
36
#include "hw/misc/imx7_snvs.h"
47
- /* Helper function for SIMD TBL and TBX. We have to do the table
37
#include "hw/misc/imx8mp_analog.h"
48
- * lookup part for the 64 bits worth of indices we're passed in.
38
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
49
- * result is the initial results vector (either zeroes for TBL
39
50
- * or some guest values for TBX), rn the register number where
40
enum FslImx8mpConfiguration {
51
- * the table starts, and numregs the number of registers in the table.
41
FSL_IMX8MP_NUM_CPUS = 4,
52
- * We return the results of the lookups.
42
+ FSL_IMX8MP_NUM_GPIOS = 5,
53
- */
43
FSL_IMX8MP_NUM_IRQS = 160,
54
- int shift;
44
FSL_IMX8MP_NUM_UARTS = 4,
55
-
45
FSL_IMX8MP_NUM_USDHCS = 3,
56
- for (shift = 0; shift < 64; shift += 8) {
46
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
57
- int index = extract64(indices, shift, 8);
47
58
- if (index < 16 * numregs) {
48
ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
59
- /* Convert index (a byte offset into the virtual table
49
GICv3State gic;
60
- * which is a series of 128-bit vectors concatenated)
50
+ IMXGPIOState gpio[FSL_IMX8MP_NUM_GPIOS];
61
- * into the correct register element plus a bit offset
51
IMX8MPCCMState ccm;
62
- * into that element, bearing in mind that the table
52
IMX8MPAnalogState analog;
63
- * can wrap around from V31 to V0.
53
IMX7SNVSState snvs;
64
- */
54
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
65
- int elt = (rn * 2 + (index >> 3)) % 64;
55
FSL_IMX8MP_UART5_IRQ = 30,
66
- int bitidx = (index & 7) * 8;
56
FSL_IMX8MP_UART6_IRQ = 16,
67
- uint64_t *q = aa64_vfp_qreg(env, elt >> 1);
57
68
- uint64_t val = extract64(q[elt & 1], bitidx, 8);
58
+ FSL_IMX8MP_GPIO1_LOW_IRQ = 64,
69
-
59
+ FSL_IMX8MP_GPIO1_HIGH_IRQ = 65,
70
- result = deposit64(result, shift, 8, val);
60
+ FSL_IMX8MP_GPIO2_LOW_IRQ = 66,
71
- }
61
+ FSL_IMX8MP_GPIO2_HIGH_IRQ = 67,
72
- }
62
+ FSL_IMX8MP_GPIO3_LOW_IRQ = 68,
73
- return result;
63
+ FSL_IMX8MP_GPIO3_HIGH_IRQ = 69,
74
-}
64
+ FSL_IMX8MP_GPIO4_LOW_IRQ = 70,
75
-
65
+ FSL_IMX8MP_GPIO4_HIGH_IRQ = 71,
76
/* 64bit/double versions of the neon float compare functions */
66
+ FSL_IMX8MP_GPIO5_LOW_IRQ = 72,
77
uint64_t HELPER(neon_ceq_f64)(float64 a, float64 b, void *fpstp)
67
+ FSL_IMX8MP_GPIO5_HIGH_IRQ = 73,
78
{
68
+
79
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
69
FSL_IMX8MP_PCI_INTA_IRQ = 126,
70
FSL_IMX8MP_PCI_INTB_IRQ = 125,
71
FSL_IMX8MP_PCI_INTC_IRQ = 124,
72
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
80
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/translate-a64.c
74
--- a/hw/arm/fsl-imx8mp.c
82
+++ b/target/arm/translate-a64.c
75
+++ b/hw/arm/fsl-imx8mp.c
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
76
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
84
int rm = extract32(insn, 16, 5);
77
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
85
int rn = extract32(insn, 5, 5);
86
int rd = extract32(insn, 0, 5);
87
- int is_tblx = extract32(insn, 12, 1);
88
- int len = extract32(insn, 13, 2);
89
- TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
90
- TCGv_i32 tcg_regno, tcg_numregs;
91
+ int is_tbx = extract32(insn, 12, 1);
92
+ int len = (extract32(insn, 13, 2) + 1) * 16;
93
94
if (op2 != 0) {
95
unallocated_encoding(s);
96
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
97
return;
98
}
78
}
99
79
100
- /* This does a table lookup: for every byte element in the input
80
+ for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
101
- * we index into a table formed from up to four vector registers,
81
+ g_autofree char *name = g_strdup_printf("gpio%d", i + 1);
102
- * and then the output is the result of the lookups. Our helper
82
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
103
- * function does the lookup operation for a single 64 bit part of
104
- * the input.
105
- */
106
- tcg_resl = tcg_temp_new_i64();
107
- tcg_resh = NULL;
108
-
109
- if (is_tblx) {
110
- read_vec_element(s, tcg_resl, rd, 0, MO_64);
111
- } else {
112
- tcg_gen_movi_i64(tcg_resl, 0);
113
- }
114
-
115
- if (is_q) {
116
- tcg_resh = tcg_temp_new_i64();
117
- if (is_tblx) {
118
- read_vec_element(s, tcg_resh, rd, 1, MO_64);
119
- } else {
120
- tcg_gen_movi_i64(tcg_resh, 0);
121
- }
122
- }
123
-
124
- tcg_idx = tcg_temp_new_i64();
125
- tcg_regno = tcg_const_i32(rn);
126
- tcg_numregs = tcg_const_i32(len + 1);
127
- read_vec_element(s, tcg_idx, rm, 0, MO_64);
128
- gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
129
- tcg_regno, tcg_numregs);
130
- if (is_q) {
131
- read_vec_element(s, tcg_idx, rm, 1, MO_64);
132
- gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
133
- tcg_regno, tcg_numregs);
134
- }
135
- tcg_temp_free_i64(tcg_idx);
136
- tcg_temp_free_i32(tcg_regno);
137
- tcg_temp_free_i32(tcg_numregs);
138
-
139
- write_vec_element(s, tcg_resl, rd, 0, MO_64);
140
- tcg_temp_free_i64(tcg_resl);
141
-
142
- if (is_q) {
143
- write_vec_element(s, tcg_resh, rd, 1, MO_64);
144
- tcg_temp_free_i64(tcg_resh);
145
- }
146
- clear_vec_high(s, is_q, rd);
147
+ tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, rd),
148
+ vec_full_reg_offset(s, rm), cpu_env,
149
+ is_q ? 16 : 8, vec_full_reg_size(s),
150
+ (len << 6) | (is_tbx << 5) | rn,
151
+ gen_helper_simd_tblx);
152
}
153
154
/* ZIP/UZP/TRN
155
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/vec_helper.c
158
+++ b/target/arm/vec_helper.c
159
@@ -XXX,XX +XXX,XX @@ DO_VRINT_RMODE(gvec_vrint_rm_h, helper_rinth, uint16_t)
160
DO_VRINT_RMODE(gvec_vrint_rm_s, helper_rints, uint32_t)
161
162
#undef DO_VRINT_RMODE
163
+
164
+#ifdef TARGET_AARCH64
165
+void HELPER(simd_tblx)(void *vd, void *vm, void *venv, uint32_t desc)
166
+{
167
+ const uint8_t *indices = vm;
168
+ CPUARMState *env = venv;
169
+ size_t oprsz = simd_oprsz(desc);
170
+ uint32_t rn = extract32(desc, SIMD_DATA_SHIFT, 5);
171
+ bool is_tbx = extract32(desc, SIMD_DATA_SHIFT + 5, 1);
172
+ uint32_t table_len = desc >> (SIMD_DATA_SHIFT + 6);
173
+ union {
174
+ uint8_t b[16];
175
+ uint64_t d[2];
176
+ } result;
177
+
178
+ /*
179
+ * We must construct the final result in a temp, lest the output
180
+ * overlaps the input table. For TBL, begin with zero; for TBX,
181
+ * begin with the original register contents. Note that we always
182
+ * copy 16 bytes here to avoid an extra branch; clearing the high
183
+ * bits of the register for oprsz == 8 is handled below.
184
+ */
185
+ if (is_tbx) {
186
+ memcpy(&result, vd, 16);
187
+ } else {
188
+ memset(&result, 0, 16);
189
+ }
83
+ }
190
+
84
+
191
+ for (size_t i = 0; i < oprsz; ++i) {
85
for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
192
+ uint32_t index = indices[H1(i)];
86
g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
87
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
88
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
89
qdev_get_gpio_in(gicdev, serial_table[i].irq));
90
}
91
92
+ /* GPIOs */
93
+ for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
94
+ struct {
95
+ hwaddr addr;
96
+ unsigned int irq_low;
97
+ unsigned int irq_high;
98
+ } gpio_table[FSL_IMX8MP_NUM_GPIOS] = {
99
+ {
100
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO1].addr,
101
+ FSL_IMX8MP_GPIO1_LOW_IRQ,
102
+ FSL_IMX8MP_GPIO1_HIGH_IRQ
103
+ },
104
+ {
105
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO2].addr,
106
+ FSL_IMX8MP_GPIO2_LOW_IRQ,
107
+ FSL_IMX8MP_GPIO2_HIGH_IRQ
108
+ },
109
+ {
110
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO3].addr,
111
+ FSL_IMX8MP_GPIO3_LOW_IRQ,
112
+ FSL_IMX8MP_GPIO3_HIGH_IRQ
113
+ },
114
+ {
115
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO4].addr,
116
+ FSL_IMX8MP_GPIO4_LOW_IRQ,
117
+ FSL_IMX8MP_GPIO4_HIGH_IRQ
118
+ },
119
+ {
120
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO5].addr,
121
+ FSL_IMX8MP_GPIO5_LOW_IRQ,
122
+ FSL_IMX8MP_GPIO5_HIGH_IRQ
123
+ },
124
+ };
193
+
125
+
194
+ if (index < table_len) {
126
+ object_property_set_bool(OBJECT(&s->gpio[i]), "has-edge-sel", true,
195
+ /*
127
+ &error_abort);
196
+ * Convert index (a byte offset into the virtual table
128
+ object_property_set_bool(OBJECT(&s->gpio[i]), "has-upper-pin-irq",
197
+ * which is a series of 128-bit vectors concatenated)
129
+ true, &error_abort);
198
+ * into the correct register element, bearing in mind
130
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
199
+ * that the table can wrap around from V31 to V0.
131
+ return;
200
+ */
201
+ const uint8_t *table = (const uint8_t *)
202
+ aa64_vfp_qreg(env, (rn + (index >> 4)) % 32);
203
+ result.b[H1(i)] = table[H1(index % 16)];
204
+ }
132
+ }
133
+
134
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
135
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
136
+ qdev_get_gpio_in(gicdev, gpio_table[i].irq_low));
137
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
138
+ qdev_get_gpio_in(gicdev, gpio_table[i].irq_high));
205
+ }
139
+ }
206
+
140
+
207
+ memcpy(vd, &result, 16);
141
/* USDHCs */
208
+ clear_tail(vd, oprsz, simd_maxsz(desc));
142
for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
209
+}
143
struct {
210
+#endif
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:
211
--
152
--
212
2.20.1
153
2.43.0
213
214
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
3
We hint the 'has_rpu' property is no longer required since commit
4
6908ec448b4 ("xlnx-zynqmp: Properly support the smp command line
5
option") which was released in QEMU v2.11.0.
6
7
Beside, this device is marked 'user_creatable = false', so the
8
only thing that could be setting the property is the board code
9
that creates the device.
10
11
Since the property is not user-facing, we can remove it without
12
going through the deprecation process.
13
2
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
16
Message-id: 20210219144350.1979905-1-f4bug@amsat.org
5
Message-id: 20250223114708.1780-11-shentey@gmail.com
6
[PMM: drop static const from i2c_table for GCC 7.5]
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
8
---
19
include/hw/arm/xlnx-zynqmp.h | 2 --
9
docs/system/arm/imx8mp-evk.rst | 1 +
20
hw/arm/xlnx-zynqmp.c | 6 ------
10
include/hw/arm/fsl-imx8mp.h | 11 +++++++++++
21
2 files changed, 8 deletions(-)
11
hw/arm/fsl-imx8mp.c | 29 +++++++++++++++++++++++++++++
12
hw/arm/Kconfig | 2 ++
13
4 files changed, 43 insertions(+)
22
14
23
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
15
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/xlnx-zynqmp.h
17
--- a/docs/system/arm/imx8mp-evk.rst
26
+++ b/include/hw/arm/xlnx-zynqmp.h
18
+++ b/docs/system/arm/imx8mp-evk.rst
27
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
19
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
28
bool secure;
20
* 3 USDHC Storage Controllers
29
/* Has the ARM Virtualization extensions? */
21
* 1 Designware PCI Express Controller
30
bool virt;
22
* 5 GPIO Controllers
31
- /* Has the RPU subsystem? */
23
+ * 6 I2C Controllers
32
- bool has_rpu;
24
* Secure Non-Volatile Storage (SNVS) including an RTC
33
25
* Clock Tree
34
/* CAN bus. */
26
35
CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
27
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
36
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
37
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/xlnx-zynqmp.c
29
--- a/include/hw/arm/fsl-imx8mp.h
39
+++ b/hw/arm/xlnx-zynqmp.c
30
+++ b/include/hw/arm/fsl-imx8mp.h
40
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
31
@@ -XXX,XX +XXX,XX @@
41
}
32
#include "cpu.h"
33
#include "hw/char/imx_serial.h"
34
#include "hw/gpio/imx_gpio.h"
35
+#include "hw/i2c/imx_i2c.h"
36
#include "hw/intc/arm_gicv3_common.h"
37
#include "hw/misc/imx7_snvs.h"
38
#include "hw/misc/imx8mp_analog.h"
39
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
40
enum FslImx8mpConfiguration {
41
FSL_IMX8MP_NUM_CPUS = 4,
42
FSL_IMX8MP_NUM_GPIOS = 5,
43
+ FSL_IMX8MP_NUM_I2CS = 6,
44
FSL_IMX8MP_NUM_IRQS = 160,
45
FSL_IMX8MP_NUM_UARTS = 4,
46
FSL_IMX8MP_NUM_USDHCS = 3,
47
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
48
IMX8MPCCMState ccm;
49
IMX8MPAnalogState analog;
50
IMX7SNVSState snvs;
51
+ IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
52
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
53
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
54
DesignwarePCIEHost pcie;
55
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
56
FSL_IMX8MP_UART5_IRQ = 30,
57
FSL_IMX8MP_UART6_IRQ = 16,
58
59
+ FSL_IMX8MP_I2C1_IRQ = 35,
60
+ FSL_IMX8MP_I2C2_IRQ = 36,
61
+ FSL_IMX8MP_I2C3_IRQ = 37,
62
+ FSL_IMX8MP_I2C4_IRQ = 38,
63
+
64
FSL_IMX8MP_GPIO1_LOW_IRQ = 64,
65
FSL_IMX8MP_GPIO1_HIGH_IRQ = 65,
66
FSL_IMX8MP_GPIO2_LOW_IRQ = 66,
67
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
68
FSL_IMX8MP_GPIO5_LOW_IRQ = 72,
69
FSL_IMX8MP_GPIO5_HIGH_IRQ = 73,
70
71
+ FSL_IMX8MP_I2C5_IRQ = 76,
72
+ FSL_IMX8MP_I2C6_IRQ = 77,
73
+
74
FSL_IMX8MP_PCI_INTA_IRQ = 126,
75
FSL_IMX8MP_PCI_INTB_IRQ = 125,
76
FSL_IMX8MP_PCI_INTC_IRQ = 124,
77
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/arm/fsl-imx8mp.c
80
+++ b/hw/arm/fsl-imx8mp.c
81
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
82
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
42
}
83
}
43
84
44
- if (s->has_rpu) {
85
+ for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
45
- info_report("The 'has_rpu' property is no longer required, to use the "
86
+ g_autofree char *name = g_strdup_printf("i2c%d", i + 1);
46
- "RPUs just use -smp 6.");
87
+ object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
47
- }
88
+ }
48
-
89
+
49
xlnx_zynqmp_create_rpu(ms, s, boot_cpu, &err);
90
for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
50
if (err) {
91
g_autofree char *name = g_strdup_printf("gpio%d", i + 1);
51
error_propagate(errp, err);
92
object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
52
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
93
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
53
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
94
qdev_get_gpio_in(gicdev, serial_table[i].irq));
54
DEFINE_PROP_BOOL("secure", XlnxZynqMPState, secure, false),
95
}
55
DEFINE_PROP_BOOL("virtualization", XlnxZynqMPState, virt, false),
96
56
- DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
97
+ /* I2Cs */
57
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
98
+ for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
58
MemoryRegion *),
99
+ struct {
59
DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
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
60
--
149
--
61
2.20.1
150
2.43.0
62
63
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Enable FEAT_SSBS for the "max" 32-bit CPU.
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
5
Message-id: 20250223114708.1780-12-shentey@gmail.com
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
[PMM: drop static const from spi_table for GCC 7.5]
7
Message-id: 20210216224543.16142-4-rebecca@nuviainc.com
8
[PMM: fix typo causing compilation failure]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
8
---
11
target/arm/cpu.c | 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/target/arm/cpu.c b/target/arm/cpu.c
14
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
16
--- a/docs/system/arm/imx8mp-evk.rst
17
+++ b/target/arm/cpu.c
17
+++ b/docs/system/arm/imx8mp-evk.rst
18
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
18
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
19
t = cpu->isar.id_pfr0;
19
* 1 Designware PCI Express Controller
20
t = FIELD_DP32(t, ID_PFR0, DIT, 1);
20
* 5 GPIO Controllers
21
cpu->isar.id_pfr0 = t;
21
* 6 I2C Controllers
22
+ * 3 SPI Controllers
23
* Secure Non-Volatile Storage (SNVS) including an RTC
24
* Clock Tree
25
26
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/arm/fsl-imx8mp.h
29
+++ b/include/hw/arm/fsl-imx8mp.h
30
@@ -XXX,XX +XXX,XX @@
31
#include "hw/pci-host/designware.h"
32
#include "hw/pci-host/fsl_imx8m_phy.h"
33
#include "hw/sd/sdhci.h"
34
+#include "hw/ssi/imx_spi.h"
35
#include "qom/object.h"
36
#include "qemu/units.h"
37
38
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
39
40
enum FslImx8mpConfiguration {
41
FSL_IMX8MP_NUM_CPUS = 4,
42
+ FSL_IMX8MP_NUM_ECSPIS = 3,
43
FSL_IMX8MP_NUM_GPIOS = 5,
44
FSL_IMX8MP_NUM_I2CS = 6,
45
FSL_IMX8MP_NUM_IRQS = 160,
46
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
47
IMX8MPCCMState ccm;
48
IMX8MPAnalogState analog;
49
IMX7SNVSState snvs;
50
+ IMXSPIState spi[FSL_IMX8MP_NUM_ECSPIS];
51
IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
52
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
53
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
54
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
55
FSL_IMX8MP_UART5_IRQ = 30,
56
FSL_IMX8MP_UART6_IRQ = 16,
57
58
+ FSL_IMX8MP_ECSPI1_IRQ = 31,
59
+ FSL_IMX8MP_ECSPI2_IRQ = 32,
60
+ FSL_IMX8MP_ECSPI3_IRQ = 33,
61
+ FSL_IMX8MP_ECSPI4_IRQ = 34,
22
+
62
+
23
+ t = cpu->isar.id_pfr2;
63
FSL_IMX8MP_I2C1_IRQ = 35,
24
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
64
FSL_IMX8MP_I2C2_IRQ = 36,
25
+ cpu->isar.id_pfr2 = t;
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);
26
}
72
}
27
#endif
73
28
}
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:
29
--
117
--
30
2.20.1
118
2.43.0
31
32
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Let add 'max' cpu while work goes on adding newer CPU types than
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Cortex-A72. This allows us to check SVE etc support.
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
5
Message-id: 20250223114708.1780-13-shentey@gmail.com
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
6
[PMM: drop static const from wdog_table for GCC 7.5]
7
Acked-by: Leif Lindholm <leif@nuviainc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210216150122.3830863-3-marcin.juszkiewicz@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
hw/arm/sbsa-ref.c | 1 +
9
docs/system/arm/imx8mp-evk.rst | 1 +
13
1 file changed, 1 insertion(+)
10
include/hw/arm/fsl-imx8mp.h | 7 +++++++
11
hw/arm/fsl-imx8mp.c | 28 ++++++++++++++++++++++++++++
12
hw/arm/Kconfig | 1 +
13
4 files changed, 37 insertions(+)
14
14
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
15
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/sbsa-ref.c
17
--- a/docs/system/arm/imx8mp-evk.rst
18
+++ b/hw/arm/sbsa-ref.c
18
+++ b/docs/system/arm/imx8mp-evk.rst
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
19
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
20
static const char * const valid_cpus[] = {
20
* 5 GPIO Controllers
21
ARM_CPU_TYPE_NAME("cortex-a57"),
21
* 6 I2C Controllers
22
ARM_CPU_TYPE_NAME("cortex-a72"),
22
* 3 SPI Controllers
23
+ ARM_CPU_TYPE_NAME("max"),
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,
24
};
44
};
25
45
26
static bool cpu_type_valid(const char *cpu)
46
struct FslImx8mpState {
47
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
48
IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
49
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
50
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
51
+ IMX2WdtState wdt[FSL_IMX8MP_NUM_WDTS];
52
DesignwarePCIEHost pcie;
53
FslImx8mPciePhyState pcie_phy;
54
};
55
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
56
FSL_IMX8MP_I2C5_IRQ = 76,
57
FSL_IMX8MP_I2C6_IRQ = 77,
58
59
+ FSL_IMX8MP_WDOG1_IRQ = 78,
60
+ FSL_IMX8MP_WDOG2_IRQ = 79,
61
+ FSL_IMX8MP_WDOG3_IRQ = 10,
62
+
63
FSL_IMX8MP_PCI_INTA_IRQ = 126,
64
FSL_IMX8MP_PCI_INTB_IRQ = 125,
65
FSL_IMX8MP_PCI_INTC_IRQ = 124,
66
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/fsl-imx8mp.c
69
+++ b/hw/arm/fsl-imx8mp.c
70
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
71
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
72
}
73
74
+ for (i = 0; i < FSL_IMX8MP_NUM_WDTS; i++) {
75
+ g_autofree char *name = g_strdup_printf("wdt%d", i);
76
+ object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
77
+ }
78
+
79
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
80
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
81
TYPE_FSL_IMX8M_PCIE_PHY);
82
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
83
sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
84
fsl_imx8mp_memmap[FSL_IMX8MP_SNVS_HP].addr);
85
86
+ /* Watchdogs */
87
+ for (i = 0; i < FSL_IMX8MP_NUM_WDTS; i++) {
88
+ struct {
89
+ hwaddr addr;
90
+ unsigned int irq;
91
+ } wdog_table[FSL_IMX8MP_NUM_WDTS] = {
92
+ { fsl_imx8mp_memmap[FSL_IMX8MP_WDOG1].addr, FSL_IMX8MP_WDOG1_IRQ },
93
+ { fsl_imx8mp_memmap[FSL_IMX8MP_WDOG2].addr, FSL_IMX8MP_WDOG2_IRQ },
94
+ { fsl_imx8mp_memmap[FSL_IMX8MP_WDOG3].addr, FSL_IMX8MP_WDOG3_IRQ },
95
+ };
96
+
97
+ object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support",
98
+ true, &error_abort);
99
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
100
+ return;
101
+ }
102
+
103
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, wdog_table[i].addr);
104
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
105
+ qdev_get_gpio_in(gicdev, wdog_table[i].irq));
106
+ }
107
+
108
/* PCIe */
109
if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie), errp)) {
110
return;
111
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
112
case FSL_IMX8MP_SNVS_HP:
113
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
114
case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
115
+ case FSL_IMX8MP_WDOG1 ... FSL_IMX8MP_WDOG3:
116
/* device implemented and treated above */
117
break;
118
119
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
120
index XXXXXXX..XXXXXXX 100644
121
--- a/hw/arm/Kconfig
122
+++ b/hw/arm/Kconfig
123
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
124
select PCI_EXPRESS_FSL_IMX8M_PHY
125
select SDHCI
126
select UNIMP
127
+ select WDT_IMX2
128
129
config FSL_IMX8MP_EVK
130
bool
27
--
131
--
28
2.20.1
132
2.43.0
29
30
diff view generated by jsdifflib
1
The AN524 has a different SYSCLK frequency from the AN505 and AN521;
1
From: Bernhard Beschow <shentey@gmail.com>
2
make the SYSCLK frequency a field in the MPS2TZMachineClass rather
3
than a compile-time constant so we can support the AN524.
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: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-2-peter.maydell@linaro.org
9
---
8
---
10
hw/arm/mps2-tz.c | 10 ++++++----
9
docs/system/arm/imx8mp-evk.rst | 1 +
11
1 file changed, 6 insertions(+), 4 deletions(-)
10
include/hw/arm/fsl-imx8mp.h | 11 +++++++
11
include/hw/timer/imx_gpt.h | 1 +
12
hw/arm/fsl-imx8mp.c | 53 ++++++++++++++++++++++++++++++++++
13
hw/timer/imx_gpt.c | 25 ++++++++++++++++
14
hw/arm/Kconfig | 1 +
15
6 files changed, 92 insertions(+)
12
16
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
17
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
19
--- a/docs/system/arm/imx8mp-evk.rst
16
+++ b/hw/arm/mps2-tz.c
20
+++ b/docs/system/arm/imx8mp-evk.rst
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
21
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
18
MachineClass parent;
22
* 6 I2C Controllers
19
MPS2TZFPGAType fpga_type;
23
* 3 SPI Controllers
20
uint32_t scc_id;
24
* 3 Watchdogs
21
+ uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
25
+ * 6 General Purpose Timers
22
const char *armsse_type;
26
* Secure Non-Volatile Storage (SNVS) including an RTC
27
* Clock Tree
28
29
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/arm/fsl-imx8mp.h
32
+++ b/include/hw/arm/fsl-imx8mp.h
33
@@ -XXX,XX +XXX,XX @@
34
#include "hw/misc/imx7_snvs.h"
35
#include "hw/misc/imx8mp_analog.h"
36
#include "hw/misc/imx8mp_ccm.h"
37
+#include "hw/or-irq.h"
38
#include "hw/pci-host/designware.h"
39
#include "hw/pci-host/fsl_imx8m_phy.h"
40
#include "hw/sd/sdhci.h"
41
#include "hw/ssi/imx_spi.h"
42
+#include "hw/timer/imx_gpt.h"
43
#include "hw/watchdog/wdt_imx2.h"
44
#include "qom/object.h"
45
#include "qemu/units.h"
46
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpConfiguration {
47
FSL_IMX8MP_NUM_CPUS = 4,
48
FSL_IMX8MP_NUM_ECSPIS = 3,
49
FSL_IMX8MP_NUM_GPIOS = 5,
50
+ FSL_IMX8MP_NUM_GPTS = 6,
51
FSL_IMX8MP_NUM_I2CS = 6,
52
FSL_IMX8MP_NUM_IRQS = 160,
53
FSL_IMX8MP_NUM_UARTS = 4,
54
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
55
56
ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
57
GICv3State gic;
58
+ IMXGPTState gpt[FSL_IMX8MP_NUM_GPTS];
59
IMXGPIOState gpio[FSL_IMX8MP_NUM_GPIOS];
60
IMX8MPCCMState ccm;
61
IMX8MPAnalogState analog;
62
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
63
IMX2WdtState wdt[FSL_IMX8MP_NUM_WDTS];
64
DesignwarePCIEHost pcie;
65
FslImx8mPciePhyState pcie_phy;
66
+ OrIRQState gpt5_gpt6_irq;
23
};
67
};
24
68
25
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
69
enum FslImx8mpMemoryRegions {
26
70
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
27
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
71
FSL_IMX8MP_I2C3_IRQ = 37,
28
72
FSL_IMX8MP_I2C4_IRQ = 38,
29
-/* Main SYSCLK frequency in Hz */
73
30
-#define SYSCLK_FRQ 20000000
74
+ FSL_IMX8MP_GPT1_IRQ = 55,
31
/* Slow 32Khz S32KCLK frequency in Hz */
75
+ FSL_IMX8MP_GPT2_IRQ = 54,
32
#define S32KCLK_FRQ (32 * 1000)
76
+ FSL_IMX8MP_GPT3_IRQ = 53,
33
77
+ FSL_IMX8MP_GPT4_IRQ = 52,
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
78
+ FSL_IMX8MP_GPT5_GPT6_IRQ = 51,
35
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
79
+
36
const char *name, hwaddr size)
80
FSL_IMX8MP_GPIO1_LOW_IRQ = 64,
81
FSL_IMX8MP_GPIO1_HIGH_IRQ = 65,
82
FSL_IMX8MP_GPIO2_LOW_IRQ = 66,
83
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
84
index XXXXXXX..XXXXXXX 100644
85
--- a/include/hw/timer/imx_gpt.h
86
+++ b/include/hw/timer/imx_gpt.h
87
@@ -XXX,XX +XXX,XX @@
88
#define TYPE_IMX6_GPT "imx6.gpt"
89
#define TYPE_IMX6UL_GPT "imx6ul.gpt"
90
#define TYPE_IMX7_GPT "imx7.gpt"
91
+#define TYPE_IMX8MP_GPT "imx8mp.gpt"
92
93
#define TYPE_IMX_GPT TYPE_IMX25_GPT
94
95
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/hw/arm/fsl-imx8mp.c
98
+++ b/hw/arm/fsl-imx8mp.c
99
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
100
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
101
}
102
103
+ for (i = 0; i < FSL_IMX8MP_NUM_GPTS; i++) {
104
+ g_autofree char *name = g_strdup_printf("gpt%d", i + 1);
105
+ object_initialize_child(obj, name, &s->gpt[i], TYPE_IMX8MP_GPT);
106
+ }
107
+ object_initialize_child(obj, "gpt5-gpt6-irq", &s->gpt5_gpt6_irq,
108
+ TYPE_OR_IRQ);
109
+
110
for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
111
g_autofree char *name = g_strdup_printf("i2c%d", i + 1);
112
object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
113
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
114
qdev_get_gpio_in(gicdev, serial_table[i].irq));
115
}
116
117
+ /* GPTs */
118
+ object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2,
119
+ &error_abort);
120
+ if (!qdev_realize(DEVICE(&s->gpt5_gpt6_irq), NULL, errp)) {
121
+ return;
122
+ }
123
+
124
+ qdev_connect_gpio_out(DEVICE(&s->gpt5_gpt6_irq), 0,
125
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_GPT5_GPT6_IRQ));
126
+
127
+ for (i = 0; i < FSL_IMX8MP_NUM_GPTS; i++) {
128
+ hwaddr gpt_addrs[FSL_IMX8MP_NUM_GPTS] = {
129
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT1].addr,
130
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT2].addr,
131
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT3].addr,
132
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT4].addr,
133
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT5].addr,
134
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT6].addr,
135
+ };
136
+
137
+ s->gpt[i].ccm = IMX_CCM(&s->ccm);
138
+
139
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) {
140
+ return;
141
+ }
142
+
143
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_addrs[i]);
144
+
145
+ if (i < FSL_IMX8MP_NUM_GPTS - 2) {
146
+ static const unsigned int gpt_irqs[FSL_IMX8MP_NUM_GPTS - 2] = {
147
+ FSL_IMX8MP_GPT1_IRQ,
148
+ FSL_IMX8MP_GPT2_IRQ,
149
+ FSL_IMX8MP_GPT3_IRQ,
150
+ FSL_IMX8MP_GPT4_IRQ,
151
+ };
152
+
153
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
154
+ qdev_get_gpio_in(gicdev, gpt_irqs[i]));
155
+ } else {
156
+ int irq = i - FSL_IMX8MP_NUM_GPTS + 2;
157
+
158
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
159
+ qdev_get_gpio_in(DEVICE(&s->gpt5_gpt6_irq), irq));
160
+ }
161
+ }
162
+
163
/* I2Cs */
164
for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
165
struct {
166
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/timer/imx_gpt.c
169
+++ b/hw/timer/imx_gpt.c
170
@@ -XXX,XX +XXX,XX @@ static const IMXClk imx7_gpt_clocks[] = {
171
CLK_NONE, /* 111 not defined */
172
};
173
174
+static const IMXClk imx8mp_gpt_clocks[] = {
175
+ CLK_NONE, /* 000 No clock source */
176
+ CLK_IPG, /* 001 ipg_clk, 532MHz */
177
+ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
178
+ CLK_EXT, /* 011 External clock */
179
+ CLK_32k, /* 100 ipg_clk_32k */
180
+ CLK_HIGH, /* 101 ipg_clk_16M */
181
+ CLK_NONE, /* 110 not defined */
182
+ CLK_NONE, /* 111 not defined */
183
+};
184
+
185
/* Must be called from within ptimer_transaction_begin/commit block */
186
static void imx_gpt_set_freq(IMXGPTState *s)
37
{
187
{
38
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
188
@@ -XXX,XX +XXX,XX @@ static void imx7_gpt_init(Object *obj)
39
CMSDKAPBUART *uart = opaque;
189
s->clocks = imx7_gpt_clocks;
40
int i = uart - &mms->uart[0];
41
int rxirqno = i * 2;
42
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
43
44
object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART);
45
qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
46
- qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
47
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
48
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
49
s = SYS_BUS_DEVICE(uart);
50
sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
51
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
52
53
/* These clocks don't need migration because they are fixed-frequency */
54
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
55
- clock_set_hz(mms->sysclk, SYSCLK_FRQ);
56
+ clock_set_hz(mms->sysclk, mmc->sysclk_frq);
57
mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
58
clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
59
60
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
61
mmc->fpga_type = FPGA_AN505;
62
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
63
mmc->scc_id = 0x41045050;
64
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
65
mmc->armsse_type = TYPE_IOTKIT;
66
}
190
}
67
191
68
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
192
+static void imx8mp_gpt_init(Object *obj)
69
mmc->fpga_type = FPGA_AN521;
193
+{
70
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
194
+ IMXGPTState *s = IMX_GPT(obj);
71
mmc->scc_id = 0x41045210;
195
+
72
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
196
+ s->clocks = imx8mp_gpt_clocks;
73
mmc->armsse_type = TYPE_SSE200;
197
+}
198
+
199
static const TypeInfo imx25_gpt_info = {
200
.name = TYPE_IMX25_GPT,
201
.parent = TYPE_SYS_BUS_DEVICE,
202
@@ -XXX,XX +XXX,XX @@ static const TypeInfo imx7_gpt_info = {
203
.instance_init = imx7_gpt_init,
204
};
205
206
+static const TypeInfo imx8mp_gpt_info = {
207
+ .name = TYPE_IMX8MP_GPT,
208
+ .parent = TYPE_IMX25_GPT,
209
+ .instance_init = imx8mp_gpt_init,
210
+};
211
+
212
static void imx_gpt_register_types(void)
213
{
214
type_register_static(&imx25_gpt_info);
215
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_register_types(void)
216
type_register_static(&imx6_gpt_info);
217
type_register_static(&imx6ul_gpt_info);
218
type_register_static(&imx7_gpt_info);
219
+ type_register_static(&imx8mp_gpt_info);
74
}
220
}
75
221
222
type_init(imx_gpt_register_types)
223
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
224
index XXXXXXX..XXXXXXX 100644
225
--- a/hw/arm/Kconfig
226
+++ b/hw/arm/Kconfig
227
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
228
select FSL_IMX8MP_CCM
229
select IMX
230
select IMX_I2C
231
+ select OR_IRQ
232
select PCI_EXPRESS_DESIGNWARE
233
select PCI_EXPRESS_FSL_IMX8M_PHY
234
select SDHCI
76
--
235
--
77
2.20.1
236
2.43.0
78
79
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
IDAU is specific to M-profile. KVM only supports A-profile.
3
The i.MX 8M Plus SoC actually has two ethernet controllers, the usual ENET one
4
Restrict this interface to TCG, as it is pointless (and
4
and a Designware one. There is no device model for the latter, so only add the
5
confusing) on a KVM-only build.
5
ENET one.
6
6
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
10
Message-id: 20210221222617.2579610-2-f4bug@amsat.org
9
Message-id: 20250223114708.1780-15-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
target/arm/cpu.c | 7 -------
12
docs/system/arm/imx8mp-evk.rst | 1 +
14
target/arm/cpu_tcg.c | 8 ++++++++
13
include/hw/arm/fsl-imx8mp.h | 8 ++++++++
15
2 files changed, 8 insertions(+), 7 deletions(-)
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(+)
16
18
17
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
19
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.c
21
--- a/docs/system/arm/imx8mp-evk.rst
20
+++ b/target/arm/cpu.c
22
+++ b/docs/system/arm/imx8mp-evk.rst
21
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
23
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
22
.class_init = arm_cpu_class_init,
24
* 4 UARTs
25
* 3 USDHC Storage Controllers
26
* 1 Designware PCI Express Controller
27
+ * 1 Ethernet Controller
28
* 5 GPIO Controllers
29
* 6 I2C Controllers
30
* 3 SPI Controllers
31
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/arm/fsl-imx8mp.h
34
+++ b/include/hw/arm/fsl-imx8mp.h
35
@@ -XXX,XX +XXX,XX @@
36
#include "hw/misc/imx7_snvs.h"
37
#include "hw/misc/imx8mp_analog.h"
38
#include "hw/misc/imx8mp_ccm.h"
39
+#include "hw/net/imx_fec.h"
40
#include "hw/or-irq.h"
41
#include "hw/pci-host/designware.h"
42
#include "hw/pci-host/fsl_imx8m_phy.h"
43
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
44
IMXSPIState spi[FSL_IMX8MP_NUM_ECSPIS];
45
IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
46
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
47
+ IMXFECState enet;
48
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
49
IMX2WdtState wdt[FSL_IMX8MP_NUM_WDTS];
50
DesignwarePCIEHost pcie;
51
FslImx8mPciePhyState pcie_phy;
52
OrIRQState gpt5_gpt6_irq;
53
+
54
+ uint32_t phy_num;
55
+ bool phy_connected;
23
};
56
};
24
57
25
-static const TypeInfo idau_interface_type_info = {
58
enum FslImx8mpMemoryRegions {
26
- .name = TYPE_IDAU_INTERFACE,
59
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
27
- .parent = TYPE_INTERFACE,
60
FSL_IMX8MP_WDOG2_IRQ = 79,
28
- .class_size = sizeof(IDAUInterfaceClass),
61
FSL_IMX8MP_WDOG3_IRQ = 10,
29
-};
62
30
-
63
+ FSL_IMX8MP_ENET1_MAC_IRQ = 118,
31
static void arm_cpu_register_types(void)
64
+ FSL_IMX6_ENET1_MAC_1588_IRQ = 121,
32
{
65
+
33
const size_t cpu_count = ARRAY_SIZE(arm_cpus);
66
FSL_IMX8MP_PCI_INTA_IRQ = 126,
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_register_types(void)
67
FSL_IMX8MP_PCI_INTB_IRQ = 125,
35
if (cpu_count) {
68
FSL_IMX8MP_PCI_INTC_IRQ = 124,
36
size_t i;
69
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
37
38
- type_register_static(&idau_interface_type_info);
39
for (i = 0; i < cpu_count; ++i) {
40
arm_cpu_register(&arm_cpus[i]);
41
}
42
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
43
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/cpu_tcg.c
71
--- a/hw/arm/fsl-imx8mp.c
45
+++ b/target/arm/cpu_tcg.c
72
+++ b/hw/arm/fsl-imx8mp.c
46
@@ -XXX,XX +XXX,XX @@
73
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
47
#include "hw/core/tcg-cpu-ops.h"
74
object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
48
#endif /* CONFIG_TCG */
75
}
49
#include "internals.h"
76
50
+#include "target/arm/idau.h"
77
+ object_initialize_child(obj, "eth0", &s->enet, TYPE_IMX_ENET);
51
78
+
52
/* CPU models. These are not needed for the AArch64 linux-user build. */
79
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
53
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
80
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
54
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
81
TYPE_FSL_IMX8M_PCIE_PHY);
55
{ .name = "pxa270-c5", .initfn = pxa270c5_initfn },
82
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
56
};
83
qdev_get_gpio_in(gicdev, spi_table[i].irq));
57
84
}
58
+static const TypeInfo idau_interface_type_info = {
85
59
+ .name = TYPE_IDAU_INTERFACE,
86
+ /* ENET1 */
60
+ .parent = TYPE_INTERFACE,
87
+ object_property_set_uint(OBJECT(&s->enet), "phy-num", s->phy_num,
61
+ .class_size = sizeof(IDAUInterfaceClass),
88
+ &error_abort);
89
+ object_property_set_uint(OBJECT(&s->enet), "tx-ring-num", 3, &error_abort);
90
+ qemu_configure_nic_device(DEVICE(&s->enet), true, NULL);
91
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->enet), errp)) {
92
+ return;
93
+ }
94
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->enet), 0,
95
+ fsl_imx8mp_memmap[FSL_IMX8MP_ENET1].addr);
96
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 0,
97
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_ENET1_MAC_IRQ));
98
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 1,
99
+ qdev_get_gpio_in(gicdev, FSL_IMX6_ENET1_MAC_1588_IRQ));
100
+
101
/* SNVS */
102
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
103
return;
104
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
105
case FSL_IMX8MP_GIC_REDIST:
106
case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
107
case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
108
+ case FSL_IMX8MP_ENET1:
109
case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
110
case FSL_IMX8MP_PCIE1:
111
case FSL_IMX8MP_PCIE_PHY1:
112
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
113
}
114
}
115
116
+static const Property fsl_imx8mp_properties[] = {
117
+ DEFINE_PROP_UINT32("fec1-phy-num", FslImx8mpState, phy_num, 0),
118
+ DEFINE_PROP_BOOL("fec1-phy-connected", FslImx8mpState, phy_connected, true),
62
+};
119
+};
63
+
120
+
64
static void arm_tcg_cpu_register_types(void)
121
static void fsl_imx8mp_class_init(ObjectClass *oc, void *data)
65
{
122
{
66
size_t i;
123
DeviceClass *dc = DEVICE_CLASS(oc);
67
124
68
+ type_register_static(&idau_interface_type_info);
125
+ device_class_set_props(dc, fsl_imx8mp_properties);
69
for (i = 0; i < ARRAY_SIZE(arm_tcg_cpus); ++i) {
126
dc->realize = fsl_imx8mp_realize;
70
arm_cpu_register(&arm_tcg_cpus[i]);
127
71
}
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
72
--
153
--
73
2.20.1
154
2.43.0
74
75
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add support for FEAT_SSBS. SSBS (Speculative Store Bypass Safe) is an
3
Split the USB MMIO regions to better keep track of the implemented vs.
4
optional feature in ARMv8.0, and mandatory in ARMv8.5.
4
unimplemented regions.
5
5
6
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Message-id: 20210216224543.16142-2-rebecca@nuviainc.com
8
Message-id: 20250223114708.1780-16-shentey@gmail.com
9
[PMM: drop "static const" from usb_table for GCC 7.5]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
target/arm/cpu.h | 15 ++++++++++++++-
12
docs/system/arm/imx8mp-evk.rst | 1 +
12
target/arm/internals.h | 6 ++++++
13
include/hw/arm/fsl-imx8mp.h | 12 +++++++++++
13
target/arm/helper.c | 37 +++++++++++++++++++++++++++++++++++++
14
hw/arm/fsl-imx8mp.c | 37 ++++++++++++++++++++++++++++++++--
14
target/arm/translate-a64.c | 12 ++++++++++++
15
hw/arm/Kconfig | 1 +
15
4 files changed, 69 insertions(+), 1 deletion(-)
16
4 files changed, 49 insertions(+), 2 deletions(-)
16
17
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
20
--- a/docs/system/arm/imx8mp-evk.rst
20
+++ b/target/arm/cpu.h
21
+++ b/docs/system/arm/imx8mp-evk.rst
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
22
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
22
#define SCTLR_TE (1U << 30) /* AArch32 only */
23
* 3 USDHC Storage Controllers
23
#define SCTLR_EnIB (1U << 30) /* v8.3, AArch64 only */
24
* 1 Designware PCI Express Controller
24
#define SCTLR_EnIA (1U << 31) /* v8.3, AArch64 only */
25
* 1 Ethernet Controller
25
+#define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */
26
+ * 2 Designware USB 3 Controllers
26
#define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */
27
* 5 GPIO Controllers
27
#define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */
28
* 6 I2C Controllers
28
#define SCTLR_ITFSB (1ULL << 37) /* v8.5-MemTag */
29
* 3 SPI Controllers
29
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
30
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
30
#define SCTLR_TCF (3ULL << 40) /* v8.5-MemTag */
31
index XXXXXXX..XXXXXXX 100644
31
#define SCTLR_ATA0 (1ULL << 42) /* v8.5-MemTag */
32
--- a/include/hw/arm/fsl-imx8mp.h
32
#define SCTLR_ATA (1ULL << 43) /* v8.5-MemTag */
33
+++ b/include/hw/arm/fsl-imx8mp.h
33
-#define SCTLR_DSSBS (1ULL << 44) /* v8.5 */
34
@@ -XXX,XX +XXX,XX @@
34
+#define SCTLR_DSSBS_64 (1ULL << 44) /* v8.5, AArch64 only */
35
#include "hw/sd/sdhci.h"
35
36
#include "hw/ssi/imx_spi.h"
36
#define CPTR_TCPAC (1U << 31)
37
#include "hw/timer/imx_gpt.h"
37
#define CPTR_TTA (1U << 20)
38
+#include "hw/usb/hcd-dwc3.h"
38
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
39
#include "hw/watchdog/wdt_imx2.h"
39
#define CPSR_IL (1U << 20)
40
#include "qom/object.h"
40
#define CPSR_DIT (1U << 21)
41
#include "qemu/units.h"
41
#define CPSR_PAN (1U << 22)
42
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpConfiguration {
42
+#define CPSR_SSBS (1U << 23)
43
FSL_IMX8MP_NUM_I2CS = 6,
43
#define CPSR_J (1U << 24)
44
FSL_IMX8MP_NUM_IRQS = 160,
44
#define CPSR_IT_0_1 (3U << 25)
45
FSL_IMX8MP_NUM_UARTS = 4,
45
#define CPSR_Q (1U << 27)
46
+ FSL_IMX8MP_NUM_USBS = 2,
46
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
47
FSL_IMX8MP_NUM_USDHCS = 3,
47
#define PSTATE_A (1U << 8)
48
FSL_IMX8MP_NUM_WDTS = 3,
48
#define PSTATE_D (1U << 9)
49
};
49
#define PSTATE_BTYPE (3U << 10)
50
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
50
+#define PSTATE_SSBS (1U << 12)
51
IMXFECState enet;
51
#define PSTATE_IL (1U << 20)
52
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
52
#define PSTATE_SS (1U << 21)
53
IMX2WdtState wdt[FSL_IMX8MP_NUM_WDTS];
53
#define PSTATE_PAN (1U << 22)
54
+ USBDWC3 usb[FSL_IMX8MP_NUM_USBS];
54
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
55
DesignwarePCIEHost pcie;
55
return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0;
56
FslImx8mPciePhyState pcie_phy;
56
}
57
OrIRQState gpt5_gpt6_irq;
57
58
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpMemoryRegions {
58
+static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
59
FSL_IMX8MP_UART4,
59
+{
60
FSL_IMX8MP_USB1,
60
+ return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
61
FSL_IMX8MP_USB2,
61
+}
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,
62
+
77
+
63
/*
78
FSL_IMX8MP_GPT1_IRQ = 55,
64
* 64-bit feature tests via id registers.
79
FSL_IMX8MP_GPT2_IRQ = 54,
65
*/
80
FSL_IMX8MP_GPT3_IRQ = 53,
66
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
81
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
67
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
68
}
69
70
+static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
71
+{
72
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
73
+}
74
+
75
/*
76
* Feature tests for "does this exist in either 32-bit or 64-bit?"
77
*/
78
diff --git a/target/arm/internals.h b/target/arm/internals.h
79
index XXXXXXX..XXXXXXX 100644
82
index XXXXXXX..XXXXXXX 100644
80
--- a/target/arm/internals.h
83
--- a/hw/arm/fsl-imx8mp.c
81
+++ b/target/arm/internals.h
84
+++ b/hw/arm/fsl-imx8mp.c
82
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch32_cpsr_valid_mask(uint64_t features,
85
@@ -XXX,XX +XXX,XX @@ static const struct {
83
if (isar_feature_aa32_dit(id)) {
86
[FSL_IMX8MP_VPU_VC8000E_ENCODER] = { 0x38320000, 2 * MiB, "vpu_vc8000e_encoder" },
84
valid |= CPSR_DIT;
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);
85
}
104
}
86
+ if (isar_feature_aa32_ssbs(id)) {
105
87
+ valid |= CPSR_SSBS;
106
+ for (i = 0; i < FSL_IMX8MP_NUM_USBS; i++) {
88
+ }
107
+ g_autofree char *name = g_strdup_printf("usb%d", i);
89
108
+ object_initialize_child(obj, name, &s->usb[i], TYPE_USB_DWC3);
90
return valid;
91
}
92
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
93
if (isar_feature_aa64_dit(id)) {
94
valid |= PSTATE_DIT;
95
}
96
+ if (isar_feature_aa64_ssbs(id)) {
97
+ valid |= PSTATE_SSBS;
98
+ }
99
if (isar_feature_aa64_mte(id)) {
100
valid |= PSTATE_TCO;
101
}
102
diff --git a/target/arm/helper.c b/target/arm/helper.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/helper.c
105
+++ b/target/arm/helper.c
106
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dit_reginfo = {
107
.readfn = aa64_dit_read, .writefn = aa64_dit_write
108
};
109
110
+static uint64_t aa64_ssbs_read(CPUARMState *env, const ARMCPRegInfo *ri)
111
+{
112
+ return env->pstate & PSTATE_SSBS;
113
+}
114
+
115
+static void aa64_ssbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
+ uint64_t value)
117
+{
118
+ env->pstate = (env->pstate & ~PSTATE_SSBS) | (value & PSTATE_SSBS);
119
+}
120
+
121
+static const ARMCPRegInfo ssbs_reginfo = {
122
+ .name = "SSBS", .state = ARM_CP_STATE_AA64,
123
+ .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 6,
124
+ .type = ARM_CP_NO_RAW, .access = PL0_RW,
125
+ .readfn = aa64_ssbs_read, .writefn = aa64_ssbs_write
126
+};
127
+
128
static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env,
129
const ARMCPRegInfo *ri,
130
bool isread)
131
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
132
if (cpu_isar_feature(aa64_dit, cpu)) {
133
define_one_arm_cp_reg(cpu, &dit_reginfo);
134
}
135
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
136
+ define_one_arm_cp_reg(cpu, &ssbs_reginfo);
137
+ }
138
139
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
140
define_arm_cp_regs(cpu, vhe_reginfo);
141
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
142
env->uncached_cpsr &= ~(CPSR_IL | CPSR_J);
143
env->daif |= mask;
144
145
+ if (cpu_isar_feature(aa32_ssbs, env_archcpu(env))) {
146
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_32) {
147
+ env->uncached_cpsr |= CPSR_SSBS;
148
+ } else {
149
+ env->uncached_cpsr &= ~CPSR_SSBS;
150
+ }
151
+ }
109
+ }
152
+
110
+
153
if (new_mode == ARM_CPU_MODE_HYP) {
111
for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
154
env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
112
g_autofree char *name = g_strdup_printf("spi%d", i + 1);
155
env->elr_el[2] = env->regs[15];
113
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
156
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
114
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
157
new_mode |= PSTATE_TCO;
115
qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
158
}
116
}
159
117
160
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
118
+ /* USBs */
161
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_64) {
119
+ for (i = 0; i < FSL_IMX8MP_NUM_USBS; i++) {
162
+ new_mode |= PSTATE_SSBS;
120
+ struct {
163
+ } else {
121
+ hwaddr addr;
164
+ new_mode &= ~PSTATE_SSBS;
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;
165
+ }
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));
166
+ }
137
+ }
167
+
138
+
168
pstate_write(env, PSTATE_DAIF | new_mode);
139
/* ECSPIs */
169
env->aarch64 = 1;
140
for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
170
aarch64_restore_sp(env, new_el);
141
struct {
171
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
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
172
index XXXXXXX..XXXXXXX 100644
151
index XXXXXXX..XXXXXXX 100644
173
--- a/target/arm/translate-a64.c
152
--- a/hw/arm/Kconfig
174
+++ b/target/arm/translate-a64.c
153
+++ b/hw/arm/Kconfig
175
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
154
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
176
tcg_temp_free_i32(t1);
155
select PCI_EXPRESS_FSL_IMX8M_PHY
177
break;
156
select SDHCI
178
157
select UNIMP
179
+ case 0x19: /* SSBS */
158
+ select USB_DWC3
180
+ if (!dc_isar_feature(aa64_ssbs, s)) {
159
select WDT_IMX2
181
+ goto do_unallocated;
160
182
+ }
161
config FSL_IMX8MP_EVK
183
+ if (crm & 1) {
184
+ set_pstate_bits(PSTATE_SSBS);
185
+ } else {
186
+ clear_pstate_bits(PSTATE_SSBS);
187
+ }
188
+ /* Don't need to rebuild hflags since SSBS is a nop */
189
+ break;
190
+
191
case 0x1a: /* DIT */
192
if (!dc_isar_feature(aa64_dit, s)) {
193
goto do_unallocated;
194
--
162
--
195
2.20.1
163
2.43.0
196
197
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Set ID_AA64PFR1_EL1.SSBS to 2 and ID_PFR2.SSBS to 1.
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
5
Message-id: 20250223114708.1780-18-shentey@gmail.com
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210216224543.16142-3-rebecca@nuviainc.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
7
---
10
target/arm/cpu64.c | 5 +++++
8
include/hw/arm/fsl-imx8mp.h | 1 +
11
1 file changed, 5 insertions(+)
9
hw/arm/fsl-imx8mp.c | 11 +++++++++++
10
2 files changed, 12 insertions(+)
12
11
13
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
12
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu64.c
14
--- a/include/hw/arm/fsl-imx8mp.h
16
+++ b/target/arm/cpu64.c
15
+++ b/include/hw/arm/fsl-imx8mp.h
17
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
16
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
18
17
DesignwarePCIEHost pcie;
19
t = cpu->isar.id_aa64pfr1;
18
FslImx8mPciePhyState pcie_phy;
20
t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
19
OrIRQState gpt5_gpt6_irq;
21
+ t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2);
20
+ MemoryRegion ocram;
22
/*
21
23
* Begin with full support for MTE. This will be downgraded to MTE=0
22
uint32_t phy_num;
24
* during realize if the board provides no tag memory, much like
23
bool phy_connected;
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
24
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
26
u = FIELD_DP32(u, ID_PFR0, DIT, 1);
25
index XXXXXXX..XXXXXXX 100644
27
cpu->isar.id_pfr0 = u;
26
--- a/hw/arm/fsl-imx8mp.c
28
27
+++ b/hw/arm/fsl-imx8mp.c
29
+ u = cpu->isar.id_pfr2;
28
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
30
+ u = FIELD_DP32(u, ID_PFR2, SSBS, 1);
29
sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie_phy), 0,
31
+ cpu->isar.id_pfr2 = u;
30
fsl_imx8mp_memmap[FSL_IMX8MP_PCIE_PHY1].addr);
31
32
+ /* On-Chip RAM */
33
+ if (!memory_region_init_ram(&s->ocram, NULL, "imx8mp.ocram",
34
+ fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].size,
35
+ errp)) {
36
+ return;
37
+ }
38
+ memory_region_add_subregion(get_system_memory(),
39
+ fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].addr,
40
+ &s->ocram);
32
+
41
+
33
u = cpu->isar.id_mmfr3;
42
/* Unimplemented devices */
34
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
43
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
35
cpu->isar.id_mmfr3 = u;
44
switch (i) {
45
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
46
case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
47
case FSL_IMX8MP_ENET1:
48
case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
49
+ case FSL_IMX8MP_OCRAM:
50
case FSL_IMX8MP_PCIE1:
51
case FSL_IMX8MP_PCIE_PHY1:
52
case FSL_IMX8MP_RAM:
36
--
53
--
37
2.20.1
54
2.43.0
38
39
diff view generated by jsdifflib
Deleted patch
1
The draw_line16_32() function in the omap_lcdc template header
2
includes an ifdef for the case where HOST_WORDS_BIGENDIAN matches
3
TARGET_WORDS_BIGENDIAN. This is trying to optimise for "source
4
bitmap and destination bitmap format match", but it is broken,
5
because in this function the formats don't match: the source is
6
16-bit colour and the destination is 32-bit colour, so a memcpy()
7
will produce corrupted graphics output. Drop the bogus ifdef.
8
1
9
This bug was introduced in commit ea644cf343129, when we dropped
10
support for DEPTH values other than 32 from the template header.
11
The old #if line was
12
#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
13
and this was mistakenly changed to
14
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
15
rather than deleting the #if as now having an always-false condition.
16
17
Fixes: ea644cf343129
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20210215103215.4944-7-peter.maydell@linaro.org
22
---
23
hw/display/omap_lcd_template.h | 4 ----
24
1 file changed, 4 deletions(-)
25
26
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/display/omap_lcd_template.h
29
+++ b/hw/display/omap_lcd_template.h
30
@@ -XXX,XX +XXX,XX @@ static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
31
static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
32
int width, int deststep)
33
{
34
-#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
35
- memcpy(d, s, width * 2);
36
-#else
37
uint16_t v;
38
uint8_t r, g, b;
39
40
@@ -XXX,XX +XXX,XX @@ static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
41
s += 2;
42
d += 4;
43
} while (-- width != 0);
44
-#endif
45
}
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel, RGB. The TCX code already
3
assumes 32bpp, but it still has some checks of is_surface_bgr()
4
in an attempt to support 32bpp BGR. is_surface_bgr() will always
5
return false for the qemu_console_surface(), unless the display
6
device itself has deliberately created an alternate-format
7
surface via a function like qemu_create_displaysurface_from().
8
1
9
Drop the never-used BGR-handling code, and assert that we have
10
a 32-bit surface rather than just doing nothing if it isn't.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20210215102149.20513-1-peter.maydell@linaro.org
16
---
17
hw/display/tcx.c | 31 ++++++++-----------------------
18
1 file changed, 8 insertions(+), 23 deletions(-)
19
20
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/display/tcx.c
23
+++ b/hw/display/tcx.c
24
@@ -XXX,XX +XXX,XX @@ static int tcx_check_dirty(TCXState *s, DirtyBitmapSnapshot *snap,
25
26
static void update_palette_entries(TCXState *s, int start, int end)
27
{
28
- DisplaySurface *surface = qemu_console_surface(s->con);
29
int i;
30
31
for (i = start; i < end; i++) {
32
- if (is_surface_bgr(surface)) {
33
- s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
34
- } else {
35
- s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
36
- }
37
+ s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
38
}
39
tcx_set_dirty(s, 0, memory_region_size(&s->vram_mem));
40
}
41
@@ -XXX,XX +XXX,XX @@ static void tcx_draw_cursor32(TCXState *s1, uint8_t *d,
42
}
43
44
/*
45
- XXX Could be much more optimal:
46
- * detect if line/page/whole screen is in 24 bit mode
47
- * if destination is also BGR, use memcpy
48
- */
49
+ * XXX Could be much more optimal:
50
+ * detect if line/page/whole screen is in 24 bit mode
51
+ */
52
static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
53
const uint8_t *s, int width,
54
const uint32_t *cplane,
55
const uint32_t *s24)
56
{
57
- DisplaySurface *surface = qemu_console_surface(s1->con);
58
- int x, bgr, r, g, b;
59
+ int x, r, g, b;
60
uint8_t val, *p8;
61
uint32_t *p = (uint32_t *)d;
62
uint32_t dval;
63
- bgr = is_surface_bgr(surface);
64
for(x = 0; x < width; x++, s++, s24++) {
65
if (be32_to_cpu(*cplane) & 0x03000000) {
66
/* 24-bit direct, BGR order */
67
@@ -XXX,XX +XXX,XX @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
68
b = *p8++;
69
g = *p8++;
70
r = *p8;
71
- if (bgr)
72
- dval = rgb_to_pixel32bgr(r, g, b);
73
- else
74
- dval = rgb_to_pixel32(r, g, b);
75
+ dval = rgb_to_pixel32(r, g, b);
76
} else {
77
/* 8-bit pseudocolor */
78
val = *s;
79
@@ -XXX,XX +XXX,XX @@ static void tcx_update_display(void *opaque)
80
int y, y_start, dd, ds;
81
uint8_t *d, *s;
82
83
- if (surface_bits_per_pixel(surface) != 32) {
84
- return;
85
- }
86
+ assert(surface_bits_per_pixel(surface) == 32);
87
88
page = 0;
89
y_start = -1;
90
@@ -XXX,XX +XXX,XX @@ static void tcx24_update_display(void *opaque)
91
uint8_t *d, *s;
92
uint32_t *cptr, *s24;
93
94
- if (surface_bits_per_pixel(surface) != 32) {
95
- return;
96
- }
97
+ assert(surface_bits_per_pixel(surface) == 32);
98
99
page = 0;
100
y_start = -1;
101
--
102
2.20.1
103
104
diff view generated by jsdifflib
Deleted patch
1
Currently the MPS2 SCC device implements a fixed number of OSCCLK
2
values (3). The variant of this device in the MPS3 AN524 board has 6
3
OSCCLK values. Switch to using a PROP_ARRAY, which allows board code
4
to specify how large the OSCCLK array should be as well as its
5
values.
6
1
7
With a variable-length property array, the SCC no longer specifies
8
default values for the OSCCLKs, so we must set them explicitly in the
9
board code. This defaults are actually incorrect for the an521 and
10
an505; we will correct this bug in a following patch.
11
12
This is a migration compatibility break for all the mps boards.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20210215115138.20465-3-peter.maydell@linaro.org
18
---
19
include/hw/misc/mps2-scc.h | 7 +++----
20
hw/arm/mps2-tz.c | 5 +++++
21
hw/arm/mps2.c | 5 +++++
22
hw/misc/mps2-scc.c | 24 +++++++++++++-----------
23
4 files changed, 26 insertions(+), 15 deletions(-)
24
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/misc/mps2-scc.h
28
+++ b/include/hw/misc/mps2-scc.h
29
@@ -XXX,XX +XXX,XX @@
30
#define TYPE_MPS2_SCC "mps2-scc"
31
OBJECT_DECLARE_SIMPLE_TYPE(MPS2SCC, MPS2_SCC)
32
33
-#define NUM_OSCCLK 3
34
-
35
struct MPS2SCC {
36
/*< private >*/
37
SysBusDevice parent_obj;
38
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
39
uint32_t dll;
40
uint32_t aid;
41
uint32_t id;
42
- uint32_t oscclk[NUM_OSCCLK];
43
- uint32_t oscclk_reset[NUM_OSCCLK];
44
+ uint32_t num_oscclk;
45
+ uint32_t *oscclk;
46
+ uint32_t *oscclk_reset;
47
};
48
49
#endif
50
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/arm/mps2-tz.c
53
+++ b/hw/arm/mps2-tz.c
54
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
55
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
56
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
57
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
58
+ /* This will need to be per-FPGA image eventually */
59
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
60
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
61
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
62
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
63
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
64
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
65
}
66
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/mps2.c
69
+++ b/hw/arm/mps2.c
70
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
71
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
72
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
73
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
74
+ /* All these FPGA images have the same OSCCLK configuration */
75
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
76
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
77
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
78
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
79
sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
80
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
81
object_initialize_child(OBJECT(mms), "fpgaio",
82
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/misc/mps2-scc.c
85
+++ b/hw/misc/mps2-scc.c
86
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
87
{
88
trace_mps2_scc_cfg_write(function, device, value);
89
90
- if (function != 1 || device >= NUM_OSCCLK) {
91
+ if (function != 1 || device >= s->num_oscclk) {
92
qemu_log_mask(LOG_GUEST_ERROR,
93
"MPS2 SCC config write: bad function %d device %d\n",
94
function, device);
95
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
96
static bool scc_cfg_read(MPS2SCC *s, unsigned function,
97
unsigned device, uint32_t *value)
98
{
99
- if (function != 1 || device >= NUM_OSCCLK) {
100
+ if (function != 1 || device >= s->num_oscclk) {
101
qemu_log_mask(LOG_GUEST_ERROR,
102
"MPS2 SCC config read: bad function %d device %d\n",
103
function, device);
104
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
105
s->cfgctrl = 0x100000;
106
s->cfgstat = 0;
107
s->dll = 0xffff0001;
108
- for (i = 0; i < NUM_OSCCLK; i++) {
109
+ for (i = 0; i < s->num_oscclk; i++) {
110
s->oscclk[i] = s->oscclk_reset[i];
111
}
112
for (i = 0; i < ARRAY_SIZE(s->led); i++) {
113
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
114
LED_COLOR_GREEN, name);
115
g_free(name);
116
}
117
+
118
+ s->oscclk = g_new0(uint32_t, s->num_oscclk);
119
}
120
121
static const VMStateDescription mps2_scc_vmstate = {
122
.name = "mps2-scc",
123
- .version_id = 1,
124
- .minimum_version_id = 1,
125
+ .version_id = 2,
126
+ .minimum_version_id = 2,
127
.fields = (VMStateField[]) {
128
VMSTATE_UINT32(cfg0, MPS2SCC),
129
VMSTATE_UINT32(cfg1, MPS2SCC),
130
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_scc_vmstate = {
131
VMSTATE_UINT32(cfgctrl, MPS2SCC),
132
VMSTATE_UINT32(cfgstat, MPS2SCC),
133
VMSTATE_UINT32(dll, MPS2SCC),
134
- VMSTATE_UINT32_ARRAY(oscclk, MPS2SCC, NUM_OSCCLK),
135
+ VMSTATE_VARRAY_UINT32(oscclk, MPS2SCC, num_oscclk,
136
+ 0, vmstate_info_uint32, uint32_t),
137
VMSTATE_END_OF_LIST()
138
}
139
};
140
@@ -XXX,XX +XXX,XX @@ static Property mps2_scc_properties[] = {
141
DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0),
142
DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
143
DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0),
144
- /* These are the initial settings for the source clocks on the board.
145
+ /*
146
+ * These are the initial settings for the source clocks on the board.
147
* In hardware they can be configured via a config file read by the
148
* motherboard configuration controller to suit the FPGA image.
149
- * These default values are used by most of the standard FPGA images.
150
*/
151
- DEFINE_PROP_UINT32("oscclk0", MPS2SCC, oscclk_reset[0], 50000000),
152
- DEFINE_PROP_UINT32("oscclk1", MPS2SCC, oscclk_reset[1], 24576000),
153
- DEFINE_PROP_UINT32("oscclk2", MPS2SCC, oscclk_reset[2], 25000000),
154
+ DEFINE_PROP_ARRAY("oscclk", MPS2SCC, num_oscclk, oscclk_reset,
155
+ qdev_prop_uint32, uint32_t),
156
DEFINE_PROP_END_OF_LIST(),
157
};
158
159
--
160
2.20.1
161
162
diff view generated by jsdifflib
Deleted patch
1
We were previously using the default OSCCLK settings, which are
2
correct for the older MPS2 boards (mps2-an385, mps2-an386,
3
mps2-an500, mps2-an511), but wrong for the mps2-an505 and mps2-511
4
implemented in mps2-tz.c. Now we're setting the values explicitly we
5
can fix them to be correct.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210215115138.20465-4-peter.maydell@linaro.org
11
---
12
hw/arm/mps2-tz.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
18
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
20
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
21
/* This will need to be per-FPGA image eventually */
22
qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
23
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
24
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
25
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
26
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
27
qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
28
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
29
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
30
--
31
2.20.1
32
33
diff view generated by jsdifflib
Deleted patch
1
The AN505 and AN511 happen to share the same OSCCLK values, but the
2
AN524 will have a different set (and more of them), so split the
3
settings out to be per-board.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-5-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 23 ++++++++++++++++++-----
11
1 file changed, 18 insertions(+), 5 deletions(-)
12
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
16
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
18
MPS2TZFPGAType fpga_type;
19
uint32_t scc_id;
20
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
21
+ uint32_t len_oscclk;
22
+ const uint32_t *oscclk;
23
const char *armsse_type;
24
};
25
26
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
27
/* Slow 32Khz S32KCLK frequency in Hz */
28
#define S32KCLK_FRQ (32 * 1000)
29
30
+static const uint32_t an505_oscclk[] = {
31
+ 40000000,
32
+ 24580000,
33
+ 25000000,
34
+};
35
+
36
/* Create an alias of an entire original MemoryRegion @orig
37
* located at @base in the memory map.
38
*/
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
40
MPS2SCC *scc = opaque;
41
DeviceState *sccdev;
42
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
43
+ uint32_t i;
44
45
object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC);
46
sccdev = DEVICE(scc);
47
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
48
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
49
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
50
- /* This will need to be per-FPGA image eventually */
51
- qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
52
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
53
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
54
- qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
55
+ qdev_prop_set_uint32(sccdev, "len-oscclk", mmc->len_oscclk);
56
+ for (i = 0; i < mmc->len_oscclk; i++) {
57
+ g_autofree char *propname = g_strdup_printf("oscclk[%u]", i);
58
+ qdev_prop_set_uint32(sccdev, propname, mmc->oscclk[i]);
59
+ }
60
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
61
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
62
}
63
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
64
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
65
mmc->scc_id = 0x41045050;
66
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
67
+ mmc->oscclk = an505_oscclk;
68
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
69
mmc->armsse_type = TYPE_IOTKIT;
70
}
71
72
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
73
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
74
mmc->scc_id = 0x41045210;
75
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
76
+ mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
77
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
78
mmc->armsse_type = TYPE_SSE200;
79
}
80
81
--
82
2.20.1
83
84
diff view generated by jsdifflib
Deleted patch
1
Set the FPGAIO num-leds and have-switches properties explicitly
2
per-board, rather than relying on the defaults. The AN505 and AN521
3
both have the same settings as the default values, but the AN524 will
4
be different.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210215115138.20465-8-peter.maydell@linaro.org
10
---
11
hw/arm/mps2-tz.c | 9 +++++++++
12
1 file changed, 9 insertions(+)
13
14
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/mps2-tz.c
17
+++ b/hw/arm/mps2-tz.c
18
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
19
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
20
uint32_t len_oscclk;
21
const uint32_t *oscclk;
22
+ uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
23
+ bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
24
const char *armsse_type;
25
};
26
27
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
28
const char *name, hwaddr size)
29
{
30
MPS2FPGAIO *fpgaio = opaque;
31
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
32
33
object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO);
34
+ qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
35
+ qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
36
sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
37
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
38
}
39
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
40
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
41
mmc->oscclk = an505_oscclk;
42
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
43
+ mmc->fpgaio_num_leds = 2;
44
+ mmc->fpgaio_has_switches = false;
45
mmc->armsse_type = TYPE_IOTKIT;
46
}
47
48
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
49
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
50
mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
51
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
52
+ mmc->fpgaio_num_leds = 2;
53
+ mmc->fpgaio_has_switches = false;
54
mmc->armsse_type = TYPE_SSE200;
55
}
56
57
--
58
2.20.1
59
60
diff view generated by jsdifflib