1
Nuvoton new board models, and some more minor stuff. I also put
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
2
in the deprecation patches for unicore32 and lm32.
2
handling series. (Lots more in my to-review queue, but I don't
3
like pullreqs growing too close to a hundred patches at a time :-))
3
4
4
thanks
5
thanks
5
-- PMM
6
-- PMM
6
7
7
The following changes since commit a68694cd1f3e5448cca814ff39b871f9ebd71ed5:
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
8
9
9
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/edk2-next-20200914' into staging (2020-09-14 12:18:58 +0100)
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
10
11
11
are available in the Git repository at:
12
are available in the Git repository at:
12
13
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200914
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
14
15
15
for you to fetch changes up to dd44ae00fc5342ed99acb68ec3508f76a71d523a:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
16
17
17
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller (2020-09-14 14:27:08 +0100)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
18
19
19
----------------------------------------------------------------
20
----------------------------------------------------------------
20
target-arm queue:
21
target-arm queue:
21
* hw/misc/a9scu: Do not allow invalid CPU count
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
22
* hw/misc/a9scu: Minor cleanups
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
23
* hw/timer/armv7m_systick: assert that board code set system_clock_scale
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
24
* decodetree: Improve identifier matching
25
* fpu: Minor NaN-related cleanups
25
* target/arm: Clean up neon fp insn size field decode
26
* MAINTAINERS: email address updates
26
* target/arm: Remove KVM support for 32-bit Arm hosts
27
* hw/arm/mps2: New board models mps2-an386, mps2-an500
28
* Deprecate Unicore32 port
29
* Deprecate lm32 port
30
* target/arm: Count PMU events when MDCR.SPME is set
31
* hw/arm: versal-virt: Correct the tx/rx GEM clocks
32
* New Nuvoton iBMC board models npcm750-evb, quanta-gsj
33
* xlnx-zynqmp: implement ZynqMP CAN controllers
34
27
35
----------------------------------------------------------------
28
----------------------------------------------------------------
36
Aaron Lindsay (1):
29
Bernhard Beschow (5):
37
target/arm: Count PMU events when MDCR.SPME is set
30
hw/net/lan9118: Extract lan9118_phy
31
hw/net/lan9118_phy: Reuse in imx_fec and consolidate implementations
32
hw/net/lan9118_phy: Fix off-by-one error in MII_ANLPAR register
33
hw/net/lan9118_phy: Reuse MII constants
34
hw/net/lan9118_phy: Add missing 100 mbps full duplex advertisement
38
35
39
Edgar E. Iglesias (1):
36
Leif Lindholm (1):
40
hw/arm: versal-virt: Correct the tx/rx GEM clocks
37
MAINTAINERS: update email address for Leif Lindholm
41
38
42
Havard Skinnemoen (14):
39
Peter Maydell (54):
43
hw/misc: Add NPCM7xx System Global Control Registers device model
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
44
hw/misc: Add NPCM7xx Clock Controller device model
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
45
hw/timer: Add NPCM7xx Timer device model
42
softfloat: Allow runtime choice of inf * 0 + NaN result
46
hw/arm: Add NPCM730 and NPCM750 SoC models
43
tests/fp: Explicitly set inf-zero-nan rule
47
hw/arm: Add two NPCM7xx-based machines
44
target/arm: Set FloatInfZeroNaNRule explicitly
48
roms: Add virtual Boot ROM for NPCM7xx SoCs
45
target/s390: Set FloatInfZeroNaNRule explicitly
49
hw/arm: Load -bios image as a boot ROM for npcm7xx
46
target/ppc: Set FloatInfZeroNaNRule explicitly
50
hw/nvram: NPCM7xx OTP device model
47
target/mips: Set FloatInfZeroNaNRule explicitly
51
hw/mem: Stubbed out NPCM7xx Memory Controller model
48
target/sparc: Set FloatInfZeroNaNRule explicitly
52
hw/ssi: NPCM7xx Flash Interface Unit device model
49
target/xtensa: Set FloatInfZeroNaNRule explicitly
53
hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj
50
target/x86: Set FloatInfZeroNaNRule explicitly
54
hw/arm/npcm7xx: add board setup stub for CPU and UART clocks
51
target/loongarch: Set FloatInfZeroNaNRule explicitly
55
docs/system: Add Nuvoton machine documentation
52
target/hppa: Set FloatInfZeroNaNRule explicitly
56
tests/acceptance: console boot tests for quanta-gsj
53
softfloat: Pass have_snan to pickNaNMulAdd
54
softfloat: Allow runtime choice of NaN propagation for muladd
55
tests/fp: Explicitly set 3-NaN propagation rule
56
target/arm: Set Float3NaNPropRule explicitly
57
target/loongarch: Set Float3NaNPropRule explicitly
58
target/ppc: Set Float3NaNPropRule explicitly
59
target/s390x: Set Float3NaNPropRule explicitly
60
target/sparc: Set Float3NaNPropRule explicitly
61
target/mips: Set Float3NaNPropRule explicitly
62
target/xtensa: Set Float3NaNPropRule explicitly
63
target/i386: Set Float3NaNPropRule explicitly
64
target/hppa: Set Float3NaNPropRule explicitly
65
fpu: Remove use_first_nan field from float_status
66
target/m68k: Don't pass NULL float_status to floatx80_default_nan()
67
softfloat: Create floatx80 default NaN from parts64_default_nan
68
target/loongarch: Use normal float_status in fclass_s and fclass_d helpers
69
target/m68k: In frem helper, initialize local float_status from env->fp_status
70
target/m68k: Init local float_status from env fp_status in gdb get/set reg
71
target/sparc: Initialize local scratch float_status from env->fp_status
72
target/ppc: Use env->fp_status in helper_compute_fprf functions
73
fpu: Allow runtime choice of default NaN value
74
tests/fp: Set default NaN pattern explicitly
75
target/microblaze: Set default NaN pattern explicitly
76
target/i386: Set default NaN pattern explicitly
77
target/hppa: Set default NaN pattern explicitly
78
target/alpha: Set default NaN pattern explicitly
79
target/arm: Set default NaN pattern explicitly
80
target/loongarch: Set default NaN pattern explicitly
81
target/m68k: Set default NaN pattern explicitly
82
target/mips: Set default NaN pattern explicitly
83
target/openrisc: Set default NaN pattern explicitly
84
target/ppc: Set default NaN pattern explicitly
85
target/sh4: Set default NaN pattern explicitly
86
target/rx: Set default NaN pattern explicitly
87
target/s390x: Set default NaN pattern explicitly
88
target/sparc: Set default NaN pattern explicitly
89
target/xtensa: Set default NaN pattern explicitly
90
target/hexagon: Set default NaN pattern explicitly
91
target/riscv: Set default NaN pattern explicitly
92
target/tricore: Set default NaN pattern explicitly
93
fpu: Remove default handling for dnan_pattern
57
94
58
Peter Maydell (11):
95
Richard Henderson (11):
59
hw/timer/armv7m_systick: assert that board code set system_clock_scale
96
target/arm: Copy entire float_status in is_ebf
60
target/arm: Convert Neon 3-same-fp size field to MO_* in decode
97
softfloat: Inline pickNaNMulAdd
61
target/arm: Convert Neon VCVT fp size field to MO_* in decode
98
softfloat: Use goto for default nan case in pick_nan_muladd
62
target/arm: Convert VCMLA, VCADD size field to MO_* in decode
99
softfloat: Remove which from parts_pick_nan_muladd
63
target/arm: Remove KVM support for 32-bit Arm hosts
100
softfloat: Pad array size in pick_nan_muladd
64
target/arm: Remove no-longer-reachable 32-bit KVM code
101
softfloat: Move propagateFloatx80NaN to softfloat.c
65
hw/arm/mps2: New board model mps2-an386
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
66
hw/arm/mps2: New board model mps2-an500
103
softfloat: Inline pickNaN
67
docs/system/arm/mps2.rst: Make board list consistent
104
softfloat: Share code between parts_pick_nan cases
68
Deprecate Unicore32 port
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
69
Deprecate lm32 port
106
softfloat: Replace WHICH with RET in parts_pick_nan
70
107
71
Philippe Mathieu-Daudé (4):
108
Vikram Garhwal (1):
72
hw/misc/a9scu: Do not allow invalid CPU count
109
MAINTAINERS: Add correct email address for Vikram Garhwal
73
hw/misc/a9scu: Simplify setting MemoryRegionOps::valid fields
74
hw/misc/a9scu: Simplify setting MemoryRegionOps::impl fields
75
hw/misc/a9scu: Report unimplemented accesses with qemu_log_mask(UNIMP)
76
110
77
Richard Henderson (1):
111
MAINTAINERS | 4 +-
78
decodetree: Improve identifier matching
112
include/fpu/softfloat-helpers.h | 38 +++-
79
113
include/fpu/softfloat-types.h | 89 +++++++-
80
Vikram Garhwal (4):
114
include/hw/net/imx_fec.h | 9 +-
81
hw/net/can: Introduce Xilinx ZynqMP CAN controller
115
include/hw/net/lan9118_phy.h | 37 ++++
82
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
116
include/hw/net/mii.h | 6 +
83
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
117
target/mips/fpu_helper.h | 20 ++
84
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
118
target/sparc/helper.h | 4 +-
85
119
fpu/softfloat.c | 19 ++
86
docs/system/arm/mps2.rst | 20 +-
120
hw/net/imx_fec.c | 146 ++------------
87
docs/system/arm/nuvoton.rst | 92 +++
121
hw/net/lan9118.c | 137 ++-----------
88
docs/system/deprecated.rst | 32 +-
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
89
docs/system/target-arm.rst | 1 +
123
linux-user/arm/nwfpe/fpa11.c | 5 +
90
configure | 2 +-
124
target/alpha/cpu.c | 2 +
91
default-configs/arm-softmmu.mak | 1 +
125
target/arm/cpu.c | 10 +
92
include/hw/arm/npcm7xx.h | 112 +++
126
target/arm/tcg/vec_helper.c | 20 +-
93
include/hw/arm/xlnx-zynqmp.h | 8 +
127
target/hexagon/cpu.c | 2 +
94
include/hw/mem/npcm7xx_mc.h | 36 +
128
target/hppa/fpu_helper.c | 12 ++
95
include/hw/misc/npcm7xx_clk.h | 48 ++
129
target/i386/tcg/fpu_helper.c | 12 ++
96
include/hw/misc/npcm7xx_gcr.h | 43 ++
130
target/loongarch/tcg/fpu_helper.c | 14 +-
97
include/hw/net/xlnx-zynqmp-can.h | 78 +++
131
target/m68k/cpu.c | 14 +-
98
include/hw/nvram/npcm7xx_otp.h | 79 +++
132
target/m68k/fpu_helper.c | 6 +-
99
include/hw/ssi/npcm7xx_fiu.h | 73 ++
133
target/m68k/helper.c | 6 +-
100
include/hw/timer/npcm7xx_timer.h | 78 +++
134
target/microblaze/cpu.c | 2 +
101
target/arm/kvm-consts.h | 7 -
135
target/mips/msa.c | 10 +
102
target/arm/kvm_arm.h | 6 -
136
target/openrisc/cpu.c | 2 +
103
target/arm/neon-dp.decode | 18 +-
137
target/ppc/cpu_init.c | 19 ++
104
target/arm/neon-shared.decode | 18 +-
138
target/ppc/fpu_helper.c | 3 +-
105
tests/decode/succ_ident1.decode | 7 +
139
target/riscv/cpu.c | 2 +
106
hw/arm/mps2.c | 97 ++-
140
target/rx/cpu.c | 2 +
107
hw/arm/npcm7xx.c | 532 +++++++++++++++
141
target/s390x/cpu.c | 5 +
108
hw/arm/npcm7xx_boards.c | 197 ++++++
142
target/sh4/cpu.c | 2 +
109
hw/arm/xlnx-versal-virt.c | 2 +-
143
target/sparc/cpu.c | 6 +
110
hw/arm/xlnx-zcu102.c | 20 +
144
target/sparc/fop_helper.c | 8 +-
111
hw/arm/xlnx-zynqmp.c | 34 +
145
target/sparc/translate.c | 4 +-
112
hw/mem/npcm7xx_mc.c | 84 +++
146
target/tricore/helper.c | 2 +
113
hw/misc/a9scu.c | 59 +-
147
target/xtensa/cpu.c | 4 +
114
hw/misc/npcm7xx_clk.c | 266 ++++++++
148
target/xtensa/fpu_helper.c | 3 +-
115
hw/misc/npcm7xx_gcr.c | 269 ++++++++
149
tests/fp/fp-bench.c | 7 +
116
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++++
150
tests/fp/fp-test-log2.c | 1 +
117
hw/nvram/npcm7xx_otp.c | 440 ++++++++++++
151
tests/fp/fp-test.c | 7 +
118
hw/ssi/npcm7xx_fiu.c | 572 ++++++++++++++++
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
119
hw/timer/armv7m_systick.c | 8 +
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
120
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++
154
.mailmap | 5 +-
121
target/arm/cpu.c | 101 ++-
155
hw/net/Kconfig | 5 +
122
target/arm/helper.c | 2 +-
156
hw/net/meson.build | 1 +
123
target/arm/kvm.c | 7 -
157
hw/net/trace-events | 10 +-
124
target/arm/kvm32.c | 595 ----------------
158
47 files changed, 778 insertions(+), 730 deletions(-)
125
tests/qtest/xlnx-can-test.c | 359 ++++++++++
159
create mode 100644 include/hw/net/lan9118_phy.h
126
.gitmodules | 3 +
160
create mode 100644 hw/net/lan9118_phy.c
127
MAINTAINERS | 18 +
128
hw/arm/Kconfig | 9 +
129
hw/arm/meson.build | 1 +
130
hw/mem/meson.build | 1 +
131
hw/misc/meson.build | 4 +
132
hw/misc/trace-events | 8 +
133
hw/net/can/meson.build | 1 +
134
hw/nvram/meson.build | 1 +
135
hw/ssi/meson.build | 1 +
136
hw/ssi/trace-events | 11 +
137
hw/timer/meson.build | 1 +
138
hw/timer/trace-events | 5 +
139
pc-bios/README | 6 +
140
pc-bios/meson.build | 1 +
141
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
142
roms/Makefile | 7 +
143
roms/vbootrom | 1 +
144
scripts/decodetree.py | 46 +-
145
target/arm/meson.build | 5 +-
146
target/arm/translate-neon.c.inc | 42 +-
147
tests/acceptance/boot_linux_console.py | 83 +++
148
tests/qtest/meson.build | 1 +
149
63 files changed, 5584 insertions(+), 783 deletions(-)
150
create mode 100644 docs/system/arm/nuvoton.rst
151
create mode 100644 include/hw/arm/npcm7xx.h
152
create mode 100644 include/hw/mem/npcm7xx_mc.h
153
create mode 100644 include/hw/misc/npcm7xx_clk.h
154
create mode 100644 include/hw/misc/npcm7xx_gcr.h
155
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
156
create mode 100644 include/hw/nvram/npcm7xx_otp.h
157
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
158
create mode 100644 include/hw/timer/npcm7xx_timer.h
159
create mode 100644 tests/decode/succ_ident1.decode
160
create mode 100644 hw/arm/npcm7xx.c
161
create mode 100644 hw/arm/npcm7xx_boards.c
162
create mode 100644 hw/mem/npcm7xx_mc.c
163
create mode 100644 hw/misc/npcm7xx_clk.c
164
create mode 100644 hw/misc/npcm7xx_gcr.c
165
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
166
create mode 100644 hw/nvram/npcm7xx_otp.c
167
create mode 100644 hw/ssi/npcm7xx_fiu.c
168
create mode 100644 hw/timer/npcm7xx_timer.c
169
delete mode 100644 target/arm/kvm32.c
170
create mode 100644 tests/qtest/xlnx-can-test.c
171
create mode 100644 pc-bios/npcm7xx_bootrom.bin
172
create mode 160000 roms/vbootrom
173
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Enough functionality to boot the Linux kernel has been implemented. This
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
includes:
4
a common implementation by extracting a device model into its own files.
5
5
6
- Correct power-on reset values so the various clock rates can be
6
Some migration state has been moved into the new device model which breaks
7
accurately calculated.
7
migration compatibility for the following machines:
8
- Clock enables stick around when written.
8
* smdkc210
9
* realview-*
10
* vexpress-*
11
* kzm
12
* mps2-*
9
13
10
In addition, a best effort attempt to implement SECCNT and CNTR25M was
14
While breaking migration ABI, fix the size of the MII registers to be 16 bit,
11
made even though I don't think the kernel needs them.
15
as defined by IEEE 802.3u.
12
16
13
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
17
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
14
Reviewed-by: Joel Stanley <joel@jms.id.au>
18
Tested-by: Guenter Roeck <linux@roeck-us.net>
15
Reviewed-by: Cédric Le Goater <clg@kaod.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
19
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
20
Message-id: 20200911052101.2602693-3-hskinnemoen@google.com
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
22
---
23
include/hw/misc/npcm7xx_clk.h | 48 ++++++
23
include/hw/net/lan9118_phy.h | 37 ++++++++
24
hw/misc/npcm7xx_clk.c | 266 ++++++++++++++++++++++++++++++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
25
hw/misc/meson.build | 1 +
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
26
hw/misc/trace-events | 4 +
26
hw/net/Kconfig | 4 +
27
4 files changed, 319 insertions(+)
27
hw/net/meson.build | 1 +
28
create mode 100644 include/hw/misc/npcm7xx_clk.h
28
5 files changed, 233 insertions(+), 115 deletions(-)
29
create mode 100644 hw/misc/npcm7xx_clk.c
29
create mode 100644 include/hw/net/lan9118_phy.h
30
create mode 100644 hw/net/lan9118_phy.c
30
31
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
32
new file mode 100644
33
new file mode 100644
33
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
34
--- /dev/null
35
--- /dev/null
35
+++ b/include/hw/misc/npcm7xx_clk.h
36
+++ b/include/hw/net/lan9118_phy.h
36
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
37
+/*
38
+/*
38
+ * Nuvoton NPCM7xx Clock Control Registers.
39
+ * SMSC LAN9118 PHY emulation
39
+ *
40
+ *
40
+ * Copyright 2020 Google LLC
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
42
+ * Written by Paul Brook
41
+ *
43
+ *
42
+ * This program is free software; you can redistribute it and/or modify it
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
43
+ * under the terms of the GNU General Public License as published by the
45
+ * See the COPYING file in the top-level directory.
44
+ * Free Software Foundation; either version 2 of the License, or
45
+ * (at your option) any later version.
46
+ *
47
+ * This program is distributed in the hope that it will be useful, but WITHOUT
48
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
49
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
50
+ * for more details.
51
+ */
46
+ */
52
+#ifndef NPCM7XX_CLK_H
47
+
53
+#define NPCM7XX_CLK_H
48
+#ifndef HW_NET_LAN9118_PHY_H
54
+
49
+#define HW_NET_LAN9118_PHY_H
55
+#include "exec/memory.h"
50
+
51
+#include "qom/object.h"
56
+#include "hw/sysbus.h"
52
+#include "hw/sysbus.h"
57
+
53
+
58
+/*
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
59
+ * The reference clock frequency for the timer modules, and the SECCNT and
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
60
+ * CNTR25M registers in this module, is always 25 MHz.
56
+
61
+ */
57
+typedef struct Lan9118PhyState {
62
+#define NPCM7XX_TIMER_REF_HZ (25000000)
58
+ SysBusDevice parent_obj;
63
+
59
+
64
+/*
60
+ uint16_t status;
65
+ * Number of registers in our device state structure. Don't change this without
61
+ uint16_t control;
66
+ * incrementing the version_id in the vmstate.
62
+ uint16_t advertise;
67
+ */
63
+ uint16_t ints;
68
+#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
64
+ uint16_t int_mask;
69
+
65
+ qemu_irq irq;
70
+typedef struct NPCM7xxCLKState {
66
+ bool link_down;
71
+ SysBusDevice parent;
67
+} Lan9118PhyState;
72
+
68
+
73
+ MemoryRegion iomem;
69
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down);
74
+
70
+void lan9118_phy_reset(Lan9118PhyState *s);
75
+ uint32_t regs[NPCM7XX_CLK_NR_REGS];
71
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg);
76
+
72
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val);
77
+ /* Time reference for SECCNT and CNTR25M, initialized by power on reset */
73
+
78
+ int64_t ref_ns;
74
+#endif
79
+} NPCM7xxCLKState;
75
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
80
+
76
index XXXXXXX..XXXXXXX 100644
81
+#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
77
--- a/hw/net/lan9118.c
82
+#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
78
+++ b/hw/net/lan9118.c
83
+
79
@@ -XXX,XX +XXX,XX @@
84
+#endif /* NPCM7XX_CLK_H */
80
#include "net/net.h"
85
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
81
#include "net/eth.h"
82
#include "hw/irq.h"
83
+#include "hw/net/lan9118_phy.h"
84
#include "hw/net/lan9118.h"
85
#include "hw/ptimer.h"
86
#include "hw/qdev-properties.h"
87
@@ -XXX,XX +XXX,XX @@ do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
88
#define MAC_CR_RXEN 0x00000004
89
#define MAC_CR_RESERVED 0x7f404213
90
91
-#define PHY_INT_ENERGYON 0x80
92
-#define PHY_INT_AUTONEG_COMPLETE 0x40
93
-#define PHY_INT_FAULT 0x20
94
-#define PHY_INT_DOWN 0x10
95
-#define PHY_INT_AUTONEG_LP 0x08
96
-#define PHY_INT_PARFAULT 0x04
97
-#define PHY_INT_AUTONEG_PAGE 0x02
98
-
99
#define GPT_TIMER_EN 0x20000000
100
101
/*
102
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
103
uint32_t mac_mii_data;
104
uint32_t mac_flow;
105
106
- uint32_t phy_status;
107
- uint32_t phy_control;
108
- uint32_t phy_advertise;
109
- uint32_t phy_int;
110
- uint32_t phy_int_mask;
111
+ Lan9118PhyState mii;
112
+ IRQState mii_irq;
113
114
int32_t eeprom_writable;
115
uint8_t eeprom[128];
116
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
117
118
static const VMStateDescription vmstate_lan9118 = {
119
.name = "lan9118",
120
- .version_id = 2,
121
- .minimum_version_id = 1,
122
+ .version_id = 3,
123
+ .minimum_version_id = 3,
124
.fields = (const VMStateField[]) {
125
VMSTATE_PTIMER(timer, lan9118_state),
126
VMSTATE_UINT32(irq_cfg, lan9118_state),
127
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118 = {
128
VMSTATE_UINT32(mac_mii_acc, lan9118_state),
129
VMSTATE_UINT32(mac_mii_data, lan9118_state),
130
VMSTATE_UINT32(mac_flow, lan9118_state),
131
- VMSTATE_UINT32(phy_status, lan9118_state),
132
- VMSTATE_UINT32(phy_control, lan9118_state),
133
- VMSTATE_UINT32(phy_advertise, lan9118_state),
134
- VMSTATE_UINT32(phy_int, lan9118_state),
135
- VMSTATE_UINT32(phy_int_mask, lan9118_state),
136
VMSTATE_INT32(eeprom_writable, lan9118_state),
137
VMSTATE_UINT8_ARRAY(eeprom, lan9118_state, 128),
138
VMSTATE_INT32(tx_fifo_size, lan9118_state),
139
@@ -XXX,XX +XXX,XX @@ static void lan9118_reload_eeprom(lan9118_state *s)
140
lan9118_mac_changed(s);
141
}
142
143
-static void phy_update_irq(lan9118_state *s)
144
+static void lan9118_update_irq(void *opaque, int n, int level)
145
{
146
- if (s->phy_int & s->phy_int_mask) {
147
+ lan9118_state *s = opaque;
148
+
149
+ if (level) {
150
s->int_sts |= PHY_INT;
151
} else {
152
s->int_sts &= ~PHY_INT;
153
@@ -XXX,XX +XXX,XX @@ static void phy_update_irq(lan9118_state *s)
154
lan9118_update(s);
155
}
156
157
-static void phy_update_link(lan9118_state *s)
158
-{
159
- /* Autonegotiation status mirrors link status. */
160
- if (qemu_get_queue(s->nic)->link_down) {
161
- s->phy_status &= ~0x0024;
162
- s->phy_int |= PHY_INT_DOWN;
163
- } else {
164
- s->phy_status |= 0x0024;
165
- s->phy_int |= PHY_INT_ENERGYON;
166
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
167
- }
168
- phy_update_irq(s);
169
-}
170
-
171
static void lan9118_set_link(NetClientState *nc)
172
{
173
- phy_update_link(qemu_get_nic_opaque(nc));
174
-}
175
-
176
-static void phy_reset(lan9118_state *s)
177
-{
178
- s->phy_status = 0x7809;
179
- s->phy_control = 0x3000;
180
- s->phy_advertise = 0x01e1;
181
- s->phy_int_mask = 0;
182
- s->phy_int = 0;
183
- phy_update_link(s);
184
+ lan9118_phy_update_link(&LAN9118(qemu_get_nic_opaque(nc))->mii,
185
+ nc->link_down);
186
}
187
188
static void lan9118_reset(DeviceState *d)
189
@@ -XXX,XX +XXX,XX @@ static void lan9118_reset(DeviceState *d)
190
s->read_word_n = 0;
191
s->write_word_n = 0;
192
193
- phy_reset(s);
194
-
195
s->eeprom_writable = 0;
196
lan9118_reload_eeprom(s);
197
}
198
@@ -XXX,XX +XXX,XX @@ static void do_tx_packet(lan9118_state *s)
199
uint32_t status;
200
201
/* FIXME: Honor TX disable, and allow queueing of packets. */
202
- if (s->phy_control & 0x4000) {
203
+ if (s->mii.control & 0x4000) {
204
/* This assumes the receive routine doesn't touch the VLANClient. */
205
qemu_receive_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
206
} else {
207
@@ -XXX,XX +XXX,XX @@ static void tx_fifo_push(lan9118_state *s, uint32_t val)
208
}
209
}
210
211
-static uint32_t do_phy_read(lan9118_state *s, int reg)
212
-{
213
- uint32_t val;
214
-
215
- switch (reg) {
216
- case 0: /* Basic Control */
217
- return s->phy_control;
218
- case 1: /* Basic Status */
219
- return s->phy_status;
220
- case 2: /* ID1 */
221
- return 0x0007;
222
- case 3: /* ID2 */
223
- return 0xc0d1;
224
- case 4: /* Auto-neg advertisement */
225
- return s->phy_advertise;
226
- case 5: /* Auto-neg Link Partner Ability */
227
- return 0x0f71;
228
- case 6: /* Auto-neg Expansion */
229
- return 1;
230
- /* TODO 17, 18, 27, 29, 30, 31 */
231
- case 29: /* Interrupt source. */
232
- val = s->phy_int;
233
- s->phy_int = 0;
234
- phy_update_irq(s);
235
- return val;
236
- case 30: /* Interrupt mask */
237
- return s->phy_int_mask;
238
- default:
239
- qemu_log_mask(LOG_GUEST_ERROR,
240
- "do_phy_read: PHY read reg %d\n", reg);
241
- return 0;
242
- }
243
-}
244
-
245
-static void do_phy_write(lan9118_state *s, int reg, uint32_t val)
246
-{
247
- switch (reg) {
248
- case 0: /* Basic Control */
249
- if (val & 0x8000) {
250
- phy_reset(s);
251
- break;
252
- }
253
- s->phy_control = val & 0x7980;
254
- /* Complete autonegotiation immediately. */
255
- if (val & 0x1000) {
256
- s->phy_status |= 0x0020;
257
- }
258
- break;
259
- case 4: /* Auto-neg advertisement */
260
- s->phy_advertise = (val & 0x2d7f) | 0x80;
261
- break;
262
- /* TODO 17, 18, 27, 31 */
263
- case 30: /* Interrupt mask */
264
- s->phy_int_mask = val & 0xff;
265
- phy_update_irq(s);
266
- break;
267
- default:
268
- qemu_log_mask(LOG_GUEST_ERROR,
269
- "do_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
270
- }
271
-}
272
-
273
static void do_mac_write(lan9118_state *s, int reg, uint32_t val)
274
{
275
switch (reg) {
276
@@ -XXX,XX +XXX,XX @@ static void do_mac_write(lan9118_state *s, int reg, uint32_t val)
277
if (val & 2) {
278
DPRINTF("PHY write %d = 0x%04x\n",
279
(val >> 6) & 0x1f, s->mac_mii_data);
280
- do_phy_write(s, (val >> 6) & 0x1f, s->mac_mii_data);
281
+ lan9118_phy_write(&s->mii, (val >> 6) & 0x1f, s->mac_mii_data);
282
} else {
283
- s->mac_mii_data = do_phy_read(s, (val >> 6) & 0x1f);
284
+ s->mac_mii_data = lan9118_phy_read(&s->mii, (val >> 6) & 0x1f);
285
DPRINTF("PHY read %d = 0x%04x\n",
286
(val >> 6) & 0x1f, s->mac_mii_data);
287
}
288
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
289
break;
290
case CSR_PMT_CTRL:
291
if (val & 0x400) {
292
- phy_reset(s);
293
+ lan9118_phy_reset(&s->mii);
294
}
295
s->pmt_ctrl &= ~0x34e;
296
s->pmt_ctrl |= (val & 0x34e);
297
@@ -XXX,XX +XXX,XX @@ static void lan9118_realize(DeviceState *dev, Error **errp)
298
const MemoryRegionOps *mem_ops =
299
s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
300
301
+ qemu_init_irq(&s->mii_irq, lan9118_update_irq, s, 0);
302
+ object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
303
+ if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
304
+ return;
305
+ }
306
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
307
+
308
memory_region_init_io(&s->mmio, OBJECT(dev), mem_ops, s,
309
"lan9118-mmio", 0x100);
310
sysbus_init_mmio(sbd, &s->mmio);
311
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
86
new file mode 100644
312
new file mode 100644
87
index XXXXXXX..XXXXXXX
313
index XXXXXXX..XXXXXXX
88
--- /dev/null
314
--- /dev/null
89
+++ b/hw/misc/npcm7xx_clk.c
315
+++ b/hw/net/lan9118_phy.c
90
@@ -XXX,XX +XXX,XX @@
316
@@ -XXX,XX +XXX,XX @@
91
+/*
317
+/*
92
+ * Nuvoton NPCM7xx Clock Control Registers.
318
+ * SMSC LAN9118 PHY emulation
93
+ *
319
+ *
94
+ * Copyright 2020 Google LLC
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
321
+ * Written by Paul Brook
95
+ *
322
+ *
96
+ * This program is free software; you can redistribute it and/or modify it
323
+ * This code is licensed under the GNU GPL v2
97
+ * under the terms of the GNU General Public License as published by the
98
+ * Free Software Foundation; either version 2 of the License, or
99
+ * (at your option) any later version.
100
+ *
324
+ *
101
+ * This program is distributed in the hope that it will be useful, but WITHOUT
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
102
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
326
+ * GNU GPL, version 2 or (at your option) any later version.
103
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
104
+ * for more details.
105
+ */
327
+ */
106
+
328
+
107
+#include "qemu/osdep.h"
329
+#include "qemu/osdep.h"
108
+
330
+#include "hw/net/lan9118_phy.h"
109
+#include "hw/misc/npcm7xx_clk.h"
331
+#include "hw/irq.h"
332
+#include "hw/resettable.h"
110
+#include "migration/vmstate.h"
333
+#include "migration/vmstate.h"
111
+#include "qemu/error-report.h"
112
+#include "qemu/log.h"
334
+#include "qemu/log.h"
113
+#include "qemu/module.h"
335
+
114
+#include "qemu/timer.h"
336
+#define PHY_INT_ENERGYON (1 << 7)
115
+#include "qemu/units.h"
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
116
+#include "trace.h"
338
+#define PHY_INT_FAULT (1 << 5)
117
+
339
+#define PHY_INT_DOWN (1 << 4)
118
+#define PLLCON_LOKI BIT(31)
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
119
+#define PLLCON_LOKS BIT(30)
341
+#define PHY_INT_PARFAULT (1 << 2)
120
+#define PLLCON_PWDEN BIT(12)
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
121
+
343
+
122
+enum NPCM7xxCLKRegisters {
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
123
+ NPCM7XX_CLK_CLKEN1,
345
+{
124
+ NPCM7XX_CLK_CLKSEL,
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
125
+ NPCM7XX_CLK_CLKDIV1,
347
+}
126
+ NPCM7XX_CLK_PLLCON0,
348
+
127
+ NPCM7XX_CLK_PLLCON1,
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
128
+ NPCM7XX_CLK_SWRSTR,
350
+{
129
+ NPCM7XX_CLK_IPSRST1 = 0x20 / sizeof(uint32_t),
351
+ uint16_t val;
130
+ NPCM7XX_CLK_IPSRST2,
352
+
131
+ NPCM7XX_CLK_CLKEN2,
353
+ switch (reg) {
132
+ NPCM7XX_CLK_CLKDIV2,
354
+ case 0: /* Basic Control */
133
+ NPCM7XX_CLK_CLKEN3,
355
+ return s->control;
134
+ NPCM7XX_CLK_IPSRST3,
356
+ case 1: /* Basic Status */
135
+ NPCM7XX_CLK_WD0RCR,
357
+ return s->status;
136
+ NPCM7XX_CLK_WD1RCR,
358
+ case 2: /* ID1 */
137
+ NPCM7XX_CLK_WD2RCR,
359
+ return 0x0007;
138
+ NPCM7XX_CLK_SWRSTC1,
360
+ case 3: /* ID2 */
139
+ NPCM7XX_CLK_SWRSTC2,
361
+ return 0xc0d1;
140
+ NPCM7XX_CLK_SWRSTC3,
362
+ case 4: /* Auto-neg advertisement */
141
+ NPCM7XX_CLK_SWRSTC4,
363
+ return s->advertise;
142
+ NPCM7XX_CLK_PLLCON2,
364
+ case 5: /* Auto-neg Link Partner Ability */
143
+ NPCM7XX_CLK_CLKDIV3,
365
+ return 0x0f71;
144
+ NPCM7XX_CLK_CORSTC,
366
+ case 6: /* Auto-neg Expansion */
145
+ NPCM7XX_CLK_PLLCONG,
367
+ return 1;
146
+ NPCM7XX_CLK_AHBCKFI,
368
+ /* TODO 17, 18, 27, 29, 30, 31 */
147
+ NPCM7XX_CLK_SECCNT,
369
+ case 29: /* Interrupt source. */
148
+ NPCM7XX_CLK_CNTR25M,
370
+ val = s->ints;
149
+ NPCM7XX_CLK_REGS_END,
371
+ s->ints = 0;
150
+};
372
+ lan9118_phy_update_irq(s);
151
+
373
+ return val;
152
+/*
374
+ case 30: /* Interrupt mask */
153
+ * These reset values were taken from version 0.91 of the NPCM750R data sheet.
375
+ return s->int_mask;
154
+ *
376
+ default:
155
+ * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on
156
+ * core domain reset, but this reset type is not yet supported by QEMU.
157
+ */
158
+static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
159
+ [NPCM7XX_CLK_CLKEN1] = 0xffffffff,
160
+ [NPCM7XX_CLK_CLKSEL] = 0x004aaaaa,
161
+ [NPCM7XX_CLK_CLKDIV1] = 0x5413f855,
162
+ [NPCM7XX_CLK_PLLCON0] = 0x00222101 | PLLCON_LOKI,
163
+ [NPCM7XX_CLK_PLLCON1] = 0x00202101 | PLLCON_LOKI,
164
+ [NPCM7XX_CLK_IPSRST1] = 0x00001000,
165
+ [NPCM7XX_CLK_IPSRST2] = 0x80000000,
166
+ [NPCM7XX_CLK_CLKEN2] = 0xffffffff,
167
+ [NPCM7XX_CLK_CLKDIV2] = 0xaa4f8f9f,
168
+ [NPCM7XX_CLK_CLKEN3] = 0xffffffff,
169
+ [NPCM7XX_CLK_IPSRST3] = 0x03000000,
170
+ [NPCM7XX_CLK_WD0RCR] = 0xffffffff,
171
+ [NPCM7XX_CLK_WD1RCR] = 0xffffffff,
172
+ [NPCM7XX_CLK_WD2RCR] = 0xffffffff,
173
+ [NPCM7XX_CLK_SWRSTC1] = 0x00000003,
174
+ [NPCM7XX_CLK_PLLCON2] = 0x00c02105 | PLLCON_LOKI,
175
+ [NPCM7XX_CLK_CORSTC] = 0x04000003,
176
+ [NPCM7XX_CLK_PLLCONG] = 0x01228606 | PLLCON_LOKI,
177
+ [NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
178
+};
179
+
180
+static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
181
+{
182
+ uint32_t reg = offset / sizeof(uint32_t);
183
+ NPCM7xxCLKState *s = opaque;
184
+ int64_t now_ns;
185
+ uint32_t value = 0;
186
+
187
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
188
+ qemu_log_mask(LOG_GUEST_ERROR,
377
+ qemu_log_mask(LOG_GUEST_ERROR,
189
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
378
+ "lan9118_phy_read: PHY read reg %d\n", reg);
190
+ __func__, offset);
191
+ return 0;
379
+ return 0;
192
+ }
380
+ }
193
+
381
+}
382
+
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
384
+{
194
+ switch (reg) {
385
+ switch (reg) {
195
+ case NPCM7XX_CLK_SWRSTR:
386
+ case 0: /* Basic Control */
196
+ qemu_log_mask(LOG_GUEST_ERROR,
387
+ if (val & 0x8000) {
197
+ "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n",
388
+ lan9118_phy_reset(s);
198
+ __func__, offset);
389
+ break;
199
+ break;
390
+ }
200
+
391
+ s->control = val & 0x7980;
201
+ case NPCM7XX_CLK_SECCNT:
392
+ /* Complete autonegotiation immediately. */
202
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
393
+ if (val & 0x1000) {
203
+ value = (now_ns - s->ref_ns) / NANOSECONDS_PER_SECOND;
394
+ s->status |= 0x0020;
204
+ break;
205
+
206
+ case NPCM7XX_CLK_CNTR25M:
207
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
208
+ /*
209
+ * This register counts 25 MHz cycles, updating every 640 ns. It rolls
210
+ * over to zero every second.
211
+ *
212
+ * The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
213
+ */
214
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
215
+ break;
216
+
217
+ default:
218
+ value = s->regs[reg];
219
+ break;
220
+ };
221
+
222
+ trace_npcm7xx_clk_read(offset, value);
223
+
224
+ return value;
225
+}
226
+
227
+static void npcm7xx_clk_write(void *opaque, hwaddr offset,
228
+ uint64_t v, unsigned size)
229
+{
230
+ uint32_t reg = offset / sizeof(uint32_t);
231
+ NPCM7xxCLKState *s = opaque;
232
+ uint32_t value = v;
233
+
234
+ trace_npcm7xx_clk_write(offset, value);
235
+
236
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
237
+ qemu_log_mask(LOG_GUEST_ERROR,
238
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
239
+ __func__, offset);
240
+ return;
241
+ }
242
+
243
+ switch (reg) {
244
+ case NPCM7XX_CLK_SWRSTR:
245
+ qemu_log_mask(LOG_UNIMP, "%s: SW reset not implemented: 0x%02x\n",
246
+ __func__, value);
247
+ value = 0;
248
+ break;
249
+
250
+ case NPCM7XX_CLK_PLLCON0:
251
+ case NPCM7XX_CLK_PLLCON1:
252
+ case NPCM7XX_CLK_PLLCON2:
253
+ case NPCM7XX_CLK_PLLCONG:
254
+ if (value & PLLCON_PWDEN) {
255
+ /* Power down -- clear lock and indicate loss of lock */
256
+ value &= ~PLLCON_LOKI;
257
+ value |= PLLCON_LOKS;
258
+ } else {
259
+ /* Normal mode -- assume always locked */
260
+ value |= PLLCON_LOKI;
261
+ /* Keep LOKS unchanged unless cleared by writing 1 */
262
+ if (value & PLLCON_LOKS) {
263
+ value &= ~PLLCON_LOKS;
264
+ } else {
265
+ value |= (value & PLLCON_LOKS);
266
+ }
267
+ }
395
+ }
268
+ break;
396
+ break;
269
+
397
+ case 4: /* Auto-neg advertisement */
270
+ case NPCM7XX_CLK_CNTR25M:
398
+ s->advertise = (val & 0x2d7f) | 0x80;
399
+ break;
400
+ /* TODO 17, 18, 27, 31 */
401
+ case 30: /* Interrupt mask */
402
+ s->int_mask = val & 0xff;
403
+ lan9118_phy_update_irq(s);
404
+ break;
405
+ default:
271
+ qemu_log_mask(LOG_GUEST_ERROR,
406
+ qemu_log_mask(LOG_GUEST_ERROR,
272
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
273
+ __func__, offset);
274
+ return;
275
+ }
408
+ }
276
+
409
+}
277
+ s->regs[reg] = value;
410
+
278
+}
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
279
+
412
+{
280
+static const struct MemoryRegionOps npcm7xx_clk_ops = {
413
+ s->link_down = link_down;
281
+ .read = npcm7xx_clk_read,
414
+
282
+ .write = npcm7xx_clk_write,
415
+ /* Autonegotiation status mirrors link status. */
283
+ .endianness = DEVICE_LITTLE_ENDIAN,
416
+ if (link_down) {
284
+ .valid = {
417
+ s->status &= ~0x0024;
285
+ .min_access_size = 4,
418
+ s->ints |= PHY_INT_DOWN;
286
+ .max_access_size = 4,
419
+ } else {
287
+ .unaligned = false,
420
+ s->status |= 0x0024;
288
+ },
421
+ s->ints |= PHY_INT_ENERGYON;
422
+ s->ints |= PHY_INT_AUTONEG_COMPLETE;
423
+ }
424
+ lan9118_phy_update_irq(s);
425
+}
426
+
427
+void lan9118_phy_reset(Lan9118PhyState *s)
428
+{
429
+ s->control = 0x3000;
430
+ s->status = 0x7809;
431
+ s->advertise = 0x01e1;
432
+ s->int_mask = 0;
433
+ s->ints = 0;
434
+ lan9118_phy_update_link(s, s->link_down);
435
+}
436
+
437
+static void lan9118_phy_reset_hold(Object *obj, ResetType type)
438
+{
439
+ Lan9118PhyState *s = LAN9118_PHY(obj);
440
+
441
+ lan9118_phy_reset(s);
442
+}
443
+
444
+static void lan9118_phy_init(Object *obj)
445
+{
446
+ Lan9118PhyState *s = LAN9118_PHY(obj);
447
+
448
+ qdev_init_gpio_out(DEVICE(s), &s->irq, 1);
449
+}
450
+
451
+static const VMStateDescription vmstate_lan9118_phy = {
452
+ .name = "lan9118-phy",
453
+ .version_id = 1,
454
+ .minimum_version_id = 1,
455
+ .fields = (const VMStateField[]) {
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
462
+ VMSTATE_END_OF_LIST()
463
+ }
289
+};
464
+};
290
+
465
+
291
+static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
292
+{
293
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
294
+
295
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
296
+
297
+ switch (type) {
298
+ case RESET_TYPE_COLD:
299
+ memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
300
+ s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
301
+ return;
302
+ }
303
+
304
+ /*
305
+ * A small number of registers need to be reset on a core domain reset,
306
+ * but no such reset type exists yet.
307
+ */
308
+ qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.",
309
+ __func__, type);
310
+}
311
+
312
+static void npcm7xx_clk_init(Object *obj)
313
+{
314
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
315
+
316
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
317
+ TYPE_NPCM7XX_CLK, 4 * KiB);
318
+ sysbus_init_mmio(&s->parent, &s->iomem);
319
+}
320
+
321
+static const VMStateDescription vmstate_npcm7xx_clk = {
322
+ .name = "npcm7xx-clk",
323
+ .version_id = 0,
324
+ .minimum_version_id = 0,
325
+ .fields = (VMStateField[]) {
326
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
327
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
328
+ VMSTATE_END_OF_LIST(),
329
+ },
330
+};
331
+
332
+static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
333
+{
467
+{
334
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
335
+ DeviceClass *dc = DEVICE_CLASS(klass);
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
336
+
470
+
337
+ QEMU_BUILD_BUG_ON(NPCM7XX_CLK_REGS_END > NPCM7XX_CLK_NR_REGS);
471
+ rc->phases.hold = lan9118_phy_reset_hold;
338
+
472
+ dc->vmsd = &vmstate_lan9118_phy;
339
+ dc->desc = "NPCM7xx Clock Control Registers";
473
+}
340
+ dc->vmsd = &vmstate_npcm7xx_clk;
474
+
341
+ rc->phases.enter = npcm7xx_clk_enter_reset;
475
+static const TypeInfo types[] = {
342
+}
476
+ {
343
+
477
+ .name = TYPE_LAN9118_PHY,
344
+static const TypeInfo npcm7xx_clk_info = {
478
+ .parent = TYPE_SYS_BUS_DEVICE,
345
+ .name = TYPE_NPCM7XX_CLK,
479
+ .instance_size = sizeof(Lan9118PhyState),
346
+ .parent = TYPE_SYS_BUS_DEVICE,
480
+ .instance_init = lan9118_phy_init,
347
+ .instance_size = sizeof(NPCM7xxCLKState),
481
+ .class_init = lan9118_phy_class_init,
348
+ .instance_init = npcm7xx_clk_init,
482
+ }
349
+ .class_init = npcm7xx_clk_class_init,
350
+};
483
+};
351
+
484
+
352
+static void npcm7xx_clk_register_type(void)
485
+DEFINE_TYPES(types)
353
+{
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
354
+ type_register_static(&npcm7xx_clk_info);
355
+}
356
+type_init(npcm7xx_clk_register_type);
357
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
358
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
359
--- a/hw/misc/meson.build
488
--- a/hw/net/Kconfig
360
+++ b/hw/misc/meson.build
489
+++ b/hw/net/Kconfig
361
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
362
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
491
config SMC91C111
363
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
492
bool
364
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
493
365
+ 'npcm7xx_clk.c',
494
+config LAN9118_PHY
366
'npcm7xx_gcr.c',
495
+ bool
367
))
496
+
368
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
497
config LAN9118
369
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
498
bool
499
+ select LAN9118_PHY
500
select PTIMER
501
502
config NE2000_ISA
503
diff --git a/hw/net/meson.build b/hw/net/meson.build
370
index XXXXXXX..XXXXXXX 100644
504
index XXXXXXX..XXXXXXX 100644
371
--- a/hw/misc/trace-events
505
--- a/hw/net/meson.build
372
+++ b/hw/misc/trace-events
506
+++ b/hw/net/meson.build
373
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
374
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
508
375
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
376
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
377
+# npcm7xx_clk.c
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
378
+npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
512
system_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c'))
379
+npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
513
system_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c'))
380
+
514
system_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c'))
381
# npcm7xx_gcr.c
382
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
383
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
384
--
515
--
385
2.20.1
516
2.34.1
386
387
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
When booting directly into a kernel, bypassing the boot loader, the CPU and
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
UART clocks are not set up correctly. This makes the system appear very
4
imx_fec having more logging and tracing. Merge these improvements into
5
slow, and causes the initrd boot test to fail when optimization is off.
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
6
6
7
The UART clock must run at 24 MHz. The default 25 MHz reference clock
7
Some migration state how resides in the new device model which breaks migration
8
cannot achieve this, so switch to PLL2/2 @ 480 MHz, which works
8
compatibility for the following machines:
9
perfectly with the default /20 divider.
9
* imx25-pdk
10
* sabrelite
11
* mcimx7d-sabre
12
* mcimx6ul-evk
10
13
11
The CPU clock should run at 800 MHz, so switch it to PLL1/2. PLL1 runs
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
12
at 800 MHz by default, so we need to double the feedback divider as well
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
13
to make it run at 1600 MHz (so PLL1/2 runs at 800 MHz).
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
17
Message-id: 20241102125724.532843-3-shentey@gmail.com
15
We don't bother checking for PLL lock because we know our emulated PLLs
16
lock instantly.
17
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Message-id: 20200911052101.2602693-13-hskinnemoen@google.com
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
19
---
24
include/hw/arm/npcm7xx.h | 1 +
20
include/hw/net/imx_fec.h | 9 ++-
25
hw/arm/npcm7xx.c | 32 ++++++++++++++++++++++++++++++++
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
26
2 files changed, 33 insertions(+)
22
hw/net/lan9118_phy.c | 82 ++++++++++++++++------
23
hw/net/Kconfig | 1 +
24
hw/net/trace-events | 10 +--
25
5 files changed, 85 insertions(+), 163 deletions(-)
27
26
28
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
29
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/npcm7xx.h
29
--- a/include/hw/net/imx_fec.h
31
+++ b/include/hw/arm/npcm7xx.h
30
+++ b/include/hw/net/imx_fec.h
32
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
33
#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
32
#define TYPE_IMX_ENET "imx.enet"
34
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
33
35
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
34
#include "hw/sysbus.h"
36
+#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
35
+#include "hw/net/lan9118_phy.h"
37
36
+#include "hw/irq.h"
38
typedef struct NPCM7xxMachine {
37
#include "net/net.h"
39
MachineState parent;
38
40
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
39
#define ENET_EIR 1
40
@@ -XXX,XX +XXX,XX @@ struct IMXFECState {
41
uint32_t tx_descriptor[ENET_TX_RING_NUM];
42
uint32_t tx_ring_num;
43
44
- uint32_t phy_status;
45
- uint32_t phy_control;
46
- uint32_t phy_advertise;
47
- uint32_t phy_int;
48
- uint32_t phy_int_mask;
49
+ Lan9118PhyState mii;
50
+ IRQState mii_irq;
51
uint32_t phy_num;
52
bool phy_connected;
53
struct IMXFECState *phy_consumer;
54
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
41
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/npcm7xx.c
56
--- a/hw/net/imx_fec.c
43
+++ b/hw/arm/npcm7xx.c
57
+++ b/hw/net/imx_fec.c
44
@@ -XXX,XX +XXX,XX @@
58
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth_txdescs = {
45
#define NPCM7XX_ROM_BA (0xffff0000)
59
46
#define NPCM7XX_ROM_SZ (64 * KiB)
60
static const VMStateDescription vmstate_imx_eth = {
47
61
.name = TYPE_IMX_FEC,
48
+/* Clock configuration values to be fixed up when bypassing bootloader */
62
- .version_id = 2,
49
+
63
- .minimum_version_id = 2,
50
+/* Run PLL1 at 1600 MHz */
64
+ .version_id = 3,
51
+#define NPCM7XX_PLLCON1_FIXUP_VAL (0x00402101)
65
+ .minimum_version_id = 3,
52
+/* Run the CPU from PLL1 and UART from PLL2 */
66
.fields = (const VMStateField[]) {
53
+#define NPCM7XX_CLKSEL_FIXUP_VAL (0x004aaba9)
67
VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
54
+
68
VMSTATE_UINT32(rx_descriptor, IMXFECState),
55
/*
69
VMSTATE_UINT32(tx_descriptor[0], IMXFECState),
56
* Interrupt lines going into the GIC. This does not include internal Cortex-A9
70
- VMSTATE_UINT32(phy_status, IMXFECState),
57
* interrupts.
71
- VMSTATE_UINT32(phy_control, IMXFECState),
58
@@ -XXX,XX +XXX,XX @@ static const struct {
72
- VMSTATE_UINT32(phy_advertise, IMXFECState),
73
- VMSTATE_UINT32(phy_int, IMXFECState),
74
- VMSTATE_UINT32(phy_int_mask, IMXFECState),
75
VMSTATE_END_OF_LIST()
76
},
77
.subsections = (const VMStateDescription * const []) {
78
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth = {
59
},
79
},
60
};
80
};
61
81
62
+static void npcm7xx_write_board_setup(ARMCPU *cpu,
82
-#define PHY_INT_ENERGYON (1 << 7)
63
+ const struct arm_boot_info *info)
83
-#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
64
+{
84
-#define PHY_INT_FAULT (1 << 5)
65
+ uint32_t board_setup[] = {
85
-#define PHY_INT_DOWN (1 << 4)
66
+ 0xe59f0010, /* ldr r0, clk_base_addr */
86
-#define PHY_INT_AUTONEG_LP (1 << 3)
67
+ 0xe59f1010, /* ldr r1, pllcon1_value */
87
-#define PHY_INT_PARFAULT (1 << 2)
68
+ 0xe5801010, /* str r1, [r0, #16] */
88
-#define PHY_INT_AUTONEG_PAGE (1 << 1)
69
+ 0xe59f100c, /* ldr r1, clksel_value */
89
-
70
+ 0xe5801004, /* str r1, [r0, #4] */
90
static void imx_eth_update(IMXFECState *s);
71
+ 0xe12fff1e, /* bx lr */
91
72
+ NPCM7XX_CLK_BA,
92
/*
73
+ NPCM7XX_PLLCON1_FIXUP_VAL,
93
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s);
74
+ NPCM7XX_CLKSEL_FIXUP_VAL,
94
* For now we don't handle any GPIO/interrupt line, so the OS will
75
+ };
95
* have to poll for the PHY status.
76
+ int i;
96
*/
77
+
97
-static void imx_phy_update_irq(IMXFECState *s)
78
+ for (i = 0; i < ARRAY_SIZE(board_setup); i++) {
98
+static void imx_phy_update_irq(void *opaque, int n, int level)
79
+ board_setup[i] = tswap32(board_setup[i]);
99
{
100
- imx_eth_update(s);
101
-}
102
-
103
-static void imx_phy_update_link(IMXFECState *s)
104
-{
105
- /* Autonegotiation status mirrors link status. */
106
- if (qemu_get_queue(s->nic)->link_down) {
107
- trace_imx_phy_update_link("down");
108
- s->phy_status &= ~0x0024;
109
- s->phy_int |= PHY_INT_DOWN;
110
- } else {
111
- trace_imx_phy_update_link("up");
112
- s->phy_status |= 0x0024;
113
- s->phy_int |= PHY_INT_ENERGYON;
114
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
115
- }
116
- imx_phy_update_irq(s);
117
+ imx_eth_update(opaque);
118
}
119
120
static void imx_eth_set_link(NetClientState *nc)
121
{
122
- imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
123
-}
124
-
125
-static void imx_phy_reset(IMXFECState *s)
126
-{
127
- trace_imx_phy_reset();
128
-
129
- s->phy_status = 0x7809;
130
- s->phy_control = 0x3000;
131
- s->phy_advertise = 0x01e1;
132
- s->phy_int_mask = 0;
133
- s->phy_int = 0;
134
- imx_phy_update_link(s);
135
+ lan9118_phy_update_link(&IMX_FEC(qemu_get_nic_opaque(nc))->mii,
136
+ nc->link_down);
137
}
138
139
static uint32_t imx_phy_read(IMXFECState *s, int reg)
140
{
141
- uint32_t val;
142
uint32_t phy = reg / 32;
143
144
if (!s->phy_connected) {
145
@@ -XXX,XX +XXX,XX @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
146
147
reg %= 32;
148
149
- switch (reg) {
150
- case 0: /* Basic Control */
151
- val = s->phy_control;
152
- break;
153
- case 1: /* Basic Status */
154
- val = s->phy_status;
155
- break;
156
- case 2: /* ID1 */
157
- val = 0x0007;
158
- break;
159
- case 3: /* ID2 */
160
- val = 0xc0d1;
161
- break;
162
- case 4: /* Auto-neg advertisement */
163
- val = s->phy_advertise;
164
- break;
165
- case 5: /* Auto-neg Link Partner Ability */
166
- val = 0x0f71;
167
- break;
168
- case 6: /* Auto-neg Expansion */
169
- val = 1;
170
- break;
171
- case 29: /* Interrupt source. */
172
- val = s->phy_int;
173
- s->phy_int = 0;
174
- imx_phy_update_irq(s);
175
- break;
176
- case 30: /* Interrupt mask */
177
- val = s->phy_int_mask;
178
- break;
179
- case 17:
180
- case 18:
181
- case 27:
182
- case 31:
183
- qemu_log_mask(LOG_UNIMP, "[%s.phy]%s: reg %d not implemented\n",
184
- TYPE_IMX_FEC, __func__, reg);
185
- val = 0;
186
- break;
187
- default:
188
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
189
- TYPE_IMX_FEC, __func__, reg);
190
- val = 0;
191
- break;
192
- }
193
-
194
- trace_imx_phy_read(val, phy, reg);
195
-
196
- return val;
197
+ return lan9118_phy_read(&s->mii, reg);
198
}
199
200
static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
201
@@ -XXX,XX +XXX,XX @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
202
203
reg %= 32;
204
205
- trace_imx_phy_write(val, phy, reg);
206
-
207
- switch (reg) {
208
- case 0: /* Basic Control */
209
- if (val & 0x8000) {
210
- imx_phy_reset(s);
211
- } else {
212
- s->phy_control = val & 0x7980;
213
- /* Complete autonegotiation immediately. */
214
- if (val & 0x1000) {
215
- s->phy_status |= 0x0020;
216
- }
217
- }
218
- break;
219
- case 4: /* Auto-neg advertisement */
220
- s->phy_advertise = (val & 0x2d7f) | 0x80;
221
- break;
222
- case 30: /* Interrupt mask */
223
- s->phy_int_mask = val & 0xff;
224
- imx_phy_update_irq(s);
225
- break;
226
- case 17:
227
- case 18:
228
- case 27:
229
- case 31:
230
- qemu_log_mask(LOG_UNIMP, "[%s.phy)%s: reg %d not implemented\n",
231
- TYPE_IMX_FEC, __func__, reg);
232
- break;
233
- default:
234
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
235
- TYPE_IMX_FEC, __func__, reg);
236
- break;
237
- }
238
+ lan9118_phy_write(&s->mii, reg, val);
239
}
240
241
static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
242
@@ -XXX,XX +XXX,XX @@ static void imx_eth_reset(DeviceState *d)
243
244
s->rx_descriptor = 0;
245
memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
246
-
247
- /* We also reset the PHY */
248
- imx_phy_reset(s);
249
}
250
251
static uint32_t imx_default_read(IMXFECState *s, uint32_t index)
252
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
253
sysbus_init_irq(sbd, &s->irq[0]);
254
sysbus_init_irq(sbd, &s->irq[1]);
255
256
+ qemu_init_irq(&s->mii_irq, imx_phy_update_irq, s, 0);
257
+ object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
258
+ if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
259
+ return;
80
+ }
260
+ }
81
+ rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup),
261
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
82
+ info->board_setup_addr);
262
+
83
+}
263
qemu_macaddr_default_if_unset(&s->conf.macaddr);
84
+
264
85
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
265
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
86
const struct arm_boot_info *info)
266
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/hw/net/lan9118_phy.c
269
+++ b/hw/net/lan9118_phy.c
270
@@ -XXX,XX +XXX,XX @@
271
* Copyright (c) 2009 CodeSourcery, LLC.
272
* Written by Paul Brook
273
*
274
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
275
+ *
276
* This code is licensed under the GNU GPL v2
277
*
278
* Contributions after 2012-01-13 are licensed under the terms of the
279
@@ -XXX,XX +XXX,XX @@
280
#include "hw/resettable.h"
281
#include "migration/vmstate.h"
282
#include "qemu/log.h"
283
+#include "trace.h"
284
285
#define PHY_INT_ENERGYON (1 << 7)
286
#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
287
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
288
289
switch (reg) {
290
case 0: /* Basic Control */
291
- return s->control;
292
+ val = s->control;
293
+ break;
294
case 1: /* Basic Status */
295
- return s->status;
296
+ val = s->status;
297
+ break;
298
case 2: /* ID1 */
299
- return 0x0007;
300
+ val = 0x0007;
301
+ break;
302
case 3: /* ID2 */
303
- return 0xc0d1;
304
+ val = 0xc0d1;
305
+ break;
306
case 4: /* Auto-neg advertisement */
307
- return s->advertise;
308
+ val = s->advertise;
309
+ break;
310
case 5: /* Auto-neg Link Partner Ability */
311
- return 0x0f71;
312
+ val = 0x0f71;
313
+ break;
314
case 6: /* Auto-neg Expansion */
315
- return 1;
316
- /* TODO 17, 18, 27, 29, 30, 31 */
317
+ val = 1;
318
+ break;
319
case 29: /* Interrupt source. */
320
val = s->ints;
321
s->ints = 0;
322
lan9118_phy_update_irq(s);
323
- return val;
324
+ break;
325
case 30: /* Interrupt mask */
326
- return s->int_mask;
327
+ val = s->int_mask;
328
+ break;
329
+ case 17:
330
+ case 18:
331
+ case 27:
332
+ case 31:
333
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
334
+ __func__, reg);
335
+ val = 0;
336
+ break;
337
default:
338
- qemu_log_mask(LOG_GUEST_ERROR,
339
- "lan9118_phy_read: PHY read reg %d\n", reg);
340
- return 0;
341
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
342
+ __func__, reg);
343
+ val = 0;
344
+ break;
345
}
346
+
347
+ trace_lan9118_phy_read(val, reg);
348
+
349
+ return val;
350
}
351
352
void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
87
{
353
{
88
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info npcm7xx_binfo = {
354
+ trace_lan9118_phy_write(val, reg);
89
.gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
355
+
90
.write_secondary_boot = npcm7xx_write_secondary_boot,
356
switch (reg) {
91
.board_id = -1,
357
case 0: /* Basic Control */
92
+ .board_setup_addr = NPCM7XX_BOARD_SETUP_ADDR,
358
if (val & 0x8000) {
93
+ .write_board_setup = npcm7xx_write_board_setup,
359
lan9118_phy_reset(s);
94
};
360
- break;
95
361
- }
96
void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
362
- s->control = val & 0x7980;
363
- /* Complete autonegotiation immediately. */
364
- if (val & 0x1000) {
365
- s->status |= 0x0020;
366
+ } else {
367
+ s->control = val & 0x7980;
368
+ /* Complete autonegotiation immediately. */
369
+ if (val & 0x1000) {
370
+ s->status |= 0x0020;
371
+ }
372
}
373
break;
374
case 4: /* Auto-neg advertisement */
375
s->advertise = (val & 0x2d7f) | 0x80;
376
break;
377
- /* TODO 17, 18, 27, 31 */
378
case 30: /* Interrupt mask */
379
s->int_mask = val & 0xff;
380
lan9118_phy_update_irq(s);
381
break;
382
+ case 17:
383
+ case 18:
384
+ case 27:
385
+ case 31:
386
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
387
+ __func__, reg);
388
+ break;
389
default:
390
- qemu_log_mask(LOG_GUEST_ERROR,
391
- "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
392
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
393
+ __func__, reg);
394
+ break;
395
}
396
}
397
398
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
399
400
/* Autonegotiation status mirrors link status. */
401
if (link_down) {
402
+ trace_lan9118_phy_update_link("down");
403
s->status &= ~0x0024;
404
s->ints |= PHY_INT_DOWN;
405
} else {
406
+ trace_lan9118_phy_update_link("up");
407
s->status |= 0x0024;
408
s->ints |= PHY_INT_ENERGYON;
409
s->ints |= PHY_INT_AUTONEG_COMPLETE;
410
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
411
412
void lan9118_phy_reset(Lan9118PhyState *s)
413
{
414
+ trace_lan9118_phy_reset();
415
+
416
s->control = 0x3000;
417
s->status = 0x7809;
418
s->advertise = 0x01e1;
419
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_phy = {
420
.version_id = 1,
421
.minimum_version_id = 1,
422
.fields = (const VMStateField[]) {
423
- VMSTATE_UINT16(control, Lan9118PhyState),
424
VMSTATE_UINT16(status, Lan9118PhyState),
425
+ VMSTATE_UINT16(control, Lan9118PhyState),
426
VMSTATE_UINT16(advertise, Lan9118PhyState),
427
VMSTATE_UINT16(ints, Lan9118PhyState),
428
VMSTATE_UINT16(int_mask, Lan9118PhyState),
429
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
430
index XXXXXXX..XXXXXXX 100644
431
--- a/hw/net/Kconfig
432
+++ b/hw/net/Kconfig
433
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_SUN8I_EMAC
434
435
config IMX_FEC
436
bool
437
+ select LAN9118_PHY
438
439
config CADENCE
440
bool
441
diff --git a/hw/net/trace-events b/hw/net/trace-events
442
index XXXXXXX..XXXXXXX 100644
443
--- a/hw/net/trace-events
444
+++ b/hw/net/trace-events
445
@@ -XXX,XX +XXX,XX @@ allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
446
allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
447
allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
448
449
+# lan9118_phy.c
450
+lan9118_phy_read(uint16_t val, int reg) "[0x%02x] -> 0x%04" PRIx16
451
+lan9118_phy_write(uint16_t val, int reg) "[0x%02x] <- 0x%04" PRIx16
452
+lan9118_phy_update_link(const char *s) "%s"
453
+lan9118_phy_reset(void) ""
454
+
455
# lance.c
456
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=0x%"PRIx64"val=0x%04x"
457
lance_mem_writew(uint64_t addr, uint32_t val) "addr=0x%"PRIx64"val=0x%04x"
458
@@ -XXX,XX +XXX,XX @@ i82596_set_multicast(uint16_t count) "Added %d multicast entries"
459
i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
460
461
# imx_fec.c
462
-imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
463
imx_phy_read_num(int phy, int configured) "read request from unconfigured phy %d (configured %d)"
464
-imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => phy[%d].reg[%d]"
465
imx_phy_write_num(int phy, int configured) "write request to unconfigured phy %d (configured %d)"
466
-imx_phy_update_link(const char *s) "%s"
467
-imx_phy_reset(void) ""
468
imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x"
469
imx_enet_read_bd(uint64_t addr, int flags, int len, int data, int options, int status) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x option 0x%04x status 0x%04x"
470
imx_eth_tx_bd_busy(void) "tx_bd ran out of descriptors to transmit"
97
--
471
--
98
2.20.1
472
2.34.1
99
100
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Reviewed-by: Cédric Le Goater <clg@kaod.org>
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
5
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
5
6
Message-id: 20200911052101.2602693-14-hskinnemoen@google.com
6
Fixes: 2a424990170b "LAN9118 emulation"
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Tested-by: Guenter Roeck <linux@roeck-us.net>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20241102125724.532843-4-shentey@gmail.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
12
---
9
docs/system/arm/nuvoton.rst | 92 +++++++++++++++++++++++++++++++++++++
13
hw/net/lan9118_phy.c | 2 +-
10
docs/system/target-arm.rst | 1 +
14
1 file changed, 1 insertion(+), 1 deletion(-)
11
2 files changed, 93 insertions(+)
12
create mode 100644 docs/system/arm/nuvoton.rst
13
15
14
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
15
new file mode 100644
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/docs/system/arm/nuvoton.rst
19
@@ -XXX,XX +XXX,XX @@
20
+Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``)
21
+=====================================================
22
+
23
+The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are
24
+designed to be used as Baseboard Management Controllers (BMCs) in various
25
+servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an
26
+assortment of peripherals targeted for either Enterprise or Data Center /
27
+Hyperscale applications. The former is a superset of the latter, so NPCM750 has
28
+all the peripherals of NPCM730 and more.
29
+
30
+.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/
31
+
32
+The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise
33
+segment. The following machines are based on this chip :
34
+
35
+- ``npcm750-evb`` Nuvoton NPCM750 Evaluation board
36
+
37
+The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and
38
+Hyperscale applications. The following machines are based on this chip :
39
+
40
+- ``quanta-gsj`` Quanta GSJ server BMC
41
+
42
+There are also two more SoCs, NPCM710 and NPCM705, which are single-core
43
+variants of NPCM750 and NPCM730, respectively. These are currently not
44
+supported by QEMU.
45
+
46
+Supported devices
47
+-----------------
48
+
49
+ * SMP (Dual Core Cortex-A9)
50
+ * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer
51
+ and Watchdog.
52
+ * SRAM, ROM and DRAM mappings
53
+ * System Global Control Registers (GCR)
54
+ * Clock and reset controller (CLK)
55
+ * Timer controller (TIM)
56
+ * Serial ports (16550-based)
57
+ * DDR4 memory controller (dummy interface indicating memory training is done)
58
+ * OTP controllers (no protection features)
59
+ * Flash Interface Unit (FIU; no protection features)
60
+
61
+Missing devices
62
+---------------
63
+
64
+ * GPIO controller
65
+ * LPC/eSPI host-to-BMC interface, including
66
+
67
+ * Keyboard and mouse controller interface (KBCI)
68
+ * Keyboard Controller Style (KCS) channels
69
+ * BIOS POST code FIFO
70
+ * System Wake-up Control (SWC)
71
+ * Shared memory (SHM)
72
+ * eSPI slave interface
73
+
74
+ * Ethernet controllers (GMAC and EMC)
75
+ * USB host (USBH)
76
+ * USB device (USBD)
77
+ * SMBus controller (SMBF)
78
+ * Peripheral SPI controller (PSPI)
79
+ * Analog to Digital Converter (ADC)
80
+ * SD/MMC host
81
+ * Random Number Generator (RNG)
82
+ * PECI interface
83
+ * Pulse Width Modulation (PWM)
84
+ * Tachometer
85
+ * PCI and PCIe root complex and bridges
86
+ * VDM and MCTP support
87
+ * Serial I/O expansion
88
+ * LPC/eSPI host
89
+ * Coprocessor
90
+ * Graphics
91
+ * Video capture
92
+ * Encoding compression engine
93
+ * Security features
94
+
95
+Boot options
96
+------------
97
+
98
+The Nuvoton machines can boot from an OpenBMC firmware image, or directly into
99
+a kernel using the ``-kernel`` option. OpenBMC images for `quanta-gsj` and
100
+possibly others can be downloaded from the OpenPOWER jenkins :
101
+
102
+ https://openpower.xyz/
103
+
104
+The firmware image should be attached as an MTD drive. Example :
105
+
106
+.. code-block:: bash
107
+
108
+ $ qemu-system-arm -machine quanta-gsj -nographic \
109
+ -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw
110
+
111
+The default root password for test images is usually ``0penBmc``.
112
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
113
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
114
--- a/docs/system/target-arm.rst
18
--- a/hw/net/lan9118_phy.c
115
+++ b/docs/system/target-arm.rst
19
+++ b/hw/net/lan9118_phy.c
116
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
117
arm/musicpal
21
val = s->advertise;
118
arm/gumstix
22
break;
119
arm/nseries
23
case 5: /* Auto-neg Link Partner Ability */
120
+ arm/nuvoton
24
- val = 0x0f71;
121
arm/orangepi
25
+ val = 0x0fe1;
122
arm/palm
26
break;
123
arm/xscale
27
case 6: /* Auto-neg Expansion */
28
val = 1;
124
--
29
--
125
2.20.1
30
2.34.1
126
127
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
This is a minimalistic boot ROM written specifically for use with QEMU.
3
Prefer named constants over magic values for better readability.
4
It supports loading the second-stage loader from SPI flash into RAM, SMP
5
boot, and not much else.
6
4
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20200911052101.2602693-7-hskinnemoen@google.com
8
Message-id: 20241102125724.532843-5-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
.gitmodules | 3 +++
11
include/hw/net/mii.h | 6 +++++
14
MAINTAINERS | 2 ++
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
15
pc-bios/README | 6 ++++++
13
2 files changed, 46 insertions(+), 23 deletions(-)
16
pc-bios/meson.build | 1 +
17
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
18
roms/Makefile | 7 +++++++
19
roms/vbootrom | 1 +
20
7 files changed, 20 insertions(+)
21
create mode 100644 pc-bios/npcm7xx_bootrom.bin
22
create mode 160000 roms/vbootrom
23
14
24
diff --git a/.gitmodules b/.gitmodules
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/.gitmodules
17
--- a/include/hw/net/mii.h
27
+++ b/.gitmodules
18
+++ b/include/hw/net/mii.h
28
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
29
[submodule "meson"]
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
30
    path = meson
21
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
31
    url = https://github.com/mesonbuild/meson/
22
32
+[submodule "roms/vbootrom"]
23
+#define MII_ANAR_RFAULT (1 << 13) /* Say we can detect faults */
33
+    path = roms/vbootrom
24
#define MII_ANAR_PAUSE_ASYM (1 << 11) /* Try for asymmetric pause */
34
+    url = https://github.com/google/vbootrom.git
25
#define MII_ANAR_PAUSE (1 << 10) /* Try for pause */
35
diff --git a/MAINTAINERS b/MAINTAINERS
26
#define MII_ANAR_TXFD (1 << 8)
27
@@ -XXX,XX +XXX,XX @@
28
#define MII_ANAR_10FD (1 << 6)
29
#define MII_ANAR_10 (1 << 5)
30
#define MII_ANAR_CSMACD (1 << 0)
31
+#define MII_ANAR_SELECT (0x001f) /* Selector bits */
32
33
#define MII_ANLPAR_ACK (1 << 14)
34
#define MII_ANLPAR_PAUSEASY (1 << 11) /* can pause asymmetrically */
35
@@ -XXX,XX +XXX,XX @@
36
#define RTL8201CP_PHYID1 0x0000
37
#define RTL8201CP_PHYID2 0x8201
38
39
+/* SMSC LAN9118 */
40
+#define SMSCLAN9118_PHYID1 0x0007
41
+#define SMSCLAN9118_PHYID2 0xc0d1
42
+
43
/* RealTek 8211E */
44
#define RTL8211E_PHYID1 0x001c
45
#define RTL8211E_PHYID2 0xc915
46
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
36
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
37
--- a/MAINTAINERS
48
--- a/hw/net/lan9118_phy.c
38
+++ b/MAINTAINERS
49
+++ b/hw/net/lan9118_phy.c
39
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
40
S: Supported
41
F: hw/*/npcm7xx*
42
F: include/hw/*/npcm7xx*
43
+F: pc-bios/npcm7xx_bootrom.bin
44
+F: roms/vbootrom
45
46
nSeries
47
M: Andrzej Zaborowski <balrogg@gmail.com>
48
diff --git a/pc-bios/README b/pc-bios/README
49
index XXXXXXX..XXXXXXX 100644
50
--- a/pc-bios/README
51
+++ b/pc-bios/README
52
@@ -XXX,XX +XXX,XX @@
50
@@ -XXX,XX +XXX,XX @@
53
("Simplified BSD License" or "FreeBSD License", SPDX: BSD-2-Clause). OpenSBI
51
54
source code also contains code reused from other projects desribed here:
52
#include "qemu/osdep.h"
55
https://github.com/riscv/opensbi/blob/master/ThirdPartyNotices.md.
53
#include "hw/net/lan9118_phy.h"
56
+
54
+#include "hw/net/mii.h"
57
+- npcm7xx_bootrom.bin is a simplified, free (Apache 2.0) boot ROM for Nuvoton
55
#include "hw/irq.h"
58
+ NPCM7xx BMC devices. It currently implements the bare minimum to load, parse,
56
#include "hw/resettable.h"
59
+ initialize and run boot images stored in SPI flash, but may grow more
57
#include "migration/vmstate.h"
60
+ features over time as needed. The source code is available at:
58
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
61
+ https://github.com/google/vbootrom
59
uint16_t val;
62
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
60
63
index XXXXXXX..XXXXXXX 100644
61
switch (reg) {
64
--- a/pc-bios/meson.build
62
- case 0: /* Basic Control */
65
+++ b/pc-bios/meson.build
63
+ case MII_BMCR:
66
@@ -XXX,XX +XXX,XX @@ blobs = files(
64
val = s->control;
67
'opensbi-riscv64-generic-fw_dynamic.bin',
65
break;
68
'opensbi-riscv32-generic-fw_dynamic.elf',
66
- case 1: /* Basic Status */
69
'opensbi-riscv64-generic-fw_dynamic.elf',
67
+ case MII_BMSR:
70
+ 'npcm7xx_bootrom.bin',
68
val = s->status;
71
)
69
break;
72
70
- case 2: /* ID1 */
73
if install_blobs
71
- val = 0x0007;
74
diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin
72
+ case MII_PHYID1:
75
new file mode 100644
73
+ val = SMSCLAN9118_PHYID1;
76
index XXXXXXX..XXXXXXX
74
break;
77
GIT binary patch
75
- case 3: /* ID2 */
78
literal 768
76
- val = 0xc0d1;
79
zcmd5)JxClu6n-<aczPbVhZYusb8wKx;7TklHfmuZdYT9pDRLwd1p_t-DFpWpyA+8(
77
+ case MII_PHYID2:
80
zwKtZg3J4a0aCM3_X(ZL&4g;46VVk5e$K;z;L99|b@aE%v^S$rQ8)h(Vm@cB9IYc+2
78
+ val = SMSCLAN9118_PHYID2;
81
z2SHd4^NwTIGE%w>9S05p1#kf90Sj5Z(jG8}+)IZIp~iXK=T&)dL`%d-q*8aR#mq{7
79
break;
82
z9`=6;Dr(H0ACe72R5x?!)^86Qj-X%{+!K9iZNA@*wkBAV&iZ(l^I9?!Gz=S2I_*1d
80
- case 4: /* Auto-neg advertisement */
83
zr+tTQDHjvyzKnw(hu00yX`u!Fv<!~XVcX?@kr#<B0(gGU?$W{gSsQa}CF^8Cfzp2X
81
+ case MII_ANAR:
84
z@P}yDV-bci(K9XL$FU!som2C`c)?Uc&294s^}Wzumap{hg1X^jN|V25M5tQZ=<9lN
82
val = s->advertise;
85
z%(zKz#t-qCwHKb;HygOCpvCNL_4@1tXV1YGf^XUE_$zr{g8zWh-6gz-teI(eibtxo
83
break;
86
z?0OZI4%rU0741PgUD`2xq@H|*4=+Rs?%N)Ox5G+q>C;DilBe_YlkeSUVHA-crNk+k
84
- case 5: /* Auto-neg Link Partner Ability */
87
jtiF_MudA<CB(}8|fqYwCf3re&=&@_s761P#-ID$TwgmBa
85
- val = 0x0fe1;
88
86
+ case MII_ANLPAR:
89
literal 0
87
+ val = MII_ANLPAR_PAUSEASY | MII_ANLPAR_PAUSE | MII_ANLPAR_T4 |
90
HcmV?d00001
88
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
91
89
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
92
diff --git a/roms/Makefile b/roms/Makefile
90
break;
93
index XXXXXXX..XXXXXXX 100644
91
- case 6: /* Auto-neg Expansion */
94
--- a/roms/Makefile
92
- val = 1;
95
+++ b/roms/Makefile
93
+ case MII_ANER:
96
@@ -XXX,XX +XXX,XX @@ find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call find-cross-ld
94
+ val = MII_ANER_NWAY;
97
# finally strip off path + toolname so we get the prefix
95
break;
98
find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1))))
96
case 29: /* Interrupt source. */
99
97
val = s->ints;
100
+arm_cross_prefix := $(call find-cross-prefix,arm)
98
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
101
powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
99
trace_lan9118_phy_write(val, reg);
102
powerpc_cross_prefix := $(call find-cross-prefix,powerpc)
100
103
x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
101
switch (reg) {
104
@@ -XXX,XX +XXX,XX @@ default help:
102
- case 0: /* Basic Control */
105
    @echo " skiboot -- update skiboot.lid"
103
- if (val & 0x8000) {
106
    @echo " u-boot.e500 -- update u-boot.e500"
104
+ case MII_BMCR:
107
    @echo " u-boot.sam460 -- update u-boot.sam460"
105
+ if (val & MII_BMCR_RESET) {
108
+    @echo " npcm7xx_bootrom -- update vbootrom for npcm7xx"
106
lan9118_phy_reset(s);
109
    @echo " efi -- update UEFI (edk2) platform firmware"
107
} else {
110
    @echo " opensbi32-generic -- update OpenSBI for 32-bit generic machine"
108
- s->control = val & 0x7980;
111
    @echo " opensbi64-generic -- update OpenSBI for 64-bit generic machine"
109
+ s->control = val & (MII_BMCR_LOOPBACK | MII_BMCR_SPEED100 |
112
@@ -XXX,XX +XXX,XX @@ bios-microvm:
110
+ MII_BMCR_AUTOEN | MII_BMCR_PDOWN | MII_BMCR_FD |
113
    $(MAKE) -C qboot
111
+ MII_BMCR_CTST);
114
    cp qboot/bios.bin ../pc-bios/bios-microvm.bin
112
/* Complete autonegotiation immediately. */
115
113
- if (val & 0x1000) {
116
+npcm7xx_bootrom:
114
- s->status |= 0x0020;
117
+    $(MAKE) -C vbootrom CROSS_COMPILE=$(arm_cross_prefix)
115
+ if (val & MII_BMCR_AUTOEN) {
118
+    cp vbootrom/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin
116
+ s->status |= MII_BMSR_AN_COMP;
119
+
117
}
120
clean:
118
}
121
    rm -rf seabios/.config seabios/out seabios/builds
119
break;
122
    $(MAKE) -C sgabios clean
120
- case 4: /* Auto-neg advertisement */
123
@@ -XXX,XX +XXX,XX @@ clean:
121
- s->advertise = (val & 0x2d7f) | 0x80;
124
    $(MAKE) -f Makefile.edk2 clean
122
+ case MII_ANAR:
125
    $(MAKE) -C opensbi clean
123
+ s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
126
    $(MAKE) -C qboot clean
124
+ MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
127
+    $(MAKE) -C vbootrom clean
125
+ MII_ANAR_SELECT))
128
diff --git a/roms/vbootrom b/roms/vbootrom
126
+ | MII_ANAR_TX;
129
new file mode 160000
127
break;
130
index XXXXXXX..XXXXXXX
128
case 30: /* Interrupt mask */
131
--- /dev/null
129
s->int_mask = val & 0xff;
132
+++ b/roms/vbootrom
130
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
133
@@ -0,0 +1 @@
131
/* Autonegotiation status mirrors link status. */
134
+Subproject commit 0c37a43527f0ee2b9584e7fb2fdc805e902635ac
132
if (link_down) {
133
trace_lan9118_phy_update_link("down");
134
- s->status &= ~0x0024;
135
+ s->status &= ~(MII_BMSR_AN_COMP | MII_BMSR_LINK_ST);
136
s->ints |= PHY_INT_DOWN;
137
} else {
138
trace_lan9118_phy_update_link("up");
139
- s->status |= 0x0024;
140
+ s->status |= MII_BMSR_AN_COMP | MII_BMSR_LINK_ST;
141
s->ints |= PHY_INT_ENERGYON;
142
s->ints |= PHY_INT_AUTONEG_COMPLETE;
143
}
144
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_reset(Lan9118PhyState *s)
145
{
146
trace_lan9118_phy_reset();
147
148
- s->control = 0x3000;
149
- s->status = 0x7809;
150
- s->advertise = 0x01e1;
151
+ s->control = MII_BMCR_AUTOEN | MII_BMCR_SPEED100;
152
+ s->status = MII_BMSR_100TX_FD
153
+ | MII_BMSR_100TX_HD
154
+ | MII_BMSR_10T_FD
155
+ | MII_BMSR_10T_HD
156
+ | MII_BMSR_AUTONEG
157
+ | MII_BMSR_EXTCAP;
158
+ s->advertise = MII_ANAR_TXFD
159
+ | MII_ANAR_TX
160
+ | MII_ANAR_10FD
161
+ | MII_ANAR_10
162
+ | MII_ANAR_CSMACD;
163
s->int_mask = 0;
164
s->ints = 0;
165
lan9118_phy_update_link(s, s->link_down);
135
--
166
--
136
2.20.1
167
2.34.1
137
138
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
3
The real device advertises this mode and the device model already advertises
4
Tests the CAN controller in loopback, sleep and snoop mode.
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
Tests filtering of incoming CAN messages.
5
make the model more realistic.
6
6
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 1597278668-339715-4-git-send-email-fnu.vikram@xilinx.com
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
[PMM: updated to meson build system]
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
tests/qtest/xlnx-can-test.c | 359 ++++++++++++++++++++++++++++++++++++
13
hw/net/lan9118_phy.c | 4 ++--
14
tests/qtest/meson.build | 1 +
14
1 file changed, 2 insertions(+), 2 deletions(-)
15
2 files changed, 360 insertions(+)
16
create mode 100644 tests/qtest/xlnx-can-test.c
17
15
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/qtest/xlnx-can-test.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QTests for the Xilinx ZynqMP CAN controller.
26
+ *
27
+ * Copyright (c) 2020 Xilinx Inc.
28
+ *
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
30
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ * of this software and associated documentation files (the "Software"), to deal
33
+ * in the Software without restriction, including without limitation the rights
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ * copies of the Software, and to permit persons to whom the Software is
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
48
+ */
49
+
50
+#include "qemu/osdep.h"
51
+#include "libqos/libqtest.h"
52
+
53
+/* Base address. */
54
+#define CAN0_BASE_ADDR 0xFF060000
55
+#define CAN1_BASE_ADDR 0xFF070000
56
+
57
+/* Register addresses. */
58
+#define R_SRR_OFFSET 0x00
59
+#define R_MSR_OFFSET 0x04
60
+#define R_SR_OFFSET 0x18
61
+#define R_ISR_OFFSET 0x1C
62
+#define R_ICR_OFFSET 0x24
63
+#define R_TXID_OFFSET 0x30
64
+#define R_TXDLC_OFFSET 0x34
65
+#define R_TXDATA1_OFFSET 0x38
66
+#define R_TXDATA2_OFFSET 0x3C
67
+#define R_RXID_OFFSET 0x50
68
+#define R_RXDLC_OFFSET 0x54
69
+#define R_RXDATA1_OFFSET 0x58
70
+#define R_RXDATA2_OFFSET 0x5C
71
+#define R_AFR 0x60
72
+#define R_AFMR1 0x64
73
+#define R_AFIR1 0x68
74
+#define R_AFMR2 0x6C
75
+#define R_AFIR2 0x70
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
81
+/* CAN modes. */
82
+#define CONFIG_MODE 0x00
83
+#define NORMAL_MODE 0x00
84
+#define LOOPBACK_MODE 0x02
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
95
+static void match_rx_tx_data(uint32_t *buf_tx, uint32_t *buf_rx,
96
+ uint8_t can_timestamp)
97
+{
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
108
+ size++;
109
+ }
110
+}
111
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
113
+{
114
+ uint32_t int_status;
115
+
116
+ /* Read the interrupt on CAN rx. */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
118
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
120
+
121
+ /* Read the RX register data for CAN. */
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
126
+
127
+ /* Clear the RX interrupt. */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
129
+}
130
+
131
+static void send_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_tx)
132
+{
133
+ uint32_t int_status;
134
+
135
+ /* Write the TX register data for CAN. */
136
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
137
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
138
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
139
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
140
+
141
+ /* Read the interrupt on CAN for tx. */
142
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
143
+
144
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
145
+
146
+ /* Clear the interrupt for tx. */
147
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
148
+}
149
+
150
+/*
151
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
152
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
153
+ * the data sent from CAN0 with received on CAN1.
154
+ */
155
+static void test_can_bus(void)
156
+{
157
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
158
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
159
+ uint32_t status = 0;
160
+ uint8_t can_timestamp = 1;
161
+
162
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
163
+ " -object can-bus,id=canbus0"
164
+ " -machine xlnx-zcu102.canbus0=canbus0"
165
+ " -machine xlnx-zcu102.canbus1=canbus0"
166
+ );
167
+
168
+ /* Configure the CAN0 and CAN1. */
169
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
171
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
173
+
174
+ /* Check here if CAN0 and CAN1 are in normal mode. */
175
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
176
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
177
+
178
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
179
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
180
+
181
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
182
+
183
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
184
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
185
+
186
+ qtest_quit(qts);
187
+}
188
+
189
+/*
190
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
191
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
192
+ */
193
+static void test_can_loopback(void)
194
+{
195
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
196
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
197
+ uint32_t status = 0;
198
+
199
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
200
+ " -object can-bus,id=canbus0"
201
+ " -machine xlnx-zcu102.canbus0=canbus0"
202
+ " -machine xlnx-zcu102.canbus1=canbus0"
203
+ );
204
+
205
+ /* Configure the CAN0 in loopback mode. */
206
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
209
+
210
+ /* Check here if CAN0 is set in loopback mode. */
211
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
212
+
213
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
214
+
215
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
216
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
217
+ match_rx_tx_data(buf_tx, buf_rx, 0);
218
+
219
+ /* Configure the CAN1 in loopback mode. */
220
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
223
+
224
+ /* Check here if CAN1 is set in loopback mode. */
225
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
226
+
227
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
228
+
229
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
230
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
231
+ match_rx_tx_data(buf_tx, buf_rx, 0);
232
+
233
+ qtest_quit(qts);
234
+}
235
+
236
+/*
237
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
238
+ * test message will pass through filter 2.
239
+ */
240
+static void test_can_filter(void)
241
+{
242
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
243
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
244
+ uint32_t status = 0;
245
+ uint8_t can_timestamp = 1;
246
+
247
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
248
+ " -object can-bus,id=canbus0"
249
+ " -machine xlnx-zcu102.canbus0=canbus0"
250
+ " -machine xlnx-zcu102.canbus1=canbus0"
251
+ );
252
+
253
+ /* Configure the CAN0 and CAN1. */
254
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
256
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
258
+
259
+ /* Check here if CAN0 and CAN1 are in normal mode. */
260
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
261
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
262
+
263
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
264
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
265
+
266
+ /* Set filter for CAN1 for incoming messages. */
267
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
276
+
277
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
278
+
279
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
280
+
281
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
282
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
283
+
284
+ qtest_quit(qts);
285
+}
286
+
287
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
288
+static void test_can_sleepmode(void)
289
+{
290
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
291
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
292
+ uint32_t status = 0;
293
+ uint8_t can_timestamp = 1;
294
+
295
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
296
+ " -object can-bus,id=canbus0"
297
+ " -machine xlnx-zcu102.canbus0=canbus0"
298
+ " -machine xlnx-zcu102.canbus1=canbus0"
299
+ );
300
+
301
+ /* Configure the CAN0. */
302
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
305
+
306
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
308
+
309
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
310
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
311
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
312
+
313
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
314
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
315
+
316
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
317
+
318
+ /*
319
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
320
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
321
+ * incoming data.
322
+ */
323
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
324
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
325
+
326
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
327
+
328
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
329
+
330
+ qtest_quit(qts);
331
+}
332
+
333
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
334
+static void test_can_snoopmode(void)
335
+{
336
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
337
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
338
+ uint32_t status = 0;
339
+ uint8_t can_timestamp = 1;
340
+
341
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
342
+ " -object can-bus,id=canbus0"
343
+ " -machine xlnx-zcu102.canbus0=canbus0"
344
+ " -machine xlnx-zcu102.canbus1=canbus0"
345
+ );
346
+
347
+ /* Configure the CAN0. */
348
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
351
+
352
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
354
+
355
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
356
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
357
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
358
+
359
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
360
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
361
+
362
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
363
+
364
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
365
+
366
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
367
+
368
+ qtest_quit(qts);
369
+}
370
+
371
+int main(int argc, char **argv)
372
+{
373
+ g_test_init(&argc, &argv, NULL);
374
+
375
+ qtest_add_func("/net/can/can_bus", test_can_bus);
376
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
377
+ qtest_add_func("/net/can/can_filter", test_can_filter);
378
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
379
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
380
+
381
+ return g_test_run();
382
+}
383
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
384
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
385
--- a/tests/qtest/meson.build
18
--- a/hw/net/lan9118_phy.c
386
+++ b/tests/qtest/meson.build
19
+++ b/hw/net/lan9118_phy.c
387
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
388
(config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-swtpm-test'] : []) + \
21
break;
389
['numa-test',
22
case MII_ANAR:
390
'boot-serial-test',
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
391
+ 'xlnx-can-test',
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
392
'migration-test']
25
- MII_ANAR_SELECT))
393
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
394
qtests_s390x = \
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
28
| MII_ANAR_TX;
29
break;
30
case 30: /* Interrupt mask */
395
--
31
--
396
2.20.1
32
2.34.1
397
398
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
For IEEE fused multiply-add, the (0 * inf) + NaN case should raise
2
Invalid for the multiplication of 0 by infinity. Currently we handle
3
this in the per-architecture ifdef ladder in pickNaNMulAdd().
4
However, since this isn't really architecture specific we can hoist
5
it up to the generic code.
2
6
3
Connect CAN0 and CAN1 on the ZynqMP.
7
For the cases where the infzero test in pickNaNMulAdd was
8
returning 2, we can delete the check entirely and allow the
9
code to fall into the normal pick-a-NaN handling, because this
10
will return 2 anyway (input 'c' being the only NaN in this case).
11
For the cases where infzero was returning 3 to indicate "return
12
the default NaN", we must retain that "return 3".
4
13
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
14
For Arm, this looks like it might be a behaviour change because we
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
used to set float_flag_invalid | float_flag_invalid_imz only if C is
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
16
a quiet NaN. However, it is not, because Arm target code never looks
8
Message-id: 1597278668-339715-3-git-send-email-fnu.vikram@xilinx.com
17
at float_flag_invalid_imz, and for the (0 * inf) + SNaN case we
18
already raised float_flag_invalid via the "abc_mask &
19
float_cmask_snan" check in pick_nan_muladd.
20
21
For any target architecture using the "default implementation" at the
22
bottom of the ifdef, this is a behaviour change but will be fixing a
23
bug (where we failed to raise the Invalid exception for (0 * inf +
24
QNaN). The architectures using the default case are:
25
* hppa
26
* i386
27
* sh4
28
* tricore
29
30
The x86, Tricore and SH4 CPU architecture manuals are clear that this
31
should have raised Invalid; HPPA is a bit vaguer but still seems
32
clear enough.
33
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Message-id: 20241202131347.498124-2-peter.maydell@linaro.org
10
---
37
---
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
38
fpu/softfloat-parts.c.inc | 13 +++++++------
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
40
2 files changed, 8 insertions(+), 34 deletions(-)
14
3 files changed, 62 insertions(+)
15
41
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
17
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
44
--- a/fpu/softfloat-parts.c.inc
19
+++ b/include/hw/arm/xlnx-zynqmp.h
45
+++ b/fpu/softfloat-parts.c.inc
20
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
#include "hw/intc/arm_gic.h"
47
int ab_mask, int abc_mask)
22
#include "hw/net/cadence_gem.h"
48
{
23
#include "hw/char/cadence_uart.h"
49
int which;
24
+#include "hw/net/xlnx-zynqmp-can.h"
50
+ bool infzero = (ab_mask == float_cmask_infzero);
25
#include "hw/ide/ahci.h"
51
26
#include "hw/sd/sdhci.h"
52
if (unlikely(abc_mask & float_cmask_snan)) {
27
#include "hw/ssi/xilinx_spips.h"
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
28
@@ -XXX,XX +XXX,XX @@
54
}
29
#include "hw/cpu/cluster.h"
55
30
#include "target/arm/cpu.h"
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
31
#include "qom/object.h"
57
- ab_mask == float_cmask_infzero, s);
32
+#include "net/can_emu.h"
58
+ if (infzero) {
33
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
35
typedef struct XlnxZynqMPState XlnxZynqMPState;
36
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(XlnxZynqMPState, XLNX_ZYNQMP,
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
38
#define XLNX_ZYNQMP_NUM_GEMS 4
39
#define XLNX_ZYNQMP_NUM_UARTS 2
40
+#define XLNX_ZYNQMP_NUM_CAN 2
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
60
};
61
62
#endif
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/xlnx-zcu102.c
66
+++ b/hw/arm/xlnx-zcu102.c
67
@@ -XXX,XX +XXX,XX @@
68
#include "sysemu/qtest.h"
69
#include "sysemu/device_tree.h"
70
#include "qom/object.h"
71
+#include "net/can_emu.h"
72
73
struct XlnxZCU102 {
74
MachineState parent_obj;
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
76
bool secure;
77
bool virt;
78
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
80
+
81
struct arm_boot_info binfo;
82
};
83
typedef struct XlnxZCU102 XlnxZCU102;
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
86
&error_fatal);
87
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
90
+
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
92
+ OBJECT(s->canbus[i]), &error_fatal);
93
+ g_free(bus_name);
94
+ }
61
+ }
95
+
62
+
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
97
64
98
/* Create and plug in the SD cards */
65
if (s->default_nan_mode || which == 3) {
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
66
- /*
100
"Set on/off to enable/disable emulating a "
67
- * Note that this check is after pickNaNMulAdd so that function
101
"guest CPU which implements the ARM "
68
- * has an opportunity to set the Invalid flag for infzero.
102
"Virtualization Extensions");
69
- */
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
70
parts_default_nan(a, s);
104
+ (Object **)&s->canbus[0],
71
return a;
105
+ object_property_allow_set_link,
72
}
106
+ 0);
73
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
74
index XXXXXXX..XXXXXXX 100644
75
--- a/fpu/softfloat-specialize.c.inc
76
+++ b/fpu/softfloat-specialize.c.inc
77
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
78
* the default NaN
79
*/
80
if (infzero && is_qnan(c_cls)) {
81
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
82
return 3;
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
86
* case sets InvalidOp and returns the default NaN
87
*/
88
if (infzero) {
89
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
90
return 3;
91
}
92
/* Prefer sNaN over qNaN, in the a, b, c order. */
93
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
94
* For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
95
* case sets InvalidOp and returns the input value 'c'
96
*/
97
- if (infzero) {
98
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
99
- return 2;
100
- }
101
/* Prefer sNaN over qNaN, in the c, a, b order. */
102
if (is_snan(c_cls)) {
103
return 2;
104
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
105
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
106
* case sets InvalidOp and returns the input value 'c'
107
*/
108
- if (infzero) {
109
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
110
- return 2;
111
- }
107
+
112
+
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
109
+ (Object **)&s->canbus[1],
114
if (is_snan(c_cls)) {
110
+ object_property_allow_set_link,
115
return 2;
111
+ 0);
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
112
}
117
* to return an input NaN if we have one (ie c) rather than generating
113
118
* a default NaN
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
119
*/
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
120
- if (infzero) {
116
index XXXXXXX..XXXXXXX 100644
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
117
--- a/hw/arm/xlnx-zynqmp.c
122
- return 2;
118
+++ b/hw/arm/xlnx-zynqmp.c
123
- }
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
124
120
21, 22,
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
121
};
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
122
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
128
return 1;
124
+ 0xFF060000, 0xFF070000,
125
+};
126
+
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
128
+ 23, 24,
129
+};
130
+
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
132
0xFF160000, 0xFF170000,
133
};
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
135
TYPE_CADENCE_UART);
136
}
129
}
137
130
#elif defined(TARGET_RISCV)
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
132
- if (infzero) {
140
+ TYPE_XLNX_ZYNQMP_CAN);
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
141
+ }
134
- }
142
+
135
return 3; /* default NaN */
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
136
#elif defined(TARGET_S390X)
144
137
if (infzero) {
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
139
return 3;
147
gic_spi[uart_intr[i]]);
148
}
140
}
149
141
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
143
return 2;
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
144
}
153
+
145
#elif defined(TARGET_SPARC)
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
146
- /* For (inf,0,nan) return c. */
155
+ OBJECT(s->canbus[i]), &error_fatal);
147
- if (infzero) {
156
+
148
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
149
- return 2;
158
+ if (err) {
150
- }
159
+ error_propagate(errp, err);
151
/* Prefer SNaN over QNaN, order C, B, A. */
160
+ return;
152
if (is_snan(c_cls)) {
161
+ }
153
return 2;
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
154
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
155
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
164
+ gic_spi[can_intr[i]]);
156
* an input NaN if we have one (ie c).
165
+ }
157
*/
166
+
158
- if (infzero) {
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
159
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
168
&error_abort);
160
- return 2;
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
161
- }
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
162
if (status->use_first_nan) {
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
163
if (is_nan(a_cls)) {
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
164
return 0;
173
MemoryRegion *),
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
175
+ CanBusState *),
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
177
+ CanBusState *),
178
DEFINE_PROP_END_OF_LIST()
179
};
180
181
--
165
--
182
2.20.1
166
2.34.1
183
184
diff view generated by jsdifflib
New patch
1
If the target sets default_nan_mode then we're always going to return
2
the default NaN, and pickNaNMulAdd() no longer has any side effects.
3
For consistency with pickNaN(), check for default_nan_mode before
4
calling pickNaNMulAdd().
1
5
6
When we convert pickNaNMulAdd() to allow runtime selection of the NaN
7
propagation rule, this means we won't have to make the targets which
8
use default_nan_mode also set a propagation rule.
9
10
Since RiscV always uses default_nan_mode, this allows us to remove
11
its ifdef case from pickNaNMulAdd().
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241202131347.498124-3-peter.maydell@linaro.org
16
---
17
fpu/softfloat-parts.c.inc | 8 ++++++--
18
fpu/softfloat-specialize.c.inc | 9 +++++++--
19
2 files changed, 13 insertions(+), 4 deletions(-)
20
21
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
23
--- a/fpu/softfloat-parts.c.inc
24
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
26
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
27
}
28
29
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
30
+ if (s->default_nan_mode) {
31
+ which = 3;
32
+ } else {
33
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
34
+ }
35
36
- if (s->default_nan_mode || which == 3) {
37
+ if (which == 3) {
38
parts_default_nan(a, s);
39
return a;
40
}
41
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
42
index XXXXXXX..XXXXXXX 100644
43
--- a/fpu/softfloat-specialize.c.inc
44
+++ b/fpu/softfloat-specialize.c.inc
45
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
46
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
47
bool infzero, float_status *status)
48
{
49
+ /*
50
+ * We guarantee not to require the target to tell us how to
51
+ * pick a NaN if we're always returning the default NaN.
52
+ * But if we're not in default-NaN mode then the target must
53
+ * specify.
54
+ */
55
+ assert(!status->default_nan_mode);
56
#if defined(TARGET_ARM)
57
/* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
58
* the default NaN
59
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
60
} else {
61
return 1;
62
}
63
-#elif defined(TARGET_RISCV)
64
- return 3; /* default NaN */
65
#elif defined(TARGET_S390X)
66
if (infzero) {
67
return 3;
68
--
69
2.34.1
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
The Nuvoton NPCM7xx SoC family are used to implement Baseboard
3
architectures thus do different things:
4
Management Controllers in servers. While the family includes four SoCs,
4
* some return the default NaN
5
this patch implements limited support for two of them: NPCM730 (targeted
5
* some return the input NaN
6
for Data Center applications) and NPCM750 (targeted for Enterprise
6
* Arm returns the default NaN if the input NaN is quiet,
7
applications).
7
and the input NaN if it is signalling
8
8
9
This patch includes little more than the bare minimum needed to boot a
9
We want to make this logic be runtime selected rather than
10
Linux kernel built with NPCM7xx support in direct-kernel mode:
10
hardcoded into the binary, because:
11
11
* this will let us have multiple targets in one QEMU binary
12
- Two Cortex-A9 CPU cores with built-in periperhals.
12
* the Arm FEAT_AFP architectural feature includes letting
13
- Global Configuration Registers.
13
the guest select a NaN propagation rule at runtime
14
- Clock Management.
14
15
- 3 Timer Modules with 5 timers each.
15
In this commit we add an enum for the propagation rule, the field in
16
- 4 serial ports.
16
float_status, and the corresponding getters and setters. We change
17
17
pickNaNMulAdd to honour this, but because all targets still leave
18
The chips themselves have a lot more features, some of which will be
18
this field at its default 0 value, the fallback logic will pick the
19
added to the model at a later stage.
19
rule type with the old ifdef ladder.
20
20
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
21
Note that four architectures both use the muladd softfloat functions
22
Reviewed-by: Joel Stanley <joel@jms.id.au>
22
and did not have a branch of the ifdef ladder to specify their
23
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
behaviour (and so were ending up with the "default" case, probably
24
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
wrongly): i386, HPPA, SH4 and Tricore. SH4 and Tricore both set
25
Tested-by: Alexander Bulekov <alxndr@bu.edu>
25
default_nan_mode, and so will never get into pickNaNMulAdd(). For
26
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
26
HPPA and i386 we retain the same behaviour as the old default-case,
27
Message-id: 20200911052101.2602693-5-hskinnemoen@google.com
27
which is to not ever return the default NaN. This might not be
28
correct but it is not a behaviour change.
29
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Message-id: 20241202131347.498124-4-peter.maydell@linaro.org
29
---
33
---
30
include/hw/arm/npcm7xx.h | 85 ++++++++
34
include/fpu/softfloat-helpers.h | 11 ++++
31
hw/arm/npcm7xx.c | 407 +++++++++++++++++++++++++++++++++++++++
35
include/fpu/softfloat-types.h | 23 +++++++++
32
hw/arm/Kconfig | 5 +
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
33
hw/arm/meson.build | 1 +
37
3 files changed, 95 insertions(+), 30 deletions(-)
34
4 files changed, 498 insertions(+)
38
35
create mode 100644 include/hw/arm/npcm7xx.h
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
36
create mode 100644 hw/arm/npcm7xx.c
40
index XXXXXXX..XXXXXXX 100644
37
41
--- a/include/fpu/softfloat-helpers.h
38
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
42
+++ b/include/fpu/softfloat-helpers.h
39
new file mode 100644
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
40
index XXXXXXX..XXXXXXX
44
status->float_2nan_prop_rule = rule;
41
--- /dev/null
45
}
42
+++ b/include/hw/arm/npcm7xx.h
46
43
@@ -XXX,XX +XXX,XX @@
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
+ float_status *status)
49
+{
50
+ status->float_infzeronan_rule = rule;
51
+}
52
+
53
static inline void set_flush_to_zero(bool val, float_status *status)
54
{
55
status->flush_to_zero = val;
56
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
57
return status->float_2nan_prop_rule;
58
}
59
60
+static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
61
+{
62
+ return status->float_infzeronan_rule;
63
+}
64
+
65
static inline bool get_flush_to_zero(float_status *status)
66
{
67
return status->flush_to_zero;
68
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/fpu/softfloat-types.h
71
+++ b/include/fpu/softfloat-types.h
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
73
float_2nan_prop_x87,
74
} Float2NaNPropRule;
75
44
+/*
76
+/*
45
+ * Nuvoton NPCM7xx SoC family.
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
78
+ * This must be a NaN, but implementations differ on whether this
79
+ * is the input NaN or the default NaN.
46
+ *
80
+ *
47
+ * Copyright 2020 Google LLC
81
+ * You don't need to set this if default_nan_mode is enabled.
48
+ *
82
+ * When not in default-NaN mode, it is an error for the target
49
+ * This program is free software; you can redistribute it and/or modify it
83
+ * not to set the rule in float_status if it uses muladd, and we
50
+ * under the terms of the GNU General Public License as published by the
84
+ * will assert if we need to handle an input NaN and no rule was
51
+ * Free Software Foundation; either version 2 of the License, or
85
+ * selected.
52
+ * (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful, but WITHOUT
55
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
56
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
57
+ * for more details.
58
+ */
86
+ */
59
+#ifndef NPCM7XX_H
87
+typedef enum __attribute__((__packed__)) {
60
+#define NPCM7XX_H
88
+ /* No propagation rule specified */
61
+
89
+ float_infzeronan_none = 0,
62
+#include "hw/boards.h"
90
+ /* Result is never the default NaN (so always the input NaN) */
63
+#include "hw/cpu/a9mpcore.h"
91
+ float_infzeronan_dnan_never,
64
+#include "hw/misc/npcm7xx_clk.h"
92
+ /* Result is always the default NaN */
65
+#include "hw/misc/npcm7xx_gcr.h"
93
+ float_infzeronan_dnan_always,
66
+#include "hw/timer/npcm7xx_timer.h"
94
+ /* Result is the default NaN if the input NaN is quiet */
67
+#include "target/arm/cpu.h"
95
+ float_infzeronan_dnan_if_qnan,
68
+
96
+} FloatInfZeroNaNRule;
69
+#define NPCM7XX_MAX_NUM_CPUS (2)
97
+
70
+
98
/*
71
+/* The first half of the address space is reserved for DDR4 DRAM. */
99
* Floating Point Status. Individual architectures may maintain
72
+#define NPCM7XX_DRAM_BA (0x00000000)
100
* several versions of float_status for different functions. The
73
+#define NPCM7XX_DRAM_SZ (2 * GiB)
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
74
+
102
FloatRoundMode float_rounding_mode;
75
+/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */
103
FloatX80RoundPrec floatx80_rounding_precision;
76
+#define NPCM7XX_LOADER_START (0x00000000) /* Start of SDRAM */
104
Float2NaNPropRule float_2nan_prop_rule;
77
+#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
78
+#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
106
bool tininess_before_rounding;
79
+#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
107
/* should denormalised results go to zero and set the inexact flag? */
80
+
108
bool flush_to_zero;
81
+typedef struct NPCM7xxState {
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
82
+ DeviceState parent;
110
index XXXXXXX..XXXXXXX 100644
83
+
111
--- a/fpu/softfloat-specialize.c.inc
84
+ ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS];
112
+++ b/fpu/softfloat-specialize.c.inc
85
+ A9MPPrivState a9mpcore;
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
86
+
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
87
+ MemoryRegion sram;
115
bool infzero, float_status *status)
88
+ MemoryRegion irom;
116
{
89
+ MemoryRegion ram3;
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
90
+ MemoryRegion *dram;
118
+
91
+
119
/*
92
+ NPCM7xxGCRState gcr;
120
* We guarantee not to require the target to tell us how to
93
+ NPCM7xxCLKState clk;
121
* pick a NaN if we're always returning the default NaN.
94
+ NPCM7xxTimerCtrlState tim[3];
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
95
+} NPCM7xxState;
123
* specify.
96
+
124
*/
97
+#define TYPE_NPCM7XX "npcm7xx"
125
assert(!status->default_nan_mode);
98
+#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
126
+
99
+
127
+ if (rule == float_infzeronan_none) {
100
+#define TYPE_NPCM730 "npcm730"
128
+ /*
101
+#define TYPE_NPCM750 "npcm750"
129
+ * Temporarily fall back to ifdef ladder
102
+
130
+ */
103
+typedef struct NPCM7xxClass {
131
#if defined(TARGET_ARM)
104
+ DeviceClass parent;
132
- /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
105
+
133
- * the default NaN
106
+ /* Bitmask of modules that are permanently disabled on this chip. */
134
- */
107
+ uint32_t disabled_modules;
135
- if (infzero && is_qnan(c_cls)) {
108
+ /* Number of CPU cores enabled in this SoC class (may be 1 or 2). */
136
- return 3;
109
+ uint32_t num_cpus;
137
+ /*
110
+} NPCM7xxClass;
138
+ * For ARM, the (inf,zero,qnan) case returns the default NaN,
111
+
139
+ * but (inf,zero,snan) returns the input NaN.
112
+#define NPCM7XX_CLASS(klass) \
140
+ */
113
+ OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
141
+ rule = float_infzeronan_dnan_if_qnan;
114
+#define NPCM7XX_GET_CLASS(obj) \
142
+#elif defined(TARGET_MIPS)
115
+ OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
143
+ if (snan_bit_is_one(status)) {
116
+
144
+ /*
117
+/**
145
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
118
+ * npcm7xx_load_kernel - Loads memory with everything needed to boot
146
+ * case sets InvalidOp and returns the default NaN
119
+ * @machine - The machine containing the SoC to be booted.
147
+ */
120
+ * @soc - The SoC containing the CPU to be booted.
148
+ rule = float_infzeronan_dnan_always;
121
+ *
149
+ } else {
122
+ * This will set up the ARM boot info structure for the specific NPCM7xx
150
+ /*
123
+ * derivative and call arm_load_kernel() to set up loading of the kernel, etc.
151
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
124
+ * into memory, if requested by the user.
152
+ * case sets InvalidOp and returns the input value 'c'
125
+ */
153
+ */
126
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc);
154
+ rule = float_infzeronan_dnan_never;
127
+
155
+ }
128
+#endif /* NPCM7XX_H */
156
+#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
157
+ defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
130
new file mode 100644
158
+ defined(TARGET_I386) || defined(TARGET_LOONGARCH)
131
index XXXXXXX..XXXXXXX
159
+ /*
132
--- /dev/null
160
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
133
+++ b/hw/arm/npcm7xx.c
161
+ * case sets InvalidOp and returns the input value 'c'
134
@@ -XXX,XX +XXX,XX @@
162
+ */
135
+/*
163
+ /*
136
+ * Nuvoton NPCM7xx SoC family.
164
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
137
+ *
165
+ * to return an input NaN if we have one (ie c) rather than generating
138
+ * Copyright 2020 Google LLC
166
+ * a default NaN
139
+ *
167
+ */
140
+ * This program is free software; you can redistribute it and/or modify it
168
+ rule = float_infzeronan_dnan_never;
141
+ * under the terms of the GNU General Public License as published by the
169
+#elif defined(TARGET_S390X)
142
+ * Free Software Foundation; either version 2 of the License, or
170
+ rule = float_infzeronan_dnan_always;
143
+ * (at your option) any later version.
171
+#endif
144
+ *
172
}
145
+ * This program is distributed in the hope that it will be useful, but WITHOUT
173
146
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
174
+ if (infzero) {
147
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
175
+ /*
148
+ * for more details.
176
+ * Inf * 0 + NaN -- some implementations return the default NaN here,
149
+ */
177
+ * and some return the input NaN.
150
+
178
+ */
151
+#include "qemu/osdep.h"
179
+ switch (rule) {
152
+
180
+ case float_infzeronan_dnan_never:
153
+#include "exec/address-spaces.h"
181
+ return 2;
154
+#include "hw/arm/boot.h"
182
+ case float_infzeronan_dnan_always:
155
+#include "hw/arm/npcm7xx.h"
183
+ return 3;
156
+#include "hw/char/serial.h"
184
+ case float_infzeronan_dnan_if_qnan:
157
+#include "hw/loader.h"
185
+ return is_qnan(c_cls) ? 3 : 2;
158
+#include "hw/misc/unimp.h"
186
+ default:
159
+#include "hw/qdev-properties.h"
187
+ g_assert_not_reached();
160
+#include "qapi/error.h"
161
+#include "qemu/units.h"
162
+#include "sysemu/sysemu.h"
163
+
164
+/*
165
+ * This covers the whole MMIO space. We'll use this to catch any MMIO accesses
166
+ * that aren't handled by any device.
167
+ */
168
+#define NPCM7XX_MMIO_BA (0x80000000)
169
+#define NPCM7XX_MMIO_SZ (0x7ffd0000)
170
+
171
+/* Core system modules. */
172
+#define NPCM7XX_L2C_BA (0xf03fc000)
173
+#define NPCM7XX_CPUP_BA (0xf03fe000)
174
+#define NPCM7XX_GCR_BA (0xf0800000)
175
+#define NPCM7XX_CLK_BA (0xf0801000)
176
+
177
+/* Internal AHB SRAM */
178
+#define NPCM7XX_RAM3_BA (0xc0008000)
179
+#define NPCM7XX_RAM3_SZ (4 * KiB)
180
+
181
+/* Memory blocks at the end of the address space */
182
+#define NPCM7XX_RAM2_BA (0xfffd0000)
183
+#define NPCM7XX_RAM2_SZ (128 * KiB)
184
+#define NPCM7XX_ROM_BA (0xffff0000)
185
+#define NPCM7XX_ROM_SZ (64 * KiB)
186
+
187
+/*
188
+ * Interrupt lines going into the GIC. This does not include internal Cortex-A9
189
+ * interrupts.
190
+ */
191
+enum NPCM7xxInterrupt {
192
+ NPCM7XX_UART0_IRQ = 2,
193
+ NPCM7XX_UART1_IRQ,
194
+ NPCM7XX_UART2_IRQ,
195
+ NPCM7XX_UART3_IRQ,
196
+ NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
197
+ NPCM7XX_TIMER1_IRQ,
198
+ NPCM7XX_TIMER2_IRQ,
199
+ NPCM7XX_TIMER3_IRQ,
200
+ NPCM7XX_TIMER4_IRQ,
201
+ NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */
202
+ NPCM7XX_TIMER6_IRQ,
203
+ NPCM7XX_TIMER7_IRQ,
204
+ NPCM7XX_TIMER8_IRQ,
205
+ NPCM7XX_TIMER9_IRQ,
206
+ NPCM7XX_TIMER10_IRQ, /* Timer Module 2 */
207
+ NPCM7XX_TIMER11_IRQ,
208
+ NPCM7XX_TIMER12_IRQ,
209
+ NPCM7XX_TIMER13_IRQ,
210
+ NPCM7XX_TIMER14_IRQ,
211
+};
212
+
213
+/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
214
+#define NPCM7XX_NUM_IRQ (160)
215
+
216
+/* Register base address for each Timer Module */
217
+static const hwaddr npcm7xx_tim_addr[] = {
218
+ 0xf0008000,
219
+ 0xf0009000,
220
+ 0xf000a000,
221
+};
222
+
223
+/* Register base address for each 16550 UART */
224
+static const hwaddr npcm7xx_uart_addr[] = {
225
+ 0xf0001000,
226
+ 0xf0002000,
227
+ 0xf0003000,
228
+ 0xf0004000,
229
+};
230
+
231
+static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
232
+ const struct arm_boot_info *info)
233
+{
234
+ /*
235
+ * The default smpboot stub halts the secondary CPU with a 'wfi'
236
+ * instruction, but the arch/arm/mach-npcm/platsmp.c in the Linux kernel
237
+ * does not send an IPI to wake it up, so the second CPU fails to boot. So
238
+ * we need to provide our own smpboot stub that can not use 'wfi', it has
239
+ * to spin the secondary CPU until the first CPU writes to the SCRPAD reg.
240
+ */
241
+ uint32_t smpboot[] = {
242
+ 0xe59f2018, /* ldr r2, bootreg_addr */
243
+ 0xe3a00000, /* mov r0, #0 */
244
+ 0xe5820000, /* str r0, [r2] */
245
+ 0xe320f002, /* wfe */
246
+ 0xe5921000, /* ldr r1, [r2] */
247
+ 0xe1110001, /* tst r1, r1 */
248
+ 0x0afffffb, /* beq <wfe> */
249
+ 0xe12fff11, /* bx r1 */
250
+ NPCM7XX_SMP_BOOTREG_ADDR,
251
+ };
252
+ int i;
253
+
254
+ for (i = 0; i < ARRAY_SIZE(smpboot); i++) {
255
+ smpboot[i] = tswap32(smpboot[i]);
256
+ }
257
+
258
+ rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
259
+ NPCM7XX_SMP_LOADER_START);
260
+}
261
+
262
+static struct arm_boot_info npcm7xx_binfo = {
263
+ .loader_start = NPCM7XX_LOADER_START,
264
+ .smp_loader_start = NPCM7XX_SMP_LOADER_START,
265
+ .smp_bootreg_addr = NPCM7XX_SMP_BOOTREG_ADDR,
266
+ .gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
267
+ .write_secondary_boot = npcm7xx_write_secondary_boot,
268
+ .board_id = -1,
269
+};
270
+
271
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
272
+{
273
+ NPCM7xxClass *sc = NPCM7XX_GET_CLASS(soc);
274
+
275
+ npcm7xx_binfo.ram_size = machine->ram_size;
276
+ npcm7xx_binfo.nb_cpus = sc->num_cpus;
277
+
278
+ arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
279
+}
280
+
281
+static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
282
+{
283
+ return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
284
+}
285
+
286
+static void npcm7xx_init(Object *obj)
287
+{
288
+ NPCM7xxState *s = NPCM7XX(obj);
289
+ int i;
290
+
291
+ for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) {
292
+ object_initialize_child(obj, "cpu[*]", &s->cpu[i],
293
+ ARM_CPU_TYPE_NAME("cortex-a9"));
294
+ }
295
+
296
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
297
+ object_initialize_child(obj, "gcr", &s->gcr, TYPE_NPCM7XX_GCR);
298
+ object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
299
+ "power-on-straps");
300
+ object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
301
+
302
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
303
+ object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
304
+ }
305
+}
306
+
307
+static void npcm7xx_realize(DeviceState *dev, Error **errp)
308
+{
309
+ NPCM7xxState *s = NPCM7XX(dev);
310
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
311
+ int i;
312
+
313
+ if (memory_region_size(s->dram) > NPCM7XX_DRAM_SZ) {
314
+ error_setg(errp, "%s: NPCM7xx cannot address more than %" PRIu64
315
+ " MiB of DRAM", __func__, NPCM7XX_DRAM_SZ / MiB);
316
+ return;
317
+ }
318
+
319
+ /* CPUs */
320
+ for (i = 0; i < nc->num_cpus; i++) {
321
+ object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity",
322
+ arm_cpu_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS),
323
+ &error_abort);
324
+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
325
+ NPCM7XX_GIC_CPU_IF_ADDR, &error_abort);
326
+ object_property_set_bool(OBJECT(&s->cpu[i]), "reset-hivecs", true,
327
+ &error_abort);
328
+
329
+ /* Disable security extensions. */
330
+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3", false,
331
+ &error_abort);
332
+
333
+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
334
+ return;
335
+ }
188
+ }
336
+ }
189
+ }
337
+
190
+
338
+ /* A9MPCORE peripherals. Can only fail if we pass bad parameters here. */
191
+#if defined(TARGET_ARM)
339
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-cpu", nc->num_cpus,
192
+
340
+ &error_abort);
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
341
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-irq", NPCM7XX_NUM_IRQ,
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
342
+ &error_abort);
195
*/
343
+ sysbus_realize(SYS_BUS_DEVICE(&s->a9mpcore), &error_abort);
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
344
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, NPCM7XX_CPUP_BA);
197
}
345
+
198
#elif defined(TARGET_MIPS)
346
+ for (i = 0; i < nc->num_cpus; i++) {
199
if (snan_bit_is_one(status)) {
347
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i,
200
- /*
348
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
349
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + nc->num_cpus,
202
- * case sets InvalidOp and returns the default NaN
350
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
203
- */
351
+ }
204
- if (infzero) {
352
+
205
- return 3;
353
+ /* L2 cache controller */
206
- }
354
+ sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL);
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
355
+
208
if (is_snan(a_cls)) {
356
+ /* System Global Control Registers (GCR). Can fail due to user input. */
209
return 0;
357
+ object_property_set_int(OBJECT(&s->gcr), "disabled-modules",
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
358
+ nc->disabled_modules, &error_abort);
211
return 2;
359
+ object_property_add_const_link(OBJECT(&s->gcr), "dram-mr", OBJECT(s->dram));
212
}
360
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) {
213
} else {
361
+ return;
214
- /*
362
+ }
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
363
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM7XX_GCR_BA);
216
- * case sets InvalidOp and returns the input value 'c'
364
+
217
- */
365
+ /* Clock Control Registers (CLK). Cannot fail. */
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
366
+ sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
219
if (is_snan(c_cls)) {
367
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
220
return 2;
368
+
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
369
+ /* Timer Modules (TIM). Cannot fail. */
222
}
370
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
223
}
371
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
224
#elif defined(TARGET_LOONGARCH64)
372
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim[i]);
225
- /*
373
+ int first_irq;
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
374
+ int j;
227
- * case sets InvalidOp and returns the input value 'c'
375
+
228
- */
376
+ sysbus_realize(sbd, &error_abort);
229
-
377
+ sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
378
+
231
if (is_snan(c_cls)) {
379
+ first_irq = NPCM7XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL;
232
return 2;
380
+ for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) {
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
381
+ qemu_irq irq = npcm7xx_irq(s, first_irq + j);
234
return 1;
382
+ sysbus_connect_irq(sbd, j, irq);
235
}
383
+ }
236
#elif defined(TARGET_PPC)
384
+ }
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
385
+
238
- * to return an input NaN if we have one (ie c) rather than generating
386
+ /* UART0..3 (16550 compatible) */
239
- * a default NaN
387
+ for (i = 0; i < ARRAY_SIZE(npcm7xx_uart_addr); i++) {
240
- */
388
+ serial_mm_init(get_system_memory(), npcm7xx_uart_addr[i], 2,
241
-
389
+ npcm7xx_irq(s, NPCM7XX_UART0_IRQ + i), 115200,
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
390
+ serial_hd(i), DEVICE_LITTLE_ENDIAN);
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
391
+ }
244
*/
392
+
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
393
+ /* RAM2 (SRAM) */
246
return 1;
394
+ memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
247
}
395
+ NPCM7XX_RAM2_SZ, &error_abort);
248
#elif defined(TARGET_S390X)
396
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM2_BA, &s->sram);
249
- if (infzero) {
397
+
250
- return 3;
398
+ /* RAM3 (SRAM) */
251
- }
399
+ memory_region_init_ram(&s->ram3, OBJECT(dev), "ram3",
252
-
400
+ NPCM7XX_RAM3_SZ, &error_abort);
253
if (is_snan(a_cls)) {
401
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM3_BA, &s->ram3);
254
return 0;
402
+
255
} else if (is_snan(b_cls)) {
403
+ /* Internal ROM */
404
+ memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM7XX_ROM_SZ,
405
+ &error_abort);
406
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
407
+
408
+ create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
409
+ create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
410
+ create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
411
+ create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
412
+ create_unimplemented_device("npcm7xx.rng", 0xf000b000, 4 * KiB);
413
+ create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
414
+ create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
415
+ create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
416
+ create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
417
+ create_unimplemented_device("npcm7xx.gpio[2]", 0xf0012000, 4 * KiB);
418
+ create_unimplemented_device("npcm7xx.gpio[3]", 0xf0013000, 4 * KiB);
419
+ create_unimplemented_device("npcm7xx.gpio[4]", 0xf0014000, 4 * KiB);
420
+ create_unimplemented_device("npcm7xx.gpio[5]", 0xf0015000, 4 * KiB);
421
+ create_unimplemented_device("npcm7xx.gpio[6]", 0xf0016000, 4 * KiB);
422
+ create_unimplemented_device("npcm7xx.gpio[7]", 0xf0017000, 4 * KiB);
423
+ create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * KiB);
424
+ create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * KiB);
425
+ create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * KiB);
426
+ create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000, 4 * KiB);
427
+ create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000, 4 * KiB);
428
+ create_unimplemented_device("npcm7xx.smbus[5]", 0xf0085000, 4 * KiB);
429
+ create_unimplemented_device("npcm7xx.smbus[6]", 0xf0086000, 4 * KiB);
430
+ create_unimplemented_device("npcm7xx.smbus[7]", 0xf0087000, 4 * KiB);
431
+ create_unimplemented_device("npcm7xx.smbus[8]", 0xf0088000, 4 * KiB);
432
+ create_unimplemented_device("npcm7xx.smbus[9]", 0xf0089000, 4 * KiB);
433
+ create_unimplemented_device("npcm7xx.smbus[10]", 0xf008a000, 4 * KiB);
434
+ create_unimplemented_device("npcm7xx.smbus[11]", 0xf008b000, 4 * KiB);
435
+ create_unimplemented_device("npcm7xx.smbus[12]", 0xf008c000, 4 * KiB);
436
+ create_unimplemented_device("npcm7xx.smbus[13]", 0xf008d000, 4 * KiB);
437
+ create_unimplemented_device("npcm7xx.smbus[14]", 0xf008e000, 4 * KiB);
438
+ create_unimplemented_device("npcm7xx.smbus[15]", 0xf008f000, 4 * KiB);
439
+ create_unimplemented_device("npcm7xx.espi", 0xf009f000, 4 * KiB);
440
+ create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
441
+ create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
442
+ create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
443
+ create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
444
+ create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
445
+ create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
446
+ create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
447
+ create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
448
+ create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB);
449
+ create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB);
450
+ create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB);
451
+ create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB);
452
+ create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB);
453
+ create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
454
+ create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
455
+ create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
456
+ create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
457
+ create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
458
+ create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
459
+ create_unimplemented_device("npcm7xx.ehci", 0xf0806000, 4 * KiB);
460
+ create_unimplemented_device("npcm7xx.ohci", 0xf0807000, 4 * KiB);
461
+ create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
462
+ create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
463
+ create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
464
+ create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
465
+ create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
466
+ create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
467
+ create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
468
+ create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
469
+ create_unimplemented_device("npcm7xx.usbd[3]", 0xf0833000, 4 * KiB);
470
+ create_unimplemented_device("npcm7xx.usbd[4]", 0xf0834000, 4 * KiB);
471
+ create_unimplemented_device("npcm7xx.usbd[5]", 0xf0835000, 4 * KiB);
472
+ create_unimplemented_device("npcm7xx.usbd[6]", 0xf0836000, 4 * KiB);
473
+ create_unimplemented_device("npcm7xx.usbd[7]", 0xf0837000, 4 * KiB);
474
+ create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
475
+ create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
476
+ create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
477
+ create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB);
478
+ create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
479
+ create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
480
+ create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);
481
+ create_unimplemented_device("npcm7xx.sha", 0xf085a000, 4 * KiB);
482
+ create_unimplemented_device("npcm7xx.secacc", 0xf085b000, 4 * KiB);
483
+ create_unimplemented_device("npcm7xx.spixcs0", 0xf8000000, 16 * MiB);
484
+ create_unimplemented_device("npcm7xx.spixcs1", 0xf9000000, 16 * MiB);
485
+ create_unimplemented_device("npcm7xx.spix", 0xfb001000, 4 * KiB);
486
+}
487
+
488
+static Property npcm7xx_properties[] = {
489
+ DEFINE_PROP_LINK("dram-mr", NPCM7xxState, dram, TYPE_MEMORY_REGION,
490
+ MemoryRegion *),
491
+ DEFINE_PROP_END_OF_LIST(),
492
+};
493
+
494
+static void npcm7xx_class_init(ObjectClass *oc, void *data)
495
+{
496
+ DeviceClass *dc = DEVICE_CLASS(oc);
497
+
498
+ dc->realize = npcm7xx_realize;
499
+ dc->user_creatable = false;
500
+ device_class_set_props(dc, npcm7xx_properties);
501
+}
502
+
503
+static void npcm730_class_init(ObjectClass *oc, void *data)
504
+{
505
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
506
+
507
+ /* NPCM730 is optimized for data center use, so no graphics, etc. */
508
+ nc->disabled_modules = 0x00300395;
509
+ nc->num_cpus = 2;
510
+}
511
+
512
+static void npcm750_class_init(ObjectClass *oc, void *data)
513
+{
514
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
515
+
516
+ /* NPCM750 has 2 cores and a full set of peripherals */
517
+ nc->disabled_modules = 0x00000000;
518
+ nc->num_cpus = 2;
519
+}
520
+
521
+static const TypeInfo npcm7xx_soc_types[] = {
522
+ {
523
+ .name = TYPE_NPCM7XX,
524
+ .parent = TYPE_DEVICE,
525
+ .instance_size = sizeof(NPCM7xxState),
526
+ .instance_init = npcm7xx_init,
527
+ .class_size = sizeof(NPCM7xxClass),
528
+ .class_init = npcm7xx_class_init,
529
+ .abstract = true,
530
+ }, {
531
+ .name = TYPE_NPCM730,
532
+ .parent = TYPE_NPCM7XX,
533
+ .class_init = npcm730_class_init,
534
+ }, {
535
+ .name = TYPE_NPCM750,
536
+ .parent = TYPE_NPCM7XX,
537
+ .class_init = npcm750_class_init,
538
+ },
539
+};
540
+
541
+DEFINE_TYPES(npcm7xx_soc_types);
542
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
543
index XXXXXXX..XXXXXXX 100644
544
--- a/hw/arm/Kconfig
545
+++ b/hw/arm/Kconfig
546
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
547
548
config NPCM7XX
549
bool
550
+ select A9MPCORE
551
+ select ARM_GIC
552
+ select PL310 # cache controller
553
+ select SERIAL
554
+ select UNIMP
555
556
config FSL_IMX25
557
bool
558
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
559
index XXXXXXX..XXXXXXX 100644
560
--- a/hw/arm/meson.build
561
+++ b/hw/arm/meson.build
562
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
563
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
564
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
565
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
566
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
567
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
568
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
569
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
570
--
256
--
571
2.20.1
257
2.34.1
572
573
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for the inf-zero-nan
2
muladd special case. In meson.build we put -DTARGET_ARM in fpcflags,
3
and so we should select here the Arm rule of
4
float_infzeronan_dnan_if_qnan.
1
5
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241202131347.498124-5-peter.maydell@linaro.org
9
---
10
tests/fp/fp-bench.c | 5 +++++
11
tests/fp/fp-test.c | 5 +++++
12
2 files changed, 10 insertions(+)
13
14
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/fp/fp-bench.c
17
+++ b/tests/fp/fp-bench.c
18
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
19
{
20
bench_func_t f;
21
22
+ /*
23
+ * These implementation-defined choices for various things IEEE
24
+ * doesn't specify match those used by the Arm architecture.
25
+ */
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
28
29
f = bench_funcs[operation][precision];
30
g_assert(f);
31
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/fp/fp-test.c
34
+++ b/tests/fp/fp-test.c
35
@@ -XXX,XX +XXX,XX @@ void run_test(void)
36
{
37
unsigned int i;
38
39
+ /*
40
+ * These implementation-defined choices for various things IEEE
41
+ * doesn't specify match those used by the Arm architecture.
42
+ */
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
44
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
45
46
genCases_setLevel(test_level);
47
verCases_maxErrorCount = n_max_errors;
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the Arm target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-6-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 3 +++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 4 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
21
+ * and the input NaN if it is signalling
22
*/
23
static void arm_set_default_fp_behaviours(float_status *s)
24
{
25
set_float_detect_tininess(float_tininess_before_rounding, s);
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
28
}
29
30
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
/*
37
* Temporarily fall back to ifdef ladder
38
*/
39
-#if defined(TARGET_ARM)
40
- /*
41
- * For ARM, the (inf,zero,qnan) case returns the default NaN,
42
- * but (inf,zero,snan) returns the input NaN.
43
- */
44
- rule = float_infzeronan_dnan_if_qnan;
45
-#elif defined(TARGET_MIPS)
46
+#if defined(TARGET_MIPS)
47
if (snan_bit_is_one(status)) {
48
/*
49
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
50
--
51
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-7-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
21
+ &env->fpu_status);
22
/* fall through */
23
case RESET_TYPE_S390_CPU_NORMAL:
24
env->psw.mask &= ~PSW_MASK_RI;
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
* a default NaN
31
*/
32
rule = float_infzeronan_dnan_never;
33
-#elif defined(TARGET_S390X)
34
- rule = float_infzeronan_dnan_always;
35
#endif
36
}
37
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the PPC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-8-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 7 +++++++
9
fpu/softfloat-specialize.c.inc | 7 +------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
22
+ * to return an input NaN if we have one (ie c) rather than generating
23
+ * a default NaN
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
27
28
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
29
ppc_spr_t *spr = &env->spr_cb[i];
30
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
32
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
*/
36
rule = float_infzeronan_dnan_never;
37
}
38
-#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
39
+#elif defined(TARGET_SPARC) || \
40
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
41
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
42
/*
43
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
44
* case sets InvalidOp and returns the input value 'c'
45
*/
46
- /*
47
- * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
48
- * to return an input NaN if we have one (ie c) rather than generating
49
- * a default NaN
50
- */
51
rule = float_infzeronan_dnan_never;
52
#endif
53
}
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the MIPS target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-9-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 9 +++++++++
9
target/mips/msa.c | 4 ++++
10
fpu/softfloat-specialize.c.inc | 16 +---------------
11
3 files changed, 14 insertions(+), 15 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_flush_mode(CPUMIPSState *env)
18
static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
{
20
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
21
+ FloatInfZeroNaNRule izn_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
set_snan_bit_is_one(!nan2008, &env->active_fpu.fp_status);
28
set_default_nan_mode(!nan2008, &env->active_fpu.fp_status);
29
+ /*
30
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
31
+ * case sets InvalidOp and returns the default NaN.
32
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
33
+ * case sets InvalidOp and returns the input value 'c'.
34
+ */
35
+ izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
36
+ set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
37
}
38
39
static inline void restore_fp_status(CPUMIPSState *env)
40
diff --git a/target/mips/msa.c b/target/mips/msa.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/mips/msa.c
43
+++ b/target/mips/msa.c
44
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
45
46
/* set proper signanling bit meaning ("1" means "quiet") */
47
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
48
+
49
+ /* Inf * 0 + NaN returns the input NaN */
50
+ set_float_infzeronan_rule(float_infzeronan_dnan_never,
51
+ &env->active_tc.msa_fp_status);
52
}
53
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
54
index XXXXXXX..XXXXXXX 100644
55
--- a/fpu/softfloat-specialize.c.inc
56
+++ b/fpu/softfloat-specialize.c.inc
57
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
58
/*
59
* Temporarily fall back to ifdef ladder
60
*/
61
-#if defined(TARGET_MIPS)
62
- if (snan_bit_is_one(status)) {
63
- /*
64
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
65
- * case sets InvalidOp and returns the default NaN
66
- */
67
- rule = float_infzeronan_dnan_always;
68
- } else {
69
- /*
70
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
71
- * case sets InvalidOp and returns the input value 'c'
72
- */
73
- rule = float_infzeronan_dnan_never;
74
- }
75
-#elif defined(TARGET_SPARC) || \
76
+#if defined(TARGET_SPARC) || \
77
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
78
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
79
/*
80
--
81
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the SPARC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-10-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_SPARC) || \
34
- defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
35
+#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
36
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
37
/*
38
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the xtensa target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-11-peter.maydell@linaro.org
7
---
8
target/xtensa/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 +-
10
2 files changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/xtensa/cpu.c
15
+++ b/target/xtensa/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
17
reset_mmu(env);
18
cs->halted = env->runstall;
19
#endif
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
set_no_signaling_nans(!dfpu, &env->fp_status);
23
xtensa_use_first_nan(env, !dfpu);
24
}
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
34
+#if defined(TARGET_HPPA) || \
35
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
36
/*
37
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the x86 target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-12-peter.maydell@linaro.org
6
---
7
target/i386/tcg/fpu_helper.c | 7 +++++++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 8 insertions(+), 1 deletion(-)
10
11
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/i386/tcg/fpu_helper.c
14
+++ b/target/i386/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
18
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
19
+ /*
20
+ * Only SSE has multiply-add instructions. In the SDM Section 14.5.2
21
+ * "Fused-Multiply-ADD (FMA) Numeric Behavior" the NaN handling is
22
+ * specified -- for 0 * inf + NaN the input NaN is selected, and if
23
+ * there are multiple input NaNs they are selected in the order a, b, c.
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
26
}
27
28
static inline uint8_t save_exception_flags(CPUX86State *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
* Temporarily fall back to ifdef ladder
35
*/
36
#if defined(TARGET_HPPA) || \
37
- defined(TARGET_I386) || defined(TARGET_LOONGARCH)
38
+ defined(TARGET_LOONGARCH)
39
/*
40
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
41
* case sets InvalidOp and returns the input value 'c'
42
--
43
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the loongarch target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-13-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 5 +++++
8
fpu/softfloat-specialize.c.inc | 7 +------
9
2 files changed, 6 insertions(+), 6 deletions(-)
10
11
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/loongarch/tcg/fpu_helper.c
14
+++ b/target/loongarch/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
16
&env->fp_status);
17
set_flush_to_zero(0, &env->fp_status);
18
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
19
+ /*
20
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
21
+ * case sets InvalidOp and returns the input value 'c'
22
+ */
23
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
}
25
26
int ieee_ex_to_loongarch(int xcpt)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
32
/*
33
* Temporarily fall back to ifdef ladder
34
*/
35
-#if defined(TARGET_HPPA) || \
36
- defined(TARGET_LOONGARCH)
37
- /*
38
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
- * case sets InvalidOp and returns the input value 'c'
40
- */
41
+#if defined(TARGET_HPPA)
42
rule = float_infzeronan_dnan_never;
43
#endif
44
}
45
--
46
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
As this is the last target to be converted to explicitly setting
5
the rule, we can remove the fallback code in pickNaNMulAdd()
6
entirely.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
11
---
12
target/hppa/fpu_helper.c | 2 ++
13
fpu/softfloat-specialize.c.inc | 13 +------------
14
2 files changed, 3 insertions(+), 12 deletions(-)
15
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/hppa/fpu_helper.c
19
+++ b/target/hppa/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
21
* HPPA does note implement a CPU reset method at all...
22
*/
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
24
+ /* For inf * 0 + NaN, return the input NaN */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
}
27
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
34
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
bool infzero, float_status *status)
36
{
37
- FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
38
-
39
/*
40
* We guarantee not to require the target to tell us how to
41
* pick a NaN if we're always returning the default NaN.
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
43
*/
44
assert(!status->default_nan_mode);
45
46
- if (rule == float_infzeronan_none) {
47
- /*
48
- * Temporarily fall back to ifdef ladder
49
- */
50
-#if defined(TARGET_HPPA)
51
- rule = float_infzeronan_dnan_never;
52
-#endif
53
- }
54
-
55
if (infzero) {
56
/*
57
* Inf * 0 + NaN -- some implementations return the default NaN here,
58
* and some return the input NaN.
59
*/
60
- switch (rule) {
61
+ switch (status->float_infzeronan_rule) {
62
case float_infzeronan_dnan_never:
63
return 2;
64
case float_infzeronan_dnan_always:
65
--
66
2.34.1
diff view generated by jsdifflib
New patch
1
The new implementation of pickNaNMulAdd() will find it convenient
2
to know whether at least one of the three arguments to the muladd
3
was a signaling NaN. We already calculate that in the caller,
4
so pass it in as a new bool have_snan.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-15-peter.maydell@linaro.org
9
---
10
fpu/softfloat-parts.c.inc | 5 +++--
11
fpu/softfloat-specialize.c.inc | 2 +-
12
2 files changed, 4 insertions(+), 3 deletions(-)
13
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
{
20
int which;
21
bool infzero = (ab_mask == float_cmask_infzero);
22
+ bool have_snan = (abc_mask & float_cmask_snan);
23
24
- if (unlikely(abc_mask & float_cmask_snan)) {
25
+ if (unlikely(have_snan)) {
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
27
}
28
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
if (s->default_nan_mode) {
31
which = 3;
32
} else {
33
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
34
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
35
}
36
37
if (which == 3) {
38
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
39
index XXXXXXX..XXXXXXX 100644
40
--- a/fpu/softfloat-specialize.c.inc
41
+++ b/fpu/softfloat-specialize.c.inc
42
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
43
| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
44
*----------------------------------------------------------------------------*/
45
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
46
- bool infzero, float_status *status)
47
+ bool infzero, bool have_snan, float_status *status)
48
{
49
/*
50
* We guarantee not to require the target to tell us how to
51
--
52
2.34.1
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
2
result if both operands of a 3-operand fused multiply-add operation
3
This adds two new machines, both supported by OpenBMC:
3
are NaNs. As a result different architectures have ended up with
4
4
different rules for propagating NaNs.
5
- npcm750-evb: Nuvoton NPCM750 Evaluation Board.
5
6
- quanta-gsj: A board with a NPCM730 chip.
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
They rely on the NPCM7xx SoC device to do the heavy lifting. They are
8
We want to make the propagation rule instead be selectable at
9
almost completely identical at the moment, apart from the SoC type,
9
runtime, because:
10
which currently only changes the reset contents of one register
10
* this will let us have multiple targets in one QEMU binary
11
(GCR.MDLR), but they might grow apart a bit more as more functionality
11
* the Arm FEAT_AFP architectural feature includes letting
12
is added.
12
the guest select a NaN propagation rule at runtime
13
13
14
Both machines can boot the Linux kernel into /bin/sh.
14
In this commit we add an enum for the propagation rule, the field in
15
15
float_status, and the corresponding getters and setters. We change
16
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
16
pickNaNMulAdd to honour this, but because all targets still leave
17
Reviewed-by: Joel Stanley <joel@jms.id.au>
17
this field at its default 0 value, the fallback logic will pick the
18
Reviewed-by: Cédric Le Goater <clg@kaod.org>
18
rule type with the old ifdef ladder.
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
It's valid not to set a propagation rule if default_nan_mode is
21
Tested-by: Alexander Bulekov <alxndr@bu.edu>
21
enabled, because in that case there's no need to pick a NaN; all the
22
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
22
callers of pickNaNMulAdd() catch this case and skip calling it.
23
Message-id: 20200911052101.2602693-6-hskinnemoen@google.com
23
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
25
---
27
---
26
default-configs/arm-softmmu.mak | 1 +
28
include/fpu/softfloat-helpers.h | 11 +++
27
include/hw/arm/npcm7xx.h | 19 +++++
29
include/fpu/softfloat-types.h | 55 +++++++++++
28
hw/arm/npcm7xx_boards.c | 145 ++++++++++++++++++++++++++++++++
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
29
hw/arm/meson.build | 2 +-
31
3 files changed, 107 insertions(+), 126 deletions(-)
30
4 files changed, 166 insertions(+), 1 deletion(-)
32
31
create mode 100644 hw/arm/npcm7xx_boards.c
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
32
33
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
34
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
35
--- a/default-configs/arm-softmmu.mak
35
--- a/include/fpu/softfloat-helpers.h
36
+++ b/default-configs/arm-softmmu.mak
36
+++ b/include/fpu/softfloat-helpers.h
37
@@ -XXX,XX +XXX,XX @@ CONFIG_GUMSTIX=y
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
38
CONFIG_SPITZ=y
38
status->float_2nan_prop_rule = rule;
39
CONFIG_TOSA=y
39
}
40
CONFIG_Z2=y
40
41
+CONFIG_NPCM7XX=y
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
42
CONFIG_COLLIE=y
42
+ float_status *status)
43
CONFIG_ASPEED_SOC=y
43
+{
44
CONFIG_NETDUINO2=y
44
+ status->float_3nan_prop_rule = rule;
45
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
45
+}
46
+
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
float_status *status)
49
{
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
51
return status->float_2nan_prop_rule;
52
}
53
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
55
+{
56
+ return status->float_3nan_prop_rule;
57
+}
58
+
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
60
{
61
return status->float_infzeronan_rule;
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
46
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
47
--- a/include/hw/arm/npcm7xx.h
64
--- a/include/fpu/softfloat-types.h
48
+++ b/include/hw/arm/npcm7xx.h
65
+++ b/include/fpu/softfloat-types.h
49
@@ -XXX,XX +XXX,XX @@
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
50
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
67
#ifndef SOFTFLOAT_TYPES_H
51
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
68
#define SOFTFLOAT_TYPES_H
52
69
53
+typedef struct NPCM7xxMachine {
70
+#include "hw/registerfields.h"
54
+ MachineState parent;
71
+
55
+} NPCM7xxMachine;
72
/*
56
+
73
* Software IEC/IEEE floating-point types.
57
+#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
74
*/
58
+#define NPCM7XX_MACHINE(obj) \
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
59
+ OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
76
float_2nan_prop_x87,
60
+
77
} Float2NaNPropRule;
61
+typedef struct NPCM7xxMachineClass {
78
62
+ MachineClass parent;
63
+
64
+ const char *soc_type;
65
+} NPCM7xxMachineClass;
66
+
67
+#define NPCM7XX_MACHINE_CLASS(klass) \
68
+ OBJECT_CLASS_CHECK(NPCM7xxMachineClass, (klass), TYPE_NPCM7XX_MACHINE)
69
+#define NPCM7XX_MACHINE_GET_CLASS(obj) \
70
+ OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
71
+
72
typedef struct NPCM7xxState {
73
DeviceState parent;
74
75
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
76
new file mode 100644
77
index XXXXXXX..XXXXXXX
78
--- /dev/null
79
+++ b/hw/arm/npcm7xx_boards.c
80
@@ -XXX,XX +XXX,XX @@
81
+/*
79
+/*
82
+ * Machine definitions for boards featuring an NPCM7xx SoC.
80
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
81
+ * architectures have different rules for which input NaN is
82
+ * propagated to the output when there is more than one NaN on the
83
+ * input.
83
+ *
84
+ *
84
+ * Copyright 2020 Google LLC
85
+ * If default_nan_mode is enabled then it is valid not to set a NaN
86
+ * propagation rule, because the softfloat code guarantees not to try
87
+ * to pick a NaN to propagate in default NaN mode. When not in
88
+ * default-NaN mode, it is an error for the target not to set the rule
89
+ * in float_status if it uses a muladd, and we will assert if we need
90
+ * to handle an input NaN and no rule was selected.
85
+ *
91
+ *
86
+ * This program is free software; you can redistribute it and/or modify it
92
+ * The naming scheme for Float3NaNPropRule values is:
87
+ * under the terms of the GNU General Public License as published by the
93
+ * float_3nan_prop_s_abc:
88
+ * Free Software Foundation; either version 2 of the License, or
94
+ * = "Prefer SNaN over QNaN, then operand A over B over C"
89
+ * (at your option) any later version.
95
+ * float_3nan_prop_abc:
96
+ * = "Prefer A over B over C regardless of SNaN vs QNAN"
90
+ *
97
+ *
91
+ * This program is distributed in the hope that it will be useful, but WITHOUT
98
+ * For QEMU, the multiply-add operation is A * B + C.
92
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
93
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
94
+ * for more details.
95
+ */
99
+ */
96
+
100
+
97
+#include "qemu/osdep.h"
101
+/*
98
+
102
+ * We set the Float3NaNPropRule enum values up so we can select the
99
+#include "exec/address-spaces.h"
103
+ * right value in pickNaNMulAdd in a data driven way.
100
+#include "hw/arm/npcm7xx.h"
104
+ */
101
+#include "hw/core/cpu.h"
105
+FIELD(3NAN, 1ST, 0, 2) /* which operand is most preferred ? */
102
+#include "qapi/error.h"
106
+FIELD(3NAN, 2ND, 2, 2) /* which operand is next most preferred ? */
103
+#include "qemu/units.h"
107
+FIELD(3NAN, 3RD, 4, 2) /* which operand is least preferred ? */
104
+
108
+FIELD(3NAN, SNAN, 6, 1) /* do we prefer SNaN over QNaN ? */
105
+#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
109
+
106
+#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
110
+#define PROPRULE(X, Y, Z) \
107
+
111
+ ((X << R_3NAN_1ST_SHIFT) | (Y << R_3NAN_2ND_SHIFT) | (Z << R_3NAN_3RD_SHIFT))
108
+static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
112
+
109
+{
113
+typedef enum __attribute__((__packed__)) {
110
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
114
+ float_3nan_prop_none = 0, /* No propagation rule specified */
111
+
115
+ float_3nan_prop_abc = PROPRULE(0, 1, 2),
112
+ object_property_set_link(OBJECT(soc), "dram-mr", OBJECT(dram),
116
+ float_3nan_prop_acb = PROPRULE(0, 2, 1),
113
+ &error_abort);
117
+ float_3nan_prop_bac = PROPRULE(1, 0, 2),
114
+}
118
+ float_3nan_prop_bca = PROPRULE(1, 2, 0),
115
+
119
+ float_3nan_prop_cab = PROPRULE(2, 0, 1),
116
+static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
120
+ float_3nan_prop_cba = PROPRULE(2, 1, 0),
117
+ uint32_t hw_straps)
121
+ float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,
118
+{
122
+ float_3nan_prop_s_acb = float_3nan_prop_acb | R_3NAN_SNAN_MASK,
119
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
123
+ float_3nan_prop_s_bac = float_3nan_prop_bac | R_3NAN_SNAN_MASK,
120
+ MachineClass *mc = &nmc->parent;
124
+ float_3nan_prop_s_bca = float_3nan_prop_bca | R_3NAN_SNAN_MASK,
121
+ Object *obj;
125
+ float_3nan_prop_s_cab = float_3nan_prop_cab | R_3NAN_SNAN_MASK,
122
+
126
+ float_3nan_prop_s_cba = float_3nan_prop_cba | R_3NAN_SNAN_MASK,
123
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
127
+} Float3NaNPropRule;
124
+ error_report("This board can only be used with %s",
128
+
125
+ mc->default_cpu_type);
129
+#undef PROPRULE
126
+ exit(1);
130
+
131
/*
132
* Rule for result of fused multiply-add 0 * Inf + NaN.
133
* This must be a NaN, but implementations differ on whether this
134
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
135
FloatRoundMode float_rounding_mode;
136
FloatX80RoundPrec floatx80_rounding_precision;
137
Float2NaNPropRule float_2nan_prop_rule;
138
+ Float3NaNPropRule float_3nan_prop_rule;
139
FloatInfZeroNaNRule float_infzeronan_rule;
140
bool tininess_before_rounding;
141
/* should denormalised results go to zero and set the inexact flag? */
142
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
143
index XXXXXXX..XXXXXXX 100644
144
--- a/fpu/softfloat-specialize.c.inc
145
+++ b/fpu/softfloat-specialize.c.inc
146
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
147
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
148
bool infzero, bool have_snan, float_status *status)
149
{
150
+ FloatClass cls[3] = { a_cls, b_cls, c_cls };
151
+ Float3NaNPropRule rule = status->float_3nan_prop_rule;
152
+ int which;
153
+
154
/*
155
* We guarantee not to require the target to tell us how to
156
* pick a NaN if we're always returning the default NaN.
157
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
158
}
159
}
160
161
+ if (rule == float_3nan_prop_none) {
162
#if defined(TARGET_ARM)
163
-
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
166
- */
167
- if (is_snan(c_cls)) {
168
- return 2;
169
- } else if (is_snan(a_cls)) {
170
- return 0;
171
- } else if (is_snan(b_cls)) {
172
- return 1;
173
- } else if (is_qnan(c_cls)) {
174
- return 2;
175
- } else if (is_qnan(a_cls)) {
176
- return 0;
177
- } else {
178
- return 1;
179
- }
180
+ /*
181
+ * This looks different from the ARM ARM pseudocode, because the ARM ARM
182
+ * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
183
+ */
184
+ rule = float_3nan_prop_s_cab;
185
#elif defined(TARGET_MIPS)
186
- if (snan_bit_is_one(status)) {
187
- /* Prefer sNaN over qNaN, in the a, b, c order. */
188
- if (is_snan(a_cls)) {
189
- return 0;
190
- } else if (is_snan(b_cls)) {
191
- return 1;
192
- } else if (is_snan(c_cls)) {
193
- return 2;
194
- } else if (is_qnan(a_cls)) {
195
- return 0;
196
- } else if (is_qnan(b_cls)) {
197
- return 1;
198
+ if (snan_bit_is_one(status)) {
199
+ rule = float_3nan_prop_s_abc;
200
} else {
201
- return 2;
202
+ rule = float_3nan_prop_s_cab;
203
}
204
- } else {
205
- /* Prefer sNaN over qNaN, in the c, a, b order. */
206
- if (is_snan(c_cls)) {
207
- return 2;
208
- } else if (is_snan(a_cls)) {
209
- return 0;
210
- } else if (is_snan(b_cls)) {
211
- return 1;
212
- } else if (is_qnan(c_cls)) {
213
- return 2;
214
- } else if (is_qnan(a_cls)) {
215
- return 0;
216
- } else {
217
- return 1;
218
- }
219
- }
220
#elif defined(TARGET_LOONGARCH64)
221
- /* Prefer sNaN over qNaN, in the c, a, b order. */
222
- if (is_snan(c_cls)) {
223
- return 2;
224
- } else if (is_snan(a_cls)) {
225
- return 0;
226
- } else if (is_snan(b_cls)) {
227
- return 1;
228
- } else if (is_qnan(c_cls)) {
229
- return 2;
230
- } else if (is_qnan(a_cls)) {
231
- return 0;
232
- } else {
233
- return 1;
234
- }
235
+ rule = float_3nan_prop_s_cab;
236
#elif defined(TARGET_PPC)
237
- /* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
238
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
239
- */
240
- if (is_nan(a_cls)) {
241
- return 0;
242
- } else if (is_nan(c_cls)) {
243
- return 2;
244
- } else {
245
- return 1;
246
- }
247
+ /*
248
+ * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
249
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
250
+ */
251
+ rule = float_3nan_prop_acb;
252
#elif defined(TARGET_S390X)
253
- if (is_snan(a_cls)) {
254
- return 0;
255
- } else if (is_snan(b_cls)) {
256
- return 1;
257
- } else if (is_snan(c_cls)) {
258
- return 2;
259
- } else if (is_qnan(a_cls)) {
260
- return 0;
261
- } else if (is_qnan(b_cls)) {
262
- return 1;
263
- } else {
264
- return 2;
265
- }
266
+ rule = float_3nan_prop_s_abc;
267
#elif defined(TARGET_SPARC)
268
- /* Prefer SNaN over QNaN, order C, B, A. */
269
- if (is_snan(c_cls)) {
270
- return 2;
271
- } else if (is_snan(b_cls)) {
272
- return 1;
273
- } else if (is_snan(a_cls)) {
274
- return 0;
275
- } else if (is_qnan(c_cls)) {
276
- return 2;
277
- } else if (is_qnan(b_cls)) {
278
- return 1;
279
- } else {
280
- return 0;
281
- }
282
+ rule = float_3nan_prop_s_cba;
283
#elif defined(TARGET_XTENSA)
284
- /*
285
- * For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
286
- * an input NaN if we have one (ie c).
287
- */
288
- if (status->use_first_nan) {
289
- if (is_nan(a_cls)) {
290
- return 0;
291
- } else if (is_nan(b_cls)) {
292
- return 1;
293
+ if (status->use_first_nan) {
294
+ rule = float_3nan_prop_abc;
295
} else {
296
- return 2;
297
+ rule = float_3nan_prop_cba;
298
}
299
- } else {
300
- if (is_nan(c_cls)) {
301
- return 2;
302
- } else if (is_nan(b_cls)) {
303
- return 1;
304
- } else {
305
- return 0;
306
- }
307
- }
308
#else
309
- /* A default implementation: prefer a to b to c.
310
- * This is unlikely to actually match any real implementation.
311
- */
312
- if (is_nan(a_cls)) {
313
- return 0;
314
- } else if (is_nan(b_cls)) {
315
- return 1;
316
- } else {
317
- return 2;
318
- }
319
+ rule = float_3nan_prop_abc;
320
#endif
127
+ }
321
+ }
128
+
322
+
129
+ obj = object_new_with_props(nmc->soc_type, OBJECT(machine), "soc",
323
+ assert(rule != float_3nan_prop_none);
130
+ &error_abort, NULL);
324
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
131
+ object_property_set_uint(obj, "power-on-straps", hw_straps, &error_abort);
325
+ /* We have at least one SNaN input and should prefer it */
132
+
326
+ do {
133
+ return NPCM7XX(obj);
327
+ which = rule & R_3NAN_1ST_MASK;
134
+}
328
+ rule >>= R_3NAN_1ST_LENGTH;
135
+
329
+ } while (!is_snan(cls[which]));
136
+static void npcm750_evb_init(MachineState *machine)
330
+ } else {
137
+{
331
+ do {
138
+ NPCM7xxState *soc;
332
+ which = rule & R_3NAN_1ST_MASK;
139
+
333
+ rule >>= R_3NAN_1ST_LENGTH;
140
+ soc = npcm7xx_create_soc(machine, NPCM750_EVB_POWER_ON_STRAPS);
334
+ } while (!is_nan(cls[which]));
141
+ npcm7xx_connect_dram(soc, machine->ram);
335
+ }
142
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
336
+ return which;
143
+
337
}
144
+ npcm7xx_load_kernel(machine, soc);
338
145
+}
339
/*----------------------------------------------------------------------------
146
+
147
+static void quanta_gsj_init(MachineState *machine)
148
+{
149
+ NPCM7xxState *soc;
150
+
151
+ soc = npcm7xx_create_soc(machine, QUANTA_GSJ_POWER_ON_STRAPS);
152
+ npcm7xx_connect_dram(soc, machine->ram);
153
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
154
+
155
+ npcm7xx_load_kernel(machine, soc);
156
+}
157
+
158
+static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type)
159
+{
160
+ NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type));
161
+ MachineClass *mc = MACHINE_CLASS(nmc);
162
+
163
+ nmc->soc_type = type;
164
+ mc->default_cpus = mc->min_cpus = mc->max_cpus = sc->num_cpus;
165
+}
166
+
167
+static void npcm7xx_machine_class_init(ObjectClass *oc, void *data)
168
+{
169
+ MachineClass *mc = MACHINE_CLASS(oc);
170
+
171
+ mc->no_floppy = 1;
172
+ mc->no_cdrom = 1;
173
+ mc->no_parallel = 1;
174
+ mc->default_ram_id = "ram";
175
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
176
+}
177
+
178
+/*
179
+ * Schematics:
180
+ * https://github.com/Nuvoton-Israel/nuvoton-info/blob/master/npcm7xx-poleg/evaluation-board/board_deliverables/NPCM750x_EB_ver.A1.1_COMPLETE.pdf
181
+ */
182
+static void npcm750_evb_machine_class_init(ObjectClass *oc, void *data)
183
+{
184
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
185
+ MachineClass *mc = MACHINE_CLASS(oc);
186
+
187
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM750);
188
+
189
+ mc->desc = "Nuvoton NPCM750 Evaluation Board (Cortex A9)";
190
+ mc->init = npcm750_evb_init;
191
+ mc->default_ram_size = 512 * MiB;
192
+};
193
+
194
+static void gsj_machine_class_init(ObjectClass *oc, void *data)
195
+{
196
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
197
+ MachineClass *mc = MACHINE_CLASS(oc);
198
+
199
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
200
+
201
+ mc->desc = "Quanta GSJ (Cortex A9)";
202
+ mc->init = quanta_gsj_init;
203
+ mc->default_ram_size = 512 * MiB;
204
+};
205
+
206
+static const TypeInfo npcm7xx_machine_types[] = {
207
+ {
208
+ .name = TYPE_NPCM7XX_MACHINE,
209
+ .parent = TYPE_MACHINE,
210
+ .instance_size = sizeof(NPCM7xxMachine),
211
+ .class_size = sizeof(NPCM7xxMachineClass),
212
+ .class_init = npcm7xx_machine_class_init,
213
+ .abstract = true,
214
+ }, {
215
+ .name = MACHINE_TYPE_NAME("npcm750-evb"),
216
+ .parent = TYPE_NPCM7XX_MACHINE,
217
+ .class_init = npcm750_evb_machine_class_init,
218
+ }, {
219
+ .name = MACHINE_TYPE_NAME("quanta-gsj"),
220
+ .parent = TYPE_NPCM7XX_MACHINE,
221
+ .class_init = gsj_machine_class_init,
222
+ },
223
+};
224
+
225
+DEFINE_TYPES(npcm7xx_machine_types)
226
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
227
index XXXXXXX..XXXXXXX 100644
228
--- a/hw/arm/meson.build
229
+++ b/hw/arm/meson.build
230
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
231
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
232
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
233
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
234
-arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
235
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c'))
236
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
237
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
238
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
239
--
340
--
240
2.20.1
341
2.34.1
241
242
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for propagating NaNs in
2
the muladd case. In meson.build we put -DTARGET_ARM in fpcflags, and
3
so we should select here the Arm rule of float_3nan_prop_s_cab.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-17-peter.maydell@linaro.org
8
---
9
tests/fp/fp-bench.c | 1 +
10
tests/fp/fp-test.c | 1 +
11
2 files changed, 2 insertions(+)
12
13
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/fp/fp-bench.c
16
+++ b/tests/fp/fp-bench.c
17
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
18
* doesn't specify match those used by the Arm architecture.
19
*/
20
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
22
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
23
24
f = bench_funcs[operation][precision];
25
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/tests/fp/fp-test.c
28
+++ b/tests/fp/fp-test.c
29
@@ -XXX,XX +XXX,XX @@ void run_test(void)
30
* doesn't specify match those used by the Arm architecture.
31
*/
32
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
33
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
34
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
35
36
genCases_setLevel(test_level);
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-18-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 5 +++++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 6 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
21
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
22
+ * but note that for QEMU muladd is a * b + c, whereas for
23
+ * the pseudocode function the arguments are in the order c, a, b.
24
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
25
* and the input NaN if it is signalling
26
*/
27
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
28
{
29
set_float_detect_tininess(float_tininess_before_rounding, s);
30
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
31
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
32
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
33
}
34
35
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
36
index XXXXXXX..XXXXXXX 100644
37
--- a/fpu/softfloat-specialize.c.inc
38
+++ b/fpu/softfloat-specialize.c.inc
39
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
40
}
41
42
if (rule == float_3nan_prop_none) {
43
-#if defined(TARGET_ARM)
44
- /*
45
- * This looks different from the ARM ARM pseudocode, because the ARM ARM
46
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
47
- */
48
- rule = float_3nan_prop_s_cab;
49
-#elif defined(TARGET_MIPS)
50
+#if defined(TARGET_MIPS)
51
if (snan_bit_is_one(status)) {
52
rule = float_3nan_prop_s_abc;
53
} else {
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for loongarch, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-19-peter.maydell@linaro.org
7
---
8
target/loongarch/tcg/fpu_helper.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/loongarch/tcg/fpu_helper.c
15
+++ b/target/loongarch/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
17
* case sets InvalidOp and returns the input value 'c'
18
*/
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
21
}
22
23
int ieee_ex_to_loongarch(int xcpt)
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_LOONGARCH64)
33
- rule = float_3nan_prop_s_cab;
34
#elif defined(TARGET_PPC)
35
/*
36
* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for PPC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-20-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 8 ++++++++
9
fpu/softfloat-specialize.c.inc | 6 ------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * NaN propagation for fused multiply-add:
22
+ * if fRA is a NaN return it; otherwise if fRB is a NaN return it;
23
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
24
+ * whereas QEMU labels the operands as (a * b) + c.
25
+ */
26
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->fp_status);
27
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->vec_status);
28
/*
29
* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
30
* to return an input NaN if we have one (ie c) rather than generating
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
} else {
37
rule = float_3nan_prop_s_cab;
38
}
39
-#elif defined(TARGET_PPC)
40
- /*
41
- * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
42
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
43
- */
44
- rule = float_3nan_prop_acb;
45
#elif defined(TARGET_S390X)
46
rule = float_3nan_prop_s_abc;
47
#elif defined(TARGET_SPARC)
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for s390x, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-21-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
21
set_float_infzeronan_rule(float_infzeronan_dnan_always,
22
&env->fpu_status);
23
/* fall through */
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_S390X)
33
- rule = float_3nan_prop_s_abc;
34
#elif defined(TARGET_SPARC)
35
rule = float_3nan_prop_s_cba;
36
#elif defined(TARGET_XTENSA)
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for SPARC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-22-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For fused-multiply add, prefer SNaN over QNaN, then C->B->A */
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
22
/* For inf * 0 + NaN, return the input NaN */
23
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
} else {
31
rule = float_3nan_prop_s_cab;
32
}
33
-#elif defined(TARGET_SPARC)
34
- rule = float_3nan_prop_s_cba;
35
#elif defined(TARGET_XTENSA)
36
if (status->use_first_nan) {
37
rule = float_3nan_prop_abc;
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-23-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 4 ++++
9
target/mips/msa.c | 3 +++
10
fpu/softfloat-specialize.c.inc | 8 +-------
11
3 files changed, 8 insertions(+), 7 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
18
{
19
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
20
FloatInfZeroNaNRule izn_rule;
21
+ Float3NaNPropRule nan3_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
28
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
29
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
30
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
31
+
32
}
33
34
static inline void restore_fp_status(CPUMIPSState *env)
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/mips/msa.c
38
+++ b/target/mips/msa.c
39
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
40
set_float_2nan_prop_rule(float_2nan_prop_s_ab,
41
&env->active_tc.msa_fp_status);
42
43
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
44
+ &env->active_tc.msa_fp_status);
45
+
46
/* clear float_status exception flags */
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
48
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
50
index XXXXXXX..XXXXXXX 100644
51
--- a/fpu/softfloat-specialize.c.inc
52
+++ b/fpu/softfloat-specialize.c.inc
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
54
}
55
56
if (rule == float_3nan_prop_none) {
57
-#if defined(TARGET_MIPS)
58
- if (snan_bit_is_one(status)) {
59
- rule = float_3nan_prop_s_abc;
60
- } else {
61
- rule = float_3nan_prop_s_cab;
62
- }
63
-#elif defined(TARGET_XTENSA)
64
+#if defined(TARGET_XTENSA)
65
if (status->use_first_nan) {
66
rule = float_3nan_prop_abc;
67
} else {
68
--
69
2.34.1
diff view generated by jsdifflib
1
The VCMLA and VCADD insns have a size field which is 0 for fp16
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
and 1 for fp32 (note that this is the reverse of the Neon 3-same
2
ifdef from pickNaNMulAdd().
3
encoding!). Convert it to MO_* values in decode for consistency.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200903133209.5141-4-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
8
---
7
---
9
target/arm/neon-shared.decode | 18 ++++++++++++------
8
target/xtensa/fpu_helper.c | 2 ++
10
target/arm/translate-neon.c.inc | 22 ++++++++++++----------
9
fpu/softfloat-specialize.c.inc | 8 --------
11
2 files changed, 24 insertions(+), 16 deletions(-)
10
2 files changed, 2 insertions(+), 8 deletions(-)
12
11
13
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-shared.decode
14
--- a/target/xtensa/fpu_helper.c
16
+++ b/target/arm/neon-shared.decode
15
+++ b/target/xtensa/fpu_helper.c
17
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
18
%vd_dp 22:1 12:4
17
set_use_first_nan(use_first, &env->fp_status);
19
%vd_sp 12:4 22:1
18
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
20
19
&env->fp_status);
21
-VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \
20
+ set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
22
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
21
+ &env->fp_status);
23
+# For VCMLA/VCADD insns, convert the single-bit size field
22
}
24
+# which is 0 for fp16 and 1 for fp32 into a MO_* constant.
23
25
+# (Note that this is the reverse of the sense of the 1-bit size
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
26
+# field in the 3same_fp Neon insns.)
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
27
+%vcadd_size 20:1 !function=plus1
28
29
-VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \
30
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
31
+VCMLA 1111 110 rot:2 . 1 . .... .... 1000 . q:1 . 0 .... \
32
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
33
+
34
+VCADD 1111 110 rot:1 1 . 0 . .... .... 1000 . q:1 . 0 .... \
35
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
36
37
# VUDOT and VSDOT
38
VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \
39
@@ -XXX,XX +XXX,XX @@ VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \
40
vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1
41
42
VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \
43
- vn=%vn_dp vd=%vd_dp size=0
44
+ vn=%vn_dp vd=%vd_dp size=1
45
VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \
46
- vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0
47
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=2 index=0
48
49
VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \
50
vm=%vm_dp vn=%vn_dp vd=%vd_dp
51
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
52
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-neon.c.inc
27
--- a/fpu/softfloat-specialize.c.inc
54
+++ b/target/arm/translate-neon.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
56
gen_helper_gvec_3_ptr *fn_gvec_ptr;
57
58
if (!dc_isar_feature(aa32_vcma, s)
59
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
60
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
61
return false;
62
}
30
}
63
31
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
32
if (rule == float_3nan_prop_none) {
33
-#if defined(TARGET_XTENSA)
34
- if (status->use_first_nan) {
35
- rule = float_3nan_prop_abc;
36
- } else {
37
- rule = float_3nan_prop_cba;
38
- }
39
-#else
40
rule = float_3nan_prop_abc;
41
-#endif
65
}
42
}
66
43
67
opr_sz = (1 + a->q) * 8;
44
assert(rule != float_3nan_prop_none);
68
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
69
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
70
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
71
+ fn_gvec_ptr = (a->size == MO_16) ?
72
+ gen_helper_gvec_fcmlah : gen_helper_gvec_fcmlas;
73
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
74
vfp_reg_offset(1, a->vn),
75
vfp_reg_offset(1, a->vm),
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
77
gen_helper_gvec_3_ptr *fn_gvec_ptr;
78
79
if (!dc_isar_feature(aa32_vcma, s)
80
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
81
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
82
return false;
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
86
}
87
88
opr_sz = (1 + a->q) * 8;
89
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
90
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
91
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
92
+ fn_gvec_ptr = (a->size == MO_16) ?
93
+ gen_helper_gvec_fcaddh : gen_helper_gvec_fcadds;
94
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
95
vfp_reg_offset(1, a->vn),
96
vfp_reg_offset(1, a->vm),
97
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
98
if (!dc_isar_feature(aa32_vcma, s)) {
99
return false;
100
}
101
- if (a->size == 0 && !dc_isar_feature(aa32_fp16_arith, s)) {
102
+ if (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s)) {
103
return false;
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
107
return true;
108
}
109
110
- fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx
111
- : gen_helper_gvec_fcmlah_idx);
112
+ fn_gvec_ptr = (a->size == MO_16) ?
113
+ gen_helper_gvec_fcmlah_idx : gen_helper_gvec_fcmlas_idx;
114
opr_sz = (1 + a->q) * 8;
115
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
116
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
117
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
118
vfp_reg_offset(1, a->vn),
119
vfp_reg_offset(1, a->vm),
120
--
45
--
121
2.20.1
46
2.34.1
122
123
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for i386. We had no
2
i386-specific behaviour in the old ifdef ladder, so we were using the
3
default "prefer a then b then c" fallback; this is actually the
4
correct per-the-spec handling for i386.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-25-peter.maydell@linaro.org
9
---
10
target/i386/tcg/fpu_helper.c | 1 +
11
1 file changed, 1 insertion(+)
12
13
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/i386/tcg/fpu_helper.c
16
+++ b/target/i386/tcg/fpu_helper.c
17
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
18
* there are multiple input NaNs they are selected in the order a, b, c.
19
*/
20
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
21
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
22
}
23
24
static inline uint8_t save_exception_flags(CPUX86State *env)
25
--
26
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
HPPA is the only target that was using the default branch of the
5
ifdef ladder (other targets either do not use muladd or set
6
default_nan_mode), so we can remove the ifdef fallback entirely now
7
(allowing the "rule not set" case to fall into the default of the
8
switch statement and assert).
9
10
We add a TODO note that the HPPA rule is probably wrong; this is
11
not a behavioural change for this refactoring.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
16
---
17
target/hppa/fpu_helper.c | 8 ++++++++
18
fpu/softfloat-specialize.c.inc | 4 ----
19
2 files changed, 8 insertions(+), 4 deletions(-)
20
21
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/hppa/fpu_helper.c
24
+++ b/target/hppa/fpu_helper.c
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
26
* HPPA does note implement a CPU reset method at all...
27
*/
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
29
+ /*
30
+ * TODO: The HPPA architecture reference only documents its NaN
31
+ * propagation rule for 2-operand operations. Testing on real hardware
32
+ * might be necessary to confirm whether this order for muladd is correct.
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
34
+ * from the documented rules for 2-operand operations.
35
+ */
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
37
/* For inf * 0 + NaN, return the input NaN */
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
39
}
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
41
index XXXXXXX..XXXXXXX 100644
42
--- a/fpu/softfloat-specialize.c.inc
43
+++ b/fpu/softfloat-specialize.c.inc
44
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
45
}
46
}
47
48
- if (rule == float_3nan_prop_none) {
49
- rule = float_3nan_prop_abc;
50
- }
51
-
52
assert(rule != float_3nan_prop_none);
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
54
/* We have at least one SNaN input and should prefer it */
55
--
56
2.34.1
diff view generated by jsdifflib
New patch
1
The use_first_nan field in float_status was an xtensa-specific way to
2
select at runtime from two different NaN propagation rules. Now that
3
xtensa is using the target-agnostic NaN propagation rule selection
4
that we've just added, we can remove use_first_nan, because there is
5
no longer any code that reads it.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20241202131347.498124-27-peter.maydell@linaro.org
10
---
11
include/fpu/softfloat-helpers.h | 5 -----
12
include/fpu/softfloat-types.h | 1 -
13
target/xtensa/fpu_helper.c | 1 -
14
3 files changed, 7 deletions(-)
15
16
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/fpu/softfloat-helpers.h
19
+++ b/include/fpu/softfloat-helpers.h
20
@@ -XXX,XX +XXX,XX @@ static inline void set_snan_bit_is_one(bool val, float_status *status)
21
status->snan_bit_is_one = val;
22
}
23
24
-static inline void set_use_first_nan(bool val, float_status *status)
25
-{
26
- status->use_first_nan = val;
27
-}
28
-
29
static inline void set_no_signaling_nans(bool val, float_status *status)
30
{
31
status->no_signaling_nans = val;
32
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/fpu/softfloat-types.h
35
+++ b/include/fpu/softfloat-types.h
36
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
37
* softfloat-specialize.inc.c)
38
*/
39
bool snan_bit_is_one;
40
- bool use_first_nan;
41
bool no_signaling_nans;
42
/* should overflowed results subtract re_bias to its exponent? */
43
bool rebias_overflow;
44
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/xtensa/fpu_helper.c
47
+++ b/target/xtensa/fpu_helper.c
48
@@ -XXX,XX +XXX,XX @@ static const struct {
49
50
void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
51
{
52
- set_use_first_nan(use_first, &env->fp_status);
53
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
54
&env->fp_status);
55
set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
56
--
57
2.34.1
diff view generated by jsdifflib
New patch
1
Currently m68k_cpu_reset_hold() calls floatx80_default_nan(NULL)
2
to get the NaN bit pattern to reset the FPU registers. This
3
works because it happens that our implementation of
4
floatx80_default_nan() doesn't actually look at the float_status
5
pointer except for TARGET_MIPS. However, this isn't guaranteed,
6
and to be able to remove the ifdef in floatx80_default_nan()
7
we're going to need a real float_status here.
1
8
9
Rearrange m68k_cpu_reset_hold() so that we initialize env->fp_status
10
earlier, and thus can pass it to floatx80_default_nan().
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20241202131347.498124-28-peter.maydell@linaro.org
15
---
16
target/m68k/cpu.c | 12 +++++++-----
17
1 file changed, 7 insertions(+), 5 deletions(-)
18
19
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/m68k/cpu.c
22
+++ b/target/m68k/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
24
CPUState *cs = CPU(obj);
25
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(obj);
26
CPUM68KState *env = cpu_env(cs);
27
- floatx80 nan = floatx80_default_nan(NULL);
28
+ floatx80 nan;
29
int i;
30
31
if (mcc->parent_phases.hold) {
32
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
33
#else
34
cpu_m68k_set_sr(env, SR_S | SR_I);
35
#endif
36
- for (i = 0; i < 8; i++) {
37
- env->fregs[i].d = nan;
38
- }
39
- cpu_m68k_set_fpcr(env, 0);
40
/*
41
* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
42
* 3.4 FLOATING-POINT INSTRUCTION DETAILS
43
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
44
* preceding paragraph for nonsignaling NaNs.
45
*/
46
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
47
+
48
+ nan = floatx80_default_nan(&env->fp_status);
49
+ for (i = 0; i < 8; i++) {
50
+ env->fregs[i].d = nan;
51
+ }
52
+ cpu_m68k_set_fpcr(env, 0);
53
env->fpsr = 0;
54
55
/* TODO: We should set PC from the interrupt vector. */
56
--
57
2.34.1
diff view generated by jsdifflib
1
Deprecate our lm32 target support. Michael Walle (former lm32 maintainer)
1
We create our 128-bit default NaN by calling parts64_default_nan()
2
suggested that we do this in 2019:
2
and then adjusting the result. We can do the same trick for creating
3
https://www.mail-archive.com/qemu-devel@nongnu.org/msg605024.html
3
the floatx80 default NaN, which lets us drop a target ifdef.
4
because the only public user of the architecture is the many-years-dead
5
milkymist project. (The Linux port to lm32 was never merged upstream.)
6
4
7
In commit 4b4d96c776f552e (March 2020) we marked it as 'orphan' in
5
floatx80 is used only by:
8
the MAINTAINERS file, but didn't officially deprecate it. Mark it
6
i386
9
deprecated now, with the intention of removing it from QEMU in
7
m68k
10
mid-2021 before the 6.1 release.
8
arm nwfpe old floating-point emulation emulation support
9
(which is essentially dead, especially the parts involving floatx80)
10
PPC (only in the xsrqpxp instruction, which just rounds an input
11
value by converting to floatx80 and back, so will never generate
12
the default NaN)
13
14
The floatx80 default NaN as currently implemented is:
15
m68k: sign = 0, exp = 1...1, int = 1, frac = 1....1
16
i386: sign = 1, exp = 1...1, int = 1, frac = 10...0
17
18
These are the same as the parts64_default_nan for these architectures.
19
20
This is technically a possible behaviour change for arm linux-user
21
nwfpe emulation emulation, because the default NaN will now have the
22
sign bit clear. But we were already generating a different floatx80
23
default NaN from the real kernel emulation we are supposedly
24
following, which appears to use an all-bits-1 value:
25
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L267
26
27
This won't affect the only "real" use of the nwfpe emulation, which
28
is ancient binaries that used it as part of the old floating point
29
calling convention; that only uses loads and stores of 32 and 64 bit
30
floats, not any of the floatx80 behaviour the original hardware had.
31
We also get the nwfpe float64 default NaN value wrong:
32
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L166
33
so if we ever cared about this obscure corner the right fix would be
34
to correct that so nwfpe used its own default-NaN setting rather
35
than the Arm VFP one.
11
36
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
38
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
39
Message-id: 20241202131347.498124-29-peter.maydell@linaro.org
15
Reviewed-by: Thomas Huth <thuth@redhat.com>
16
Acked-by: Michael Walle <michael@walle.cc>
17
Message-id: 20200827113259.25064-1-peter.maydell@linaro.org
18
---
40
---
19
docs/system/deprecated.rst | 8 ++++++++
41
fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
20
1 file changed, 8 insertions(+)
42
1 file changed, 10 insertions(+), 10 deletions(-)
21
43
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
44
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
23
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
24
--- a/docs/system/deprecated.rst
46
--- a/fpu/softfloat-specialize.c.inc
25
+++ b/docs/system/deprecated.rst
47
+++ b/fpu/softfloat-specialize.c.inc
26
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
48
@@ -XXX,XX +XXX,XX @@ static void parts128_silence_nan(FloatParts128 *p, float_status *status)
27
linux-user mode CPUs
49
floatx80 floatx80_default_nan(float_status *status)
28
--------------------
50
{
29
51
floatx80 r;
30
+``lm32`` CPUs (since 5.2.0)
52
+ /*
31
+'''''''''''''''''''''''''''
53
+ * Extrapolate from the choices made by parts64_default_nan to fill
32
+
54
+ * in the floatx80 format. We assume that floatx80's explicit
33
+The ``lm32`` guest CPU support is deprecated and will be removed in
55
+ * integer bit is always set (this is true for i386 and m68k,
34
+a future version of QEMU. The only public user of this architecture
56
+ * which are the only real users of this format).
35
+was the milkymist project, which has been dead for years; there was
57
+ */
36
+never an upstream Linux port.
58
+ FloatParts64 p64;
37
+
59
+ parts64_default_nan(&p64, status);
38
``unicore32`` CPUs (since 5.2.0)
60
39
''''''''''''''''''''''''''''''''
61
- /* None of the targets that have snan_bit_is_one use floatx80. */
62
- assert(!snan_bit_is_one(status));
63
-#if defined(TARGET_M68K)
64
- r.low = UINT64_C(0xFFFFFFFFFFFFFFFF);
65
- r.high = 0x7FFF;
66
-#else
67
- /* X86 */
68
- r.low = UINT64_C(0xC000000000000000);
69
- r.high = 0xFFFF;
70
-#endif
71
+ r.high = 0x7FFF | (p64.sign << 15);
72
+ r.low = (1ULL << DECOMPOSED_BINARY_POINT) | p64.frac;
73
return r;
74
}
40
75
41
--
76
--
42
2.20.1
77
2.34.1
43
44
diff view generated by jsdifflib
New patch
1
In target/loongarch's helper_fclass_s() and helper_fclass_d() we pass
2
a zero-initialized float_status struct to float32_is_quiet_nan() and
3
float64_is_quiet_nan(), with the cryptic comment "for
4
snan_bit_is_one".
1
5
6
This pattern appears to have been copied from target/riscv, where it
7
is used because the functions there do not have ready access to the
8
CPU state struct. The comment presumably refers to the fact that the
9
main reason the is_quiet_nan() functions want the float_state is
10
because they want to know about the snan_bit_is_one config.
11
12
In the loongarch helpers, though, we have the CPU state struct
13
to hand. Use the usual env->fp_status here. This avoids our needing
14
to track that we need to update the initializer of the local
15
float_status structs when the core softfloat code adds new
16
options for targets to configure their behaviour.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20241202131347.498124-30-peter.maydell@linaro.org
21
---
22
target/loongarch/tcg/fpu_helper.c | 6 ++----
23
1 file changed, 2 insertions(+), 4 deletions(-)
24
25
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/loongarch/tcg/fpu_helper.c
28
+++ b/target/loongarch/tcg/fpu_helper.c
29
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
30
} else if (float32_is_zero_or_denormal(f)) {
31
return sign ? 1 << 4 : 1 << 8;
32
} else if (float32_is_any_nan(f)) {
33
- float_status s = { }; /* for snan_bit_is_one */
34
- return float32_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
35
+ return float32_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
36
} else {
37
return sign ? 1 << 3 : 1 << 7;
38
}
39
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
40
} else if (float64_is_zero_or_denormal(f)) {
41
return sign ? 1 << 4 : 1 << 8;
42
} else if (float64_is_any_nan(f)) {
43
- float_status s = { }; /* for snan_bit_is_one */
44
- return float64_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
45
+ return float64_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
46
} else {
47
return sign ? 1 << 3 : 1 << 7;
48
}
49
--
50
2.34.1
diff view generated by jsdifflib
New patch
1
In the frem helper, we have a local float_status because we want to
2
execute the floatx80_div() with a custom rounding mode. Instead of
3
zero-initializing the local float_status and then having to set it up
4
with the m68k standard behaviour (including the NaN propagation rule
5
and copying the rounding precision from env->fp_status), initialize
6
it as a complete copy of env->fp_status. This will avoid our having
7
to add new code in this function for every new config knob we add
8
to fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-31-peter.maydell@linaro.org
13
---
14
target/m68k/fpu_helper.c | 6 ++----
15
1 file changed, 2 insertions(+), 4 deletions(-)
16
17
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/fpu_helper.c
20
+++ b/target/m68k/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
22
23
fp_rem = floatx80_rem(val1->d, val0->d, &env->fp_status);
24
if (!floatx80_is_any_nan(fp_rem)) {
25
- float_status fp_status = { };
26
+ /* Use local temporary fp_status to set different rounding mode */
27
+ float_status fp_status = env->fp_status;
28
uint32_t quotient;
29
int sign;
30
31
/* Calculate quotient directly using round to nearest mode */
32
- set_float_2nan_prop_rule(float_2nan_prop_ab, &fp_status);
33
set_float_rounding_mode(float_round_nearest_even, &fp_status);
34
- set_floatx80_rounding_precision(
35
- get_floatx80_rounding_precision(&env->fp_status), &fp_status);
36
fp_quot.d = floatx80_div(val1->d, val0->d, &fp_status);
37
38
sign = extractFloatx80Sign(fp_quot.d);
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
In cf_fpu_gdb_get_reg() and cf_fpu_gdb_set_reg() we do the conversion
2
from float64 to floatx80 using a scratch float_status, because we
3
don't want the conversion to affect the CPU's floating point exception
4
status. Currently we use a zero-initialized float_status. This will
5
get steadily more awkward as we add config knobs to float_status
6
that the target must initialize. Avoid having to add any of that
7
configuration here by instead initializing our local float_status
8
from the env->fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-32-peter.maydell@linaro.org
13
---
14
target/m68k/helper.c | 6 ++++--
15
1 file changed, 4 insertions(+), 2 deletions(-)
16
17
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/helper.c
20
+++ b/target/m68k/helper.c
21
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n)
22
CPUM68KState *env = &cpu->env;
23
24
if (n < 8) {
25
- float_status s = {};
26
+ /* Use scratch float_status so any exceptions don't change CPU state */
27
+ float_status s = env->fp_status;
28
return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
29
}
30
switch (n) {
31
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
32
CPUM68KState *env = &cpu->env;
33
34
if (n < 8) {
35
- float_status s = {};
36
+ /* Use scratch float_status so any exceptions don't change CPU state */
37
+ float_status s = env->fp_status;
38
env->fregs[n].d = float64_to_floatx80(ldq_be_p(mem_buf), &s);
39
return 8;
40
}
41
--
42
2.34.1
diff view generated by jsdifflib
1
Implement a model of the MPS2 with the AN500 firmware. This is
1
In the helper functions flcmps and flcmpd we use a scratch float_status
2
similar to the AN385, with the following differences:
2
so that we don't change the CPU state if the comparison raises any
3
* Cortex-M7 CPU
3
floating point exception flags. Instead of zero-initializing this
4
* PSRAM is at 0x6000_0000
4
scratch float_status, initialize it as a copy of env->fp_status. This
5
* Ethernet is at 0xa000_0000
5
avoids the need to explicitly initialize settings like the NaN
6
* No zbt_boot_ctrl remapping of the low 16K
6
propagation rule or others we might add to softfloat in future.
7
(but QEMU doesn't implement this anyway)
7
8
* no "block RAM" at 0x01000000
8
To do this we need to pass the CPU env pointer in to the helper.
9
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200903202048.15370-3-peter.maydell@linaro.org
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
13
---
13
---
14
docs/system/arm/mps2.rst | 6 ++--
14
target/sparc/helper.h | 4 ++--
15
hw/arm/mps2.c | 67 +++++++++++++++++++++++++++++++++-------
15
target/sparc/fop_helper.c | 8 ++++----
16
2 files changed, 60 insertions(+), 13 deletions(-)
16
target/sparc/translate.c | 4 ++--
17
3 files changed, 8 insertions(+), 8 deletions(-)
17
18
18
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/mps2.rst
21
--- a/target/sparc/helper.h
21
+++ b/docs/system/arm/mps2.rst
22
+++ b/target/sparc/helper.h
22
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
23
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
24
-================================================================================================
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
25
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
26
+================================================================================================================
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
27
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
28
These board models all use Arm M-profile CPUs.
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
29
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
30
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
31
Cortex-M3 as documented in ARM Application Note AN385
32
32
``mps2-an386``
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
33
Cortex-M4 as documented in ARM Application Note AN386
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
34
+``mps2-an500``
35
+ Cortex-M7 as documented in ARM Application Note AN500
36
``mps2-an511``
37
Cortex-M3 'DesignStart' as documented in AN511
38
``mps2-an505``
39
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
40
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/mps2.c
36
--- a/target/sparc/fop_helper.c
42
+++ b/hw/arm/mps2.c
37
+++ b/target/sparc/fop_helper.c
43
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
44
* We model the following FPGA images:
39
return finish_fcmp(env, r, GETPC());
45
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
40
}
46
* "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
41
47
+ * "mps2-an500" -- Cortex-M7 as documented in ARM Application Note AN500
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
48
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
49
*
44
{
50
* Links to the TRM for the board itself and to the various Application
45
/*
51
@@ -XXX,XX +XXX,XX @@
46
* FLCMP never raises an exception nor modifies any FSR fields.
52
typedef enum MPS2FPGAType {
47
* Perform the comparison with a dummy fp environment.
53
FPGA_AN385,
54
FPGA_AN386,
55
+ FPGA_AN500,
56
FPGA_AN511,
57
} MPS2FPGAType;
58
59
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineClass {
60
MachineClass parent;
61
MPS2FPGAType fpga_type;
62
uint32_t scc_id;
63
+ bool has_block_ram;
64
+ hwaddr ethernet_base;
65
+ hwaddr psram_base;
66
};
67
typedef struct MPS2MachineClass MPS2MachineClass;
68
69
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
70
#define TYPE_MPS2_MACHINE "mps2"
71
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
72
#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
73
+#define TYPE_MPS2_AN500_MACHINE MACHINE_TYPE_NAME("mps2-an500")
74
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
75
76
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
77
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
78
*
79
* AN385/AN386/AN511:
80
* 0x21000000 .. 0x21ffffff : PSRAM (16MB)
81
- * AN385/AN386 only:
82
+ * AN385/AN386/AN500:
83
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
84
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
85
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
86
* 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3
87
+ * AN385/AN386 only:
88
* 0x01000000 .. 0x01003fff : block RAM (16K)
89
* 0x01004000 .. 0x01007fff : mirror of above
90
* 0x01008000 .. 0x0100bfff : mirror of above
91
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
92
* 0x00400000 .. 0x007fffff : ZBT SSRAM1
93
* 0x20000000 .. 0x2001ffff : SRAM
94
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
95
+ * AN500 only:
96
+ * 0x60000000 .. 0x60ffffff : PSRAM (16MB)
97
*
98
* The AN385/AN386 has a feature where the lowest 16K can be mapped
99
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
100
* This is of no use for QEMU so we don't implement it (as if
101
* zbt_boot_ctrl is always zero).
102
*/
48
*/
103
- memory_region_add_subregion(system_memory, 0x21000000, machine->ram);
49
- float_status discard = { };
104
+ memory_region_add_subregion(system_memory, mmc->psram_base, machine->ram);
50
+ float_status discard = env->fp_status;
105
51
FloatRelation r;
106
- switch (mmc->fpga_type) {
52
107
- case FPGA_AN385:
53
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
108
- case FPGA_AN386:
54
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
109
- make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
55
g_assert_not_reached();
110
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
111
- make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
112
- make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
113
- &mms->ssram23, 0x20400000);
114
+ if (mmc->has_block_ram) {
115
make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000);
116
make_ram_alias(&mms->blockram_m1, "mps.blockram_m1",
117
&mms->blockram, 0x01004000);
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
&mms->blockram, 0x01008000);
120
make_ram_alias(&mms->blockram_m3, "mps.blockram_m3",
121
&mms->blockram, 0x0100c000);
122
+ }
123
+
124
+ switch (mmc->fpga_type) {
125
+ case FPGA_AN385:
126
+ case FPGA_AN386:
127
+ case FPGA_AN500:
128
+ make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
129
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
130
+ make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
131
+ make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
132
+ &mms->ssram23, 0x20400000);
133
break;
134
case FPGA_AN511:
135
make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000);
136
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
137
switch (mmc->fpga_type) {
138
case FPGA_AN385:
139
case FPGA_AN386:
140
+ case FPGA_AN500:
141
qdev_prop_set_uint32(armv7m, "num-irq", 32);
142
break;
143
case FPGA_AN511:
144
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
145
switch (mmc->fpga_type) {
146
case FPGA_AN385:
147
case FPGA_AN386:
148
+ case FPGA_AN500:
149
{
150
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
151
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
152
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
153
/* In hardware this is a LAN9220; the LAN9118 is software compatible
154
* except that it doesn't support the checksum-offload feature.
155
*/
156
- lan9118_init(&nd_table[0], 0x40200000,
157
+ lan9118_init(&nd_table[0], mmc->ethernet_base,
158
qdev_get_gpio_in(armv7m,
159
mmc->fpga_type == FPGA_AN511 ? 47 : 13));
160
161
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
162
mmc->fpga_type = FPGA_AN385;
163
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
164
mmc->scc_id = 0x41043850;
165
+ mmc->psram_base = 0x21000000;
166
+ mmc->ethernet_base = 0x40200000;
167
+ mmc->has_block_ram = true;
168
}
56
}
169
57
170
static void mps2_an386_class_init(ObjectClass *oc, void *data)
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
171
@@ -XXX,XX +XXX,XX @@ static void mps2_an386_class_init(ObjectClass *oc, void *data)
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
172
mmc->fpga_type = FPGA_AN386;
60
{
173
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
61
- float_status discard = { };
174
mmc->scc_id = 0x41043860;
62
+ float_status discard = env->fp_status;
175
+ mmc->psram_base = 0x21000000;
63
FloatRelation r;
176
+ mmc->ethernet_base = 0x40200000;
64
177
+ mmc->has_block_ram = true;
65
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
178
+}
66
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
179
+
67
index XXXXXXX..XXXXXXX 100644
180
+static void mps2_an500_class_init(ObjectClass *oc, void *data)
68
--- a/target/sparc/translate.c
181
+{
69
+++ b/target/sparc/translate.c
182
+ MachineClass *mc = MACHINE_CLASS(oc);
70
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
183
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
71
184
+
72
src1 = gen_load_fpr_F(dc, a->rs1);
185
+ mc->desc = "ARM MPS2 with AN500 FPGA image for Cortex-M7";
73
src2 = gen_load_fpr_F(dc, a->rs2);
186
+ mmc->fpga_type = FPGA_AN500;
74
- gen_helper_flcmps(cpu_fcc[a->cc], src1, src2);
187
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m7");
75
+ gen_helper_flcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
188
+ mmc->scc_id = 0x41045000;
76
return advance_pc(dc);
189
+ mmc->psram_base = 0x60000000;
190
+ mmc->ethernet_base = 0xa0000000;
191
+ mmc->has_block_ram = false;
192
}
77
}
193
78
194
static void mps2_an511_class_init(ObjectClass *oc, void *data)
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
195
@@ -XXX,XX +XXX,XX @@ static void mps2_an511_class_init(ObjectClass *oc, void *data)
80
196
mmc->fpga_type = FPGA_AN511;
81
src1 = gen_load_fpr_D(dc, a->rs1);
197
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
82
src2 = gen_load_fpr_D(dc, a->rs2);
198
mmc->scc_id = 0x41045110;
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
199
+ mmc->psram_base = 0x21000000;
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
200
+ mmc->ethernet_base = 0x40200000;
85
return advance_pc(dc);
201
+ mmc->has_block_ram = false;
202
}
86
}
203
87
204
static const TypeInfo mps2_info = {
205
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an386_info = {
206
.class_init = mps2_an386_class_init,
207
};
208
209
+static const TypeInfo mps2_an500_info = {
210
+ .name = TYPE_MPS2_AN500_MACHINE,
211
+ .parent = TYPE_MPS2_MACHINE,
212
+ .class_init = mps2_an500_class_init,
213
+};
214
+
215
static const TypeInfo mps2_an511_info = {
216
.name = TYPE_MPS2_AN511_MACHINE,
217
.parent = TYPE_MPS2_MACHINE,
218
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
219
type_register_static(&mps2_info);
220
type_register_static(&mps2_an385_info);
221
type_register_static(&mps2_an386_info);
222
+ type_register_static(&mps2_an500_info);
223
type_register_static(&mps2_an511_info);
224
}
225
226
--
88
--
227
2.20.1
89
2.34.1
228
229
diff view generated by jsdifflib
New patch
1
In the helper_compute_fprf functions, we pass a dummy float_status
2
in to the is_signaling_nan() function. This is unnecessary, because
3
we have convenient access to the CPU env pointer here and that
4
is already set up with the correct values for the snan_bit_is_one
5
and no_signaling_nans config settings. is_signaling_nan() doesn't
6
ever update the fp_status with any exception flags, so there is
7
no reason not to use env->fp_status here.
1
8
9
Use env->fp_status instead of the dummy fp_status.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20241202131347.498124-34-peter.maydell@linaro.org
14
---
15
target/ppc/fpu_helper.c | 3 +--
16
1 file changed, 1 insertion(+), 2 deletions(-)
17
18
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/ppc/fpu_helper.c
21
+++ b/target/ppc/fpu_helper.c
22
@@ -XXX,XX +XXX,XX @@ void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \
23
} else if (tp##_is_infinity(arg)) { \
24
fprf = neg ? 0x09 << FPSCR_FPRF : 0x05 << FPSCR_FPRF; \
25
} else { \
26
- float_status dummy = { }; /* snan_bit_is_one = 0 */ \
27
- if (tp##_is_signaling_nan(arg, &dummy)) { \
28
+ if (tp##_is_signaling_nan(arg, &env->fp_status)) { \
29
fprf = 0x00 << FPSCR_FPRF; \
30
} else { \
31
fprf = 0x11 << FPSCR_FPRF; \
32
--
33
2.34.1
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This adds two acceptance tests for the quanta-gsj machine.
3
Now that float_status has a bunch of fp parameters,
4
it is easier to copy an existing structure than create
5
one from scratch. Begin by copying the structure that
6
corresponds to the FPSR and make only the adjustments
7
required for BFloat16 semantics.
4
8
5
One test downloads a lightly patched openbmc flash image from github and
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
verifies that it boots all the way to the login prompt.
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
The other test downloads a kernel, initrd and dtb built from the same
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
9
openbmc source and verifies that the kernel detects all CPUs and boots
10
to the point where it can't find the root filesystem (because we have no
11
flash image in this case).
12
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Message-id: 20200911052101.2602693-15-hskinnemoen@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
14
---
19
tests/acceptance/boot_linux_console.py | 83 ++++++++++++++++++++++++++
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
20
1 file changed, 83 insertions(+)
16
1 file changed, 7 insertions(+), 13 deletions(-)
21
17
22
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/tests/acceptance/boot_linux_console.py
20
--- a/target/arm/tcg/vec_helper.c
25
+++ b/tests/acceptance/boot_linux_console.py
21
+++ b/target/arm/tcg/vec_helper.c
26
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(LinuxKernelTest):
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
27
'sda')
23
* no effect on AArch32 instructions.
28
# cubieboard's reboot is not functioning; omit reboot test.
24
*/
29
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
30
+ def test_arm_quanta_gsj(self):
26
- *statusp = (float_status){
31
+ """
27
- .tininess_before_rounding = float_tininess_before_rounding,
32
+ :avocado: tags=arch:arm
28
- .float_rounding_mode = float_round_to_odd_inf,
33
+ :avocado: tags=machine:quanta-gsj
29
- .flush_to_zero = true,
34
+ """
30
- .flush_inputs_to_zero = true,
35
+ # 25 MiB compressed, 32 MiB uncompressed.
31
- .default_nan_mode = true,
36
+ image_url = (
32
- };
37
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
38
+ '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
39
+ image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
40
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
41
+ image_name = 'obmc.mtd'
42
+ image_path = os.path.join(self.workdir, image_name)
43
+ archive.gzip_uncompress(image_path_gz, image_path)
44
+
33
+
45
+ self.vm.set_console()
34
+ *statusp = env->vfp.fp_status;
46
+ drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
35
+ set_default_nan_mode(true, statusp);
47
+ self.vm.add_args('-drive', drive_args)
36
48
+ self.vm.launch()
37
if (ebf) {
49
+
38
- float_status *fpst = &env->vfp.fp_status;
50
+ # Disable drivers and services that stall for a long time during boot,
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
51
+ # to avoid running past the 90-second timeout. These may be removed
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
52
+ # as the corresponding device support is added.
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
53
+ kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
42
-
54
+ 'console=${console} '
43
/* EBF=1 needs to do a step with round-to-odd semantics */
55
+ 'mem=${mem} '
44
*oddstatusp = *statusp;
56
+ 'initcall_blacklist=npcm_i2c_bus_driver_init '
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
57
+ 'systemd.mask=systemd-random-seed.service '
46
+ } else {
58
+ 'systemd.mask=dropbearkey.service '
47
+ set_flush_to_zero(true, statusp);
59
+ )
48
+ set_flush_inputs_to_zero(true, statusp);
60
+
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
61
+ self.wait_for_console_pattern('> BootBlock by Nuvoton')
50
}
62
+ self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
51
-
63
+ self.wait_for_console_pattern('>Skip DDR init.')
52
return ebf;
64
+ self.wait_for_console_pattern('U-Boot ')
53
}
65
+ interrupt_interactive_console_until_pattern(
54
66
+ self, 'Hit any key to stop autoboot:', 'U-Boot>')
67
+ exec_command_and_wait_for_pattern(
68
+ self, "setenv bootargs ${bootargs} " + kernel_command_line,
69
+ 'U-Boot>')
70
+ exec_command_and_wait_for_pattern(
71
+ self, 'run romboot', 'Booting Kernel from flash')
72
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
73
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
74
+ self.wait_for_console_pattern('OpenBMC Project Reference Distro')
75
+ self.wait_for_console_pattern('gsj login:')
76
+
77
+ def test_arm_quanta_gsj_initrd(self):
78
+ """
79
+ :avocado: tags=arch:arm
80
+ :avocado: tags=machine:quanta-gsj
81
+ """
82
+ initrd_url = (
83
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
84
+ '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
85
+ initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
86
+ initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
87
+ kernel_url = (
88
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
89
+ '20200711-gsj-qemu-0/uImage-gsj.bin')
90
+ kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
91
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
92
+ dtb_url = (
93
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
94
+ '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
95
+ dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
96
+ dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
97
+
98
+ self.vm.set_console()
99
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
100
+ 'console=ttyS0,115200n8 '
101
+ 'earlycon=uart8250,mmio32,0xf0001000')
102
+ self.vm.add_args('-kernel', kernel_path,
103
+ '-initrd', initrd_path,
104
+ '-dtb', dtb_path,
105
+ '-append', kernel_command_line)
106
+ self.vm.launch()
107
+
108
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
109
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
110
+ self.wait_for_console_pattern(
111
+ 'Give root password for system maintenance')
112
+
113
def test_arm_orangepi(self):
114
"""
115
:avocado: tags=arch:arm
116
--
55
--
117
2.20.1
56
2.34.1
118
57
119
58
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
Currently we hardcode the default NaN value in parts64_default_nan()
2
using a compile-time ifdef ladder. This is awkward for two cases:
3
* for single-QEMU-binary we can't hard-code target-specifics like this
4
* for Arm FEAT_AFP the default NaN value depends on FPCR.AH
5
(specifically the sign bit is different)
2
6
3
This just implements the bare minimum to cause the boot block to skip
7
Add a field to float_status to specify the default NaN value; fall
4
memory initialization.
8
back to the old ifdef behaviour if these are not set.
5
9
6
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
10
The default NaN value is specified by setting a uint8_t to a
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
11
pattern corresponding to the sign and upper fraction parts of
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
the NaN; the lower bits of the fraction are set from bit 0 of
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
the pattern.
10
Tested-by: Alexander Bulekov <alxndr@bu.edu>
14
11
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
12
Message-id: 20200911052101.2602693-10-hskinnemoen@google.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20241202131347.498124-35-peter.maydell@linaro.org
14
---
18
---
15
include/hw/arm/npcm7xx.h | 2 +
19
include/fpu/softfloat-helpers.h | 11 +++++++
16
include/hw/mem/npcm7xx_mc.h | 36 ++++++++++++++++
20
include/fpu/softfloat-types.h | 10 ++++++
17
hw/arm/npcm7xx.c | 6 +++
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
18
hw/mem/npcm7xx_mc.c | 84 +++++++++++++++++++++++++++++++++++++
22
3 files changed, 54 insertions(+), 22 deletions(-)
19
hw/mem/meson.build | 1 +
20
5 files changed, 129 insertions(+)
21
create mode 100644 include/hw/mem/npcm7xx_mc.h
22
create mode 100644 hw/mem/npcm7xx_mc.c
23
23
24
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
25
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/arm/npcm7xx.h
26
--- a/include/fpu/softfloat-helpers.h
27
+++ b/include/hw/arm/npcm7xx.h
27
+++ b/include/fpu/softfloat-helpers.h
28
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
29
29
status->float_infzeronan_rule = rule;
30
#include "hw/boards.h"
30
}
31
#include "hw/cpu/a9mpcore.h"
31
32
+#include "hw/mem/npcm7xx_mc.h"
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
33
#include "hw/misc/npcm7xx_clk.h"
33
+ float_status *status)
34
#include "hw/misc/npcm7xx_gcr.h"
35
#include "hw/nvram/npcm7xx_otp.h"
36
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
37
NPCM7xxTimerCtrlState tim[3];
38
NPCM7xxOTPState key_storage;
39
NPCM7xxOTPState fuse_array;
40
+ NPCM7xxMCState mc;
41
} NPCM7xxState;
42
43
#define TYPE_NPCM7XX "npcm7xx"
44
diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h
45
new file mode 100644
46
index XXXXXXX..XXXXXXX
47
--- /dev/null
48
+++ b/include/hw/mem/npcm7xx_mc.h
49
@@ -XXX,XX +XXX,XX @@
50
+/*
51
+ * Nuvoton NPCM7xx Memory Controller stub
52
+ *
53
+ * Copyright 2020 Google LLC
54
+ *
55
+ * This program is free software; you can redistribute it and/or modify it
56
+ * under the terms of the GNU General Public License as published by the
57
+ * Free Software Foundation; either version 2 of the License, or
58
+ * (at your option) any later version.
59
+ *
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
63
+ * for more details.
64
+ */
65
+#ifndef NPCM7XX_MC_H
66
+#define NPCM7XX_MC_H
67
+
68
+#include "exec/memory.h"
69
+#include "hw/sysbus.h"
70
+
71
+/**
72
+ * struct NPCM7xxMCState - Device state for the memory controller.
73
+ * @parent: System bus device.
74
+ * @mmio: Memory region through which registers are accessed.
75
+ */
76
+typedef struct NPCM7xxMCState {
77
+ SysBusDevice parent;
78
+
79
+ MemoryRegion mmio;
80
+} NPCM7xxMCState;
81
+
82
+#define TYPE_NPCM7XX_MC "npcm7xx-mc"
83
+#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC)
84
+
85
+#endif /* NPCM7XX_MC_H */
86
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/npcm7xx.c
89
+++ b/hw/arm/npcm7xx.c
90
@@ -XXX,XX +XXX,XX @@
91
#define NPCM7XX_CPUP_BA (0xf03fe000)
92
#define NPCM7XX_GCR_BA (0xf0800000)
93
#define NPCM7XX_CLK_BA (0xf0801000)
94
+#define NPCM7XX_MC_BA (0xf0824000)
95
96
/* Internal AHB SRAM */
97
#define NPCM7XX_RAM3_BA (0xc0008000)
98
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
99
TYPE_NPCM7XX_KEY_STORAGE);
100
object_initialize_child(obj, "otp2", &s->fuse_array,
101
TYPE_NPCM7XX_FUSE_ARRAY);
102
+ object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
103
104
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
105
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
107
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
108
npcm7xx_init_fuses(s);
109
110
+ /* Fake Memory Controller (MC). Cannot fail. */
111
+ sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
112
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
113
+
114
/* Timer Modules (TIM). Cannot fail. */
115
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
116
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
117
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
118
new file mode 100644
119
index XXXXXXX..XXXXXXX
120
--- /dev/null
121
+++ b/hw/mem/npcm7xx_mc.c
122
@@ -XXX,XX +XXX,XX @@
123
+/*
124
+ * Nuvoton NPCM7xx Memory Controller stub
125
+ *
126
+ * Copyright 2020 Google LLC
127
+ *
128
+ * This program is free software; you can redistribute it and/or modify it
129
+ * under the terms of the GNU General Public License as published by the
130
+ * Free Software Foundation; either version 2 of the License, or
131
+ * (at your option) any later version.
132
+ *
133
+ * This program is distributed in the hope that it will be useful, but WITHOUT
134
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
135
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
136
+ * for more details.
137
+ */
138
+
139
+#include "qemu/osdep.h"
140
+
141
+#include "hw/mem/npcm7xx_mc.h"
142
+#include "qapi/error.h"
143
+#include "qemu/log.h"
144
+#include "qemu/module.h"
145
+#include "qemu/units.h"
146
+
147
+#define NPCM7XX_MC_REGS_SIZE (4 * KiB)
148
+
149
+static uint64_t npcm7xx_mc_read(void *opaque, hwaddr addr, unsigned int size)
150
+{
34
+{
151
+ /*
35
+ status->default_nan_pattern = dnan_pattern;
152
+ * If bits 8..11 @ offset 0 are not zero, the boot block thinks the memory
153
+ * controller has already been initialized and will skip DDR training.
154
+ */
155
+ if (addr == 0) {
156
+ return 0x100;
157
+ }
158
+
159
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
160
+
161
+ return 0;
162
+}
36
+}
163
+
37
+
164
+static void npcm7xx_mc_write(void *opaque, hwaddr addr, uint64_t v,
38
static inline void set_flush_to_zero(bool val, float_status *status)
165
+ unsigned int size)
39
{
40
status->flush_to_zero = val;
41
@@ -XXX,XX +XXX,XX @@ static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status
42
return status->float_infzeronan_rule;
43
}
44
45
+static inline uint8_t get_float_default_nan_pattern(float_status *status)
166
+{
46
+{
167
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
47
+ return status->default_nan_pattern;
168
+}
48
+}
169
+
49
+
170
+static const MemoryRegionOps npcm7xx_mc_ops = {
50
static inline bool get_flush_to_zero(float_status *status)
171
+ .read = npcm7xx_mc_read,
51
{
172
+ .write = npcm7xx_mc_write,
52
return status->flush_to_zero;
173
+ .endianness = DEVICE_LITTLE_ENDIAN,
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
174
+ .valid = {
54
index XXXXXXX..XXXXXXX 100644
175
+ .min_access_size = 4,
55
--- a/include/fpu/softfloat-types.h
176
+ .max_access_size = 4,
56
+++ b/include/fpu/softfloat-types.h
177
+ .unaligned = false,
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
178
+ },
58
/* should denormalised inputs go to zero and set the input_denormal flag? */
179
+};
59
bool flush_inputs_to_zero;
60
bool default_nan_mode;
61
+ /*
62
+ * The pattern to use for the default NaN. Here the high bit specifies
63
+ * the default NaN's sign bit, and bits 6..0 specify the high bits of the
64
+ * fractional part. The low bits of the fractional part are copies of bit 0.
65
+ * The exponent of the default NaN is (as for any NaN) always all 1s.
66
+ * Note that a value of 0 here is not a valid NaN. The target must set
67
+ * this to the correct non-zero value, or we will assert when trying to
68
+ * create a default NaN.
69
+ */
70
+ uint8_t default_nan_pattern;
71
/*
72
* The flags below are not used on all specializations and may
73
* constant fold away (see snan_bit_is_one()/no_signalling_nans() in
74
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
75
index XXXXXXX..XXXXXXX 100644
76
--- a/fpu/softfloat-specialize.c.inc
77
+++ b/fpu/softfloat-specialize.c.inc
78
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
79
{
80
bool sign = 0;
81
uint64_t frac;
82
+ uint8_t dnan_pattern = status->default_nan_pattern;
83
84
+ if (dnan_pattern == 0) {
85
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
86
- /* !snan_bit_is_one, set all bits */
87
- frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
88
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
89
+ /* Sign bit clear, all frac bits set */
90
+ dnan_pattern = 0b01111111;
91
+#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
92
|| defined(TARGET_MICROBLAZE)
93
- /* !snan_bit_is_one, set sign and msb */
94
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
95
- sign = 1;
96
+ /* Sign bit set, most significant frac bit set */
97
+ dnan_pattern = 0b11000000;
98
#elif defined(TARGET_HPPA)
99
- /* snan_bit_is_one, set msb-1. */
100
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
101
+ /* Sign bit clear, msb-1 frac bit set */
102
+ dnan_pattern = 0b00100000;
103
#elif defined(TARGET_HEXAGON)
104
- sign = 1;
105
- frac = ~0ULL;
106
+ /* Sign bit set, all frac bits set. */
107
+ dnan_pattern = 0b11111111;
108
#else
109
- /*
110
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
111
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
112
- * do not have floating-point.
113
- */
114
- if (snan_bit_is_one(status)) {
115
- /* set all bits other than msb */
116
- frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
117
- } else {
118
- /* set msb */
119
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
120
- }
121
+ /*
122
+ * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
123
+ * S390, SH4, TriCore, and Xtensa. Our other supported targets
124
+ * do not have floating-point.
125
+ */
126
+ if (snan_bit_is_one(status)) {
127
+ /* sign bit clear, set all frac bits other than msb */
128
+ dnan_pattern = 0b00111111;
129
+ } else {
130
+ /* sign bit clear, set frac msb */
131
+ dnan_pattern = 0b01000000;
132
+ }
133
#endif
134
+ }
135
+ assert(dnan_pattern != 0);
180
+
136
+
181
+static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
137
+ sign = dnan_pattern >> 7;
182
+{
138
+ /*
183
+ NPCM7xxMCState *s = NPCM7XX_MC(dev);
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
184
+
140
+ * and replecate bit [0] down into [55:0]
185
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
141
+ */
186
+ NPCM7XX_MC_REGS_SIZE);
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
187
+ sysbus_init_mmio(&s->parent, &s->mmio);
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
188
+}
144
189
+
145
*p = (FloatParts64) {
190
+static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
146
.cls = float_class_qnan,
191
+{
192
+ DeviceClass *dc = DEVICE_CLASS(klass);
193
+
194
+ dc->desc = "NPCM7xx Memory Controller stub";
195
+ dc->realize = npcm7xx_mc_realize;
196
+}
197
+
198
+static const TypeInfo npcm7xx_mc_types[] = {
199
+ {
200
+ .name = TYPE_NPCM7XX_MC,
201
+ .parent = TYPE_SYS_BUS_DEVICE,
202
+ .instance_size = sizeof(NPCM7xxMCState),
203
+ .class_init = npcm7xx_mc_class_init,
204
+ },
205
+};
206
+DEFINE_TYPES(npcm7xx_mc_types);
207
diff --git a/hw/mem/meson.build b/hw/mem/meson.build
208
index XXXXXXX..XXXXXXX 100644
209
--- a/hw/mem/meson.build
210
+++ b/hw/mem/meson.build
211
@@ -XXX,XX +XXX,XX @@
212
mem_ss = ss.source_set()
213
mem_ss.add(files('memory-device.c'))
214
mem_ss.add(when: 'CONFIG_DIMM', if_true: files('pc-dimm.c'))
215
+mem_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_mc.c'))
216
mem_ss.add(when: 'CONFIG_NVDIMM', if_true: files('nvdimm.c'))
217
218
softmmu_ss.add_all(when: 'CONFIG_MEM_DEVICE', if_true: mem_ss)
219
--
147
--
220
2.20.1
148
2.34.1
221
222
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the tests/fp code.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-36-peter.maydell@linaro.org
6
---
7
tests/fp/fp-bench.c | 1 +
8
tests/fp/fp-test-log2.c | 1 +
9
tests/fp/fp-test.c | 1 +
10
3 files changed, 3 insertions(+)
11
12
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/fp/fp-bench.c
15
+++ b/tests/fp/fp-bench.c
16
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
17
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
18
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
19
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
20
+ set_float_default_nan_pattern(0b01000000, &soft_status);
21
22
f = bench_funcs[operation][precision];
23
g_assert(f);
24
diff --git a/tests/fp/fp-test-log2.c b/tests/fp/fp-test-log2.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/tests/fp/fp-test-log2.c
27
+++ b/tests/fp/fp-test-log2.c
28
@@ -XXX,XX +XXX,XX @@ int main(int ac, char **av)
29
int i;
30
31
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
32
+ set_float_default_nan_pattern(0b01000000, &qsf);
33
set_float_rounding_mode(float_round_nearest_even, &qsf);
34
35
test.d = 0.0;
36
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/fp/fp-test.c
39
+++ b/tests/fp/fp-test.c
40
@@ -XXX,XX +XXX,XX @@ void run_test(void)
41
*/
42
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
43
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
44
+ set_float_default_nan_pattern(0b01000000, &qsf);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
46
47
genCases_setLevel(test_level);
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
parts64_default_nan().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-37-peter.maydell@linaro.org
7
---
8
target/microblaze/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/microblaze/cpu.c
15
+++ b/target/microblaze/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_reset_hold(Object *obj, ResetType type)
17
* this architecture.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
20
+ /* Default NaN: sign bit set, most significant frac bit set */
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
22
23
#if defined(CONFIG_USER_ONLY)
24
/* start in user mode with interrupts enabled. */
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
31
/* Sign bit clear, all frac bits set */
32
dnan_pattern = 0b01111111;
33
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
34
- || defined(TARGET_MICROBLAZE)
35
+#elif defined(TARGET_I386) || defined(TARGET_X86_64)
36
/* Sign bit set, most significant frac bit set */
37
dnan_pattern = 0b11000000;
38
#elif defined(TARGET_HPPA)
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
parts64_default_nan().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-38-peter.maydell@linaro.org
7
---
8
target/i386/tcg/fpu_helper.c | 4 ++++
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 4 insertions(+), 3 deletions(-)
11
12
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/i386/tcg/fpu_helper.c
15
+++ b/target/i386/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
17
*/
18
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
19
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
20
+ /* Default NaN: sign bit set, most significant frac bit set */
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
22
+ set_float_default_nan_pattern(0b11000000, &env->mmx_status);
23
+ set_float_default_nan_pattern(0b11000000, &env->sse_status);
24
}
25
26
static inline uint8_t save_exception_flags(CPUX86State *env)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
32
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
33
/* Sign bit clear, all frac bits set */
34
dnan_pattern = 0b01111111;
35
-#elif defined(TARGET_I386) || defined(TARGET_X86_64)
36
- /* Sign bit set, most significant frac bit set */
37
- dnan_pattern = 0b11000000;
38
#elif defined(TARGET_HPPA)
39
/* Sign bit clear, msb-1 frac bit set */
40
dnan_pattern = 0b00100000;
41
--
42
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
parts64_default_nan().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-39-peter.maydell@linaro.org
7
---
8
target/hppa/fpu_helper.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 2 insertions(+), 3 deletions(-)
11
12
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/hppa/fpu_helper.c
15
+++ b/target/hppa/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
17
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
18
/* For inf * 0 + NaN, return the input NaN */
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ /* Default NaN: sign bit clear, msb-1 frac bit set */
21
+ set_float_default_nan_pattern(0b00100000, &env->fp_status);
22
}
23
24
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
31
/* Sign bit clear, all frac bits set */
32
dnan_pattern = 0b01111111;
33
-#elif defined(TARGET_HPPA)
34
- /* Sign bit clear, msb-1 frac bit set */
35
- dnan_pattern = 0b00100000;
36
#elif defined(TARGET_HEXAGON)
37
/* Sign bit set, all frac bits set. */
38
dnan_pattern = 0b11111111;
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the alpha target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-40-peter.maydell@linaro.org
6
---
7
target/alpha/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/alpha/cpu.c
13
+++ b/target/alpha/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_initfn(Object *obj)
15
* operand in Fa. That is float_2nan_prop_ba.
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
18
+ /* Default NaN: sign bit clear, msb frac bit set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
#if defined(CONFIG_USER_ONLY)
21
env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
22
cpu_alpha_store_fpcr(env, (uint64_t)(FPCR_INVD | FPCR_DZED | FPCR_OVFD
23
--
24
2.34.1
diff view generated by jsdifflib
1
Now that 32-bit KVM host support is gone, KVM can never
1
Set the default NaN pattern explicitly for the arm target.
2
be enabled unless CONFIG_AARCH64 is true, and some code
2
This includes setting it for the old linux-user nwfpe emulation.
3
paths are no longer reachable and can be deleted.
3
For nwfpe, our default doesn't match the real kernel, but we
4
avoid making a behaviour change in this commit.
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
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20241202131347.498124-41-peter.maydell@linaro.org
8
Message-id: 20200904154156.31943-3-peter.maydell@linaro.org
9
---
9
---
10
target/arm/kvm-consts.h | 7 ---
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
11
target/arm/kvm_arm.h | 6 ---
11
target/arm/cpu.c | 2 ++
12
target/arm/cpu.c | 101 +++++++++++++++++++---------------------
12
2 files changed, 7 insertions(+)
13
target/arm/kvm.c | 7 ---
14
4 files changed, 47 insertions(+), 74 deletions(-)
15
13
16
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm-consts.h
16
--- a/linux-user/arm/nwfpe/fpa11.c
19
+++ b/target/arm/kvm-consts.h
17
+++ b/linux-user/arm/nwfpe/fpa11.c
20
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED);
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
21
*/
19
* this late date.
22
#define QEMU_KVM_ARM_TARGET_NONE UINT_MAX
20
*/
23
21
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
24
-#ifdef TARGET_AARCH64
22
+ /*
25
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_AEM_V8, KVM_ARM_TARGET_AEM_V8);
23
+ * Use the same default NaN value as Arm VFP. This doesn't match
26
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8);
24
+ * the Linux kernel's nwfpe emulation, which uses an all-1s value.
27
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57);
25
+ */
28
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_XGENE_POTENZA);
26
+ set_float_default_nan_pattern(0b01000000, &fpa11->fp_status);
29
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_CORTEX_A53);
27
}
30
-#else
28
31
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15);
29
void SetRoundingMode(const unsigned int opcode)
32
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
33
-#endif
34
35
#define CP_REG_ARM64 0x6000000000000000ULL
36
#define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000
37
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
38
/* No kernel define but it's useful to QEMU */
39
#define CP_REG_ARM64_SYSREG_CP (CP_REG_ARM64_SYSREG >> CP_REG_ARM_COPROC_SHIFT)
40
41
-#ifdef TARGET_AARCH64
42
MISMATCH_CHECK(CP_REG_ARM64, KVM_REG_ARM64);
43
MISMATCH_CHECK(CP_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_MASK);
44
MISMATCH_CHECK(CP_REG_ARM_COPROC_SHIFT, KVM_REG_ARM_COPROC_SHIFT);
45
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRM_MASK);
46
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRM_SHIFT);
47
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK);
48
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_ARM64_SYSREG_OP2_SHIFT);
49
-#endif
50
51
#undef MISMATCH_CHECK
52
53
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/kvm_arm.h
56
+++ b/target/arm/kvm_arm.h
57
@@ -XXX,XX +XXX,XX @@ static inline const char *gic_class_name(void)
58
static inline const char *gicv3_class_name(void)
59
{
60
if (kvm_irqchip_in_kernel()) {
61
-#ifdef TARGET_AARCH64
62
return "kvm-arm-gicv3";
63
-#else
64
- error_report("KVM GICv3 acceleration is not supported on this "
65
- "platform");
66
- exit(1);
67
-#endif
68
} else {
69
if (kvm_enabled()) {
70
error_report("Userspace GICv3 is not supported with KVM");
71
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
72
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/cpu.c
32
--- a/target/arm/cpu.c
74
+++ b/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
75
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
35
* the pseudocode function the arguments are in the order c, a, b.
36
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
37
* and the input NaN if it is signalling
38
+ * * Default NaN has sign bit clear, msb frac bit set
39
*/
40
static void arm_set_default_fp_behaviours(float_status *s)
41
{
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
46
+ set_float_default_nan_pattern(0b01000000, s);
76
}
47
}
77
48
78
#ifndef TARGET_AARCH64
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
79
-/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
80
- * otherwise, a CPU with as many features enabled as our emulation supports.
81
+/*
82
+ * -cpu max: a CPU with as many features enabled as our emulation supports.
83
* The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
84
- * this only needs to handle 32 bits.
85
+ * this only needs to handle 32 bits, and need not care about KVM.
86
*/
87
static void arm_max_initfn(Object *obj)
88
{
89
ARMCPU *cpu = ARM_CPU(obj);
90
91
- if (kvm_enabled()) {
92
- kvm_arm_set_cpu_features_from_host(cpu);
93
- } else {
94
- cortex_a15_initfn(obj);
95
+ cortex_a15_initfn(obj);
96
97
- /* old-style VFP short-vector support */
98
- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
99
+ /* old-style VFP short-vector support */
100
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
101
102
#ifdef CONFIG_USER_ONLY
103
- /* We don't set these in system emulation mode for the moment,
104
- * since we don't correctly set (all of) the ID registers to
105
- * advertise them.
106
- */
107
- set_feature(&cpu->env, ARM_FEATURE_V8);
108
- {
109
- uint32_t t;
110
+ /*
111
+ * We don't set these in system emulation mode for the moment,
112
+ * since we don't correctly set (all of) the ID registers to
113
+ * advertise them.
114
+ */
115
+ set_feature(&cpu->env, ARM_FEATURE_V8);
116
+ {
117
+ uint32_t t;
118
119
- t = cpu->isar.id_isar5;
120
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
121
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
122
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
123
- t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
124
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
125
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
126
- cpu->isar.id_isar5 = t;
127
+ t = cpu->isar.id_isar5;
128
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2);
129
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
130
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
131
+ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
132
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
133
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
134
+ cpu->isar.id_isar5 = t;
135
136
- t = cpu->isar.id_isar6;
137
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
138
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
139
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
140
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
141
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
142
- cpu->isar.id_isar6 = t;
143
+ t = cpu->isar.id_isar6;
144
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
145
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1);
146
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
147
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
148
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
149
+ cpu->isar.id_isar6 = t;
150
151
- t = cpu->isar.mvfr1;
152
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
153
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
154
- cpu->isar.mvfr1 = t;
155
+ t = cpu->isar.mvfr1;
156
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
157
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
158
+ cpu->isar.mvfr1 = t;
159
160
- t = cpu->isar.mvfr2;
161
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
162
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
163
- cpu->isar.mvfr2 = t;
164
+ t = cpu->isar.mvfr2;
165
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
166
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
167
+ cpu->isar.mvfr2 = t;
168
169
- t = cpu->isar.id_mmfr3;
170
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
171
- cpu->isar.id_mmfr3 = t;
172
+ t = cpu->isar.id_mmfr3;
173
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
174
+ cpu->isar.id_mmfr3 = t;
175
176
- t = cpu->isar.id_mmfr4;
177
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
178
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
179
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
180
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
181
- cpu->isar.id_mmfr4 = t;
182
- }
183
-#endif
184
+ t = cpu->isar.id_mmfr4;
185
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
186
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
187
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
188
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
189
+ cpu->isar.id_mmfr4 = t;
190
}
191
+#endif
192
}
193
#endif
194
195
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
196
197
static const TypeInfo host_arm_cpu_type_info = {
198
.name = TYPE_ARM_HOST_CPU,
199
-#ifdef TARGET_AARCH64
200
.parent = TYPE_AARCH64_CPU,
201
-#else
202
- .parent = TYPE_ARM_CPU,
203
-#endif
204
.instance_init = arm_host_initfn,
205
};
206
207
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
208
index XXXXXXX..XXXXXXX 100644
209
--- a/target/arm/kvm.c
210
+++ b/target/arm/kvm.c
211
@@ -XXX,XX +XXX,XX @@ int kvm_arch_process_async_events(CPUState *cs)
212
return 0;
213
}
214
215
-/* The #ifdef protections are until 32bit headers are imported and can
216
- * be removed once both 32 and 64 bit reach feature parity.
217
- */
218
void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg)
219
{
220
-#ifdef KVM_GUESTDBG_USE_SW_BP
221
if (kvm_sw_breakpoints_active(cs)) {
222
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
223
}
224
-#endif
225
-#ifdef KVM_GUESTDBG_USE_HW
226
if (kvm_arm_hw_debug_active(cs)) {
227
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW;
228
kvm_arm_copy_hw_debug_data(&dbg->arch);
229
}
230
-#endif
231
}
232
233
void kvm_arch_init_irq_routing(KVMState *s)
234
--
50
--
235
2.20.1
51
2.34.1
236
237
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for loongarch.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-42-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/loongarch/tcg/fpu_helper.c
13
+++ b/target/loongarch/tcg/fpu_helper.c
14
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
15
*/
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
17
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
18
+ /* Default NaN: sign bit clear, msb frac bit set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
}
21
22
int ieee_ex_to_loongarch(int xcpt)
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for m68k.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-43-peter.maydell@linaro.org
6
---
7
target/m68k/cpu.c | 2 ++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 3 insertions(+), 1 deletion(-)
10
11
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/m68k/cpu.c
14
+++ b/target/m68k/cpu.c
15
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
16
* preceding paragraph for nonsignaling NaNs.
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
+ /* Default NaN: sign bit clear, all frac bits set */
20
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
21
22
nan = floatx80_default_nan(&env->fp_status);
23
for (i = 0; i < 8; i++) {
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
29
uint8_t dnan_pattern = status->default_nan_pattern;
30
31
if (dnan_pattern == 0) {
32
-#if defined(TARGET_SPARC) || defined(TARGET_M68K)
33
+#if defined(TARGET_SPARC)
34
/* Sign bit clear, all frac bits set */
35
dnan_pattern = 0b01111111;
36
#elif defined(TARGET_HEXAGON)
37
--
38
2.34.1
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Set the default NaN pattern explicitly for MIPS. Note that this
2
is our only target which currently changes the default NaN
3
at runtime (which it was previously doing indirectly when it
4
changed the snan_bit_is_one setting).
2
5
3
Report unimplemented register accesses using qemu_log_mask(UNIMP).
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-44-peter.maydell@linaro.org
9
---
10
target/mips/fpu_helper.h | 7 +++++++
11
target/mips/msa.c | 3 +++
12
2 files changed, 10 insertions(+)
4
13
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200901144100.116742-5-f4bug@amsat.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/misc/a9scu.c | 6 ++++++
11
1 file changed, 6 insertions(+)
12
13
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/misc/a9scu.c
16
--- a/target/mips/fpu_helper.h
16
+++ b/hw/misc/a9scu.c
17
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
18
#include "hw/qdev-properties.h"
19
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
19
#include "migration/vmstate.h"
20
nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
20
#include "qapi/error.h"
21
set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
21
+#include "qemu/log.h"
22
+ /*
22
#include "qemu/module.h"
23
+ * With nan2008, the default NaN value has the sign bit clear and the
23
24
+ * frac msb set; with the older mode, the sign bit is clear, and all
24
#define A9_SCU_CPU_MAX 4
25
+ * frac bits except the msb are set.
25
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
26
+ */
26
case 0x54: /* SCU Non-secure Access Control Register */
27
+ set_float_default_nan_pattern(nan2008 ? 0b01000000 : 0b00111111,
27
/* unimplemented, fall through */
28
+ &env->active_fpu.fp_status);
28
default:
29
29
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx"\n",
30
+ __func__, offset);
31
return 0;
32
}
33
}
30
}
34
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
31
35
case 0x54: /* SCU Non-secure Access Control Register */
32
diff --git a/target/mips/msa.c b/target/mips/msa.c
36
/* unimplemented, fall through */
33
index XXXXXXX..XXXXXXX 100644
37
default:
34
--- a/target/mips/msa.c
38
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx
35
+++ b/target/mips/msa.c
39
+ " value 0x%"PRIx64"\n",
36
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
40
+ __func__, offset, value);
37
/* Inf * 0 + NaN returns the input NaN */
41
break;
38
set_float_infzeronan_rule(float_infzeronan_dnan_never,
42
}
39
&env->active_tc.msa_fp_status);
40
+ /* Default NaN: sign bit clear, frac msb set */
41
+ set_float_default_nan_pattern(0b01000000,
42
+ &env->active_tc.msa_fp_status);
43
}
43
}
44
--
44
--
45
2.20.1
45
2.34.1
46
47
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for openrisc.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-45-peter.maydell@linaro.org
6
---
7
target/openrisc/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/openrisc/cpu.c
13
+++ b/target/openrisc/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_reset_hold(Object *obj, ResetType type)
15
*/
16
set_float_2nan_prop_rule(float_2nan_prop_x87, &cpu->env.fp_status);
17
18
+ /* Default NaN: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &cpu->env.fp_status);
20
21
#ifndef CONFIG_USER_ONLY
22
cpu->env.picmr = 0x00000000;
23
--
24
2.34.1
diff view generated by jsdifflib
1
Deprecate our Unicore32 target support:
1
Set the default NaN pattern explicitly for ppc.
2
* the Linux kernel dropped support for unicore32 in commit
3
05119217a9bd199c for its 5.9 release (with rationale in the
4
cover letter: https://lkml.org/lkml/2020/8/3/232 )
5
* there is apparently no upstream toolchain that can create unicore32
6
binaries
7
* the maintainer doesn't seem to have made any contributions to
8
QEMU since the port first landed in 2012
9
* nobody else seems to have made changes to the unicore code except
10
for generic cleanups either
11
2
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200825172719.19422-1-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-46-peter.maydell@linaro.org
15
---
6
---
16
docs/system/deprecated.rst | 8 ++++++++
7
target/ppc/cpu_init.c | 4 ++++
17
1 file changed, 8 insertions(+)
8
1 file changed, 4 insertions(+)
18
9
19
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
20
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/deprecated.rst
12
--- a/target/ppc/cpu_init.c
22
+++ b/docs/system/deprecated.rst
13
+++ b/target/ppc/cpu_init.c
23
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
24
linux-user mode CPUs
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
25
--------------------
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
26
17
27
+``unicore32`` CPUs (since 5.2.0)
18
+ /* Default NaN: sign bit clear, set frac msb */
28
+''''''''''''''''''''''''''''''''
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
29
+
21
+
30
+The ``unicore32`` guest CPU support is deprecated and will be removed in
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
31
+a future version of QEMU. Support for this CPU was removed from the
23
ppc_spr_t *spr = &env->spr_cb[i];
32
+upstream Linux kernel, and there is no available upstream toolchain
33
+to build binaries for it.
34
+
35
``tilegx`` CPUs (since 5.1.0)
36
'''''''''''''''''''''''''''''
37
24
38
--
25
--
39
2.20.1
26
2.34.1
40
41
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for sh4. Note that sh4
2
is one of the only three targets (the others being HPPA and
3
sometimes MIPS) that has snan_bit_is_one set.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-47-peter.maydell@linaro.org
8
---
9
target/sh4/cpu.c | 2 ++
10
1 file changed, 2 insertions(+)
11
12
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sh4/cpu.c
15
+++ b/target/sh4/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
17
set_flush_to_zero(1, &env->fp_status);
18
#endif
19
set_default_nan_mode(1, &env->fp_status);
20
+ /* sign bit clear, set all frac bits other than msb */
21
+ set_float_default_nan_pattern(0b00111111, &env->fp_status);
22
}
23
24
static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
25
--
26
2.34.1
diff view generated by jsdifflib
1
In the Neon instructions, some instruction formats have a 2-bit size
1
Set the default NaN pattern explicitly for rx.
2
field which corresponds exactly to QEMU's MO_8/16/32/64. However the
3
floating-point insns in the 3-same group have a 1-bit size field
4
which is "0 for 32-bit float and 1 for 16-bit float". Currently we
5
pass these values directly through to trans_ functions, which means
6
that when reading a particular trans_ function you need to know if
7
that insn uses a 2-bit size or a 1-bit size.
8
9
Move the handling of the 1-bit size to the decodetree file, so that
10
all these insns consistently pass a size to the trans_ function which
11
is an MO_8/16/32/64 value.
12
13
In this commit we switch over the insns using the 3same_fp and
14
3same_fp_q0 formats.
15
2
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20200903133209.5141-2-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-48-peter.maydell@linaro.org
19
---
6
---
20
target/arm/neon-dp.decode | 15 ++++++++++-----
7
target/rx/cpu.c | 2 ++
21
target/arm/translate-neon.c.inc | 16 +++++++++++-----
8
1 file changed, 2 insertions(+)
22
2 files changed, 21 insertions(+), 10 deletions(-)
23
9
24
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
25
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/neon-dp.decode
12
--- a/target/rx/cpu.c
27
+++ b/target/arm/neon-dp.decode
13
+++ b/target/rx/cpu.c
28
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
29
@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
30
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
16
*/
31
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
32
-# For FP insns the high bit of 'size' is used as part of opcode decode
18
+ /* Default NaN value: sign bit clear, set frac msb */
33
-@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
34
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
35
-@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \
36
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
37
+# For FP insns the high bit of 'size' is used as part of opcode decode,
38
+# and the 'size' bit is 0 for 32-bit float and 1 for 16-bit float.
39
+# This converts this encoding to the same MO_8/16/32/64 values that the
40
+# integer neon insns use.
41
+%3same_fp_size 20:1 !function=neon_3same_fp_size
42
+
43
+@3same_fp .... ... . . . . . .... .... .... . q:1 . . .... \
44
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%3same_fp_size
45
+@3same_fp_q0 .... ... . . . . . .... .... .... . 0 . . .... \
46
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 size=%3same_fp_size
47
48
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
49
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
50
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-neon.c.inc
53
+++ b/target/arm/translate-neon.c.inc
54
@@ -XXX,XX +XXX,XX @@ static inline int rsub_8(DisasContext *s, int x)
55
return 8 - x;
56
}
20
}
57
21
58
+static inline int neon_3same_fp_size(DisasContext *s, int x)
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
59
+{
60
+ /* Convert 0==fp32, 1==fp16 into a MO_* value */
61
+ return MO_32 - x;
62
+}
63
+
64
/* Include the generated Neon decoder */
65
#include "decode-neon-dp.c.inc"
66
#include "decode-neon-ls.c.inc"
67
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
68
WRAP_FP_GVEC(gen_##INSN##_fp16_3s, FPST_STD_F16, HFUNC) \
69
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
70
{ \
71
- if (a->size != 0) { \
72
+ if (a->size == MO_16) { \
73
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
74
return false; \
75
} \
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
77
return false;
78
}
79
80
- if (a->size != 0) {
81
+ if (a->size == MO_16) {
82
if (!dc_isar_feature(aa32_fp16_arith, s)) {
83
return false;
84
}
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
86
return false;
87
}
88
89
- if (a->size != 0) {
90
+ if (a->size == MO_16) {
91
if (!dc_isar_feature(aa32_fp16_arith, s)) {
92
return false;
93
}
94
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
95
assert(a->q == 0); /* enforced by decode patterns */
96
97
98
- fpstatus = fpstatus_ptr(a->size != 0 ? FPST_STD_F16 : FPST_STD);
99
+ fpstatus = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
100
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
101
vfp_reg_offset(1, a->vn),
102
vfp_reg_offset(1, a->vm),
103
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
104
#define DO_3S_FP_PAIR(INSN,FUNC) \
105
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
106
{ \
107
- if (a->size != 0) { \
108
+ if (a->size == MO_16) { \
109
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
110
return false; \
111
} \
112
--
23
--
113
2.20.1
24
2.34.1
114
115
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Set the default NaN pattern explicitly for s390x.
2
2
3
This model implementation is designed for 32-bit accesses.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
We can simplify setting the MemoryRegionOps::impl min/max
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
fields to 32-bit (memory::access_with_adjusted_size() will
5
Message-id: 20241202131347.498124-49-peter.maydell@linaro.org
6
take care of the 8/16-bit accesses).
6
---
7
target/s390x/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
7
9
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200901144100.116742-4-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/misc/a9scu.c | 16 +++++-----------
14
1 file changed, 5 insertions(+), 11 deletions(-)
15
16
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/a9scu.c
12
--- a/target/s390x/cpu.c
19
+++ b/hw/misc/a9scu.c
13
+++ b/target/s390x/cpu.c
20
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
14
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
21
return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
15
set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
22
case 0x08: /* CPU Power Status */
16
set_float_infzeronan_rule(float_infzeronan_dnan_always,
23
return s->status;
17
&env->fpu_status);
24
- case 0x09: /* CPU status. */
18
+ /* Default NaN value: sign bit clear, frac msb set */
25
- return s->status >> 8;
19
+ set_float_default_nan_pattern(0b01000000, &env->fpu_status);
26
- case 0x0a: /* CPU status. */
20
/* fall through */
27
- return s->status >> 16;
21
case RESET_TYPE_S390_CPU_NORMAL:
28
- case 0x0b: /* CPU status. */
22
env->psw.mask &= ~PSW_MASK_RI;
29
- return s->status >> 24;
30
case 0x0c: /* Invalidate All Registers In Secure State */
31
return 0;
32
case 0x40: /* Filtering Start Address Register */
33
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
34
uint64_t value, unsigned size)
35
{
36
A9SCUState *s = (A9SCUState *)opaque;
37
- uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
38
- uint32_t shift;
39
40
switch (offset) {
41
case 0x00: /* Control */
42
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
43
case 0x4: /* Configuration: RO */
44
break;
45
case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
46
- shift = (offset - 0x8) * 8;
47
- s->status &= ~(mask << shift);
48
- s->status |= ((value & mask) << shift);
49
+ s->status = value;
50
break;
51
case 0x0c: /* Invalidate All Registers In Secure State */
52
/* no-op as we do not implement caches */
53
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
54
static const MemoryRegionOps a9_scu_ops = {
55
.read = a9_scu_read,
56
.write = a9_scu_write,
57
+ .impl = {
58
+ .min_access_size = 4,
59
+ .max_access_size = 4,
60
+ },
61
.valid = {
62
.min_access_size = 1,
63
.max_access_size = 4,
64
--
23
--
65
2.20.1
24
2.34.1
66
67
diff view generated by jsdifflib
1
Convert the insns using the 2reg_vcvt and 2reg_vcvt_f16 formats
1
Set the default NaN pattern explicitly for SPARC, and remove
2
to pass the size through to the trans function as a MO_* value
2
the ifdef from parts64_default_nan.
3
rather than the '0==f32, 1==f16' used in the fp 3-same encodings.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200903133209.5141-3-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-50-peter.maydell@linaro.org
8
---
7
---
9
target/arm/neon-dp.decode | 3 +--
8
target/sparc/cpu.c | 2 ++
10
target/arm/translate-neon.c.inc | 4 ++--
9
fpu/softfloat-specialize.c.inc | 5 +----
11
2 files changed, 3 insertions(+), 4 deletions(-)
10
2 files changed, 3 insertions(+), 4 deletions(-)
12
11
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
14
--- a/target/sparc/cpu.c
16
+++ b/target/arm/neon-dp.decode
15
+++ b/target/sparc/cpu.c
17
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
18
@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \
17
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
19
&2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
18
/* For inf * 0 + NaN, return the input NaN */
20
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
21
-# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
20
+ /* Default NaN value: sign bit clear, all frac bits set */
22
@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \
21
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
23
- &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
22
24
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5
23
cpu_exec_realizefn(cs, &local_err);
25
@2reg_vcvt_f16 .... ... . . . 11 .... .... .... . q:1 . . .... \
24
if (local_err != NULL) {
26
&2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
27
28
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
29
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-neon.c.inc
27
--- a/fpu/softfloat-specialize.c.inc
31
+++ b/target/arm/translate-neon.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
32
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
33
return false;
30
uint8_t dnan_pattern = status->default_nan_pattern;
34
}
31
35
32
if (dnan_pattern == 0) {
36
- if (a->size != 0) {
33
-#if defined(TARGET_SPARC)
37
+ if (a->size == MO_16) {
34
- /* Sign bit clear, all frac bits set */
38
if (!dc_isar_feature(aa32_fp16_arith, s)) {
35
- dnan_pattern = 0b01111111;
39
return false;
36
-#elif defined(TARGET_HEXAGON)
40
}
37
+#if defined(TARGET_HEXAGON)
41
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
38
/* Sign bit set, all frac bits set. */
42
return true;
39
dnan_pattern = 0b11111111;
43
}
40
#else
44
45
- fpst = fpstatus_ptr(a->size ? FPST_STD_F16 : FPST_STD);
46
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
47
tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn);
48
tcg_temp_free_ptr(fpst);
49
return true;
50
--
41
--
51
2.20.1
42
2.34.1
52
53
diff view generated by jsdifflib
1
Make the list of MPS2 boards consistent in the phrasing of each
1
Set the default NaN pattern explicitly for xtensa.
2
entry, use the correct casing of "Arm", and move the mps2-an511
3
entry so the list is in numeric order.
4
2
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200903202048.15370-4-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-51-peter.maydell@linaro.org
8
---
6
---
9
docs/system/arm/mps2.rst | 14 +++++++-------
7
target/xtensa/cpu.c | 2 ++
10
1 file changed, 7 insertions(+), 7 deletions(-)
8
1 file changed, 2 insertions(+)
11
9
12
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
13
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/system/arm/mps2.rst
12
--- a/target/xtensa/cpu.c
15
+++ b/docs/system/arm/mps2.rst
13
+++ b/target/xtensa/cpu.c
16
@@ -XXX,XX +XXX,XX @@ as seen by the guest depend significantly on the FPGA image.
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
17
QEMU models the following FPGA images:
15
/* For inf * 0 + NaN, return the input NaN */
18
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
19
``mps2-an385``
17
set_no_signaling_nans(!dfpu, &env->fp_status);
20
- Cortex-M3 as documented in ARM Application Note AN385
18
+ /* Default NaN value: sign bit clear, set frac msb */
21
+ Cortex-M3 as documented in Arm Application Note AN385
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
22
``mps2-an386``
20
xtensa_use_first_nan(env, !dfpu);
23
- Cortex-M4 as documented in ARM Application Note AN386
21
}
24
+ Cortex-M4 as documented in Arm Application Note AN386
25
``mps2-an500``
26
- Cortex-M7 as documented in ARM Application Note AN500
27
-``mps2-an511``
28
- Cortex-M3 'DesignStart' as documented in AN511
29
+ Cortex-M7 as documented in Arm Application Note AN500
30
``mps2-an505``
31
- Cortex-M33 as documented in ARM Application Note AN505
32
+ Cortex-M33 as documented in Arm Application Note AN505
33
+``mps2-an511``
34
+ Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
35
``mps2-an521``
36
- Dual Cortex-M33 as documented in Application Note AN521
37
+ Dual Cortex-M33 as documented in Arm Application Note AN521
38
39
Differences between QEMU and real hardware:
40
22
41
--
23
--
42
2.20.1
24
2.34.1
43
44
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
Set the default NaN pattern explicitly for hexagon.
2
Remove the ifdef from parts64_default_nan(); the only
3
remaining unconverted targets all use the default case.
2
4
3
If a -bios option is specified on the command line, load the image into
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the internal ROM memory region, which contains the first instructions
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
run by the CPU after reset.
7
Message-id: 20241202131347.498124-52-peter.maydell@linaro.org
8
---
9
target/hexagon/cpu.c | 2 ++
10
fpu/softfloat-specialize.c.inc | 5 -----
11
2 files changed, 2 insertions(+), 5 deletions(-)
6
12
7
If -bios is not specified, the vbootrom included with qemu is loaded by
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
8
default.
9
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
15
Message-id: 20200911052101.2602693-8-hskinnemoen@google.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/arm/npcm7xx_boards.c | 32 ++++++++++++++++++++++++++++++++
19
1 file changed, 32 insertions(+)
20
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/npcm7xx_boards.c
15
--- a/target/hexagon/cpu.c
24
+++ b/hw/arm/npcm7xx_boards.c
16
+++ b/target/hexagon/cpu.c
25
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
26
#include "exec/address-spaces.h"
18
27
#include "hw/arm/npcm7xx.h"
19
set_default_nan_mode(1, &env->fp_status);
28
#include "hw/core/cpu.h"
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
29
+#include "hw/loader.h"
21
+ /* Default NaN value: sign bit set, all frac bits set */
30
#include "qapi/error.h"
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
31
+#include "qemu-common.h"
32
#include "qemu/units.h"
33
+#include "sysemu/sysemu.h"
34
35
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
36
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
37
38
+static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
39
+
40
+static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
41
+{
42
+ g_autofree char *filename = NULL;
43
+ int ret;
44
+
45
+ if (!bios_name) {
46
+ bios_name = npcm7xx_default_bootrom;
47
+ }
48
+
49
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
50
+ if (!filename) {
51
+ error_report("Could not find ROM image '%s'", bios_name);
52
+ if (!machine->kernel_filename) {
53
+ /* We can't boot without a bootrom or a kernel image. */
54
+ exit(1);
55
+ }
56
+ return;
57
+ }
58
+ ret = load_image_mr(filename, &soc->irom);
59
+ if (ret < 0) {
60
+ error_report("Failed to load ROM image '%s'", filename);
61
+ exit(1);
62
+ }
63
+}
64
+
65
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
66
{
67
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
68
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
69
npcm7xx_connect_dram(soc, machine->ram);
70
qdev_realize(DEVICE(soc), NULL, &error_fatal);
71
72
+ npcm7xx_load_bootrom(machine, soc);
73
npcm7xx_load_kernel(machine, soc);
74
}
23
}
75
24
76
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
25
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
77
npcm7xx_connect_dram(soc, machine->ram);
26
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
78
qdev_realize(DEVICE(soc), NULL, &error_fatal);
27
index XXXXXXX..XXXXXXX 100644
79
28
--- a/fpu/softfloat-specialize.c.inc
80
+ npcm7xx_load_bootrom(machine, soc);
29
+++ b/fpu/softfloat-specialize.c.inc
81
npcm7xx_load_kernel(machine, soc);
30
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
82
}
31
uint8_t dnan_pattern = status->default_nan_pattern;
32
33
if (dnan_pattern == 0) {
34
-#if defined(TARGET_HEXAGON)
35
- /* Sign bit set, all frac bits set. */
36
- dnan_pattern = 0b11111111;
37
-#else
38
/*
39
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
40
* S390, SH4, TriCore, and Xtensa. Our other supported targets
41
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
42
/* sign bit clear, set frac msb */
43
dnan_pattern = 0b01000000;
44
}
45
-#endif
46
}
47
assert(dnan_pattern != 0);
83
48
84
--
49
--
85
2.20.1
50
2.34.1
86
87
diff view generated by jsdifflib
1
It is the responsibility of board code for an armv7m system to set
1
Set the default NaN pattern explicitly for riscv.
2
system_clock_scale appropriately for the CPU speed of the core.
3
If it forgets to do this, then QEMU will hang if the guest tries
4
to use the systick timer in the "tick at the CPU clock frequency" mode.
5
6
We forgot that in a couple of our boards (see commits ce4f70e81ed23c93f,
7
e7e5a9595ab1136). Add an assertion in the systick reset method so
8
we don't let any new boards in with the same bug.
9
2
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200825160847.18091-1-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-53-peter.maydell@linaro.org
13
---
6
---
14
hw/timer/armv7m_systick.c | 8 ++++++++
7
target/riscv/cpu.c | 2 ++
15
1 file changed, 8 insertions(+)
8
1 file changed, 2 insertions(+)
16
9
17
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
18
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/timer/armv7m_systick.c
12
--- a/target/riscv/cpu.c
20
+++ b/hw/timer/armv7m_systick.c
13
+++ b/target/riscv/cpu.c
21
@@ -XXX,XX +XXX,XX @@ static void systick_reset(DeviceState *dev)
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
22
{
15
cs->exception_index = RISCV_EXCP_NONE;
23
SysTickState *s = SYSTICK(dev);
16
env->load_res = -1;
24
17
set_default_nan_mode(1, &env->fp_status);
25
+ /*
18
+ /* Default NaN value: sign bit clear, frac msb set */
26
+ * Forgetting to set system_clock_scale is always a board code
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
27
+ * bug. We can't check this earlier because for some boards
20
env->vill = true;
28
+ * (like stellaris) it is not yet configured at the point where
21
29
+ * the systick device is realized.
22
#ifndef CONFIG_USER_ONLY
30
+ */
31
+ assert(system_clock_scale != 0);
32
+
33
s->control = 0;
34
s->reload = 0;
35
s->tick = 0;
36
--
23
--
37
2.20.1
24
2.34.1
38
39
diff view generated by jsdifflib
1
Implement a model of the MPS2 with the AN386 firmware. This is
1
Set the default NaN pattern explicitly for tricore.
2
essentially identical to the AN385 firmware, but it has a
3
Cortex-M4 rather than a Cortex-M3.
4
2
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 20241202131347.498124-54-peter.maydell@linaro.org
8
Message-id: 20200903202048.15370-2-peter.maydell@linaro.org
9
---
6
---
10
docs/system/arm/mps2.rst | 8 +++++---
7
target/tricore/helper.c | 2 ++
11
hw/arm/mps2.c | 34 +++++++++++++++++++++++++++++-----
8
1 file changed, 2 insertions(+)
12
2 files changed, 34 insertions(+), 8 deletions(-)
13
9
14
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
15
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/mps2.rst
12
--- a/target/tricore/helper.c
17
+++ b/docs/system/arm/mps2.rst
13
+++ b/target/tricore/helper.c
18
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
19
-Arm MPS2 boards (``mps2-an385``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
15
set_flush_to_zero(1, &env->fp_status);
20
-================================================================================
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
21
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
17
set_default_nan_mode(1, &env->fp_status);
22
+================================================================================================
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
23
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
24
These board models all use Arm M-profile CPUs.
25
26
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
27
28
``mps2-an385``
29
Cortex-M3 as documented in ARM Application Note AN385
30
+``mps2-an386``
31
+ Cortex-M4 as documented in ARM Application Note AN386
32
``mps2-an511``
33
Cortex-M3 'DesignStart' as documented in AN511
34
``mps2-an505``
35
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
36
37
Differences between QEMU and real hardware:
38
39
-- AN385 remapping of low 16K of memory to either ZBT SSRAM1 or to
40
+- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
41
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
42
if zbt_boot_ctrl is always zero)
43
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
44
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/mps2.c
47
+++ b/hw/arm/mps2.c
48
@@ -XXX,XX +XXX,XX @@
49
* as seen by the guest depend significantly on the FPGA image.
50
* We model the following FPGA images:
51
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
52
+ * "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
53
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
54
*
55
* Links to the TRM for the board itself and to the various Application
56
@@ -XXX,XX +XXX,XX @@
57
58
typedef enum MPS2FPGAType {
59
FPGA_AN385,
60
+ FPGA_AN386,
61
FPGA_AN511,
62
} MPS2FPGAType;
63
64
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
65
66
#define TYPE_MPS2_MACHINE "mps2"
67
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
68
+#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
69
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
70
71
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
72
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
73
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
74
* call the 16MB our "system memory", as it's the largest lump.
75
*
76
- * Common to both boards:
77
- * 0x21000000..0x21ffffff : PSRAM (16MB)
78
- * AN385 only:
79
+ * AN385/AN386/AN511:
80
+ * 0x21000000 .. 0x21ffffff : PSRAM (16MB)
81
+ * AN385/AN386 only:
82
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
83
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
84
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
85
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
86
* 0x20000000 .. 0x2001ffff : SRAM
87
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
88
*
89
- * The AN385 has a feature where the lowest 16K can be mapped
90
+ * The AN385/AN386 has a feature where the lowest 16K can be mapped
91
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
92
* This is of no use for QEMU so we don't implement it (as if
93
* zbt_boot_ctrl is always zero).
94
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
95
96
switch (mmc->fpga_type) {
97
case FPGA_AN385:
98
+ case FPGA_AN386:
99
make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
100
make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
101
make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
102
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
103
armv7m = DEVICE(&mms->armv7m);
104
switch (mmc->fpga_type) {
105
case FPGA_AN385:
106
+ case FPGA_AN386:
107
qdev_prop_set_uint32(armv7m, "num-irq", 32);
108
break;
109
case FPGA_AN511:
110
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
111
112
switch (mmc->fpga_type) {
113
case FPGA_AN385:
114
+ case FPGA_AN386:
115
{
116
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
117
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
*/
120
lan9118_init(&nd_table[0], 0x40200000,
121
qdev_get_gpio_in(armv7m,
122
- mmc->fpga_type == FPGA_AN385 ? 13 : 47));
123
+ mmc->fpga_type == FPGA_AN511 ? 47 : 13));
124
125
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
126
127
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
128
mmc->scc_id = 0x41043850;
129
}
20
}
130
21
131
+static void mps2_an386_class_init(ObjectClass *oc, void *data)
22
uint32_t psw_read(CPUTriCoreState *env)
132
+{
133
+ MachineClass *mc = MACHINE_CLASS(oc);
134
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
135
+
136
+ mc->desc = "ARM MPS2 with AN386 FPGA image for Cortex-M4";
137
+ mmc->fpga_type = FPGA_AN386;
138
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
139
+ mmc->scc_id = 0x41043860;
140
+}
141
+
142
static void mps2_an511_class_init(ObjectClass *oc, void *data)
143
{
144
MachineClass *mc = MACHINE_CLASS(oc);
145
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an385_info = {
146
.class_init = mps2_an385_class_init,
147
};
148
149
+static const TypeInfo mps2_an386_info = {
150
+ .name = TYPE_MPS2_AN386_MACHINE,
151
+ .parent = TYPE_MPS2_MACHINE,
152
+ .class_init = mps2_an386_class_init,
153
+};
154
+
155
static const TypeInfo mps2_an511_info = {
156
.name = TYPE_MPS2_AN511_MACHINE,
157
.parent = TYPE_MPS2_MACHINE,
158
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
159
{
160
type_register_static(&mps2_info);
161
type_register_static(&mps2_an385_info);
162
+ type_register_static(&mps2_an386_info);
163
type_register_static(&mps2_an511_info);
164
}
165
166
--
23
--
167
2.20.1
24
2.34.1
168
169
diff view generated by jsdifflib
1
We deprecated the support for KVM on 32-bit Arm hosts in time
1
Now that all our targets have bene converted to explicitly specify
2
for release 5.0, which means that our deprecation policy allows
2
their pattern for the default NaN value we can remove the remaining
3
us to drop it in release 5.2. Remove the code.
3
fallback code in parts64_default_nan().
4
5
To repeat the rationale from the deprecation note: the Linux
6
kernel dropped support for 32-bit Arm KVM hosts in 5.7.
7
8
Running 32-bit guests on a 64-bit Arm host remains supported.
9
4
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
13
Message-id: 20200904154156.31943-2-peter.maydell@linaro.org
14
---
8
---
15
docs/system/deprecated.rst | 16 +-
9
fpu/softfloat-specialize.c.inc | 14 --------------
16
configure | 2 +-
10
1 file changed, 14 deletions(-)
17
target/arm/kvm32.c | 595 -------------------------------------
18
target/arm/meson.build | 5 +-
19
4 files changed, 10 insertions(+), 608 deletions(-)
20
delete mode 100644 target/arm/kvm32.c
21
11
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
23
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
24
--- a/docs/system/deprecated.rst
14
--- a/fpu/softfloat-specialize.c.inc
25
+++ b/docs/system/deprecated.rst
15
+++ b/fpu/softfloat-specialize.c.inc
26
@@ -XXX,XX +XXX,XX @@ The ``compat`` property used to set backwards compatibility modes for
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
27
the processor has been deprecated. The ``max-cpu-compat`` property of
17
uint64_t frac;
28
the ``pseries`` machine type should be used instead.
18
uint8_t dnan_pattern = status->default_nan_pattern;
29
19
30
-KVM guest support on 32-bit Arm hosts (since 5.0)
20
- if (dnan_pattern == 0) {
31
-'''''''''''''''''''''''''''''''''''''''''''''''''
32
-
33
-The Linux kernel has dropped support for allowing 32-bit Arm systems
34
-to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
35
-its support for this configuration and will remove it in a future version.
36
-Running 32-bit guests on a 64-bit Arm host remains supported.
37
-
38
System emulator devices
39
-----------------------
40
41
@@ -XXX,XX +XXX,XX @@ should be used instead of the 1.09.1 version.
42
System emulator CPUS
43
--------------------
44
45
+KVM guest support on 32-bit Arm hosts (removed in 5.2)
46
+''''''''''''''''''''''''''''''''''''''''''''''''''''''
47
+
48
+The Linux kernel has dropped support for allowing 32-bit Arm systems
49
+to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
50
+its support for this configuration and will remove it in a future version.
51
+Running 32-bit guests on a 64-bit Arm host remains supported.
52
+
53
RISC-V ISA Specific CPUs (removed in 5.1)
54
'''''''''''''''''''''''''''''''''''''''''
55
56
diff --git a/configure b/configure
57
index XXXXXXX..XXXXXXX 100755
58
--- a/configure
59
+++ b/configure
60
@@ -XXX,XX +XXX,XX @@ supported_kvm_target() {
61
test "$kvm" = "yes" || return 1
62
glob "$1" "*-softmmu" || return 1
63
case "${1%-softmmu}:$cpu" in
64
- arm:arm | aarch64:aarch64 | \
65
+ aarch64:aarch64 | \
66
i386:i386 | i386:x86_64 | i386:x32 | \
67
x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \
68
mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \
69
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
70
deleted file mode 100644
71
index XXXXXXX..XXXXXXX
72
--- a/target/arm/kvm32.c
73
+++ /dev/null
74
@@ -XXX,XX +XXX,XX @@
75
-/*
76
- * ARM implementation of KVM hooks, 32 bit specific code.
77
- *
78
- * Copyright Christoffer Dall 2009-2010
79
- *
80
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
81
- * See the COPYING file in the top-level directory.
82
- *
83
- */
84
-
85
-#include "qemu/osdep.h"
86
-#include <sys/ioctl.h>
87
-
88
-#include <linux/kvm.h>
89
-
90
-#include "qemu-common.h"
91
-#include "cpu.h"
92
-#include "qemu/timer.h"
93
-#include "sysemu/runstate.h"
94
-#include "sysemu/kvm.h"
95
-#include "kvm_arm.h"
96
-#include "internals.h"
97
-#include "qemu/log.h"
98
-
99
-static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id)
100
-{
101
- struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret };
102
-
103
- assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32);
104
- return ioctl(fd, KVM_GET_ONE_REG, &idreg);
105
-}
106
-
107
-bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
108
-{
109
- /* Identify the feature bits corresponding to the host CPU, and
110
- * fill out the ARMHostCPUClass fields accordingly. To do this
111
- * we have to create a scratch VM, create a single CPU inside it,
112
- * and then query that CPU for the relevant ID registers.
113
- */
114
- int err = 0, fdarray[3];
115
- uint32_t midr, id_pfr0;
116
- uint64_t features = 0;
117
-
118
- /* Old kernels may not know about the PREFERRED_TARGET ioctl: however
119
- * we know these will only support creating one kind of guest CPU,
120
- * which is its preferred CPU type.
121
- */
122
- static const uint32_t cpus_to_try[] = {
123
- QEMU_KVM_ARM_TARGET_CORTEX_A15,
124
- QEMU_KVM_ARM_TARGET_NONE
125
- };
126
- /*
127
- * target = -1 informs kvm_arm_create_scratch_host_vcpu()
128
- * to use the preferred target
129
- */
130
- struct kvm_vcpu_init init = { .target = -1, };
131
-
132
- if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
133
- return false;
134
- }
135
-
136
- ahcf->target = init.target;
137
-
138
- /* This is not strictly blessed by the device tree binding docs yet,
139
- * but in practice the kernel does not care about this string so
140
- * there is no point maintaining an KVM_ARM_TARGET_* -> string table.
141
- */
142
- ahcf->dtb_compatible = "arm,arm-v7";
143
-
144
- err |= read_sys_reg32(fdarray[2], &midr, ARM_CP15_REG32(0, 0, 0, 0));
145
- err |= read_sys_reg32(fdarray[2], &id_pfr0, ARM_CP15_REG32(0, 0, 1, 0));
146
-
147
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
148
- ARM_CP15_REG32(0, 0, 2, 0));
149
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
150
- ARM_CP15_REG32(0, 0, 2, 1));
151
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2,
152
- ARM_CP15_REG32(0, 0, 2, 2));
153
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3,
154
- ARM_CP15_REG32(0, 0, 2, 3));
155
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4,
156
- ARM_CP15_REG32(0, 0, 2, 4));
157
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5,
158
- ARM_CP15_REG32(0, 0, 2, 5));
159
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6,
160
- ARM_CP15_REG32(0, 0, 2, 7))) {
161
- /*
21
- /*
162
- * Older kernels don't support reading ID_ISAR6. This register was
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
163
- * only introduced in ARMv8, so we can assume that it is zero on a
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
164
- * CPU that a kernel this old is running on.
24
- * do not have floating-point.
165
- */
25
- */
166
- ahcf->isar.id_isar6 = 0;
26
- if (snan_bit_is_one(status)) {
167
- }
27
- /* sign bit clear, set all frac bits other than msb */
168
-
28
- dnan_pattern = 0b00111111;
169
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
29
- } else {
170
- ARM_CP15_REG32(0, 0, 1, 2));
30
- /* sign bit clear, set frac msb */
171
-
31
- dnan_pattern = 0b01000000;
172
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
173
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
174
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR0);
175
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1,
176
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
177
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR1);
178
- /*
179
- * FIXME: There is not yet a way to read MVFR2.
180
- * Fortunately there is not yet anything in there that affects migration.
181
- */
182
-
183
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
184
- ARM_CP15_REG32(0, 0, 1, 4));
185
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
186
- ARM_CP15_REG32(0, 0, 1, 5));
187
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
188
- ARM_CP15_REG32(0, 0, 1, 6));
189
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
190
- ARM_CP15_REG32(0, 0, 1, 7));
191
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
192
- ARM_CP15_REG32(0, 0, 2, 6))) {
193
- /*
194
- * Older kernels don't support reading ID_MMFR4 (a new in v8
195
- * register); assume it's zero.
196
- */
197
- ahcf->isar.id_mmfr4 = 0;
198
- }
199
-
200
- /*
201
- * There is no way to read DBGDIDR, because currently 32-bit KVM
202
- * doesn't implement debug at all. Leave it at zero.
203
- */
204
-
205
- kvm_arm_destroy_scratch_host_vcpu(fdarray);
206
-
207
- if (err < 0) {
208
- return false;
209
- }
210
-
211
- /* Now we've retrieved all the register information we can
212
- * set the feature bits based on the ID register fields.
213
- * We can assume any KVM supporting CPU is at least a v7
214
- * with VFPv3, virtualization extensions, and the generic
215
- * timers; this in turn implies most of the other feature
216
- * bits, but a few must be tested.
217
- */
218
- features |= 1ULL << ARM_FEATURE_V7VE;
219
- features |= 1ULL << ARM_FEATURE_GENERIC_TIMER;
220
-
221
- if (extract32(id_pfr0, 12, 4) == 1) {
222
- features |= 1ULL << ARM_FEATURE_THUMB2EE;
223
- }
224
- if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
225
- features |= 1ULL << ARM_FEATURE_NEON;
226
- }
227
-
228
- ahcf->features = features;
229
-
230
- return true;
231
-}
232
-
233
-bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
234
-{
235
- /* Return true if the regidx is a register we should synchronize
236
- * via the cpreg_tuples array (ie is not a core reg we sync by
237
- * hand in kvm_arch_get/put_registers())
238
- */
239
- switch (regidx & KVM_REG_ARM_COPROC_MASK) {
240
- case KVM_REG_ARM_CORE:
241
- case KVM_REG_ARM_VFP:
242
- return false;
243
- default:
244
- return true;
245
- }
246
-}
247
-
248
-typedef struct CPRegStateLevel {
249
- uint64_t regidx;
250
- int level;
251
-} CPRegStateLevel;
252
-
253
-/* All coprocessor registers not listed in the following table are assumed to
254
- * be of the level KVM_PUT_RUNTIME_STATE. If a register should be written less
255
- * often, you must add it to this table with a state of either
256
- * KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE.
257
- */
258
-static const CPRegStateLevel non_runtime_cpregs[] = {
259
- { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
260
-};
261
-
262
-int kvm_arm_cpreg_level(uint64_t regidx)
263
-{
264
- int i;
265
-
266
- for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) {
267
- const CPRegStateLevel *l = &non_runtime_cpregs[i];
268
- if (l->regidx == regidx) {
269
- return l->level;
270
- }
32
- }
271
- }
33
- }
272
-
34
assert(dnan_pattern != 0);
273
- return KVM_PUT_RUNTIME_STATE;
35
274
-}
36
sign = dnan_pattern >> 7;
275
-
276
-#define ARM_CPU_ID_MPIDR 0, 0, 0, 5
277
-
278
-int kvm_arch_init_vcpu(CPUState *cs)
279
-{
280
- int ret;
281
- uint64_t v;
282
- uint32_t mpidr;
283
- struct kvm_one_reg r;
284
- ARMCPU *cpu = ARM_CPU(cs);
285
-
286
- if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
287
- fprintf(stderr, "KVM is not supported for this guest CPU type\n");
288
- return -EINVAL;
289
- }
290
-
291
- qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
292
-
293
- /* Determine init features for this CPU */
294
- memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
295
- if (cs->start_powered_off) {
296
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF;
297
- }
298
- if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) {
299
- cpu->psci_version = 2;
300
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2;
301
- }
302
-
303
- /* Do KVM_ARM_VCPU_INIT ioctl */
304
- ret = kvm_arm_vcpu_init(cs);
305
- if (ret) {
306
- return ret;
307
- }
308
-
309
- /* Query the kernel to make sure it supports 32 VFP
310
- * registers: QEMU's "cortex-a15" CPU is always a
311
- * VFP-D32 core. The simplest way to do this is just
312
- * to attempt to read register d31.
313
- */
314
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31;
315
- r.addr = (uintptr_t)(&v);
316
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
317
- if (ret == -ENOENT) {
318
- return -EINVAL;
319
- }
320
-
321
- /*
322
- * When KVM is in use, PSCI is emulated in-kernel and not by qemu.
323
- * Currently KVM has its own idea about MPIDR assignment, so we
324
- * override our defaults with what we get from KVM.
325
- */
326
- ret = kvm_get_one_reg(cs, ARM_CP15_REG32(ARM_CPU_ID_MPIDR), &mpidr);
327
- if (ret) {
328
- return ret;
329
- }
330
- cpu->mp_affinity = mpidr & ARM32_AFFINITY_MASK;
331
-
332
- /* Check whether userspace can specify guest syndrome value */
333
- kvm_arm_init_serror_injection(cs);
334
-
335
- return kvm_arm_init_cpreg_list(cpu);
336
-}
337
-
338
-int kvm_arch_destroy_vcpu(CPUState *cs)
339
-{
340
-    return 0;
341
-}
342
-
343
-typedef struct Reg {
344
- uint64_t id;
345
- int offset;
346
-} Reg;
347
-
348
-#define COREREG(KERNELNAME, QEMUFIELD) \
349
- { \
350
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
351
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
352
- offsetof(CPUARMState, QEMUFIELD) \
353
- }
354
-
355
-#define VFPSYSREG(R) \
356
- { \
357
- KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \
358
- KVM_REG_ARM_VFP_##R, \
359
- offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
360
- }
361
-
362
-/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */
363
-#define COREREG64(KERNELNAME, QEMUFIELD) \
364
- { \
365
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
366
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
367
- offsetoflow32(CPUARMState, QEMUFIELD) \
368
- }
369
-
370
-static const Reg regs[] = {
371
- /* R0_usr .. R14_usr */
372
- COREREG(usr_regs.uregs[0], regs[0]),
373
- COREREG(usr_regs.uregs[1], regs[1]),
374
- COREREG(usr_regs.uregs[2], regs[2]),
375
- COREREG(usr_regs.uregs[3], regs[3]),
376
- COREREG(usr_regs.uregs[4], regs[4]),
377
- COREREG(usr_regs.uregs[5], regs[5]),
378
- COREREG(usr_regs.uregs[6], regs[6]),
379
- COREREG(usr_regs.uregs[7], regs[7]),
380
- COREREG(usr_regs.uregs[8], usr_regs[0]),
381
- COREREG(usr_regs.uregs[9], usr_regs[1]),
382
- COREREG(usr_regs.uregs[10], usr_regs[2]),
383
- COREREG(usr_regs.uregs[11], usr_regs[3]),
384
- COREREG(usr_regs.uregs[12], usr_regs[4]),
385
- COREREG(usr_regs.uregs[13], banked_r13[BANK_USRSYS]),
386
- COREREG(usr_regs.uregs[14], banked_r14[BANK_USRSYS]),
387
- /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
388
- COREREG(svc_regs[0], banked_r13[BANK_SVC]),
389
- COREREG(svc_regs[1], banked_r14[BANK_SVC]),
390
- COREREG64(svc_regs[2], banked_spsr[BANK_SVC]),
391
- COREREG(abt_regs[0], banked_r13[BANK_ABT]),
392
- COREREG(abt_regs[1], banked_r14[BANK_ABT]),
393
- COREREG64(abt_regs[2], banked_spsr[BANK_ABT]),
394
- COREREG(und_regs[0], banked_r13[BANK_UND]),
395
- COREREG(und_regs[1], banked_r14[BANK_UND]),
396
- COREREG64(und_regs[2], banked_spsr[BANK_UND]),
397
- COREREG(irq_regs[0], banked_r13[BANK_IRQ]),
398
- COREREG(irq_regs[1], banked_r14[BANK_IRQ]),
399
- COREREG64(irq_regs[2], banked_spsr[BANK_IRQ]),
400
- /* R8_fiq .. R14_fiq and SPSR_fiq */
401
- COREREG(fiq_regs[0], fiq_regs[0]),
402
- COREREG(fiq_regs[1], fiq_regs[1]),
403
- COREREG(fiq_regs[2], fiq_regs[2]),
404
- COREREG(fiq_regs[3], fiq_regs[3]),
405
- COREREG(fiq_regs[4], fiq_regs[4]),
406
- COREREG(fiq_regs[5], banked_r13[BANK_FIQ]),
407
- COREREG(fiq_regs[6], banked_r14[BANK_FIQ]),
408
- COREREG64(fiq_regs[7], banked_spsr[BANK_FIQ]),
409
- /* R15 */
410
- COREREG(usr_regs.uregs[15], regs[15]),
411
- /* VFP system registers */
412
- VFPSYSREG(FPSID),
413
- VFPSYSREG(MVFR1),
414
- VFPSYSREG(MVFR0),
415
- VFPSYSREG(FPEXC),
416
- VFPSYSREG(FPINST),
417
- VFPSYSREG(FPINST2),
418
-};
419
-
420
-int kvm_arch_put_registers(CPUState *cs, int level)
421
-{
422
- ARMCPU *cpu = ARM_CPU(cs);
423
- CPUARMState *env = &cpu->env;
424
- struct kvm_one_reg r;
425
- int mode, bn;
426
- int ret, i;
427
- uint32_t cpsr, fpscr;
428
-
429
- /* Make sure the banked regs are properly set */
430
- mode = env->uncached_cpsr & CPSR_M;
431
- bn = bank_number(mode);
432
- if (mode == ARM_CPU_MODE_FIQ) {
433
- memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
434
- } else {
435
- memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
436
- }
437
- env->banked_r13[bn] = env->regs[13];
438
- env->banked_spsr[bn] = env->spsr;
439
- env->banked_r14[r14_bank_number(mode)] = env->regs[14];
440
-
441
- /* Now we can safely copy stuff down to the kernel */
442
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
443
- r.id = regs[i].id;
444
- r.addr = (uintptr_t)(env) + regs[i].offset;
445
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
446
- if (ret) {
447
- return ret;
448
- }
449
- }
450
-
451
- /* Special cases which aren't a single CPUARMState field */
452
- cpsr = cpsr_read(env);
453
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
454
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
455
- r.addr = (uintptr_t)(&cpsr);
456
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
457
- if (ret) {
458
- return ret;
459
- }
460
-
461
- /* VFP registers */
462
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
463
- for (i = 0; i < 32; i++) {
464
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
465
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
466
- if (ret) {
467
- return ret;
468
- }
469
- r.id++;
470
- }
471
-
472
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
473
- KVM_REG_ARM_VFP_FPSCR;
474
- fpscr = vfp_get_fpscr(env);
475
- r.addr = (uintptr_t)&fpscr;
476
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
477
- if (ret) {
478
- return ret;
479
- }
480
-
481
- write_cpustate_to_list(cpu, true);
482
-
483
- if (!write_list_to_kvmstate(cpu, level)) {
484
- return EINVAL;
485
- }
486
-
487
- /*
488
- * Setting VCPU events should be triggered after syncing the registers
489
- * to avoid overwriting potential changes made by KVM upon calling
490
- * KVM_SET_VCPU_EVENTS ioctl
491
- */
492
- ret = kvm_put_vcpu_events(cpu);
493
- if (ret) {
494
- return ret;
495
- }
496
-
497
- kvm_arm_sync_mpstate_to_kvm(cpu);
498
-
499
- return ret;
500
-}
501
-
502
-int kvm_arch_get_registers(CPUState *cs)
503
-{
504
- ARMCPU *cpu = ARM_CPU(cs);
505
- CPUARMState *env = &cpu->env;
506
- struct kvm_one_reg r;
507
- int mode, bn;
508
- int ret, i;
509
- uint32_t cpsr, fpscr;
510
-
511
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
512
- r.id = regs[i].id;
513
- r.addr = (uintptr_t)(env) + regs[i].offset;
514
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
515
- if (ret) {
516
- return ret;
517
- }
518
- }
519
-
520
- /* Special cases which aren't a single CPUARMState field */
521
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
522
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
523
- r.addr = (uintptr_t)(&cpsr);
524
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
525
- if (ret) {
526
- return ret;
527
- }
528
- cpsr_write(env, cpsr, 0xffffffff, CPSRWriteRaw);
529
-
530
- /* Make sure the current mode regs are properly set */
531
- mode = env->uncached_cpsr & CPSR_M;
532
- bn = bank_number(mode);
533
- if (mode == ARM_CPU_MODE_FIQ) {
534
- memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
535
- } else {
536
- memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
537
- }
538
- env->regs[13] = env->banked_r13[bn];
539
- env->spsr = env->banked_spsr[bn];
540
- env->regs[14] = env->banked_r14[r14_bank_number(mode)];
541
-
542
- /* VFP registers */
543
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
544
- for (i = 0; i < 32; i++) {
545
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
546
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
547
- if (ret) {
548
- return ret;
549
- }
550
- r.id++;
551
- }
552
-
553
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
554
- KVM_REG_ARM_VFP_FPSCR;
555
- r.addr = (uintptr_t)&fpscr;
556
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
557
- if (ret) {
558
- return ret;
559
- }
560
- vfp_set_fpscr(env, fpscr);
561
-
562
- ret = kvm_get_vcpu_events(cpu);
563
- if (ret) {
564
- return ret;
565
- }
566
-
567
- if (!write_kvmstate_to_list(cpu)) {
568
- return EINVAL;
569
- }
570
- /* Note that it's OK to have registers which aren't in CPUState,
571
- * so we can ignore a failure return here.
572
- */
573
- write_list_to_cpustate(cpu);
574
-
575
- kvm_arm_sync_mpstate_to_qemu(cpu);
576
-
577
- return 0;
578
-}
579
-
580
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
581
-{
582
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
583
- return -EINVAL;
584
-}
585
-
586
-int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
587
-{
588
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
589
- return -EINVAL;
590
-}
591
-
592
-bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit)
593
-{
594
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
595
- return false;
596
-}
597
-
598
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
599
- target_ulong len, int type)
600
-{
601
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
602
- return -EINVAL;
603
-}
604
-
605
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
606
- target_ulong len, int type)
607
-{
608
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
609
- return -EINVAL;
610
-}
611
-
612
-void kvm_arch_remove_all_hw_breakpoints(void)
613
-{
614
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
615
-}
616
-
617
-void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr)
618
-{
619
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
620
-}
621
-
622
-bool kvm_arm_hw_debug_active(CPUState *cs)
623
-{
624
- return false;
625
-}
626
-
627
-void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
628
-{
629
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
630
-}
631
-
632
-void kvm_arm_pmu_init(CPUState *cs)
633
-{
634
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
635
-}
636
-
637
-#define ARM_REG_DFSR ARM_CP15_REG32(0, 5, 0, 0)
638
-#define ARM_REG_TTBCR ARM_CP15_REG32(0, 2, 0, 2)
639
-/*
640
- *DFSR:
641
- * TTBCR.EAE == 0
642
- * FS[4] - DFSR[10]
643
- * FS[3:0] - DFSR[3:0]
644
- * TTBCR.EAE == 1
645
- * FS, bits [5:0]
646
- */
647
-#define DFSR_FSC(lpae, v) \
648
- ((lpae) ? ((v) & 0x3F) : (((v) >> 6) | ((v) & 0x1F)))
649
-
650
-#define DFSC_EXTABT(lpae) ((lpae) ? 0x10 : 0x08)
651
-
652
-bool kvm_arm_verify_ext_dabt_pending(CPUState *cs)
653
-{
654
- uint32_t dfsr_val;
655
-
656
- if (!kvm_get_one_reg(cs, ARM_REG_DFSR, &dfsr_val)) {
657
- ARMCPU *cpu = ARM_CPU(cs);
658
- CPUARMState *env = &cpu->env;
659
- uint32_t ttbcr;
660
- int lpae = 0;
661
-
662
- if (!kvm_get_one_reg(cs, ARM_REG_TTBCR, &ttbcr)) {
663
- lpae = arm_feature(env, ARM_FEATURE_LPAE) && (ttbcr & TTBCR_EAE);
664
- }
665
- /* The verification is based on FS filed of the DFSR reg only*/
666
- return (DFSR_FSC(lpae, dfsr_val) == DFSC_EXTABT(lpae));
667
- }
668
- return false;
669
-}
670
diff --git a/target/arm/meson.build b/target/arm/meson.build
671
index XXXXXXX..XXXXXXX 100644
672
--- a/target/arm/meson.build
673
+++ b/target/arm/meson.build
674
@@ -XXX,XX +XXX,XX @@ arm_ss.add(zlib)
675
676
arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
677
678
-kvm_ss = ss.source_set()
679
-kvm_ss.add(when: 'TARGET_AARCH64', if_true: files('kvm64.c'), if_false: files('kvm32.c'))
680
-arm_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
681
-arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
682
+arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
683
684
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
685
'cpu64.c',
686
--
37
--
687
2.20.1
38
2.34.1
688
689
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This allows these NPCM7xx-based boards to boot from a flash image, e.g.
3
Inline pickNaNMulAdd into its only caller. This makes
4
one built with OpenBMC. For example like this:
4
one assert redundant with the immediately preceding IF.
5
5
6
IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
qemu-system-arm -machine quanta-gsj -nographic \
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
    -drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
9
9
[PMM: keep comment from old code in new location]
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Tested-by: Cédric Le Goater <clg@kaod.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20200911052101.2602693-12-hskinnemoen@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
11
---
19
hw/arm/npcm7xx_boards.c | 20 ++++++++++++++++++++
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
20
1 file changed, 20 insertions(+)
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
14
2 files changed, 40 insertions(+), 55 deletions(-)
21
15
22
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/arm/npcm7xx_boards.c
18
--- a/fpu/softfloat-parts.c.inc
25
+++ b/hw/arm/npcm7xx_boards.c
19
+++ b/fpu/softfloat-parts.c.inc
26
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
27
#include "hw/arm/npcm7xx.h"
21
}
28
#include "hw/core/cpu.h"
22
29
#include "hw/loader.h"
23
if (s->default_nan_mode) {
30
+#include "hw/qdev-properties.h"
24
+ /*
31
#include "qapi/error.h"
25
+ * We guarantee not to require the target to tell us how to
32
#include "qemu-common.h"
26
+ * pick a NaN if we're always returning the default NaN.
33
#include "qemu/units.h"
27
+ * But if we're not in default-NaN mode then the target must
34
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
28
+ * specify.
29
+ */
30
which = 3;
31
+ } else if (infzero) {
32
+ /*
33
+ * Inf * 0 + NaN -- some implementations return the
34
+ * default NaN here, and some return the input NaN.
35
+ */
36
+ switch (s->float_infzeronan_rule) {
37
+ case float_infzeronan_dnan_never:
38
+ which = 2;
39
+ break;
40
+ case float_infzeronan_dnan_always:
41
+ which = 3;
42
+ break;
43
+ case float_infzeronan_dnan_if_qnan:
44
+ which = is_qnan(c->cls) ? 3 : 2;
45
+ break;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
} else {
50
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
51
+ FloatClass cls[3] = { a->cls, b->cls, c->cls };
52
+ Float3NaNPropRule rule = s->float_3nan_prop_rule;
53
+
54
+ assert(rule != float_3nan_prop_none);
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
56
+ /* We have at least one SNaN input and should prefer it */
57
+ do {
58
+ which = rule & R_3NAN_1ST_MASK;
59
+ rule >>= R_3NAN_1ST_LENGTH;
60
+ } while (!is_snan(cls[which]));
61
+ } else {
62
+ do {
63
+ which = rule & R_3NAN_1ST_MASK;
64
+ rule >>= R_3NAN_1ST_LENGTH;
65
+ } while (!is_nan(cls[which]));
66
+ }
67
}
68
69
if (which == 3) {
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
71
index XXXXXXX..XXXXXXX 100644
72
--- a/fpu/softfloat-specialize.c.inc
73
+++ b/fpu/softfloat-specialize.c.inc
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
35
}
75
}
36
}
76
}
37
77
38
+static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
78
-/*----------------------------------------------------------------------------
39
+ const char *flash_type, DriveInfo *dinfo)
79
-| Select which NaN to propagate for a three-input operation.
40
+{
80
-| For the moment we assume that no CPU needs the 'larger significand'
41
+ DeviceState *flash;
81
-| information.
42
+ qemu_irq flash_cs;
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
43
+
83
-*----------------------------------------------------------------------------*/
44
+ flash = qdev_new(flash_type);
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
45
+ if (dinfo) {
85
- bool infzero, bool have_snan, float_status *status)
46
+ qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo));
86
-{
47
+ }
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
48
+ qdev_realize_and_unref(flash, BUS(fiu->spi), &error_fatal);
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
49
+
89
- int which;
50
+ flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
90
-
51
+ qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs);
91
- /*
52
+}
92
- * We guarantee not to require the target to tell us how to
53
+
93
- * pick a NaN if we're always returning the default NaN.
54
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
94
- * But if we're not in default-NaN mode then the target must
55
{
95
- * specify.
56
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
96
- */
57
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
97
- assert(!status->default_nan_mode);
58
qdev_realize(DEVICE(soc), NULL, &error_fatal);
98
-
59
99
- if (infzero) {
60
npcm7xx_load_bootrom(machine, soc);
100
- /*
61
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
101
- * Inf * 0 + NaN -- some implementations return the default NaN here,
62
npcm7xx_load_kernel(machine, soc);
102
- * and some return the input NaN.
63
}
103
- */
64
104
- switch (status->float_infzeronan_rule) {
65
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
105
- case float_infzeronan_dnan_never:
66
qdev_realize(DEVICE(soc), NULL, &error_fatal);
106
- return 2;
67
107
- case float_infzeronan_dnan_always:
68
npcm7xx_load_bootrom(machine, soc);
108
- return 3;
69
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
109
- case float_infzeronan_dnan_if_qnan:
70
+ drive_get(IF_MTD, 0, 0));
110
- return is_qnan(c_cls) ? 3 : 2;
71
npcm7xx_load_kernel(machine, soc);
111
- default:
72
}
112
- g_assert_not_reached();
73
113
- }
114
- }
115
-
116
- assert(rule != float_3nan_prop_none);
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
118
- /* We have at least one SNaN input and should prefer it */
119
- do {
120
- which = rule & R_3NAN_1ST_MASK;
121
- rule >>= R_3NAN_1ST_LENGTH;
122
- } while (!is_snan(cls[which]));
123
- } else {
124
- do {
125
- which = rule & R_3NAN_1ST_MASK;
126
- rule >>= R_3NAN_1ST_LENGTH;
127
- } while (!is_nan(cls[which]));
128
- }
129
- return which;
130
-}
131
-
132
/*----------------------------------------------------------------------------
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
134
| NaN; otherwise returns 0.
74
--
135
--
75
2.20.1
136
2.34.1
76
137
77
138
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This implements a device model for the NPCM7xx SPI flash controller.
3
Remove "3" as a special case for which and simply
4
branch to return the desired value.
4
5
5
Direct reads and writes, and user-mode transactions have been tested in
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
various modes. Protection features are not implemented yet.
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
8
All the FIU instances are available in the SoC's address space,
9
regardless of whether or not they're connected to actual flash chips.
10
11
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
Reviewed-by: Cédric Le Goater <clg@kaod.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Tested-by: Alexander Bulekov <alxndr@bu.edu>
16
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
17
Message-id: 20200911052101.2602693-11-hskinnemoen@google.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
10
---
20
include/hw/arm/npcm7xx.h | 2 +
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
21
include/hw/ssi/npcm7xx_fiu.h | 73 +++++
12
1 file changed, 10 insertions(+), 10 deletions(-)
22
hw/arm/npcm7xx.c | 58 ++++
23
hw/ssi/npcm7xx_fiu.c | 572 +++++++++++++++++++++++++++++++++++
24
hw/arm/Kconfig | 1 +
25
hw/ssi/meson.build | 1 +
26
hw/ssi/trace-events | 11 +
27
7 files changed, 718 insertions(+)
28
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
29
create mode 100644 hw/ssi/npcm7xx_fiu.c
30
13
31
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
32
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/arm/npcm7xx.h
16
--- a/fpu/softfloat-parts.c.inc
34
+++ b/include/hw/arm/npcm7xx.h
17
+++ b/fpu/softfloat-parts.c.inc
35
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
36
#include "hw/misc/npcm7xx_gcr.h"
19
* But if we're not in default-NaN mode then the target must
37
#include "hw/nvram/npcm7xx_otp.h"
20
* specify.
38
#include "hw/timer/npcm7xx_timer.h"
21
*/
39
+#include "hw/ssi/npcm7xx_fiu.h"
22
- which = 3;
40
#include "target/arm/cpu.h"
23
+ goto default_nan;
41
24
} else if (infzero) {
42
#define NPCM7XX_MAX_NUM_CPUS (2)
25
/*
43
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
26
* Inf * 0 + NaN -- some implementations return the
44
NPCM7xxOTPState key_storage;
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
45
NPCM7xxOTPState fuse_array;
28
*/
46
NPCM7xxMCState mc;
29
switch (s->float_infzeronan_rule) {
47
+ NPCM7xxFIUState fiu[2];
30
case float_infzeronan_dnan_never:
48
} NPCM7xxState;
31
- which = 2;
49
32
break;
50
#define TYPE_NPCM7XX "npcm7xx"
33
case float_infzeronan_dnan_always:
51
diff --git a/include/hw/ssi/npcm7xx_fiu.h b/include/hw/ssi/npcm7xx_fiu.h
34
- which = 3;
52
new file mode 100644
35
- break;
53
index XXXXXXX..XXXXXXX
36
+ goto default_nan;
54
--- /dev/null
37
case float_infzeronan_dnan_if_qnan:
55
+++ b/include/hw/ssi/npcm7xx_fiu.h
38
- which = is_qnan(c->cls) ? 3 : 2;
56
@@ -XXX,XX +XXX,XX @@
39
+ if (is_qnan(c->cls)) {
57
+/*
40
+ goto default_nan;
58
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
41
+ }
59
+ *
42
break;
60
+ * Copyright 2020 Google LLC
43
default:
61
+ *
44
g_assert_not_reached();
62
+ * This program is free software; you can redistribute it and/or modify it
45
}
63
+ * under the terms of the GNU General Public License as published by the
46
+ which = 2;
64
+ * Free Software Foundation; either version 2 of the License, or
47
} else {
65
+ * (at your option) any later version.
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
66
+ *
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
67
+ * This program is distributed in the hope that it will be useful, but WITHOUT
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
68
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
51
}
69
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
52
}
70
+ * for more details.
53
71
+ */
54
- if (which == 3) {
72
+#ifndef NPCM7XX_FIU_H
55
- parts_default_nan(a, s);
73
+#define NPCM7XX_FIU_H
56
- return a;
57
- }
58
-
59
switch (which) {
60
case 0:
61
break;
62
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
63
parts_silence_nan(a, s);
64
}
65
return a;
74
+
66
+
75
+#include "hw/ssi/ssi.h"
67
+ default_nan:
76
+#include "hw/sysbus.h"
68
+ parts_default_nan(a, s);
77
+
69
+ return a;
78
+/*
79
+ * Number of registers in our device state structure. Don't change this without
80
+ * incrementing the version_id in the vmstate.
81
+ */
82
+#define NPCM7XX_FIU_NR_REGS (0x7c / sizeof(uint32_t))
83
+
84
+typedef struct NPCM7xxFIUState NPCM7xxFIUState;
85
+
86
+/**
87
+ * struct NPCM7xxFIUFlash - Per-chipselect flash controller state.
88
+ * @direct_access: Memory region for direct flash access.
89
+ * @fiu: Pointer to flash controller shared state.
90
+ */
91
+typedef struct NPCM7xxFIUFlash {
92
+ MemoryRegion direct_access;
93
+ NPCM7xxFIUState *fiu;
94
+} NPCM7xxFIUFlash;
95
+
96
+/**
97
+ * NPCM7xxFIUState - Device state for one Flash Interface Unit.
98
+ * @parent: System bus device.
99
+ * @mmio: Memory region for register access.
100
+ * @cs_count: Number of flash chips that may be connected to this module.
101
+ * @active_cs: Currently active chip select, or -1 if no chip is selected.
102
+ * @cs_lines: GPIO lines that may be wired to flash chips.
103
+ * @flash: Array of @cs_count per-flash-chip state objects.
104
+ * @spi: The SPI bus mastered by this controller.
105
+ * @regs: Register contents.
106
+ *
107
+ * Each FIU has a shared bank of registers, and controls up to four chip
108
+ * selects. Each chip select has a dedicated memory region which may be used to
109
+ * read and write the flash connected to that chip select as if it were memory.
110
+ */
111
+struct NPCM7xxFIUState {
112
+ SysBusDevice parent;
113
+
114
+ MemoryRegion mmio;
115
+
116
+ int32_t cs_count;
117
+ int32_t active_cs;
118
+ qemu_irq *cs_lines;
119
+ NPCM7xxFIUFlash *flash;
120
+
121
+ SSIBus *spi;
122
+
123
+ uint32_t regs[NPCM7XX_FIU_NR_REGS];
124
+};
125
+
126
+#define TYPE_NPCM7XX_FIU "npcm7xx-fiu"
127
+#define NPCM7XX_FIU(obj) OBJECT_CHECK(NPCM7xxFIUState, (obj), TYPE_NPCM7XX_FIU)
128
+
129
+#endif /* NPCM7XX_FIU_H */
130
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/arm/npcm7xx.c
133
+++ b/hw/arm/npcm7xx.c
134
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_uart_addr[] = {
135
0xf0004000,
136
};
137
138
+/* Direct memory-mapped access to SPI0 CS0-1. */
139
+static const hwaddr npcm7xx_fiu0_flash_addr[] = {
140
+ 0x80000000, /* CS0 */
141
+ 0x88000000, /* CS1 */
142
+};
143
+
144
+/* Direct memory-mapped access to SPI3 CS0-3. */
145
+static const hwaddr npcm7xx_fiu3_flash_addr[] = {
146
+ 0xa0000000, /* CS0 */
147
+ 0xa8000000, /* CS1 */
148
+ 0xb0000000, /* CS2 */
149
+ 0xb8000000, /* CS3 */
150
+};
151
+
152
+static const struct {
153
+ const char *name;
154
+ hwaddr regs_addr;
155
+ int cs_count;
156
+ const hwaddr *flash_addr;
157
+} npcm7xx_fiu[] = {
158
+ {
159
+ .name = "fiu0",
160
+ .regs_addr = 0xfb000000,
161
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr),
162
+ .flash_addr = npcm7xx_fiu0_flash_addr,
163
+ }, {
164
+ .name = "fiu3",
165
+ .regs_addr = 0xc0000000,
166
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr),
167
+ .flash_addr = npcm7xx_fiu3_flash_addr,
168
+ },
169
+};
170
+
171
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
172
const struct arm_boot_info *info)
173
{
174
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
175
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
176
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
177
}
178
+
179
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
180
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
181
+ object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
182
+ TYPE_NPCM7XX_FIU);
183
+ }
184
}
70
}
185
71
186
static void npcm7xx_realize(DeviceState *dev, Error **errp)
72
/*
187
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
188
serial_hd(i), DEVICE_LITTLE_ENDIAN);
189
}
190
191
+ /*
192
+ * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
193
+ * specified, but this is a programming error.
194
+ */
195
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
196
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
197
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]);
198
+ int j;
199
+
200
+ object_property_set_int(OBJECT(sbd), "cs-count",
201
+ npcm7xx_fiu[i].cs_count, &error_abort);
202
+ sysbus_realize(sbd, &error_abort);
203
+
204
+ sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr);
205
+ for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) {
206
+ sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]);
207
+ }
208
+ }
209
+
210
/* RAM2 (SRAM) */
211
memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
212
NPCM7XX_RAM2_SZ, &error_abort);
213
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
214
new file mode 100644
215
index XXXXXXX..XXXXXXX
216
--- /dev/null
217
+++ b/hw/ssi/npcm7xx_fiu.c
218
@@ -XXX,XX +XXX,XX @@
219
+/*
220
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
221
+ *
222
+ * Copyright 2020 Google LLC
223
+ *
224
+ * This program is free software; you can redistribute it and/or modify it
225
+ * under the terms of the GNU General Public License as published by the
226
+ * Free Software Foundation; either version 2 of the License, or
227
+ * (at your option) any later version.
228
+ *
229
+ * This program is distributed in the hope that it will be useful, but WITHOUT
230
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
231
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
232
+ * for more details.
233
+ */
234
+
235
+#include "qemu/osdep.h"
236
+
237
+#include "hw/irq.h"
238
+#include "hw/qdev-properties.h"
239
+#include "hw/ssi/npcm7xx_fiu.h"
240
+#include "migration/vmstate.h"
241
+#include "qapi/error.h"
242
+#include "qemu/error-report.h"
243
+#include "qemu/log.h"
244
+#include "qemu/module.h"
245
+#include "qemu/units.h"
246
+
247
+#include "trace.h"
248
+
249
+/* Up to 128 MiB of flash may be accessed directly as memory. */
250
+#define NPCM7XX_FIU_FLASH_WINDOW_SIZE (128 * MiB)
251
+
252
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
253
+#define NPCM7XX_FIU_CTRL_REGS_SIZE (4 * KiB)
254
+
255
+/* 32-bit FIU register indices. */
256
+enum NPCM7xxFIURegister {
257
+ NPCM7XX_FIU_DRD_CFG,
258
+ NPCM7XX_FIU_DWR_CFG,
259
+ NPCM7XX_FIU_UMA_CFG,
260
+ NPCM7XX_FIU_UMA_CTS,
261
+ NPCM7XX_FIU_UMA_CMD,
262
+ NPCM7XX_FIU_UMA_ADDR,
263
+ NPCM7XX_FIU_PRT_CFG,
264
+ NPCM7XX_FIU_UMA_DW0 = 0x0020 / sizeof(uint32_t),
265
+ NPCM7XX_FIU_UMA_DW1,
266
+ NPCM7XX_FIU_UMA_DW2,
267
+ NPCM7XX_FIU_UMA_DW3,
268
+ NPCM7XX_FIU_UMA_DR0,
269
+ NPCM7XX_FIU_UMA_DR1,
270
+ NPCM7XX_FIU_UMA_DR2,
271
+ NPCM7XX_FIU_UMA_DR3,
272
+ NPCM7XX_FIU_PRT_CMD0,
273
+ NPCM7XX_FIU_PRT_CMD1,
274
+ NPCM7XX_FIU_PRT_CMD2,
275
+ NPCM7XX_FIU_PRT_CMD3,
276
+ NPCM7XX_FIU_PRT_CMD4,
277
+ NPCM7XX_FIU_PRT_CMD5,
278
+ NPCM7XX_FIU_PRT_CMD6,
279
+ NPCM7XX_FIU_PRT_CMD7,
280
+ NPCM7XX_FIU_PRT_CMD8,
281
+ NPCM7XX_FIU_PRT_CMD9,
282
+ NPCM7XX_FIU_CFG = 0x78 / sizeof(uint32_t),
283
+ NPCM7XX_FIU_REGS_END,
284
+};
285
+
286
+/* FIU_{DRD,DWR,UMA,PTR}_CFG cannot be written when this bit is set. */
287
+#define NPCM7XX_FIU_CFG_LCK BIT(31)
288
+
289
+/* Direct Read configuration register fields. */
290
+#define FIU_DRD_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
291
+#define FIU_ADDSIZ_3BYTES 0
292
+#define FIU_ADDSIZ_4BYTES 1
293
+#define FIU_DRD_CFG_DBW(rv) extract32(rv, 12, 2)
294
+#define FIU_DRD_CFG_ACCTYPE(rv) extract32(rv, 8, 2)
295
+#define FIU_DRD_CFG_RDCMD(rv) extract32(rv, 0, 8)
296
+
297
+/* Direct Write configuration register fields. */
298
+#define FIU_DWR_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
299
+#define FIU_DWR_CFG_WRCMD(rv) extract32(rv, 0, 8)
300
+
301
+/* User-Mode Access register fields. */
302
+
303
+/* Command Mode Lock and the bits protected by it. */
304
+#define FIU_UMA_CFG_CMMLCK BIT(30)
305
+#define FIU_UMA_CFG_CMMLCK_MASK 0x00000403
306
+
307
+#define FIU_UMA_CFG_RDATSIZ(rv) extract32(rv, 24, 5)
308
+#define FIU_UMA_CFG_DBSIZ(rv) extract32(rv, 21, 3)
309
+#define FIU_UMA_CFG_WDATSIZ(rv) extract32(rv, 16, 5)
310
+#define FIU_UMA_CFG_ADDSIZ(rv) extract32(rv, 11, 3)
311
+#define FIU_UMA_CFG_CMDSIZ(rv) extract32(rv, 10, 1)
312
+#define FIU_UMA_CFG_DBPCK(rv) extract32(rv, 6, 2)
313
+
314
+#define FIU_UMA_CTS_RDYIE BIT(25)
315
+#define FIU_UMA_CTS_RDYST BIT(24)
316
+#define FIU_UMA_CTS_SW_CS BIT(16)
317
+#define FIU_UMA_CTS_DEV_NUM(rv) extract32(rv, 8, 2)
318
+#define FIU_UMA_CTS_EXEC_DONE BIT(0)
319
+
320
+/*
321
+ * Returns the index of flash in the fiu->flash array. This corresponds to the
322
+ * chip select ID of the flash.
323
+ */
324
+static int npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, NPCM7xxFIUFlash *flash)
325
+{
326
+ int index = flash - fiu->flash;
327
+
328
+ g_assert(index >= 0 && index < fiu->cs_count);
329
+
330
+ return index;
331
+}
332
+
333
+/* Assert the chip select specified in the UMA Control/Status Register. */
334
+static void npcm7xx_fiu_select(NPCM7xxFIUState *s, int cs_id)
335
+{
336
+ trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id);
337
+
338
+ if (cs_id < s->cs_count) {
339
+ qemu_irq_lower(s->cs_lines[cs_id]);
340
+ } else {
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: UMA to CS%d; this module has only %d chip selects",
343
+ DEVICE(s)->canonical_path, cs_id, s->cs_count);
344
+ cs_id = -1;
345
+ }
346
+
347
+ s->active_cs = cs_id;
348
+}
349
+
350
+/* Deassert the currently active chip select. */
351
+static void npcm7xx_fiu_deselect(NPCM7xxFIUState *s)
352
+{
353
+ if (s->active_cs < 0) {
354
+ return;
355
+ }
356
+
357
+ trace_npcm7xx_fiu_deselect(DEVICE(s)->canonical_path, s->active_cs);
358
+
359
+ qemu_irq_raise(s->cs_lines[s->active_cs]);
360
+ s->active_cs = -1;
361
+}
362
+
363
+/* Direct flash memory read handler. */
364
+static uint64_t npcm7xx_fiu_flash_read(void *opaque, hwaddr addr,
365
+ unsigned int size)
366
+{
367
+ NPCM7xxFIUFlash *f = opaque;
368
+ NPCM7xxFIUState *fiu = f->fiu;
369
+ uint64_t value = 0;
370
+ uint32_t drd_cfg;
371
+ int dummy_cycles;
372
+ int i;
373
+
374
+ if (fiu->active_cs != -1) {
375
+ qemu_log_mask(LOG_GUEST_ERROR,
376
+ "%s: direct flash read with CS%d already active",
377
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
378
+ }
379
+
380
+ npcm7xx_fiu_select(fiu, npcm7xx_fiu_cs_index(fiu, f));
381
+
382
+ drd_cfg = fiu->regs[NPCM7XX_FIU_DRD_CFG];
383
+ ssi_transfer(fiu->spi, FIU_DRD_CFG_RDCMD(drd_cfg));
384
+
385
+ switch (FIU_DRD_CFG_ADDSIZ(drd_cfg)) {
386
+ case FIU_ADDSIZ_4BYTES:
387
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
388
+ /* fall through */
389
+ case FIU_ADDSIZ_3BYTES:
390
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
391
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
392
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
393
+ break;
394
+
395
+ default:
396
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
397
+ DEVICE(fiu)->canonical_path, FIU_DRD_CFG_ADDSIZ(drd_cfg));
398
+ break;
399
+ }
400
+
401
+ /* Flash chip model expects one transfer per dummy bit, not byte */
402
+ dummy_cycles =
403
+ (FIU_DRD_CFG_DBW(drd_cfg) * 8) >> FIU_DRD_CFG_ACCTYPE(drd_cfg);
404
+ for (i = 0; i < dummy_cycles; i++) {
405
+ ssi_transfer(fiu->spi, 0);
406
+ }
407
+
408
+ for (i = 0; i < size; i++) {
409
+ value = deposit64(value, 8 * i, 8, ssi_transfer(fiu->spi, 0));
410
+ }
411
+
412
+ trace_npcm7xx_fiu_flash_read(DEVICE(fiu)->canonical_path, fiu->active_cs,
413
+ addr, size, value);
414
+
415
+ npcm7xx_fiu_deselect(fiu);
416
+
417
+ return value;
418
+}
419
+
420
+/* Direct flash memory write handler. */
421
+static void npcm7xx_fiu_flash_write(void *opaque, hwaddr addr, uint64_t v,
422
+ unsigned int size)
423
+{
424
+ NPCM7xxFIUFlash *f = opaque;
425
+ NPCM7xxFIUState *fiu = f->fiu;
426
+ uint32_t dwr_cfg;
427
+ int cs_id;
428
+ int i;
429
+
430
+ if (fiu->active_cs != -1) {
431
+ qemu_log_mask(LOG_GUEST_ERROR,
432
+ "%s: direct flash write with CS%d already active",
433
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
434
+ }
435
+
436
+ cs_id = npcm7xx_fiu_cs_index(fiu, f);
437
+ trace_npcm7xx_fiu_flash_write(DEVICE(fiu)->canonical_path, cs_id, addr,
438
+ size, v);
439
+ npcm7xx_fiu_select(fiu, cs_id);
440
+
441
+ dwr_cfg = fiu->regs[NPCM7XX_FIU_DWR_CFG];
442
+ ssi_transfer(fiu->spi, FIU_DWR_CFG_WRCMD(dwr_cfg));
443
+
444
+ switch (FIU_DWR_CFG_ADDSIZ(dwr_cfg)) {
445
+ case FIU_ADDSIZ_4BYTES:
446
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
447
+ /* fall through */
448
+ case FIU_ADDSIZ_3BYTES:
449
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
450
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
451
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
452
+ break;
453
+
454
+ default:
455
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
456
+ DEVICE(fiu)->canonical_path, FIU_DWR_CFG_ADDSIZ(dwr_cfg));
457
+ break;
458
+ }
459
+
460
+ for (i = 0; i < size; i++) {
461
+ ssi_transfer(fiu->spi, extract64(v, i * 8, 8));
462
+ }
463
+
464
+ npcm7xx_fiu_deselect(fiu);
465
+}
466
+
467
+static const MemoryRegionOps npcm7xx_fiu_flash_ops = {
468
+ .read = npcm7xx_fiu_flash_read,
469
+ .write = npcm7xx_fiu_flash_write,
470
+ .endianness = DEVICE_LITTLE_ENDIAN,
471
+ .valid = {
472
+ .min_access_size = 1,
473
+ .max_access_size = 8,
474
+ .unaligned = true,
475
+ },
476
+};
477
+
478
+/* Control register read handler. */
479
+static uint64_t npcm7xx_fiu_ctrl_read(void *opaque, hwaddr addr,
480
+ unsigned int size)
481
+{
482
+ hwaddr reg = addr / sizeof(uint32_t);
483
+ NPCM7xxFIUState *s = opaque;
484
+ uint32_t value;
485
+
486
+ if (reg < NPCM7XX_FIU_NR_REGS) {
487
+ value = s->regs[reg];
488
+ } else {
489
+ qemu_log_mask(LOG_GUEST_ERROR,
490
+ "%s: read from invalid offset 0x%" PRIx64 "\n",
491
+ DEVICE(s)->canonical_path, addr);
492
+ value = 0;
493
+ }
494
+
495
+ trace_npcm7xx_fiu_ctrl_read(DEVICE(s)->canonical_path, addr, value);
496
+
497
+ return value;
498
+}
499
+
500
+/* Send the specified number of address bytes from the UMA address register. */
501
+static void send_address(SSIBus *spi, unsigned int addsiz, uint32_t addr)
502
+{
503
+ switch (addsiz) {
504
+ case 4:
505
+ ssi_transfer(spi, extract32(addr, 24, 8));
506
+ /* fall through */
507
+ case 3:
508
+ ssi_transfer(spi, extract32(addr, 16, 8));
509
+ /* fall through */
510
+ case 2:
511
+ ssi_transfer(spi, extract32(addr, 8, 8));
512
+ /* fall through */
513
+ case 1:
514
+ ssi_transfer(spi, extract32(addr, 0, 8));
515
+ /* fall through */
516
+ case 0:
517
+ break;
518
+ }
519
+}
520
+
521
+/* Send the number of dummy bits specified in the UMA config register. */
522
+static void send_dummy_bits(SSIBus *spi, uint32_t uma_cfg, uint32_t uma_cmd)
523
+{
524
+ unsigned int bits_per_clock = 1U << FIU_UMA_CFG_DBPCK(uma_cfg);
525
+ unsigned int i;
526
+
527
+ for (i = 0; i < FIU_UMA_CFG_DBSIZ(uma_cfg); i++) {
528
+ /* Use bytes 0 and 1 first, then keep repeating byte 2 */
529
+ unsigned int field = (i < 2) ? ((i + 1) * 8) : 24;
530
+ unsigned int j;
531
+
532
+ for (j = 0; j < 8; j += bits_per_clock) {
533
+ ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock));
534
+ }
535
+ }
536
+}
537
+
538
+/* Perform a User-Mode Access transaction. */
539
+static void npcm7xx_fiu_uma_transaction(NPCM7xxFIUState *s)
540
+{
541
+ uint32_t uma_cts = s->regs[NPCM7XX_FIU_UMA_CTS];
542
+ uint32_t uma_cfg;
543
+ unsigned int i;
544
+
545
+ /* SW_CS means the CS is already forced low, so don't touch it. */
546
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
547
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
548
+ npcm7xx_fiu_select(s, cs_id);
549
+ }
550
+
551
+ /* Send command, if present. */
552
+ uma_cfg = s->regs[NPCM7XX_FIU_UMA_CFG];
553
+ if (FIU_UMA_CFG_CMDSIZ(uma_cfg) > 0) {
554
+ ssi_transfer(s->spi, extract32(s->regs[NPCM7XX_FIU_UMA_CMD], 0, 8));
555
+ }
556
+
557
+ /* Send address, if present. */
558
+ send_address(s->spi, FIU_UMA_CFG_ADDSIZ(uma_cfg),
559
+ s->regs[NPCM7XX_FIU_UMA_ADDR]);
560
+
561
+ /* Write data, if present. */
562
+ for (i = 0; i < FIU_UMA_CFG_WDATSIZ(uma_cfg); i++) {
563
+ unsigned int reg =
564
+ (i < 16) ? (NPCM7XX_FIU_UMA_DW0 + i / 4) : NPCM7XX_FIU_UMA_DW3;
565
+ unsigned int field = (i % 4) * 8;
566
+
567
+ ssi_transfer(s->spi, extract32(s->regs[reg], field, 8));
568
+ }
569
+
570
+ /* Send dummy bits, if present. */
571
+ send_dummy_bits(s->spi, uma_cfg, s->regs[NPCM7XX_FIU_UMA_CMD]);
572
+
573
+ /* Read data, if present. */
574
+ for (i = 0; i < FIU_UMA_CFG_RDATSIZ(uma_cfg); i++) {
575
+ unsigned int reg = NPCM7XX_FIU_UMA_DR0 + i / 4;
576
+ unsigned int field = (i % 4) * 8;
577
+ uint8_t c;
578
+
579
+ c = ssi_transfer(s->spi, 0);
580
+ if (reg <= NPCM7XX_FIU_UMA_DR3) {
581
+ s->regs[reg] = deposit32(s->regs[reg], field, 8, c);
582
+ }
583
+ }
584
+
585
+ /* Again, don't touch CS if the user is forcing it low. */
586
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
587
+ npcm7xx_fiu_deselect(s);
588
+ }
589
+
590
+ /* RDYST means a command has completed since it was cleared. */
591
+ s->regs[NPCM7XX_FIU_UMA_CTS] |= FIU_UMA_CTS_RDYST;
592
+ /* EXEC_DONE means Execute Command / Not Done, so clear it here. */
593
+ s->regs[NPCM7XX_FIU_UMA_CTS] &= ~FIU_UMA_CTS_EXEC_DONE;
594
+}
595
+
596
+/* Control register write handler. */
597
+static void npcm7xx_fiu_ctrl_write(void *opaque, hwaddr addr, uint64_t v,
598
+ unsigned int size)
599
+{
600
+ hwaddr reg = addr / sizeof(uint32_t);
601
+ NPCM7xxFIUState *s = opaque;
602
+ uint32_t value = v;
603
+
604
+ trace_npcm7xx_fiu_ctrl_write(DEVICE(s)->canonical_path, addr, value);
605
+
606
+ switch (reg) {
607
+ case NPCM7XX_FIU_UMA_CFG:
608
+ if (s->regs[reg] & FIU_UMA_CFG_CMMLCK) {
609
+ value &= ~FIU_UMA_CFG_CMMLCK_MASK;
610
+ value |= (s->regs[reg] & FIU_UMA_CFG_CMMLCK_MASK);
611
+ }
612
+ /* fall through */
613
+ case NPCM7XX_FIU_DRD_CFG:
614
+ case NPCM7XX_FIU_DWR_CFG:
615
+ if (s->regs[reg] & NPCM7XX_FIU_CFG_LCK) {
616
+ qemu_log_mask(LOG_GUEST_ERROR,
617
+ "%s: write to locked register @ 0x%" PRIx64 "\n",
618
+ DEVICE(s)->canonical_path, addr);
619
+ return;
620
+ }
621
+ s->regs[reg] = value;
622
+ break;
623
+
624
+ case NPCM7XX_FIU_UMA_CTS:
625
+ if (value & FIU_UMA_CTS_RDYST) {
626
+ value &= ~FIU_UMA_CTS_RDYST;
627
+ } else {
628
+ value |= s->regs[reg] & FIU_UMA_CTS_RDYST;
629
+ }
630
+ if ((s->regs[reg] ^ value) & FIU_UMA_CTS_SW_CS) {
631
+ if (value & FIU_UMA_CTS_SW_CS) {
632
+ /*
633
+ * Don't drop CS if there's a transfer in progress, or we're
634
+ * about to start one.
635
+ */
636
+ if (!((value | s->regs[reg]) & FIU_UMA_CTS_EXEC_DONE)) {
637
+ npcm7xx_fiu_deselect(s);
638
+ }
639
+ } else {
640
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
641
+ npcm7xx_fiu_select(s, cs_id);
642
+ }
643
+ }
644
+ s->regs[reg] = value | (s->regs[reg] & FIU_UMA_CTS_EXEC_DONE);
645
+ if (value & FIU_UMA_CTS_EXEC_DONE) {
646
+ npcm7xx_fiu_uma_transaction(s);
647
+ }
648
+ break;
649
+
650
+ case NPCM7XX_FIU_UMA_DR0 ... NPCM7XX_FIU_UMA_DR3:
651
+ qemu_log_mask(LOG_GUEST_ERROR,
652
+ "%s: write to read-only register @ 0x%" PRIx64 "\n",
653
+ DEVICE(s)->canonical_path, addr);
654
+ return;
655
+
656
+ case NPCM7XX_FIU_PRT_CFG:
657
+ case NPCM7XX_FIU_PRT_CMD0 ... NPCM7XX_FIU_PRT_CMD9:
658
+ qemu_log_mask(LOG_UNIMP, "%s: PRT is not implemented\n", __func__);
659
+ break;
660
+
661
+ case NPCM7XX_FIU_UMA_CMD:
662
+ case NPCM7XX_FIU_UMA_ADDR:
663
+ case NPCM7XX_FIU_UMA_DW0 ... NPCM7XX_FIU_UMA_DW3:
664
+ case NPCM7XX_FIU_CFG:
665
+ s->regs[reg] = value;
666
+ break;
667
+
668
+ default:
669
+ qemu_log_mask(LOG_GUEST_ERROR,
670
+ "%s: write to invalid offset 0x%" PRIx64 "\n",
671
+ DEVICE(s)->canonical_path, addr);
672
+ return;
673
+ }
674
+}
675
+
676
+static const MemoryRegionOps npcm7xx_fiu_ctrl_ops = {
677
+ .read = npcm7xx_fiu_ctrl_read,
678
+ .write = npcm7xx_fiu_ctrl_write,
679
+ .endianness = DEVICE_LITTLE_ENDIAN,
680
+ .valid = {
681
+ .min_access_size = 4,
682
+ .max_access_size = 4,
683
+ .unaligned = false,
684
+ },
685
+};
686
+
687
+static void npcm7xx_fiu_enter_reset(Object *obj, ResetType type)
688
+{
689
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
690
+
691
+ trace_npcm7xx_fiu_enter_reset(DEVICE(obj)->canonical_path, type);
692
+
693
+ memset(s->regs, 0, sizeof(s->regs));
694
+
695
+ s->regs[NPCM7XX_FIU_DRD_CFG] = 0x0300100b;
696
+ s->regs[NPCM7XX_FIU_DWR_CFG] = 0x03000002;
697
+ s->regs[NPCM7XX_FIU_UMA_CFG] = 0x00000400;
698
+ s->regs[NPCM7XX_FIU_UMA_CTS] = 0x00010000;
699
+ s->regs[NPCM7XX_FIU_UMA_CMD] = 0x0000000b;
700
+ s->regs[NPCM7XX_FIU_PRT_CFG] = 0x00000400;
701
+ s->regs[NPCM7XX_FIU_CFG] = 0x0000000b;
702
+}
703
+
704
+static void npcm7xx_fiu_hold_reset(Object *obj)
705
+{
706
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
707
+ int i;
708
+
709
+ trace_npcm7xx_fiu_hold_reset(DEVICE(obj)->canonical_path);
710
+
711
+ for (i = 0; i < s->cs_count; i++) {
712
+ qemu_irq_raise(s->cs_lines[i]);
713
+ }
714
+}
715
+
716
+static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
717
+{
718
+ NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
719
+ SysBusDevice *sbd = &s->parent;
720
+ int i;
721
+
722
+ if (s->cs_count <= 0) {
723
+ error_setg(errp, "%s: %d chip selects specified, need at least one",
724
+ dev->canonical_path, s->cs_count);
725
+ return;
726
+ }
727
+
728
+ s->spi = ssi_create_bus(dev, "spi");
729
+ s->cs_lines = g_new0(qemu_irq, s->cs_count);
730
+ qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", s->cs_count);
731
+ s->flash = g_new0(NPCM7xxFIUFlash, s->cs_count);
732
+
733
+ /*
734
+ * Register the control registers region first. It may be followed by one
735
+ * or more direct flash access regions.
736
+ */
737
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_fiu_ctrl_ops, s, "ctrl",
738
+ NPCM7XX_FIU_CTRL_REGS_SIZE);
739
+ sysbus_init_mmio(sbd, &s->mmio);
740
+
741
+ for (i = 0; i < s->cs_count; i++) {
742
+ NPCM7xxFIUFlash *flash = &s->flash[i];
743
+ flash->fiu = s;
744
+ memory_region_init_io(&flash->direct_access, OBJECT(s),
745
+ &npcm7xx_fiu_flash_ops, &s->flash[i], "flash",
746
+ NPCM7XX_FIU_FLASH_WINDOW_SIZE);
747
+ sysbus_init_mmio(sbd, &flash->direct_access);
748
+ }
749
+}
750
+
751
+static const VMStateDescription vmstate_npcm7xx_fiu = {
752
+ .name = "npcm7xx-fiu",
753
+ .version_id = 0,
754
+ .minimum_version_id = 0,
755
+ .fields = (VMStateField[]) {
756
+ VMSTATE_INT32(active_cs, NPCM7xxFIUState),
757
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxFIUState, NPCM7XX_FIU_NR_REGS),
758
+ VMSTATE_END_OF_LIST(),
759
+ },
760
+};
761
+
762
+static Property npcm7xx_fiu_properties[] = {
763
+ DEFINE_PROP_INT32("cs-count", NPCM7xxFIUState, cs_count, 0),
764
+ DEFINE_PROP_END_OF_LIST(),
765
+};
766
+
767
+static void npcm7xx_fiu_class_init(ObjectClass *klass, void *data)
768
+{
769
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
770
+ DeviceClass *dc = DEVICE_CLASS(klass);
771
+
772
+ QEMU_BUILD_BUG_ON(NPCM7XX_FIU_REGS_END > NPCM7XX_FIU_NR_REGS);
773
+
774
+ dc->desc = "NPCM7xx Flash Interface Unit";
775
+ dc->realize = npcm7xx_fiu_realize;
776
+ dc->vmsd = &vmstate_npcm7xx_fiu;
777
+ rc->phases.enter = npcm7xx_fiu_enter_reset;
778
+ rc->phases.hold = npcm7xx_fiu_hold_reset;
779
+ device_class_set_props(dc, npcm7xx_fiu_properties);
780
+}
781
+
782
+static const TypeInfo npcm7xx_fiu_types[] = {
783
+ {
784
+ .name = TYPE_NPCM7XX_FIU,
785
+ .parent = TYPE_SYS_BUS_DEVICE,
786
+ .instance_size = sizeof(NPCM7xxFIUState),
787
+ .class_init = npcm7xx_fiu_class_init,
788
+ },
789
+};
790
+DEFINE_TYPES(npcm7xx_fiu_types);
791
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
792
index XXXXXXX..XXXXXXX 100644
793
--- a/hw/arm/Kconfig
794
+++ b/hw/arm/Kconfig
795
@@ -XXX,XX +XXX,XX @@ config NPCM7XX
796
select ARM_GIC
797
select PL310 # cache controller
798
select SERIAL
799
+ select SSI
800
select UNIMP
801
802
config FSL_IMX25
803
diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build
804
index XXXXXXX..XXXXXXX 100644
805
--- a/hw/ssi/meson.build
806
+++ b/hw/ssi/meson.build
807
@@ -XXX,XX +XXX,XX @@
808
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_smc.c'))
809
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-spi.c'))
810
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_fiu.c'))
811
softmmu_ss.add(when: 'CONFIG_PL022', if_true: files('pl022.c'))
812
softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c'))
813
softmmu_ss.add(when: 'CONFIG_STM32F2XX_SPI', if_true: files('stm32f2xx_spi.c'))
814
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
815
index XXXXXXX..XXXXXXX 100644
816
--- a/hw/ssi/trace-events
817
+++ b/hw/ssi/trace-events
818
@@ -XXX,XX +XXX,XX @@ aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
819
aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x"
820
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
821
aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
822
+
823
+# npcm7xx_fiu.c
824
+
825
+npcm7xx_fiu_enter_reset(const char *id, int reset_type) "%s reset type: %d"
826
+npcm7xx_fiu_hold_reset(const char *id) "%s"
827
+npcm7xx_fiu_select(const char *id, int cs) "%s select CS%d"
828
+npcm7xx_fiu_deselect(const char *id, int cs) "%s deselect CS%d"
829
+npcm7xx_fiu_ctrl_read(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
830
+npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
831
+npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
832
+npcm7xx_fiu_flash_write(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
833
--
73
--
834
2.20.1
74
2.34.1
835
75
836
76
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Per the datasheet (DDI0407 r2p0):
3
Assign the pointer return value to 'a' directly,
4
rather than going through an intermediary index.
4
5
5
"All SCU registers are byte accessible" and are 32-bit aligned.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Set MemoryRegionOps::valid min/max fields and simplify the write()
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
8
handler.
9
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200901144100.116742-3-f4bug@amsat.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
hw/misc/a9scu.c | 21 +++++----------------
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
16
1 file changed, 5 insertions(+), 16 deletions(-)
12
1 file changed, 10 insertions(+), 22 deletions(-)
17
13
18
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/a9scu.c
16
--- a/fpu/softfloat-parts.c.inc
21
+++ b/hw/misc/a9scu.c
17
+++ b/fpu/softfloat-parts.c.inc
22
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
23
uint64_t value, unsigned size)
19
FloatPartsN *c, float_status *s,
20
int ab_mask, int abc_mask)
24
{
21
{
25
A9SCUState *s = (A9SCUState *)opaque;
22
- int which;
26
- uint32_t mask;
23
bool infzero = (ab_mask == float_cmask_infzero);
27
+ uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
24
bool have_snan = (abc_mask & float_cmask_snan);
28
uint32_t shift;
25
+ FloatPartsN *ret;
29
- switch (size) {
26
27
if (unlikely(have_snan)) {
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
default:
31
g_assert_not_reached();
32
}
33
- which = 2;
34
+ ret = c;
35
} else {
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
37
+ FloatPartsN *val[3] = { a, b, c };
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
40
assert(rule != float_3nan_prop_none);
41
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
42
/* We have at least one SNaN input and should prefer it */
43
do {
44
- which = rule & R_3NAN_1ST_MASK;
45
+ ret = val[rule & R_3NAN_1ST_MASK];
46
rule >>= R_3NAN_1ST_LENGTH;
47
- } while (!is_snan(cls[which]));
48
+ } while (!is_snan(ret->cls));
49
} else {
50
do {
51
- which = rule & R_3NAN_1ST_MASK;
52
+ ret = val[rule & R_3NAN_1ST_MASK];
53
rule >>= R_3NAN_1ST_LENGTH;
54
- } while (!is_nan(cls[which]));
55
+ } while (!is_nan(ret->cls));
56
}
57
}
58
59
- switch (which) {
60
- case 0:
61
- break;
30
- case 1:
62
- case 1:
31
- mask = 0xff;
63
- a = b;
32
- break;
64
- break;
33
- case 2:
65
- case 2:
34
- mask = 0xffff;
66
- a = c;
35
- break;
36
- case 4:
37
- mask = 0xffffffff;
38
- break;
67
- break;
39
- default:
68
- default:
40
- fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
69
- g_assert_not_reached();
41
- size, (unsigned)offset);
70
+ if (is_snan(ret->cls)) {
42
- return;
71
+ parts_silence_nan(ret, s);
72
}
73
- if (is_snan(a->cls)) {
74
- parts_silence_nan(a, s);
43
- }
75
- }
44
76
- return a;
45
switch (offset) {
77
+ return ret;
46
case 0x00: /* Control */
78
47
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
79
default_nan:
48
static const MemoryRegionOps a9_scu_ops = {
80
parts_default_nan(a, s);
49
.read = a9_scu_read,
50
.write = a9_scu_write,
51
+ .valid = {
52
+ .min_access_size = 1,
53
+ .max_access_size = 4,
54
+ },
55
.endianness = DEVICE_NATIVE_ENDIAN,
56
};
57
58
--
81
--
59
2.20.1
82
2.34.1
60
83
61
84
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Correct the GEMs tx/rx clocks to use the 125Mhz fixed-clock.
3
While all indices into val[] should be in [0-2], the mask
4
This matches the setup with the fixed-link 100Mbit PHY.
4
applied is two bits. To help static analysis see there is
5
It also avoids the following warnings from the Linux kernel
5
no possibility of read beyond the end of the array, pad the
6
driver:
6
array to 4 entries, with the final being (implicitly) NULL.
7
7
8
eth0: unable to generate target frequency: 125000000 Hz
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
11
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
13
Message-id: 20200909174647.662864-2-edgar.iglesias@gmail.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
12
---
16
hw/arm/xlnx-versal-virt.c | 2 +-
13
fpu/softfloat-parts.c.inc | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
18
15
19
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/xlnx-versal-virt.c
18
--- a/fpu/softfloat-parts.c.inc
22
+++ b/hw/arm/xlnx-versal-virt.c
19
+++ b/fpu/softfloat-parts.c.inc
23
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gem_nodes(VersalVirt *s)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
24
s->phandle.ethernet_phy[i]);
21
}
25
qemu_fdt_setprop_cells(s->fdt, name, "clocks",
22
ret = c;
26
s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
23
} else {
27
- s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
24
- FloatPartsN *val[3] = { a, b, c };
28
+ s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
29
qemu_fdt_setprop(s->fdt, name, "clock-names",
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
30
clocknames, sizeof(clocknames));
27
31
qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
28
assert(rule != float_3nan_prop_none);
32
--
29
--
33
2.20.1
30
2.34.1
34
31
35
32
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
3
This function is part of the public interface and
4
implementation. Bus connection and socketCAN connection for each CAN module
4
is not "specialized" to any target in any way.
5
can be set through command lines.
6
5
7
Example for using single CAN:
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
-object can-bus,id=canbus0 \
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
-machine xlnx-zcu102.canbus0=canbus0 \
8
Message-id: 20241203203949.483774-7-richard.henderson@linaro.org
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
11
12
Example for connecting both CAN to same virtual CAN on host machine:
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
24
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Message-id: 1597278668-339715-2-git-send-email-fnu.vikram@xilinx.com
26
[PMM: updated to meson build system]
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
10
---
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
30
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
31
hw/net/can/meson.build | 1 +
13
2 files changed, 52 insertions(+), 52 deletions(-)
32
3 files changed, 1244 insertions(+)
33
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
34
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
35
14
36
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
37
new file mode 100644
16
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX
17
--- a/fpu/softfloat.c
39
--- /dev/null
18
+++ b/fpu/softfloat.c
40
+++ b/include/hw/net/xlnx-zynqmp-can.h
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
41
@@ -XXX,XX +XXX,XX @@
20
*zExpPtr = 1 - shiftCount;
42
+/*
21
}
43
+ * QEMU model of the Xilinx ZynqMP CAN controller.
22
44
+ *
23
+/*----------------------------------------------------------------------------
45
+ * Copyright (c) 2020 Xilinx Inc.
24
+| Takes two extended double-precision floating-point values `a' and `b', one
46
+ *
25
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
47
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
26
+| `b' is a signaling NaN, the invalid exception is raised.
48
+ *
27
+*----------------------------------------------------------------------------*/
49
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
50
+ * Pavel Pisa.
51
+ *
52
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
53
+ * of this software and associated documentation files (the "Software"), to deal
54
+ * in the Software without restriction, including without limitation the rights
55
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56
+ * copies of the Software, and to permit persons to whom the Software is
57
+ * furnished to do so, subject to the following conditions:
58
+ *
59
+ * The above copyright notice and this permission notice shall be included in
60
+ * all copies or substantial portions of the Software.
61
+ *
62
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
65
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68
+ * THE SOFTWARE.
69
+ */
70
+
28
+
71
+#ifndef XLNX_ZYNQMP_CAN_H
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
72
+#define XLNX_ZYNQMP_CAN_H
30
+{
31
+ bool aIsLargerSignificand;
32
+ FloatClass a_cls, b_cls;
73
+
33
+
74
+#include "hw/register.h"
34
+ /* This is not complete, but is good enough for pickNaN. */
75
+#include "net/can_emu.h"
35
+ a_cls = (!floatx80_is_any_nan(a)
76
+#include "net/can_host.h"
36
+ ? float_class_normal
77
+#include "qemu/fifo32.h"
37
+ : floatx80_is_signaling_nan(a, status)
78
+#include "hw/ptimer.h"
38
+ ? float_class_snan
79
+#include "hw/qdev-clock.h"
39
+ : float_class_qnan);
40
+ b_cls = (!floatx80_is_any_nan(b)
41
+ ? float_class_normal
42
+ : floatx80_is_signaling_nan(b, status)
43
+ ? float_class_snan
44
+ : float_class_qnan);
80
+
45
+
81
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
82
+
47
+ float_raise(float_flag_invalid, status);
83
+#define XLNX_ZYNQMP_CAN(obj) \
84
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
85
+
86
+#define MAX_CAN_CTRLS 2
87
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
88
+#define MAILBOX_CAPACITY 64
89
+#define CAN_TIMER_MAX 0XFFFFUL
90
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
91
+
92
+/* Each CAN_FRAME will have 4 * 32bit size. */
93
+#define CAN_FRAME_SIZE 4
94
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
95
+
96
+typedef struct XlnxZynqMPCANState {
97
+ SysBusDevice parent_obj;
98
+ MemoryRegion iomem;
99
+
100
+ qemu_irq irq;
101
+
102
+ CanBusClientState bus_client;
103
+ CanBusState *canbus;
104
+
105
+ struct {
106
+ uint32_t ext_clk_freq;
107
+ } cfg;
108
+
109
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
110
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
111
+
112
+ Fifo32 rx_fifo;
113
+ Fifo32 tx_fifo;
114
+ Fifo32 txhpb_fifo;
115
+
116
+ ptimer_state *can_timer;
117
+} XlnxZynqMPCANState;
118
+
119
+#endif
120
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
121
new file mode 100644
122
index XXXXXXX..XXXXXXX
123
--- /dev/null
124
+++ b/hw/net/can/xlnx-zynqmp-can.c
125
@@ -XXX,XX +XXX,XX @@
126
+/*
127
+ * QEMU model of the Xilinx ZynqMP CAN controller.
128
+ * This implementation is based on the following datasheet:
129
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
130
+ *
131
+ * Copyright (c) 2020 Xilinx Inc.
132
+ *
133
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
134
+ *
135
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
136
+ * Pavel Pisa
137
+ *
138
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
139
+ * of this software and associated documentation files (the "Software"), to deal
140
+ * in the Software without restriction, including without limitation the rights
141
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
142
+ * copies of the Software, and to permit persons to whom the Software is
143
+ * furnished to do so, subject to the following conditions:
144
+ *
145
+ * The above copyright notice and this permission notice shall be included in
146
+ * all copies or substantial portions of the Software.
147
+ *
148
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
149
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
151
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
152
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
153
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
154
+ * THE SOFTWARE.
155
+ */
156
+
157
+#include "qemu/osdep.h"
158
+#include "hw/sysbus.h"
159
+#include "hw/register.h"
160
+#include "hw/irq.h"
161
+#include "qapi/error.h"
162
+#include "qemu/bitops.h"
163
+#include "qemu/log.h"
164
+#include "qemu/cutils.h"
165
+#include "sysemu/sysemu.h"
166
+#include "migration/vmstate.h"
167
+#include "hw/qdev-properties.h"
168
+#include "net/can_emu.h"
169
+#include "net/can_host.h"
170
+#include "qemu/event_notifier.h"
171
+#include "qom/object_interfaces.h"
172
+#include "hw/net/xlnx-zynqmp-can.h"
173
+
174
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
175
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
176
+#endif
177
+
178
+#define DB_PRINT(dev, ...) do { \
179
+ if (XLNX_ZYNQMP_CAN_ERR_DEBUG) { \
180
+ g_autofree char *path = object_get_canonical_path(OBJECT(dev)); \
181
+ qemu_log("%s: %s", path, ## __VA_ARGS__); \
182
+ } \
183
+} while (0)
184
+
185
+#define MAX_DLC 8
186
+#undef ERROR
187
+
188
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
189
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
190
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
191
+REG32(MODE_SELECT_REGISTER, 0x4)
192
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
193
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
194
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
195
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
196
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
197
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
198
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
199
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
200
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
201
+REG32(ERROR_COUNTER_REGISTER, 0x10)
202
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
203
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
204
+REG32(ERROR_STATUS_REGISTER, 0x14)
205
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
206
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
207
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
208
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
209
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
210
+REG32(STATUS_REGISTER, 0x18)
211
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
212
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
213
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
214
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
215
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
216
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
217
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
218
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
219
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
220
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
221
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
222
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
223
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
224
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
225
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
226
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
227
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
228
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
229
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
230
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
231
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
232
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
233
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
234
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
235
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
236
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
237
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
238
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
239
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
240
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
241
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
242
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
243
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
244
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
245
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
246
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
247
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
248
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
249
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
250
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
251
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
252
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
253
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
254
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
255
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
256
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
257
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
258
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
259
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
260
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
261
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
262
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
263
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
264
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
265
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
266
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
267
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
268
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
269
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
270
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
271
+REG32(TIMESTAMP_REGISTER, 0x28)
272
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
273
+REG32(WIR, 0x2c)
274
+ FIELD(WIR, EW, 8, 8)
275
+ FIELD(WIR, FW, 0, 8)
276
+REG32(TXFIFO_ID, 0x30)
277
+ FIELD(TXFIFO_ID, IDH, 21, 11)
278
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
279
+ FIELD(TXFIFO_ID, IDE, 19, 1)
280
+ FIELD(TXFIFO_ID, IDL, 1, 18)
281
+ FIELD(TXFIFO_ID, RTR, 0, 1)
282
+REG32(TXFIFO_DLC, 0x34)
283
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
284
+REG32(TXFIFO_DATA1, 0x38)
285
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
286
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
287
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
288
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
289
+REG32(TXFIFO_DATA2, 0x3c)
290
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
291
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
292
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
293
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
294
+REG32(TXHPB_ID, 0x40)
295
+ FIELD(TXHPB_ID, IDH, 21, 11)
296
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
297
+ FIELD(TXHPB_ID, IDE, 19, 1)
298
+ FIELD(TXHPB_ID, IDL, 1, 18)
299
+ FIELD(TXHPB_ID, RTR, 0, 1)
300
+REG32(TXHPB_DLC, 0x44)
301
+ FIELD(TXHPB_DLC, DLC, 28, 4)
302
+REG32(TXHPB_DATA1, 0x48)
303
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
304
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
305
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
306
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
307
+REG32(TXHPB_DATA2, 0x4c)
308
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
309
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
310
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
311
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
312
+REG32(RXFIFO_ID, 0x50)
313
+ FIELD(RXFIFO_ID, IDH, 21, 11)
314
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
315
+ FIELD(RXFIFO_ID, IDE, 19, 1)
316
+ FIELD(RXFIFO_ID, IDL, 1, 18)
317
+ FIELD(RXFIFO_ID, RTR, 0, 1)
318
+REG32(RXFIFO_DLC, 0x54)
319
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
320
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
321
+REG32(RXFIFO_DATA1, 0x58)
322
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
323
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
324
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
325
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
326
+REG32(RXFIFO_DATA2, 0x5c)
327
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
328
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
329
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
330
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
331
+REG32(AFR, 0x60)
332
+ FIELD(AFR, UAF4, 3, 1)
333
+ FIELD(AFR, UAF3, 2, 1)
334
+ FIELD(AFR, UAF2, 1, 1)
335
+ FIELD(AFR, UAF1, 0, 1)
336
+REG32(AFMR1, 0x64)
337
+ FIELD(AFMR1, AMIDH, 21, 11)
338
+ FIELD(AFMR1, AMSRR, 20, 1)
339
+ FIELD(AFMR1, AMIDE, 19, 1)
340
+ FIELD(AFMR1, AMIDL, 1, 18)
341
+ FIELD(AFMR1, AMRTR, 0, 1)
342
+REG32(AFIR1, 0x68)
343
+ FIELD(AFIR1, AIIDH, 21, 11)
344
+ FIELD(AFIR1, AISRR, 20, 1)
345
+ FIELD(AFIR1, AIIDE, 19, 1)
346
+ FIELD(AFIR1, AIIDL, 1, 18)
347
+ FIELD(AFIR1, AIRTR, 0, 1)
348
+REG32(AFMR2, 0x6c)
349
+ FIELD(AFMR2, AMIDH, 21, 11)
350
+ FIELD(AFMR2, AMSRR, 20, 1)
351
+ FIELD(AFMR2, AMIDE, 19, 1)
352
+ FIELD(AFMR2, AMIDL, 1, 18)
353
+ FIELD(AFMR2, AMRTR, 0, 1)
354
+REG32(AFIR2, 0x70)
355
+ FIELD(AFIR2, AIIDH, 21, 11)
356
+ FIELD(AFIR2, AISRR, 20, 1)
357
+ FIELD(AFIR2, AIIDE, 19, 1)
358
+ FIELD(AFIR2, AIIDL, 1, 18)
359
+ FIELD(AFIR2, AIRTR, 0, 1)
360
+REG32(AFMR3, 0x74)
361
+ FIELD(AFMR3, AMIDH, 21, 11)
362
+ FIELD(AFMR3, AMSRR, 20, 1)
363
+ FIELD(AFMR3, AMIDE, 19, 1)
364
+ FIELD(AFMR3, AMIDL, 1, 18)
365
+ FIELD(AFMR3, AMRTR, 0, 1)
366
+REG32(AFIR3, 0x78)
367
+ FIELD(AFIR3, AIIDH, 21, 11)
368
+ FIELD(AFIR3, AISRR, 20, 1)
369
+ FIELD(AFIR3, AIIDE, 19, 1)
370
+ FIELD(AFIR3, AIIDL, 1, 18)
371
+ FIELD(AFIR3, AIRTR, 0, 1)
372
+REG32(AFMR4, 0x7c)
373
+ FIELD(AFMR4, AMIDH, 21, 11)
374
+ FIELD(AFMR4, AMSRR, 20, 1)
375
+ FIELD(AFMR4, AMIDE, 19, 1)
376
+ FIELD(AFMR4, AMIDL, 1, 18)
377
+ FIELD(AFMR4, AMRTR, 0, 1)
378
+REG32(AFIR4, 0x80)
379
+ FIELD(AFIR4, AIIDH, 21, 11)
380
+ FIELD(AFIR4, AISRR, 20, 1)
381
+ FIELD(AFIR4, AIIDE, 19, 1)
382
+ FIELD(AFIR4, AIIDL, 1, 18)
383
+ FIELD(AFIR4, AIRTR, 0, 1)
384
+
385
+static void can_update_irq(XlnxZynqMPCANState *s)
386
+{
387
+ uint32_t irq;
388
+
389
+ /* Watermark register interrupts. */
390
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
391
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
392
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
393
+ }
48
+ }
394
+
49
+
395
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
50
+ if (status->default_nan_mode) {
396
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
51
+ return floatx80_default_nan(status);
397
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
398
+ }
52
+ }
399
+
53
+
400
+ /* RX Interrupts. */
54
+ if (a.low < b.low) {
401
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
55
+ aIsLargerSignificand = 0;
402
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
56
+ } else if (b.low < a.low) {
57
+ aIsLargerSignificand = 1;
58
+ } else {
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
403
+ }
60
+ }
404
+
61
+
405
+ /* TX interrupts. */
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
406
+ if (fifo32_is_empty(&s->tx_fifo)) {
63
+ if (is_snan(b_cls)) {
407
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
64
+ return floatx80_silence_nan(b, status);
408
+ }
65
+ }
409
+
66
+ return b;
410
+ if (fifo32_is_full(&s->tx_fifo)) {
411
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
412
+ }
413
+
414
+ if (fifo32_is_full(&s->txhpb_fifo)) {
415
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
416
+ }
417
+
418
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
419
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
420
+
421
+ qemu_set_irq(s->irq, irq);
422
+}
423
+
424
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val64)
425
+{
426
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
427
+
428
+ can_update_irq(s);
429
+}
430
+
431
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val64)
432
+{
433
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
434
+ uint32_t val = val64;
435
+
436
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
437
+ can_update_irq(s);
438
+
439
+ return 0;
440
+}
441
+
442
+static void can_config_reset(XlnxZynqMPCANState *s)
443
+{
444
+ /* Reset all the configuration registers. */
445
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
446
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
447
+ register_reset(
448
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
449
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
450
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
451
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
452
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
453
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
454
+ register_reset(&s->reg_info[R_WIR]);
455
+}
456
+
457
+static void can_config_mode(XlnxZynqMPCANState *s)
458
+{
459
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
460
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
461
+
462
+ /* Put XlnxZynqMPCAN in configuration mode. */
463
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
464
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
465
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
466
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
467
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
468
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
469
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
470
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
471
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
472
+
473
+ can_update_irq(s);
474
+}
475
+
476
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
477
+{
478
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
479
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
480
+ /* Wake up interrupt bit. */
481
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
482
+ /* Sleep interrupt bit. */
483
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
484
+
485
+ /* Clear previous core mode status bits. */
486
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
487
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
488
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
489
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
490
+
491
+ /* set current mode bit and generate irqs accordingly. */
492
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
493
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
494
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
495
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
496
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
497
+ sleep_irq_val);
498
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
499
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
500
+ } else {
67
+ } else {
501
+ /*
68
+ if (is_snan(a_cls)) {
502
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
69
+ return floatx80_silence_nan(a, status);
503
+ */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
505
+ /* Set wakeup interrupt bit. */
506
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
507
+ wakeup_irq_val);
508
+ }
509
+
510
+ can_update_irq(s);
511
+}
512
+
513
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
514
+{
515
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
516
+ update_status_register_mode_bits(s);
517
+}
518
+
519
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
520
+{
521
+ frame->can_id = data[0];
522
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
523
+
524
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
525
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
526
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
527
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
528
+
529
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
530
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
531
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
532
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
533
+}
534
+
535
+static bool tx_ready_check(XlnxZynqMPCANState *s)
536
+{
537
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
538
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
539
+
540
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
541
+ " data while controller is in reset mode.\n",
542
+ path);
543
+ return false;
544
+ }
545
+
546
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
547
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
548
+
549
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
550
+ " data while controller is in configuration mode. Reset"
551
+ " the core so operations can start fresh.\n",
552
+ path);
553
+ return false;
554
+ }
555
+
556
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
557
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
558
+
559
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
560
+ " data while controller is in SNOOP MODE.\n",
561
+ path);
562
+ return false;
563
+ }
564
+
565
+ return true;
566
+}
567
+
568
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
569
+{
570
+ qemu_can_frame frame;
571
+ uint32_t data[CAN_FRAME_SIZE];
572
+ int i;
573
+ bool can_tx = tx_ready_check(s);
574
+
575
+ if (can_tx) {
576
+ while (!fifo32_is_empty(fifo)) {
577
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
578
+ data[i] = fifo32_pop(fifo);
579
+ }
580
+
581
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
582
+ /*
583
+ * Controller is in loopback. In Loopback mode, the CAN core
584
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
585
+ * Any message transmitted is looped back to the RX line and
586
+ * acknowledged. The XlnxZynqMPCAN core receives any message
587
+ * that it transmits.
588
+ */
589
+ if (fifo32_is_full(&s->rx_fifo)) {
590
+ DB_PRINT(s, "Loopback: RX FIFO is full."
591
+ " TX FIFO will be flushed.\n");
592
+
593
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
594
+ RXOFLW, 1);
595
+ } else {
596
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
597
+ fifo32_push(&s->rx_fifo, data[i]);
598
+ }
599
+
600
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
601
+ RXOK, 1);
602
+ }
603
+ } else {
604
+ /* Normal mode Tx. */
605
+ generate_frame(&frame, data);
606
+
607
+ can_bus_client_send(&s->bus_client, &frame, 1);
608
+ }
609
+ }
70
+ }
610
+
71
+ return a;
611
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
612
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
613
+
614
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
615
+ can_exit_sleep_mode(s);
616
+ }
617
+ } else {
618
+ DB_PRINT(s, "Not enabled for data transfer.\n");
619
+ }
620
+
621
+ can_update_irq(s);
622
+}
623
+
624
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val64)
625
+{
626
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
627
+ uint32_t val = val64;
628
+
629
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
630
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
631
+
632
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
633
+ DB_PRINT(s, "Resetting controller.\n");
634
+
635
+ /* First, core will do software reset then will enter in config mode. */
636
+ can_config_reset(s);
637
+ }
638
+
639
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
640
+ can_config_mode(s);
641
+ } else {
642
+ /*
643
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
644
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
645
+ * register states.
646
+ */
647
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
648
+
649
+ ptimer_transaction_begin(s->can_timer);
650
+ ptimer_set_count(s->can_timer, 0);
651
+ ptimer_transaction_commit(s->can_timer);
652
+
653
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
654
+ transfer_fifo(s, &s->txhpb_fifo);
655
+ transfer_fifo(s, &s->tx_fifo);
656
+ }
657
+
658
+ update_status_register_mode_bits(s);
659
+
660
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
661
+}
662
+
663
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val64)
664
+{
665
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
666
+ uint32_t val = val64;
667
+ uint8_t multi_mode;
668
+
669
+ /*
670
+ * Multiple mode set check. This is done to make sure user doesn't set
671
+ * multiple modes.
672
+ */
673
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
674
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
675
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
676
+
677
+ if (multi_mode > 1) {
678
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
679
+
680
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
681
+ " several modes simultaneously. One mode will be selected"
682
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
683
+ path);
684
+ }
685
+
686
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
687
+ /* We are in configuration mode, any mode can be selected. */
688
+ s->regs[R_MODE_SELECT_REGISTER] = val;
689
+ } else {
690
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
691
+
692
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
693
+
694
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
695
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
696
+
697
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
698
+ " LBACK mode without setting CEN bit as 0.\n",
699
+ path);
700
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
701
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
702
+
703
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
704
+ " SNOOP mode without setting CEN bit as 0.\n",
705
+ path);
706
+ }
707
+
708
+ update_status_register_mode_bits(s);
709
+ }
710
+
711
+ return s->regs[R_MODE_SELECT_REGISTER];
712
+}
713
+
714
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val64)
715
+{
716
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
717
+ uint32_t val = val64;
718
+
719
+ /* Only allow writes when in config mode. */
720
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
721
+ val = s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
722
+ }
723
+
724
+ return val;
725
+}
726
+
727
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val64)
728
+{
729
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
730
+ uint32_t val = val64;
731
+
732
+ /* Only allow writes when in config mode. */
733
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
734
+ val = s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
735
+ }
736
+
737
+ return val;
738
+}
739
+
740
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val64)
741
+{
742
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
743
+ uint32_t val = val64;
744
+
745
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
746
+ ptimer_transaction_begin(s->can_timer);
747
+ ptimer_set_count(s->can_timer, 0);
748
+ ptimer_transaction_commit(s->can_timer);
749
+ }
750
+
751
+ return 0;
752
+}
753
+
754
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
755
+{
756
+ bool filter_pass = false;
757
+ uint16_t timestamp = 0;
758
+
759
+ /* If no filter is enabled. Message will be stored in FIFO. */
760
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
761
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
762
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
763
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
764
+ filter_pass = true;
765
+ }
766
+
767
+ /*
768
+ * Messages that pass any of the acceptance filters will be stored in
769
+ * the RX FIFO.
770
+ */
771
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
772
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
773
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
774
+
775
+ if (filter_id_masked == id_masked) {
776
+ filter_pass = true;
777
+ }
778
+ }
779
+
780
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
781
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
782
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
783
+
784
+ if (filter_id_masked == id_masked) {
785
+ filter_pass = true;
786
+ }
787
+ }
788
+
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
790
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
799
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ /* Store the message in fifo if it passed through any of the filters. */
808
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
809
+
810
+ if (fifo32_is_full(&s->rx_fifo)) {
811
+ DB_PRINT(s, "RX FIFO is full.\n");
812
+
813
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
814
+ } else {
815
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
816
+
817
+ fifo32_push(&s->rx_fifo, frame->can_id);
818
+
819
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
820
+ R_RXFIFO_DLC_DLC_LENGTH,
821
+ frame->can_dlc) |
822
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
823
+ R_RXFIFO_DLC_RXT_LENGTH,
824
+ timestamp));
825
+
826
+ /* First 32 bit of the data. */
827
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
828
+ R_TXFIFO_DATA1_DB3_LENGTH,
829
+ frame->data[0]) |
830
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
831
+ R_TXFIFO_DATA1_DB2_LENGTH,
832
+ frame->data[1]) |
833
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
834
+ R_TXFIFO_DATA1_DB1_LENGTH,
835
+ frame->data[2]) |
836
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
837
+ R_TXFIFO_DATA1_DB0_LENGTH,
838
+ frame->data[3]));
839
+ /* Last 32 bit of the data. */
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
841
+ R_TXFIFO_DATA2_DB7_LENGTH,
842
+ frame->data[4]) |
843
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
844
+ R_TXFIFO_DATA2_DB6_LENGTH,
845
+ frame->data[5]) |
846
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
847
+ R_TXFIFO_DATA2_DB5_LENGTH,
848
+ frame->data[6]) |
849
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
850
+ R_TXFIFO_DATA2_DB4_LENGTH,
851
+ frame->data[7]));
852
+
853
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
854
+ }
855
+
856
+ can_update_irq(s);
857
+ } else {
858
+ DB_PRINT(s, "Message didn't pass through any filter or dlc"
859
+ " is not in range.\n");
860
+ }
72
+ }
861
+}
73
+}
862
+
74
+
863
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val64)
75
/*----------------------------------------------------------------------------
864
+{
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
865
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
866
+ uint32_t r = 0;
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
867
+
868
+ if (!fifo32_is_empty(&s->rx_fifo)) {
869
+ r = fifo32_pop(&s->rx_fifo);
870
+ } else {
871
+ DB_PRINT(s, "No message in RXFIFO.\n");
872
+
873
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
874
+ }
875
+
876
+ can_update_irq(s);
877
+ return r;
878
+}
879
+
880
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val64)
881
+{
882
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
883
+
884
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
885
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
886
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
887
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
888
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
889
+ } else {
890
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
891
+ }
892
+}
893
+
894
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val64)
895
+{
896
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
897
+ uint32_t reg_idx = (reg->access->addr) / 4;
898
+ uint32_t val = val64;
899
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
900
+
901
+ /* modify an acceptance filter, the corresponding UAF bit should be '0.' */
902
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
903
+ s->regs[reg_idx] = val;
904
+ } else {
905
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
906
+
907
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
908
+ " mask is not set as corresponding UAF bit is not 0.\n",
909
+ path, filter_number + 1);
910
+ }
911
+
912
+ return s->regs[reg_idx];
913
+}
914
+
915
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val64)
916
+{
917
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
918
+ uint32_t reg_idx = (reg->access->addr) / 4;
919
+ uint32_t val = val64;
920
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
921
+
922
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
923
+ s->regs[reg_idx] = val;
924
+ } else {
925
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
926
+
927
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
928
+ " id is not set as corresponding UAF bit is not 0.\n",
929
+ path, filter_number + 1);
930
+ }
931
+
932
+ return s->regs[reg_idx];
933
+}
934
+
935
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val64)
936
+{
937
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
938
+ uint32_t val = val64;
939
+
940
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
941
+
942
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
943
+ (reg->access->addr == A_TXHPB_DATA2);
944
+
945
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
946
+
947
+ DB_PRINT(s, "TX FIFO write.\n");
948
+
949
+ if (!fifo32_is_full(f)) {
950
+ fifo32_push(f, val);
951
+ } else {
952
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
953
+
954
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
955
+ }
956
+
957
+ /* Initiate the message send if TX register is written. */
958
+ if (initiate_transfer &&
959
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
960
+ transfer_fifo(s, f);
961
+ }
962
+
963
+ can_update_irq(s);
964
+}
965
+
966
+static const RegisterAccessInfo can_regs_info[] = {
967
+ { .name = "SOFTWARE_RESET_REGISTER",
968
+ .addr = A_SOFTWARE_RESET_REGISTER,
969
+ .rsvd = 0xfffffffc,
970
+ .pre_write = can_srr_pre_write,
971
+ },{ .name = "MODE_SELECT_REGISTER",
972
+ .addr = A_MODE_SELECT_REGISTER,
973
+ .rsvd = 0xfffffff8,
974
+ .pre_write = can_msr_pre_write,
975
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
976
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
977
+ .rsvd = 0xffffff00,
978
+ .pre_write = can_brpr_pre_write,
979
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
980
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
981
+ .rsvd = 0xfffffe00,
982
+ .pre_write = can_btr_pre_write,
983
+ },{ .name = "ERROR_COUNTER_REGISTER",
984
+ .addr = A_ERROR_COUNTER_REGISTER,
985
+ .rsvd = 0xffff0000,
986
+ .ro = 0xffffffff,
987
+ },{ .name = "ERROR_STATUS_REGISTER",
988
+ .addr = A_ERROR_STATUS_REGISTER,
989
+ .rsvd = 0xffffffe0,
990
+ .w1c = 0x1f,
991
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
992
+ .reset = 0x1,
993
+ .rsvd = 0xffffe000,
994
+ .ro = 0x1fff,
995
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
996
+ .addr = A_INTERRUPT_STATUS_REGISTER,
997
+ .reset = 0x6000,
998
+ .rsvd = 0xffff8000,
999
+ .ro = 0x7fff,
1000
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1001
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1002
+ .rsvd = 0xffff8000,
1003
+ .post_write = can_ier_post_write,
1004
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1005
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1006
+ .rsvd = 0xffff8000,
1007
+ .pre_write = can_icr_pre_write,
1008
+ },{ .name = "TIMESTAMP_REGISTER",
1009
+ .addr = A_TIMESTAMP_REGISTER,
1010
+ .rsvd = 0xfffffffe,
1011
+ .pre_write = can_tcr_pre_write,
1012
+ },{ .name = "WIR", .addr = A_WIR,
1013
+ .reset = 0x3f3f,
1014
+ .rsvd = 0xffff0000,
1015
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1016
+ .post_write = can_tx_post_write,
1017
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1018
+ .rsvd = 0xfffffff,
1019
+ .post_write = can_tx_post_write,
1020
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1021
+ .post_write = can_tx_post_write,
1022
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1023
+ .post_write = can_tx_post_write,
1024
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1025
+ .post_write = can_tx_post_write,
1026
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1027
+ .rsvd = 0xfffffff,
1028
+ .post_write = can_tx_post_write,
1029
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1030
+ .post_write = can_tx_post_write,
1031
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1032
+ .post_write = can_tx_post_write,
1033
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1034
+ .ro = 0xffffffff,
1035
+ .post_read = can_rxfifo_pre_read,
1036
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1037
+ .rsvd = 0xfff0000,
1038
+ .post_read = can_rxfifo_pre_read,
1039
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1040
+ .post_read = can_rxfifo_pre_read,
1041
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1042
+ .post_read = can_rxfifo_pre_read,
1043
+ },{ .name = "AFR", .addr = A_AFR,
1044
+ .rsvd = 0xfffffff0,
1045
+ .post_write = can_filter_enable_post_write,
1046
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1047
+ .pre_write = can_filter_mask_pre_write,
1048
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1049
+ .pre_write = can_filter_id_pre_write,
1050
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1051
+ .pre_write = can_filter_mask_pre_write,
1052
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1053
+ .pre_write = can_filter_id_pre_write,
1054
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1055
+ .pre_write = can_filter_mask_pre_write,
1056
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1057
+ .pre_write = can_filter_id_pre_write,
1058
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1059
+ .pre_write = can_filter_mask_pre_write,
1060
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1061
+ .pre_write = can_filter_id_pre_write,
1062
+ }
1063
+};
1064
+
1065
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1066
+{
1067
+ /* No action required on the timer rollover. */
1068
+}
1069
+
1070
+static const MemoryRegionOps can_ops = {
1071
+ .read = register_read_memory,
1072
+ .write = register_write_memory,
1073
+ .endianness = DEVICE_LITTLE_ENDIAN,
1074
+ .valid = {
1075
+ .min_access_size = 4,
1076
+ .max_access_size = 4,
1077
+ },
1078
+};
1079
+
1080
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1081
+{
1082
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1083
+ unsigned int i;
1084
+
1085
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1086
+ register_reset(&s->reg_info[i]);
1087
+ }
1088
+
1089
+ ptimer_transaction_begin(s->can_timer);
1090
+ ptimer_set_count(s->can_timer, 0);
1091
+ ptimer_transaction_commit(s->can_timer);
1092
+}
1093
+
1094
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1095
+{
1096
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1097
+ unsigned int i;
1098
+
1099
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1100
+ register_reset(&s->reg_info[i]);
1101
+ }
1102
+
1103
+ /*
1104
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1105
+ * done by post_write which gets called from register_reset function,
1106
+ * post_write handle will not be able to trigger tx because CAN will be
1107
+ * disabled when software_reset_register is cleared first.
1108
+ */
1109
+ fifo32_reset(&s->rx_fifo);
1110
+ fifo32_reset(&s->tx_fifo);
1111
+ fifo32_reset(&s->txhpb_fifo);
1112
+}
1113
+
1114
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1115
+{
1116
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1117
+ bus_client);
1118
+
1119
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1120
+ DB_PRINT(s, "Controller is in reset.\n");
1121
+ return false;
1122
+ } else if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1123
+ DB_PRINT(s, "Controller is disabled. Incoming messages"
1124
+ " will be discarded.\n");
1125
+ return false;
1126
+ } else {
1127
+ return true;
1128
+ }
1129
+}
1130
+
1131
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1132
+ const qemu_can_frame *buf, size_t buf_size) {
1133
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1134
+ bus_client);
1135
+ const qemu_can_frame *frame = buf;
1136
+
1137
+ DB_PRINT(s, "Incoming data.\n");
1138
+
1139
+ if (buf_size <= 0) {
1140
+ DB_PRINT(s, "Junk data received.\n");
1141
+ return 0;
1142
+ }
1143
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
1144
+ /*
1145
+ * XlnxZynqMPCAN will not participate in normal bus communication
1146
+ * and will not receive any messages transmitted by other CAN nodes.
1147
+ */
1148
+ DB_PRINT(s, "Controller is in loopback mode. It will not"
1149
+ " receive data.\n");
1150
+
1151
+ } else if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1152
+ /* Snoop Mode: Just keep the data. no response back. */
1153
+ update_rx_fifo(s, frame);
1154
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1155
+ /*
1156
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1157
+ * up state.
1158
+ */
1159
+ can_exit_sleep_mode(s);
1160
+ update_rx_fifo(s, frame);
1161
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1162
+ update_rx_fifo(s, frame);
1163
+ } else {
1164
+ DB_PRINT(s, "Cannot receive data as controller is not configured"
1165
+ " correctly.\n");
1166
+ }
1167
+
1168
+ return 1;
1169
+}
1170
+
1171
+static CanBusClientInfo can_xilinx_bus_client_info = {
1172
+ .can_receive = xlnx_zynqmp_can_can_receive,
1173
+ .receive = xlnx_zynqmp_can_receive,
1174
+};
1175
+
1176
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1177
+ CanBusState *bus)
1178
+{
1179
+ s->bus_client.info = &can_xilinx_bus_client_info;
1180
+
1181
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1182
+ return -1;
1183
+ }
1184
+ return 0;
1185
+}
1186
+
1187
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1188
+{
1189
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1190
+
1191
+ if (s->canbus) {
1192
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1193
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1194
+
1195
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1196
+ " failed.", path);
1197
+ return;
1198
+ }
1199
+
1200
+ } else {
1201
+ /* If no bus is set. */
1202
+ DB_PRINT(s, "Canbus property is not set.\n");
1203
+ }
1204
+
1205
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
1206
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
1207
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
1208
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
1209
+
1210
+ /* Allocate a new timer. */
1211
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
1212
+ PTIMER_POLICY_DEFAULT);
1213
+
1214
+ ptimer_transaction_begin(s->can_timer);
1215
+
1216
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
1217
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
1218
+ ptimer_run(s->can_timer, 0);
1219
+ ptimer_transaction_commit(s->can_timer);
1220
+}
1221
+
1222
+static void xlnx_zynqmp_can_init(Object *obj)
1223
+{
1224
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1225
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1226
+
1227
+ RegisterInfoArray *reg_array;
1228
+
1229
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
1230
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1231
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1232
+ ARRAY_SIZE(can_regs_info),
1233
+ s->reg_info, s->regs,
1234
+ &can_ops,
1235
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1236
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1237
+
1238
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
1239
+ sysbus_init_mmio(sbd, &s->iomem);
1240
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
1241
+}
1242
+
1243
+static const VMStateDescription vmstate_can = {
1244
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1245
+ .version_id = 1,
1246
+ .minimum_version_id = 1,
1247
+ .fields = (VMStateField[]) {
1248
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
1249
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
1250
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
1251
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
1252
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
1253
+ VMSTATE_END_OF_LIST(),
1254
+ }
1255
+};
1256
+
1257
+static Property xlnx_zynqmp_can_properties[] = {
1258
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
1259
+ CAN_DEFAULT_CLOCK),
1260
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1261
+ CanBusState *),
1262
+ DEFINE_PROP_END_OF_LIST(),
1263
+};
1264
+
1265
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
1266
+{
1267
+ DeviceClass *dc = DEVICE_CLASS(klass);
1268
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1269
+
1270
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
1271
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
1272
+ dc->realize = xlnx_zynqmp_can_realize;
1273
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
1274
+ dc->vmsd = &vmstate_can;
1275
+}
1276
+
1277
+static const TypeInfo can_info = {
1278
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1279
+ .parent = TYPE_SYS_BUS_DEVICE,
1280
+ .instance_size = sizeof(XlnxZynqMPCANState),
1281
+ .class_init = xlnx_zynqmp_can_class_init,
1282
+ .instance_init = xlnx_zynqmp_can_init,
1283
+};
1284
+
1285
+static void can_register_types(void)
1286
+{
1287
+ type_register_static(&can_info);
1288
+}
1289
+
1290
+type_init(can_register_types)
1291
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
1292
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
1293
--- a/hw/net/can/meson.build
80
--- a/fpu/softfloat-specialize.c.inc
1294
+++ b/hw/net/can/meson.build
81
+++ b/fpu/softfloat-specialize.c.inc
1295
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_SJA1000', if_true: files('can_sja1000.c'))
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
1296
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_kvaser_pci.c'))
83
return a;
1297
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
84
}
1298
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
85
1299
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
86
-/*----------------------------------------------------------------------------
87
-| Takes two extended double-precision floating-point values `a' and `b', one
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
89
-| `b' is a signaling NaN, the invalid exception is raised.
90
-*----------------------------------------------------------------------------*/
91
-
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
93
-{
94
- bool aIsLargerSignificand;
95
- FloatClass a_cls, b_cls;
96
-
97
- /* This is not complete, but is good enough for pickNaN. */
98
- a_cls = (!floatx80_is_any_nan(a)
99
- ? float_class_normal
100
- : floatx80_is_signaling_nan(a, status)
101
- ? float_class_snan
102
- : float_class_qnan);
103
- b_cls = (!floatx80_is_any_nan(b)
104
- ? float_class_normal
105
- : floatx80_is_signaling_nan(b, status)
106
- ? float_class_snan
107
- : float_class_qnan);
108
-
109
- if (is_snan(a_cls) || is_snan(b_cls)) {
110
- float_raise(float_flag_invalid, status);
111
- }
112
-
113
- if (status->default_nan_mode) {
114
- return floatx80_default_nan(status);
115
- }
116
-
117
- if (a.low < b.low) {
118
- aIsLargerSignificand = 0;
119
- } else if (b.low < a.low) {
120
- aIsLargerSignificand = 1;
121
- } else {
122
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
123
- }
124
-
125
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
126
- if (is_snan(b_cls)) {
127
- return floatx80_silence_nan(b, status);
128
- }
129
- return b;
130
- } else {
131
- if (is_snan(a_cls)) {
132
- return floatx80_silence_nan(a, status);
133
- }
134
- return a;
135
- }
136
-}
137
-
138
/*----------------------------------------------------------------------------
139
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
140
| NaN; otherwise returns 0.
1300
--
141
--
1301
2.20.1
142
2.34.1
1302
1303
diff view generated by jsdifflib
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This check was backwards when introduced in commit
3
Unpacking and repacking the parts may be slightly more work
4
033614c47de78409ad3fb39bb7bd1483b71c6789:
4
than we did before, but we get to reuse more code. For a
5
code path handling exceptional values, this is an improvement.
5
6
6
target/arm: Filter cycle counter based on PMCCFILTR_EL0
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
fpu/softfloat.c | 43 +++++--------------------------------------
13
1 file changed, 5 insertions(+), 38 deletions(-)
7
14
8
Cc: qemu-stable@nongnu.org
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
9
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/helper.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
17
--- a/fpu/softfloat.c
19
+++ b/target/arm/helper.c
18
+++ b/fpu/softfloat.c
20
@@ -XXX,XX +XXX,XX @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
21
}
20
22
} else {
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
23
prohibited = arm_feature(env, ARM_FEATURE_EL3) &&
22
{
24
- (env->cp15.mdcr_el3 & MDCR_SPME);
23
- bool aIsLargerSignificand;
25
+ !(env->cp15.mdcr_el3 & MDCR_SPME);
24
- FloatClass a_cls, b_cls;
25
+ FloatParts128 pa, pb, *pr;
26
27
- /* This is not complete, but is good enough for pickNaN. */
28
- a_cls = (!floatx80_is_any_nan(a)
29
- ? float_class_normal
30
- : floatx80_is_signaling_nan(a, status)
31
- ? float_class_snan
32
- : float_class_qnan);
33
- b_cls = (!floatx80_is_any_nan(b)
34
- ? float_class_normal
35
- : floatx80_is_signaling_nan(b, status)
36
- ? float_class_snan
37
- : float_class_qnan);
38
-
39
- if (is_snan(a_cls) || is_snan(b_cls)) {
40
- float_raise(float_flag_invalid, status);
41
- }
42
-
43
- if (status->default_nan_mode) {
44
+ if (!floatx80_unpack_canonical(&pa, a, status) ||
45
+ !floatx80_unpack_canonical(&pb, b, status)) {
46
return floatx80_default_nan(status);
26
}
47
}
27
48
28
if (prohibited && counter == 31) {
49
- if (a.low < b.low) {
50
- aIsLargerSignificand = 0;
51
- } else if (b.low < a.low) {
52
- aIsLargerSignificand = 1;
53
- } else {
54
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
55
- }
56
-
57
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
58
- if (is_snan(b_cls)) {
59
- return floatx80_silence_nan(b, status);
60
- }
61
- return b;
62
- } else {
63
- if (is_snan(a_cls)) {
64
- return floatx80_silence_nan(a, status);
65
- }
66
- return a;
67
- }
68
+ pr = parts_pick_nan(&pa, &pb, status);
69
+ return floatx80_round_pack_canonical(pr, status);
70
}
71
72
/*----------------------------------------------------------------------------
29
--
73
--
30
2.20.1
74
2.34.1
31
32
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The NPCM730 and NPCM750 SoCs have three timer modules each holding five
3
Inline pickNaN into its only caller. This makes one assert
4
timers and some shared registers (e.g. interrupt status).
4
redundant with the immediately preceding IF.
5
5
6
Each timer runs at 25 MHz divided by a prescaler, and counts down from a
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
configurable initial value to zero. When zero is reached, the interrupt
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
flag for the timer is set, and the timer is disabled (one-shot mode) or
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
9
reloaded from its initial value (periodic mode).
10
11
This implementation is sufficient to boot a Linux kernel configured for
12
NPCM750. Note that the kernel does not seem to actually turn on the
13
interrupts.
14
15
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
16
Reviewed-by: Joel Stanley <joel@jms.id.au>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Message-id: 20200911052101.2602693-4-hskinnemoen@google.com
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
10
---
24
include/hw/timer/npcm7xx_timer.h | 78 +++++
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
25
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
26
hw/timer/meson.build | 1 +
13
2 files changed, 73 insertions(+), 105 deletions(-)
27
hw/timer/trace-events | 5 +
14
28
4 files changed, 627 insertions(+)
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
29
create mode 100644 include/hw/timer/npcm7xx_timer.h
16
index XXXXXXX..XXXXXXX 100644
30
create mode 100644 hw/timer/npcm7xx_timer.c
17
--- a/fpu/softfloat-parts.c.inc
31
18
+++ b/fpu/softfloat-parts.c.inc
32
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
33
new file mode 100644
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
34
index XXXXXXX..XXXXXXX
21
float_status *s)
35
--- /dev/null
22
{
36
+++ b/include/hw/timer/npcm7xx_timer.h
23
+ int cmp, which;
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * Nuvoton NPCM7xx Timer Controller
40
+ *
41
+ * Copyright 2020 Google LLC
42
+ *
43
+ * This program is free software; you can redistribute it and/or modify it
44
+ * under the terms of the GNU General Public License as published by the
45
+ * Free Software Foundation; either version 2 of the License, or
46
+ * (at your option) any later version.
47
+ *
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51
+ * for more details.
52
+ */
53
+#ifndef NPCM7XX_TIMER_H
54
+#define NPCM7XX_TIMER_H
55
+
24
+
56
+#include "exec/memory.h"
25
if (is_snan(a->cls) || is_snan(b->cls)) {
57
+#include "hw/sysbus.h"
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
58
+#include "qemu/timer.h"
27
}
28
29
if (s->default_nan_mode) {
30
parts_default_nan(a, s);
31
- } else {
32
- int cmp = frac_cmp(a, b);
33
- if (cmp == 0) {
34
- cmp = a->sign < b->sign;
35
- }
36
+ return a;
37
+ }
38
39
- if (pickNaN(a->cls, b->cls, cmp > 0, s)) {
40
- a = b;
41
- }
42
+ cmp = frac_cmp(a, b);
43
+ if (cmp == 0) {
44
+ cmp = a->sign < b->sign;
45
+ }
59
+
46
+
60
+/* Each Timer Module (TIM) instance holds five 25 MHz timers. */
47
+ switch (s->float_2nan_prop_rule) {
61
+#define NPCM7XX_TIMERS_PER_CTRL (5)
48
+ case float_2nan_prop_s_ab:
62
+
49
if (is_snan(a->cls)) {
63
+/*
50
- parts_silence_nan(a, s);
64
+ * Number of registers in our device state structure. Don't change this without
51
+ which = 0;
65
+ * incrementing the version_id in the vmstate.
52
+ } else if (is_snan(b->cls)) {
66
+ */
53
+ which = 1;
67
+#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
54
+ } else if (is_qnan(a->cls)) {
68
+
55
+ which = 0;
69
+typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
56
+ } else {
70
+
57
+ which = 1;
71
+/**
58
}
72
+ * struct NPCM7xxTimer - Individual timer state.
59
+ break;
73
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
60
+ case float_2nan_prop_s_ba:
74
+ * @qtimer: QEMU timer that notifies us on expiration.
61
+ if (is_snan(b->cls)) {
75
+ * @expires_ns: Absolute virtual expiration time.
62
+ which = 1;
76
+ * @remaining_ns: Remaining time until expiration if timer is paused.
63
+ } else if (is_snan(a->cls)) {
77
+ * @tcsr: The Timer Control and Status Register.
64
+ which = 0;
78
+ * @ticr: The Timer Initial Count Register.
65
+ } else if (is_qnan(b->cls)) {
79
+ */
66
+ which = 1;
80
+typedef struct NPCM7xxTimer {
67
+ } else {
81
+ NPCM7xxTimerCtrlState *ctrl;
68
+ which = 0;
82
+
83
+ qemu_irq irq;
84
+ QEMUTimer qtimer;
85
+ int64_t expires_ns;
86
+ int64_t remaining_ns;
87
+
88
+ uint32_t tcsr;
89
+ uint32_t ticr;
90
+} NPCM7xxTimer;
91
+
92
+/**
93
+ * struct NPCM7xxTimerCtrlState - Timer Module device state.
94
+ * @parent: System bus device.
95
+ * @iomem: Memory region through which registers are accessed.
96
+ * @tisr: The Timer Interrupt Status Register.
97
+ * @wtcr: The Watchdog Timer Control Register.
98
+ * @timer: The five individual timers managed by this module.
99
+ */
100
+struct NPCM7xxTimerCtrlState {
101
+ SysBusDevice parent;
102
+
103
+ MemoryRegion iomem;
104
+
105
+ uint32_t tisr;
106
+ uint32_t wtcr;
107
+
108
+ NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
109
+};
110
+
111
+#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
112
+#define NPCM7XX_TIMER(obj) \
113
+ OBJECT_CHECK(NPCM7xxTimerCtrlState, (obj), TYPE_NPCM7XX_TIMER)
114
+
115
+#endif /* NPCM7XX_TIMER_H */
116
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
117
new file mode 100644
118
index XXXXXXX..XXXXXXX
119
--- /dev/null
120
+++ b/hw/timer/npcm7xx_timer.c
121
@@ -XXX,XX +XXX,XX @@
122
+/*
123
+ * Nuvoton NPCM7xx Timer Controller
124
+ *
125
+ * Copyright 2020 Google LLC
126
+ *
127
+ * This program is free software; you can redistribute it and/or modify it
128
+ * under the terms of the GNU General Public License as published by the
129
+ * Free Software Foundation; either version 2 of the License, or
130
+ * (at your option) any later version.
131
+ *
132
+ * This program is distributed in the hope that it will be useful, but WITHOUT
133
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
134
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
135
+ * for more details.
136
+ */
137
+
138
+#include "qemu/osdep.h"
139
+
140
+#include "hw/irq.h"
141
+#include "hw/misc/npcm7xx_clk.h"
142
+#include "hw/timer/npcm7xx_timer.h"
143
+#include "migration/vmstate.h"
144
+#include "qemu/bitops.h"
145
+#include "qemu/error-report.h"
146
+#include "qemu/log.h"
147
+#include "qemu/module.h"
148
+#include "qemu/timer.h"
149
+#include "qemu/units.h"
150
+#include "trace.h"
151
+
152
+/* 32-bit register indices. */
153
+enum NPCM7xxTimerRegisters {
154
+ NPCM7XX_TIMER_TCSR0,
155
+ NPCM7XX_TIMER_TCSR1,
156
+ NPCM7XX_TIMER_TICR0,
157
+ NPCM7XX_TIMER_TICR1,
158
+ NPCM7XX_TIMER_TDR0,
159
+ NPCM7XX_TIMER_TDR1,
160
+ NPCM7XX_TIMER_TISR,
161
+ NPCM7XX_TIMER_WTCR,
162
+ NPCM7XX_TIMER_TCSR2,
163
+ NPCM7XX_TIMER_TCSR3,
164
+ NPCM7XX_TIMER_TICR2,
165
+ NPCM7XX_TIMER_TICR3,
166
+ NPCM7XX_TIMER_TDR2,
167
+ NPCM7XX_TIMER_TDR3,
168
+ NPCM7XX_TIMER_TCSR4 = 0x0040 / sizeof(uint32_t),
169
+ NPCM7XX_TIMER_TICR4 = 0x0048 / sizeof(uint32_t),
170
+ NPCM7XX_TIMER_TDR4 = 0x0050 / sizeof(uint32_t),
171
+ NPCM7XX_TIMER_REGS_END,
172
+};
173
+
174
+/* Register field definitions. */
175
+#define NPCM7XX_TCSR_CEN BIT(30)
176
+#define NPCM7XX_TCSR_IE BIT(29)
177
+#define NPCM7XX_TCSR_PERIODIC BIT(27)
178
+#define NPCM7XX_TCSR_CRST BIT(26)
179
+#define NPCM7XX_TCSR_CACT BIT(25)
180
+#define NPCM7XX_TCSR_RSVD 0x01ffff00
181
+#define NPCM7XX_TCSR_PRESCALE_START 0
182
+#define NPCM7XX_TCSR_PRESCALE_LEN 8
183
+
184
+/*
185
+ * Returns the index of timer in the tc->timer array. This can be used to
186
+ * locate the registers that belong to this timer.
187
+ */
188
+static int npcm7xx_timer_index(NPCM7xxTimerCtrlState *tc, NPCM7xxTimer *timer)
189
+{
190
+ int index = timer - tc->timer;
191
+
192
+ g_assert(index >= 0 && index < NPCM7XX_TIMERS_PER_CTRL);
193
+
194
+ return index;
195
+}
196
+
197
+/* Return the value by which to divide the reference clock rate. */
198
+static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
199
+{
200
+ return extract32(tcsr, NPCM7XX_TCSR_PRESCALE_START,
201
+ NPCM7XX_TCSR_PRESCALE_LEN) + 1;
202
+}
203
+
204
+/* Convert a timer cycle count to a time interval in nanoseconds. */
205
+static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
206
+{
207
+ int64_t ns = count;
208
+
209
+ ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
210
+ ns *= npcm7xx_tcsr_prescaler(t->tcsr);
211
+
212
+ return ns;
213
+}
214
+
215
+/* Convert a time interval in nanoseconds to a timer cycle count. */
216
+static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
217
+{
218
+ int64_t count;
219
+
220
+ count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
221
+ count /= npcm7xx_tcsr_prescaler(t->tcsr);
222
+
223
+ return count;
224
+}
225
+
226
+/*
227
+ * Raise the interrupt line if there's a pending interrupt and interrupts are
228
+ * enabled for this timer. If not, lower it.
229
+ */
230
+static void npcm7xx_timer_check_interrupt(NPCM7xxTimer *t)
231
+{
232
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
233
+ int index = npcm7xx_timer_index(tc, t);
234
+ bool pending = (t->tcsr & NPCM7XX_TCSR_IE) && (tc->tisr & BIT(index));
235
+
236
+ qemu_set_irq(t->irq, pending);
237
+ trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, pending);
238
+}
239
+
240
+/* Start or resume the timer. */
241
+static void npcm7xx_timer_start(NPCM7xxTimer *t)
242
+{
243
+ int64_t now;
244
+
245
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
246
+ t->expires_ns = now + t->remaining_ns;
247
+ timer_mod(&t->qtimer, t->expires_ns);
248
+}
249
+
250
+/*
251
+ * Called when the counter reaches zero. Sets the interrupt flag, and either
252
+ * restarts or disables the timer.
253
+ */
254
+static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t)
255
+{
256
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
257
+ int index = npcm7xx_timer_index(tc, t);
258
+
259
+ tc->tisr |= BIT(index);
260
+
261
+ if (t->tcsr & NPCM7XX_TCSR_PERIODIC) {
262
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
263
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
264
+ npcm7xx_timer_start(t);
265
+ }
69
+ }
266
+ } else {
70
+ break;
267
+ t->tcsr &= ~(NPCM7XX_TCSR_CEN | NPCM7XX_TCSR_CACT);
71
+ case float_2nan_prop_ab:
268
+ }
72
+ which = is_nan(a->cls) ? 0 : 1;
269
+
73
+ break;
270
+ npcm7xx_timer_check_interrupt(t);
74
+ case float_2nan_prop_ba:
271
+}
75
+ which = is_nan(b->cls) ? 1 : 0;
272
+
76
+ break;
273
+/* Stop counting. Record the time remaining so we can continue later. */
77
+ case float_2nan_prop_x87:
274
+static void npcm7xx_timer_pause(NPCM7xxTimer *t)
78
+ /*
275
+{
79
+ * This implements x87 NaN propagation rules:
276
+ int64_t now;
80
+ * SNaN + QNaN => return the QNaN
277
+
81
+ * two SNaNs => return the one with the larger significand, silenced
278
+ timer_del(&t->qtimer);
82
+ * two QNaNs => return the one with the larger significand
279
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
83
+ * SNaN and a non-NaN => return the SNaN, silenced
280
+ t->remaining_ns = t->expires_ns - now;
84
+ * QNaN and a non-NaN => return the QNaN
281
+ if (t->remaining_ns <= 0) {
85
+ *
282
+ npcm7xx_timer_reached_zero(t);
86
+ * If we get down to comparing significands and they are the same,
283
+ }
87
+ * return the NaN with the positive sign bit (if any).
284
+}
88
+ */
285
+
89
+ if (is_snan(a->cls)) {
286
+/*
90
+ if (is_snan(b->cls)) {
287
+ * Restart the timer from its initial value. If the timer was enabled and stays
91
+ which = cmp > 0 ? 0 : 1;
288
+ * enabled, adjust the QEMU timer according to the new count. If the timer is
92
+ } else {
289
+ * transitioning from disabled to enabled, the caller is expected to start the
93
+ which = is_qnan(b->cls) ? 1 : 0;
290
+ * timer later.
94
+ }
291
+ */
95
+ } else if (is_qnan(a->cls)) {
292
+static void npcm7xx_timer_restart(NPCM7xxTimer *t, uint32_t old_tcsr)
96
+ if (is_snan(b->cls) || !is_qnan(b->cls)) {
293
+{
97
+ which = 0;
294
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
98
+ } else {
295
+
99
+ which = cmp > 0 ? 0 : 1;
296
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
100
+ }
297
+ npcm7xx_timer_start(t);
101
+ } else {
298
+ }
102
+ which = 1;
299
+}
300
+
301
+/* Register read and write handlers */
302
+
303
+static uint32_t npcm7xx_timer_read_tdr(NPCM7xxTimer *t)
304
+{
305
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
306
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
307
+
308
+ return npcm7xx_timer_ns_to_count(t, t->expires_ns - now);
309
+ }
310
+
311
+ return npcm7xx_timer_ns_to_count(t, t->remaining_ns);
312
+}
313
+
314
+static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
315
+{
316
+ uint32_t old_tcsr = t->tcsr;
317
+ uint32_t tdr;
318
+
319
+ if (new_tcsr & NPCM7XX_TCSR_RSVD) {
320
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: reserved bits in 0x%08x ignored\n",
321
+ __func__, new_tcsr);
322
+ new_tcsr &= ~NPCM7XX_TCSR_RSVD;
323
+ }
324
+ if (new_tcsr & NPCM7XX_TCSR_CACT) {
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only bits in 0x%08x ignored\n",
326
+ __func__, new_tcsr);
327
+ new_tcsr &= ~NPCM7XX_TCSR_CACT;
328
+ }
329
+ if ((new_tcsr & NPCM7XX_TCSR_CRST) && (new_tcsr & NPCM7XX_TCSR_CEN)) {
330
+ qemu_log_mask(LOG_GUEST_ERROR,
331
+ "%s: both CRST and CEN set; ignoring CEN.\n",
332
+ __func__);
333
+ new_tcsr &= ~NPCM7XX_TCSR_CEN;
334
+ }
335
+
336
+ /* Calculate the value of TDR before potentially changing the prescaler. */
337
+ tdr = npcm7xx_timer_read_tdr(t);
338
+
339
+ t->tcsr = (t->tcsr & NPCM7XX_TCSR_CACT) | new_tcsr;
340
+
341
+ if (npcm7xx_tcsr_prescaler(old_tcsr) != npcm7xx_tcsr_prescaler(new_tcsr)) {
342
+ /* Recalculate time remaining based on the current TDR value. */
343
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, tdr);
344
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
345
+ npcm7xx_timer_start(t);
346
+ }
103
+ }
347
+ }
104
+ break;
348
+
349
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_IE) {
350
+ npcm7xx_timer_check_interrupt(t);
351
+ }
352
+ if (new_tcsr & NPCM7XX_TCSR_CRST) {
353
+ npcm7xx_timer_restart(t, old_tcsr);
354
+ t->tcsr &= ~NPCM7XX_TCSR_CRST;
355
+ }
356
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_CEN) {
357
+ if (new_tcsr & NPCM7XX_TCSR_CEN) {
358
+ t->tcsr |= NPCM7XX_TCSR_CACT;
359
+ npcm7xx_timer_start(t);
360
+ } else {
361
+ t->tcsr &= ~NPCM7XX_TCSR_CACT;
362
+ npcm7xx_timer_pause(t);
363
+ }
364
+ }
365
+}
366
+
367
+static void npcm7xx_timer_write_ticr(NPCM7xxTimer *t, uint32_t new_ticr)
368
+{
369
+ t->ticr = new_ticr;
370
+
371
+ npcm7xx_timer_restart(t, t->tcsr);
372
+}
373
+
374
+static void npcm7xx_timer_write_tisr(NPCM7xxTimerCtrlState *s, uint32_t value)
375
+{
376
+ int i;
377
+
378
+ s->tisr &= ~value;
379
+ for (i = 0; i < ARRAY_SIZE(s->timer); i++) {
380
+ if (value & (1U << i)) {
381
+ npcm7xx_timer_check_interrupt(&s->timer[i]);
382
+ }
383
+ }
384
+}
385
+
386
+static hwaddr npcm7xx_tcsr_index(hwaddr reg)
387
+{
388
+ switch (reg) {
389
+ case NPCM7XX_TIMER_TCSR0:
390
+ return 0;
391
+ case NPCM7XX_TIMER_TCSR1:
392
+ return 1;
393
+ case NPCM7XX_TIMER_TCSR2:
394
+ return 2;
395
+ case NPCM7XX_TIMER_TCSR3:
396
+ return 3;
397
+ case NPCM7XX_TIMER_TCSR4:
398
+ return 4;
399
+ default:
105
+ default:
400
+ g_assert_not_reached();
106
+ g_assert_not_reached();
401
+ }
107
+ }
402
+}
403
+
108
+
404
+static hwaddr npcm7xx_ticr_index(hwaddr reg)
109
+ if (which) {
405
+{
110
+ a = b;
406
+ switch (reg) {
111
+ }
407
+ case NPCM7XX_TIMER_TICR0:
112
+ if (is_snan(a->cls)) {
408
+ return 0;
113
+ parts_silence_nan(a, s);
409
+ case NPCM7XX_TIMER_TICR1:
114
}
410
+ return 1;
115
return a;
411
+ case NPCM7XX_TIMER_TICR2:
116
}
412
+ return 2;
117
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
413
+ case NPCM7XX_TIMER_TICR3:
414
+ return 3;
415
+ case NPCM7XX_TIMER_TICR4:
416
+ return 4;
417
+ default:
418
+ g_assert_not_reached();
419
+ }
420
+}
421
+
422
+static hwaddr npcm7xx_tdr_index(hwaddr reg)
423
+{
424
+ switch (reg) {
425
+ case NPCM7XX_TIMER_TDR0:
426
+ return 0;
427
+ case NPCM7XX_TIMER_TDR1:
428
+ return 1;
429
+ case NPCM7XX_TIMER_TDR2:
430
+ return 2;
431
+ case NPCM7XX_TIMER_TDR3:
432
+ return 3;
433
+ case NPCM7XX_TIMER_TDR4:
434
+ return 4;
435
+ default:
436
+ g_assert_not_reached();
437
+ }
438
+}
439
+
440
+static uint64_t npcm7xx_timer_read(void *opaque, hwaddr offset, unsigned size)
441
+{
442
+ NPCM7xxTimerCtrlState *s = opaque;
443
+ uint64_t value = 0;
444
+ hwaddr reg;
445
+
446
+ reg = offset / sizeof(uint32_t);
447
+ switch (reg) {
448
+ case NPCM7XX_TIMER_TCSR0:
449
+ case NPCM7XX_TIMER_TCSR1:
450
+ case NPCM7XX_TIMER_TCSR2:
451
+ case NPCM7XX_TIMER_TCSR3:
452
+ case NPCM7XX_TIMER_TCSR4:
453
+ value = s->timer[npcm7xx_tcsr_index(reg)].tcsr;
454
+ break;
455
+
456
+ case NPCM7XX_TIMER_TICR0:
457
+ case NPCM7XX_TIMER_TICR1:
458
+ case NPCM7XX_TIMER_TICR2:
459
+ case NPCM7XX_TIMER_TICR3:
460
+ case NPCM7XX_TIMER_TICR4:
461
+ value = s->timer[npcm7xx_ticr_index(reg)].ticr;
462
+ break;
463
+
464
+ case NPCM7XX_TIMER_TDR0:
465
+ case NPCM7XX_TIMER_TDR1:
466
+ case NPCM7XX_TIMER_TDR2:
467
+ case NPCM7XX_TIMER_TDR3:
468
+ case NPCM7XX_TIMER_TDR4:
469
+ value = npcm7xx_timer_read_tdr(&s->timer[npcm7xx_tdr_index(reg)]);
470
+ break;
471
+
472
+ case NPCM7XX_TIMER_TISR:
473
+ value = s->tisr;
474
+ break;
475
+
476
+ case NPCM7XX_TIMER_WTCR:
477
+ value = s->wtcr;
478
+ break;
479
+
480
+ default:
481
+ qemu_log_mask(LOG_GUEST_ERROR,
482
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
483
+ __func__, offset);
484
+ break;
485
+ }
486
+
487
+ trace_npcm7xx_timer_read(DEVICE(s)->canonical_path, offset, value);
488
+
489
+ return value;
490
+}
491
+
492
+static void npcm7xx_timer_write(void *opaque, hwaddr offset,
493
+ uint64_t v, unsigned size)
494
+{
495
+ uint32_t reg = offset / sizeof(uint32_t);
496
+ NPCM7xxTimerCtrlState *s = opaque;
497
+ uint32_t value = v;
498
+
499
+ trace_npcm7xx_timer_write(DEVICE(s)->canonical_path, offset, value);
500
+
501
+ switch (reg) {
502
+ case NPCM7XX_TIMER_TCSR0:
503
+ case NPCM7XX_TIMER_TCSR1:
504
+ case NPCM7XX_TIMER_TCSR2:
505
+ case NPCM7XX_TIMER_TCSR3:
506
+ case NPCM7XX_TIMER_TCSR4:
507
+ npcm7xx_timer_write_tcsr(&s->timer[npcm7xx_tcsr_index(reg)], value);
508
+ return;
509
+
510
+ case NPCM7XX_TIMER_TICR0:
511
+ case NPCM7XX_TIMER_TICR1:
512
+ case NPCM7XX_TIMER_TICR2:
513
+ case NPCM7XX_TIMER_TICR3:
514
+ case NPCM7XX_TIMER_TICR4:
515
+ npcm7xx_timer_write_ticr(&s->timer[npcm7xx_ticr_index(reg)], value);
516
+ return;
517
+
518
+ case NPCM7XX_TIMER_TDR0:
519
+ case NPCM7XX_TIMER_TDR1:
520
+ case NPCM7XX_TIMER_TDR2:
521
+ case NPCM7XX_TIMER_TDR3:
522
+ case NPCM7XX_TIMER_TDR4:
523
+ qemu_log_mask(LOG_GUEST_ERROR,
524
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
525
+ __func__, offset);
526
+ return;
527
+
528
+ case NPCM7XX_TIMER_TISR:
529
+ npcm7xx_timer_write_tisr(s, value);
530
+ return;
531
+
532
+ case NPCM7XX_TIMER_WTCR:
533
+ qemu_log_mask(LOG_UNIMP, "%s: WTCR write not implemented: 0x%08x\n",
534
+ __func__, value);
535
+ return;
536
+ }
537
+
538
+ qemu_log_mask(LOG_GUEST_ERROR,
539
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
540
+ __func__, offset);
541
+}
542
+
543
+static const struct MemoryRegionOps npcm7xx_timer_ops = {
544
+ .read = npcm7xx_timer_read,
545
+ .write = npcm7xx_timer_write,
546
+ .endianness = DEVICE_LITTLE_ENDIAN,
547
+ .valid = {
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
551
+ },
552
+};
553
+
554
+/* Called when the QEMU timer expires. */
555
+static void npcm7xx_timer_expired(void *opaque)
556
+{
557
+ NPCM7xxTimer *t = opaque;
558
+
559
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
560
+ npcm7xx_timer_reached_zero(t);
561
+ }
562
+}
563
+
564
+static void npcm7xx_timer_enter_reset(Object *obj, ResetType type)
565
+{
566
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
567
+ int i;
568
+
569
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
570
+ NPCM7xxTimer *t = &s->timer[i];
571
+
572
+ timer_del(&t->qtimer);
573
+ t->expires_ns = 0;
574
+ t->remaining_ns = 0;
575
+ t->tcsr = 0x00000005;
576
+ t->ticr = 0x00000000;
577
+ }
578
+
579
+ s->tisr = 0x00000000;
580
+ s->wtcr = 0x00000400;
581
+}
582
+
583
+static void npcm7xx_timer_hold_reset(Object *obj)
584
+{
585
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
586
+ int i;
587
+
588
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
589
+ qemu_irq_lower(s->timer[i].irq);
590
+ }
591
+}
592
+
593
+static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
594
+{
595
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
596
+ SysBusDevice *sbd = &s->parent;
597
+ int i;
598
+
599
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
600
+ NPCM7xxTimer *t = &s->timer[i];
601
+ t->ctrl = s;
602
+ timer_init_ns(&t->qtimer, QEMU_CLOCK_VIRTUAL, npcm7xx_timer_expired, t);
603
+ sysbus_init_irq(sbd, &t->irq);
604
+ }
605
+
606
+ memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
607
+ TYPE_NPCM7XX_TIMER, 4 * KiB);
608
+ sysbus_init_mmio(sbd, &s->iomem);
609
+}
610
+
611
+static const VMStateDescription vmstate_npcm7xx_timer = {
612
+ .name = "npcm7xx-timer",
613
+ .version_id = 0,
614
+ .minimum_version_id = 0,
615
+ .fields = (VMStateField[]) {
616
+ VMSTATE_TIMER(qtimer, NPCM7xxTimer),
617
+ VMSTATE_INT64(expires_ns, NPCM7xxTimer),
618
+ VMSTATE_INT64(remaining_ns, NPCM7xxTimer),
619
+ VMSTATE_UINT32(tcsr, NPCM7xxTimer),
620
+ VMSTATE_UINT32(ticr, NPCM7xxTimer),
621
+ VMSTATE_END_OF_LIST(),
622
+ },
623
+};
624
+
625
+static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
626
+ .name = "npcm7xx-timer-ctrl",
627
+ .version_id = 0,
628
+ .minimum_version_id = 0,
629
+ .fields = (VMStateField[]) {
630
+ VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
631
+ VMSTATE_UINT32(wtcr, NPCM7xxTimerCtrlState),
632
+ VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
633
+ NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
634
+ NPCM7xxTimer),
635
+ VMSTATE_END_OF_LIST(),
636
+ },
637
+};
638
+
639
+static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
640
+{
641
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
642
+ DeviceClass *dc = DEVICE_CLASS(klass);
643
+
644
+ QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
645
+
646
+ dc->desc = "NPCM7xx Timer Controller";
647
+ dc->realize = npcm7xx_timer_realize;
648
+ dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
649
+ rc->phases.enter = npcm7xx_timer_enter_reset;
650
+ rc->phases.hold = npcm7xx_timer_hold_reset;
651
+}
652
+
653
+static const TypeInfo npcm7xx_timer_info = {
654
+ .name = TYPE_NPCM7XX_TIMER,
655
+ .parent = TYPE_SYS_BUS_DEVICE,
656
+ .instance_size = sizeof(NPCM7xxTimerCtrlState),
657
+ .class_init = npcm7xx_timer_class_init,
658
+};
659
+
660
+static void npcm7xx_timer_register_type(void)
661
+{
662
+ type_register_static(&npcm7xx_timer_info);
663
+}
664
+type_init(npcm7xx_timer_register_type);
665
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
666
index XXXXXXX..XXXXXXX 100644
118
index XXXXXXX..XXXXXXX 100644
667
--- a/hw/timer/meson.build
119
--- a/fpu/softfloat-specialize.c.inc
668
+++ b/hw/timer/meson.build
120
+++ b/fpu/softfloat-specialize.c.inc
669
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_timer.c'))
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
670
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-sysctl.c'))
122
}
671
softmmu_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gictimer.c'))
123
}
672
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-timer.c'))
124
673
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_timer.c'))
125
-/*----------------------------------------------------------------------------
674
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_timer.c'))
126
-| Select which NaN to propagate for a two-input operation.
675
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gptimer.c'))
127
-| IEEE754 doesn't specify all the details of this, so the
676
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_synctimer.c'))
128
-| algorithm is target-specific.
677
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
129
-| The routine is passed various bits of information about the
678
index XXXXXXX..XXXXXXX 100644
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
679
--- a/hw/timer/trace-events
131
-| Note that signalling NaNs are always squashed to quiet NaNs
680
+++ b/hw/timer/trace-events
132
-| by the caller, by calling floatXX_silence_nan() before
681
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A
133
-| returning them.
682
cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
134
-|
683
cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset"
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
684
136
-| of some kind, and is true if a has the larger significand,
685
+# npcm7xx_timer.c
137
-| or if both a and b have the same significand but a is
686
+npcm7xx_timer_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
138
-| positive but b is negative. It is only needed for the x87
687
+npcm7xx_timer_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
139
-| tie-break rule.
688
+npcm7xx_timer_irq(const char *id, int timer, int state) "%s timer %d state %d"
140
-*----------------------------------------------------------------------------*/
689
+
141
-
690
# nrf51_timer.c
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
691
nrf51_timer_read(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
143
- bool aIsLargerSignificand, float_status *status)
692
nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
144
-{
145
- /*
146
- * We guarantee not to require the target to tell us how to
147
- * pick a NaN if we're always returning the default NaN.
148
- * But if we're not in default-NaN mode then the target must
149
- * specify via set_float_2nan_prop_rule().
150
- */
151
- assert(!status->default_nan_mode);
152
-
153
- switch (status->float_2nan_prop_rule) {
154
- case float_2nan_prop_s_ab:
155
- if (is_snan(a_cls)) {
156
- return 0;
157
- } else if (is_snan(b_cls)) {
158
- return 1;
159
- } else if (is_qnan(a_cls)) {
160
- return 0;
161
- } else {
162
- return 1;
163
- }
164
- break;
165
- case float_2nan_prop_s_ba:
166
- if (is_snan(b_cls)) {
167
- return 1;
168
- } else if (is_snan(a_cls)) {
169
- return 0;
170
- } else if (is_qnan(b_cls)) {
171
- return 1;
172
- } else {
173
- return 0;
174
- }
175
- break;
176
- case float_2nan_prop_ab:
177
- if (is_nan(a_cls)) {
178
- return 0;
179
- } else {
180
- return 1;
181
- }
182
- break;
183
- case float_2nan_prop_ba:
184
- if (is_nan(b_cls)) {
185
- return 1;
186
- } else {
187
- return 0;
188
- }
189
- break;
190
- case float_2nan_prop_x87:
191
- /*
192
- * This implements x87 NaN propagation rules:
193
- * SNaN + QNaN => return the QNaN
194
- * two SNaNs => return the one with the larger significand, silenced
195
- * two QNaNs => return the one with the larger significand
196
- * SNaN and a non-NaN => return the SNaN, silenced
197
- * QNaN and a non-NaN => return the QNaN
198
- *
199
- * If we get down to comparing significands and they are the same,
200
- * return the NaN with the positive sign bit (if any).
201
- */
202
- if (is_snan(a_cls)) {
203
- if (is_snan(b_cls)) {
204
- return aIsLargerSignificand ? 0 : 1;
205
- }
206
- return is_qnan(b_cls) ? 1 : 0;
207
- } else if (is_qnan(a_cls)) {
208
- if (is_snan(b_cls) || !is_qnan(b_cls)) {
209
- return 0;
210
- } else {
211
- return aIsLargerSignificand ? 0 : 1;
212
- }
213
- } else {
214
- return 1;
215
- }
216
- default:
217
- g_assert_not_reached();
218
- }
219
-}
220
-
221
/*----------------------------------------------------------------------------
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
223
| NaN; otherwise returns 0.
693
--
224
--
694
2.20.1
225
2.34.1
695
226
696
227
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This supports reading and writing OTP fuses and keys. Only fuse reading
3
Remember if there was an SNaN, and use that to simplify
4
has been tested. Protection is not implemented.
4
float_2nan_prop_s_{ab,ba} to only the snan component.
5
Then, fall through to the corresponding
6
float_2nan_prop_{ab,ba} case to handle any remaining
7
nans, which must be quiet.
5
8
6
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
9
Tested-by: Alexander Bulekov <alxndr@bu.edu>
10
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
11
Message-id: 20200911052101.2602693-9-hskinnemoen@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
include/hw/arm/npcm7xx.h | 3 +
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
15
include/hw/nvram/npcm7xx_otp.h | 79 ++++++
15
1 file changed, 12 insertions(+), 20 deletions(-)
16
hw/arm/npcm7xx.c | 29 +++
17
hw/nvram/npcm7xx_otp.c | 440 +++++++++++++++++++++++++++++++++
18
hw/nvram/meson.build | 1 +
19
5 files changed, 552 insertions(+)
20
create mode 100644 include/hw/nvram/npcm7xx_otp.h
21
create mode 100644 hw/nvram/npcm7xx_otp.c
22
16
23
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/npcm7xx.h
19
--- a/fpu/softfloat-parts.c.inc
26
+++ b/include/hw/arm/npcm7xx.h
20
+++ b/fpu/softfloat-parts.c.inc
27
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
28
#include "hw/cpu/a9mpcore.h"
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
29
#include "hw/misc/npcm7xx_clk.h"
23
float_status *s)
30
#include "hw/misc/npcm7xx_gcr.h"
31
+#include "hw/nvram/npcm7xx_otp.h"
32
#include "hw/timer/npcm7xx_timer.h"
33
#include "target/arm/cpu.h"
34
35
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
36
NPCM7xxGCRState gcr;
37
NPCM7xxCLKState clk;
38
NPCM7xxTimerCtrlState tim[3];
39
+ NPCM7xxOTPState key_storage;
40
+ NPCM7xxOTPState fuse_array;
41
} NPCM7xxState;
42
43
#define TYPE_NPCM7XX "npcm7xx"
44
diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h
45
new file mode 100644
46
index XXXXXXX..XXXXXXX
47
--- /dev/null
48
+++ b/include/hw/nvram/npcm7xx_otp.h
49
@@ -XXX,XX +XXX,XX @@
50
+/*
51
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
52
+ *
53
+ * Copyright 2020 Google LLC
54
+ *
55
+ * This program is free software; you can redistribute it and/or modify it
56
+ * under the terms of the GNU General Public License as published by the
57
+ * Free Software Foundation; either version 2 of the License, or
58
+ * (at your option) any later version.
59
+ *
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
63
+ * for more details.
64
+ */
65
+#ifndef NPCM7XX_OTP_H
66
+#define NPCM7XX_OTP_H
67
+
68
+#include "exec/memory.h"
69
+#include "hw/sysbus.h"
70
+
71
+/* Each OTP module holds 8192 bits of one-time programmable storage */
72
+#define NPCM7XX_OTP_ARRAY_BITS (8192)
73
+#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE)
74
+
75
+/* Fuse array offsets */
76
+#define NPCM7XX_FUSE_FUSTRAP (0)
77
+#define NPCM7XX_FUSE_CP_FUSTRAP (12)
78
+#define NPCM7XX_FUSE_DAC_CALIB (16)
79
+#define NPCM7XX_FUSE_ADC_CALIB (24)
80
+#define NPCM7XX_FUSE_DERIVATIVE (64)
81
+#define NPCM7XX_FUSE_TEST_SIG (72)
82
+#define NPCM7XX_FUSE_DIE_LOCATION (74)
83
+#define NPCM7XX_FUSE_GP1 (80)
84
+#define NPCM7XX_FUSE_GP2 (128)
85
+
86
+/*
87
+ * Number of registers in our device state structure. Don't change this without
88
+ * incrementing the version_id in the vmstate.
89
+ */
90
+#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t))
91
+
92
+/**
93
+ * struct NPCM7xxOTPState - Device state for one OTP module.
94
+ * @parent: System bus device.
95
+ * @mmio: Memory region through which registers are accessed.
96
+ * @regs: Register contents.
97
+ * @array: OTP storage array.
98
+ */
99
+typedef struct NPCM7xxOTPState {
100
+ SysBusDevice parent;
101
+
102
+ MemoryRegion mmio;
103
+ uint32_t regs[NPCM7XX_OTP_NR_REGS];
104
+ uint8_t array[NPCM7XX_OTP_ARRAY_BYTES];
105
+} NPCM7xxOTPState;
106
+
107
+#define TYPE_NPCM7XX_OTP "npcm7xx-otp"
108
+#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP)
109
+
110
+#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage"
111
+#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array"
112
+
113
+typedef struct NPCM7xxOTPClass NPCM7xxOTPClass;
114
+
115
+/**
116
+ * npcm7xx_otp_array_write - ECC encode and write data to OTP array.
117
+ * @s: OTP module.
118
+ * @data: Data to be encoded and written.
119
+ * @offset: Offset of first byte to be written in the OTP array.
120
+ * @len: Number of bytes before ECC encoding.
121
+ *
122
+ * Each nibble of data is encoded into a byte, so the number of bytes written
123
+ * to the array will be @len * 2.
124
+ */
125
+extern void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
126
+ unsigned int offset, unsigned int len);
127
+
128
+#endif /* NPCM7XX_OTP_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/npcm7xx.c
132
+++ b/hw/arm/npcm7xx.c
133
@@ -XXX,XX +XXX,XX @@
134
#define NPCM7XX_MMIO_BA (0x80000000)
135
#define NPCM7XX_MMIO_SZ (0x7ffd0000)
136
137
+/* OTP key storage and fuse strap array */
138
+#define NPCM7XX_OTP1_BA (0xf0189000)
139
+#define NPCM7XX_OTP2_BA (0xf018a000)
140
+
141
/* Core system modules. */
142
#define NPCM7XX_L2C_BA (0xf03fc000)
143
#define NPCM7XX_CPUP_BA (0xf03fe000)
144
@@ -XXX,XX +XXX,XX @@ void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
145
arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
146
}
147
148
+static void npcm7xx_init_fuses(NPCM7xxState *s)
149
+{
150
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
151
+ uint32_t value;
152
+
153
+ /*
154
+ * The initial mask of disabled modules indicates the chip derivative (e.g.
155
+ * NPCM750 or NPCM730).
156
+ */
157
+ value = tswap32(nc->disabled_modules);
158
+ npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
159
+ sizeof(value));
160
+}
161
+
162
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
163
{
24
{
164
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
25
+ bool have_snan = false;
165
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
26
int cmp, which;
166
object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
27
167
"power-on-straps");
28
if (is_snan(a->cls) || is_snan(b->cls)) {
168
object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
169
+ object_initialize_child(obj, "otp1", &s->key_storage,
30
+ have_snan = true;
170
+ TYPE_NPCM7XX_KEY_STORAGE);
31
}
171
+ object_initialize_child(obj, "otp2", &s->fuse_array,
32
172
+ TYPE_NPCM7XX_FUSE_ARRAY);
33
if (s->default_nan_mode) {
173
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
174
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
35
175
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
36
switch (s->float_2nan_prop_rule) {
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
37
case float_2nan_prop_s_ab:
177
sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
38
- if (is_snan(a->cls)) {
178
sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
39
- which = 0;
179
40
- } else if (is_snan(b->cls)) {
180
+ /* OTP key storage and fuse strap array. Cannot fail. */
41
- which = 1;
181
+ sysbus_realize(SYS_BUS_DEVICE(&s->key_storage), &error_abort);
42
- } else if (is_qnan(a->cls)) {
182
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA);
43
- which = 0;
183
+ sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort);
44
- } else {
184
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
45
- which = 1;
185
+ npcm7xx_init_fuses(s);
46
+ if (have_snan) {
186
+
47
+ which = is_snan(a->cls) ? 0 : 1;
187
/* Timer Modules (TIM). Cannot fail. */
188
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
189
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
190
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
191
new file mode 100644
192
index XXXXXXX..XXXXXXX
193
--- /dev/null
194
+++ b/hw/nvram/npcm7xx_otp.c
195
@@ -XXX,XX +XXX,XX @@
196
+/*
197
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
198
+ *
199
+ * Copyright 2020 Google LLC
200
+ *
201
+ * This program is free software; you can redistribute it and/or modify it
202
+ * under the terms of the GNU General Public License as published by the
203
+ * Free Software Foundation; either version 2 of the License, or
204
+ * (at your option) any later version.
205
+ *
206
+ * This program is distributed in the hope that it will be useful, but WITHOUT
207
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
208
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
209
+ * for more details.
210
+ */
211
+
212
+#include "qemu/osdep.h"
213
+
214
+#include "hw/nvram/npcm7xx_otp.h"
215
+#include "migration/vmstate.h"
216
+#include "qapi/error.h"
217
+#include "qemu/bitops.h"
218
+#include "qemu/log.h"
219
+#include "qemu/module.h"
220
+#include "qemu/units.h"
221
+
222
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
223
+#define NPCM7XX_OTP_REGS_SIZE (4 * KiB)
224
+
225
+/* 32-bit register indices. */
226
+typedef enum NPCM7xxOTPRegister {
227
+ NPCM7XX_OTP_FST,
228
+ NPCM7XX_OTP_FADDR,
229
+ NPCM7XX_OTP_FDATA,
230
+ NPCM7XX_OTP_FCFG,
231
+ /* Offset 0x10 is FKEYIND in OTP1, FUSTRAP in OTP2 */
232
+ NPCM7XX_OTP_FKEYIND = 0x0010 / sizeof(uint32_t),
233
+ NPCM7XX_OTP_FUSTRAP = 0x0010 / sizeof(uint32_t),
234
+ NPCM7XX_OTP_FCTL,
235
+ NPCM7XX_OTP_REGS_END,
236
+} NPCM7xxOTPRegister;
237
+
238
+/* Register field definitions. */
239
+#define FST_RIEN BIT(2)
240
+#define FST_RDST BIT(1)
241
+#define FST_RDY BIT(0)
242
+#define FST_RO_MASK (FST_RDST | FST_RDY)
243
+
244
+#define FADDR_BYTEADDR(rv) extract32((rv), 0, 10)
245
+#define FADDR_BITPOS(rv) extract32((rv), 10, 3)
246
+
247
+#define FDATA_CLEAR 0x00000001
248
+
249
+#define FCFG_FDIS BIT(31)
250
+#define FCFG_FCFGLK_MASK 0x00ff0000
251
+
252
+#define FCTL_PROG_CMD1 0x00000001
253
+#define FCTL_PROG_CMD2 0xbf79e5d0
254
+#define FCTL_READ_CMD 0x00000002
255
+
256
+/**
257
+ * struct NPCM7xxOTPClass - OTP module class.
258
+ * @parent: System bus device class.
259
+ * @mmio_ops: MMIO register operations for this type of module.
260
+ *
261
+ * The two OTP modules (key-storage and fuse-array) have slightly different
262
+ * behavior, so we give them different MMIO register operations.
263
+ */
264
+struct NPCM7xxOTPClass {
265
+ SysBusDeviceClass parent;
266
+
267
+ const MemoryRegionOps *mmio_ops;
268
+};
269
+
270
+#define NPCM7XX_OTP_CLASS(klass) \
271
+ OBJECT_CLASS_CHECK(NPCM7xxOTPClass, (klass), TYPE_NPCM7XX_OTP)
272
+#define NPCM7XX_OTP_GET_CLASS(obj) \
273
+ OBJECT_GET_CLASS(NPCM7xxOTPClass, (obj), TYPE_NPCM7XX_OTP)
274
+
275
+static uint8_t ecc_encode_nibble(uint8_t n)
276
+{
277
+ uint8_t result = n;
278
+
279
+ result |= (((n >> 0) & 1) ^ ((n >> 1) & 1)) << 4;
280
+ result |= (((n >> 2) & 1) ^ ((n >> 3) & 1)) << 5;
281
+ result |= (((n >> 0) & 1) ^ ((n >> 2) & 1)) << 6;
282
+ result |= (((n >> 1) & 1) ^ ((n >> 3) & 1)) << 7;
283
+
284
+ return result;
285
+}
286
+
287
+void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
288
+ unsigned int offset, unsigned int len)
289
+{
290
+ const uint8_t *src = data;
291
+ uint8_t *dst = &s->array[offset];
292
+
293
+ while (len-- > 0) {
294
+ uint8_t c = *src++;
295
+
296
+ *dst++ = ecc_encode_nibble(extract8(c, 0, 4));
297
+ *dst++ = ecc_encode_nibble(extract8(c, 4, 4));
298
+ }
299
+}
300
+
301
+/* Common register read handler for both OTP classes. */
302
+static uint64_t npcm7xx_otp_read(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg)
303
+{
304
+ uint32_t value = 0;
305
+
306
+ switch (reg) {
307
+ case NPCM7XX_OTP_FST:
308
+ case NPCM7XX_OTP_FADDR:
309
+ case NPCM7XX_OTP_FDATA:
310
+ case NPCM7XX_OTP_FCFG:
311
+ value = s->regs[reg];
312
+ break;
313
+
314
+ case NPCM7XX_OTP_FCTL:
315
+ qemu_log_mask(LOG_GUEST_ERROR,
316
+ "%s: read from write-only FCTL register\n",
317
+ DEVICE(s)->canonical_path);
318
+ break;
319
+
320
+ default:
321
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read from invalid offset 0x%zx\n",
322
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
323
+ break;
324
+ }
325
+
326
+ return value;
327
+}
328
+
329
+/* Read a byte from the OTP array into the data register. */
330
+static void npcm7xx_otp_read_array(NPCM7xxOTPState *s)
331
+{
332
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
333
+
334
+ s->regs[NPCM7XX_OTP_FDATA] = s->array[FADDR_BYTEADDR(faddr)];
335
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
336
+}
337
+
338
+/* Program a byte from the data register into the OTP array. */
339
+static void npcm7xx_otp_program_array(NPCM7xxOTPState *s)
340
+{
341
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
342
+
343
+ /* Bits can only go 0->1, never 1->0. */
344
+ s->array[FADDR_BYTEADDR(faddr)] |= (1U << FADDR_BITPOS(faddr));
345
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
346
+}
347
+
348
+/* Compute the next value of the FCFG register. */
349
+static uint32_t npcm7xx_otp_compute_fcfg(uint32_t cur_value, uint32_t new_value)
350
+{
351
+ uint32_t lock_mask;
352
+ uint32_t value;
353
+
354
+ /*
355
+ * FCFGLK holds sticky bits 16..23, indicating which bits in FPRGLK (8..15)
356
+ * and FRDLK (0..7) that are read-only.
357
+ */
358
+ lock_mask = (cur_value & FCFG_FCFGLK_MASK) >> 8;
359
+ lock_mask |= lock_mask >> 8;
360
+ /* FDIS and FCFGLK bits are sticky (write 1 to set; can't clear). */
361
+ value = cur_value & (FCFG_FDIS | FCFG_FCFGLK_MASK);
362
+ /* Preserve read-only bits in FPRGLK and FRDLK */
363
+ value |= cur_value & lock_mask;
364
+ /* Set all bits that aren't read-only. */
365
+ value |= new_value & ~lock_mask;
366
+
367
+ return value;
368
+}
369
+
370
+/* Common register write handler for both OTP classes. */
371
+static void npcm7xx_otp_write(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg,
372
+ uint32_t value)
373
+{
374
+ switch (reg) {
375
+ case NPCM7XX_OTP_FST:
376
+ /* RDST is cleared by writing 1 to it. */
377
+ if (value & FST_RDST) {
378
+ s->regs[NPCM7XX_OTP_FST] &= ~FST_RDST;
379
+ }
380
+ /* Preserve read-only and write-one-to-clear bits */
381
+ value &= ~FST_RO_MASK;
382
+ value |= s->regs[NPCM7XX_OTP_FST] & FST_RO_MASK;
383
+ break;
384
+
385
+ case NPCM7XX_OTP_FADDR:
386
+ break;
387
+
388
+ case NPCM7XX_OTP_FDATA:
389
+ /*
390
+ * This register is cleared by writing a magic value to it; no other
391
+ * values can be written.
392
+ */
393
+ if (value == FDATA_CLEAR) {
394
+ value = 0;
395
+ } else {
396
+ value = s->regs[NPCM7XX_OTP_FDATA];
397
+ }
398
+ break;
399
+
400
+ case NPCM7XX_OTP_FCFG:
401
+ value = npcm7xx_otp_compute_fcfg(s->regs[NPCM7XX_OTP_FCFG], value);
402
+ break;
403
+
404
+ case NPCM7XX_OTP_FCTL:
405
+ switch (value) {
406
+ case FCTL_READ_CMD:
407
+ npcm7xx_otp_read_array(s);
408
+ break;
48
+ break;
409
+
49
}
410
+ case FCTL_PROG_CMD1:
50
- break;
411
+ /*
51
- case float_2nan_prop_s_ba:
412
+ * Programming requires writing two separate magic values to this
52
- if (is_snan(b->cls)) {
413
+ * register; this is the first one. Just store it so it can be
53
- which = 1;
414
+ * verified later when the second magic value is received.
54
- } else if (is_snan(a->cls)) {
415
+ */
55
- which = 0;
416
+ break;
56
- } else if (is_qnan(b->cls)) {
417
+
57
- which = 1;
418
+ case FCTL_PROG_CMD2:
58
- } else {
419
+ /*
59
- which = 0;
420
+ * Only initiate programming if we received the first half of the
60
- }
421
+ * command immediately before this one.
61
- break;
422
+ */
62
+ /* fall through */
423
+ if (s->regs[NPCM7XX_OTP_FCTL] == FCTL_PROG_CMD1) {
63
case float_2nan_prop_ab:
424
+ npcm7xx_otp_program_array(s);
64
which = is_nan(a->cls) ? 0 : 1;
425
+ }
65
break;
426
+ break;
66
+ case float_2nan_prop_s_ba:
427
+
67
+ if (have_snan) {
428
+ default:
68
+ which = is_snan(b->cls) ? 1 : 0;
429
+ qemu_log_mask(LOG_GUEST_ERROR,
430
+ "%s: unrecognized FCNTL value 0x%" PRIx32 "\n",
431
+ DEVICE(s)->canonical_path, value);
432
+ break;
69
+ break;
433
+ }
70
+ }
434
+ if (value != FCTL_PROG_CMD1) {
71
+ /* fall through */
435
+ value = 0;
72
case float_2nan_prop_ba:
436
+ }
73
which = is_nan(b->cls) ? 1 : 0;
437
+ break;
74
break;
438
+
439
+ default:
440
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to invalid offset 0x%zx\n",
441
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
442
+ return;
443
+ }
444
+
445
+ s->regs[reg] = value;
446
+}
447
+
448
+/* Register read handler specific to the fuse array OTP module. */
449
+static uint64_t npcm7xx_fuse_array_read(void *opaque, hwaddr addr,
450
+ unsigned int size)
451
+{
452
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
453
+ NPCM7xxOTPState *s = opaque;
454
+ uint32_t value;
455
+
456
+ /*
457
+ * Only the Fuse Strap register needs special handling; all other registers
458
+ * work the same way for both kinds of OTP modules.
459
+ */
460
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
461
+ value = npcm7xx_otp_read(s, reg);
462
+ } else {
463
+ /* FUSTRAP is stored as three copies in the OTP array. */
464
+ uint32_t fustrap[3];
465
+
466
+ memcpy(fustrap, &s->array[0], sizeof(fustrap));
467
+
468
+ /* Determine value by a majority vote on each bit. */
469
+ value = (fustrap[0] & fustrap[1]) | (fustrap[0] & fustrap[2]) |
470
+ (fustrap[1] & fustrap[2]);
471
+ }
472
+
473
+ return value;
474
+}
475
+
476
+/* Register write handler specific to the fuse array OTP module. */
477
+static void npcm7xx_fuse_array_write(void *opaque, hwaddr addr, uint64_t v,
478
+ unsigned int size)
479
+{
480
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
481
+ NPCM7xxOTPState *s = opaque;
482
+
483
+ /*
484
+ * The Fuse Strap register is read-only. Other registers are handled by
485
+ * common code.
486
+ */
487
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
488
+ npcm7xx_otp_write(s, reg, v);
489
+ }
490
+}
491
+
492
+static const MemoryRegionOps npcm7xx_fuse_array_ops = {
493
+ .read = npcm7xx_fuse_array_read,
494
+ .write = npcm7xx_fuse_array_write,
495
+ .endianness = DEVICE_LITTLE_ENDIAN,
496
+ .valid = {
497
+ .min_access_size = 4,
498
+ .max_access_size = 4,
499
+ .unaligned = false,
500
+ },
501
+};
502
+
503
+/* Register read handler specific to the key storage OTP module. */
504
+static uint64_t npcm7xx_key_storage_read(void *opaque, hwaddr addr,
505
+ unsigned int size)
506
+{
507
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
508
+ NPCM7xxOTPState *s = opaque;
509
+
510
+ /*
511
+ * Only the Fuse Key Index register needs special handling; all other
512
+ * registers work the same way for both kinds of OTP modules.
513
+ */
514
+ if (reg != NPCM7XX_OTP_FKEYIND) {
515
+ return npcm7xx_otp_read(s, reg);
516
+ }
517
+
518
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
519
+
520
+ return s->regs[NPCM7XX_OTP_FKEYIND];
521
+}
522
+
523
+/* Register write handler specific to the key storage OTP module. */
524
+static void npcm7xx_key_storage_write(void *opaque, hwaddr addr, uint64_t v,
525
+ unsigned int size)
526
+{
527
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
528
+ NPCM7xxOTPState *s = opaque;
529
+
530
+ /*
531
+ * Only the Fuse Key Index register needs special handling; all other
532
+ * registers work the same way for both kinds of OTP modules.
533
+ */
534
+ if (reg != NPCM7XX_OTP_FKEYIND) {
535
+ npcm7xx_otp_write(s, reg, v);
536
+ return;
537
+ }
538
+
539
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
540
+
541
+ s->regs[NPCM7XX_OTP_FKEYIND] = v;
542
+}
543
+
544
+static const MemoryRegionOps npcm7xx_key_storage_ops = {
545
+ .read = npcm7xx_key_storage_read,
546
+ .write = npcm7xx_key_storage_write,
547
+ .endianness = DEVICE_LITTLE_ENDIAN,
548
+ .valid = {
549
+ .min_access_size = 4,
550
+ .max_access_size = 4,
551
+ .unaligned = false,
552
+ },
553
+};
554
+
555
+static void npcm7xx_otp_enter_reset(Object *obj, ResetType type)
556
+{
557
+ NPCM7xxOTPState *s = NPCM7XX_OTP(obj);
558
+
559
+ memset(s->regs, 0, sizeof(s->regs));
560
+
561
+ s->regs[NPCM7XX_OTP_FST] = 0x00000001;
562
+ s->regs[NPCM7XX_OTP_FCFG] = 0x20000000;
563
+}
564
+
565
+static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
566
+{
567
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
568
+ NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
569
+ SysBusDevice *sbd = &s->parent;
570
+
571
+ memset(s->array, 0, sizeof(s->array));
572
+
573
+ memory_region_init_io(&s->mmio, OBJECT(s), oc->mmio_ops, s, "regs",
574
+ NPCM7XX_OTP_REGS_SIZE);
575
+ sysbus_init_mmio(sbd, &s->mmio);
576
+}
577
+
578
+static const VMStateDescription vmstate_npcm7xx_otp = {
579
+ .name = "npcm7xx-otp",
580
+ .version_id = 0,
581
+ .minimum_version_id = 0,
582
+ .fields = (VMStateField[]) {
583
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxOTPState, NPCM7XX_OTP_NR_REGS),
584
+ VMSTATE_UINT8_ARRAY(array, NPCM7xxOTPState, NPCM7XX_OTP_ARRAY_BYTES),
585
+ VMSTATE_END_OF_LIST(),
586
+ },
587
+};
588
+
589
+static void npcm7xx_otp_class_init(ObjectClass *klass, void *data)
590
+{
591
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
592
+ DeviceClass *dc = DEVICE_CLASS(klass);
593
+
594
+ QEMU_BUILD_BUG_ON(NPCM7XX_OTP_REGS_END > NPCM7XX_OTP_NR_REGS);
595
+
596
+ dc->realize = npcm7xx_otp_realize;
597
+ dc->vmsd = &vmstate_npcm7xx_otp;
598
+ rc->phases.enter = npcm7xx_otp_enter_reset;
599
+}
600
+
601
+static void npcm7xx_key_storage_class_init(ObjectClass *klass, void *data)
602
+{
603
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
604
+
605
+ oc->mmio_ops = &npcm7xx_key_storage_ops;
606
+}
607
+
608
+static void npcm7xx_fuse_array_class_init(ObjectClass *klass, void *data)
609
+{
610
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
611
+
612
+ oc->mmio_ops = &npcm7xx_fuse_array_ops;
613
+}
614
+
615
+static const TypeInfo npcm7xx_otp_types[] = {
616
+ {
617
+ .name = TYPE_NPCM7XX_OTP,
618
+ .parent = TYPE_SYS_BUS_DEVICE,
619
+ .instance_size = sizeof(NPCM7xxOTPState),
620
+ .class_size = sizeof(NPCM7xxOTPClass),
621
+ .class_init = npcm7xx_otp_class_init,
622
+ .abstract = true,
623
+ },
624
+ {
625
+ .name = TYPE_NPCM7XX_KEY_STORAGE,
626
+ .parent = TYPE_NPCM7XX_OTP,
627
+ .class_init = npcm7xx_key_storage_class_init,
628
+ },
629
+ {
630
+ .name = TYPE_NPCM7XX_FUSE_ARRAY,
631
+ .parent = TYPE_NPCM7XX_OTP,
632
+ .class_init = npcm7xx_fuse_array_class_init,
633
+ },
634
+};
635
+DEFINE_TYPES(npcm7xx_otp_types);
636
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
637
index XXXXXXX..XXXXXXX 100644
638
--- a/hw/nvram/meson.build
639
+++ b/hw/nvram/meson.build
640
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_DS1225Y', if_true: files('ds1225y.c'))
641
softmmu_ss.add(when: 'CONFIG_NMC93XX_EEPROM', if_true: files('eeprom93xx.c'))
642
softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c'))
643
softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c'))
644
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c'))
645
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c'))
646
647
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
648
--
75
--
649
2.20.1
76
2.34.1
650
651
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Only argument set members have to be C identifiers, everything
3
Move the fractional comparison to the end of the
4
else gets prefixed during conversion to C. Some places just
4
float_2nan_prop_x87 case. This is not required for
5
checked the leading character, and some places matched a leading
5
any other 2nan propagation rule. Reorganize the
6
character plus a C identifier.
6
x87 case itself to break out of the switch when the
7
fractional comparison is not required.
7
8
8
Convert everything to match full identifiers, including the
9
[&%@&] prefix, and drop the full C identifier requirement.
10
11
Reported-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20200903192334.1603773-1-richard.henderson@linaro.org
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
13
---
17
tests/decode/succ_ident1.decode | 7 +++++
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
18
scripts/decodetree.py | 46 +++++++++++++++++++++------------
15
1 file changed, 9 insertions(+), 10 deletions(-)
19
2 files changed, 37 insertions(+), 16 deletions(-)
20
create mode 100644 tests/decode/succ_ident1.decode
21
16
22
diff --git a/tests/decode/succ_ident1.decode b/tests/decode/succ_ident1.decode
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
23
new file mode 100644
24
index XXXXXXX..XXXXXXX
25
--- /dev/null
26
+++ b/tests/decode/succ_ident1.decode
27
@@ -XXX,XX +XXX,XX @@
28
+%1f 0:8
29
+%2f 8:8
30
+%3f 16:8
31
+
32
+&3arg a b c
33
+@3arg ........ ........ ........ ........ &3arg a=%1f b=%2f c=%3f
34
+3insn 00000000 ........ ........ ........ @3arg
35
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
36
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
37
--- a/scripts/decodetree.py
19
--- a/fpu/softfloat-parts.c.inc
38
+++ b/scripts/decodetree.py
20
+++ b/fpu/softfloat-parts.c.inc
39
@@ -XXX,XX +XXX,XX @@ output_fd = None
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
40
insntype = 'uint32_t'
22
return a;
41
decode_function = 'decode'
23
}
42
24
43
-re_ident = '[a-zA-Z][a-zA-Z0-9_]*'
25
- cmp = frac_cmp(a, b);
44
+# An identifier for C.
26
- if (cmp == 0) {
45
+re_C_ident = '[a-zA-Z][a-zA-Z0-9_]*'
27
- cmp = a->sign < b->sign;
46
28
- }
47
+# Identifiers for Arguments, Fields, Formats and Patterns.
29
-
48
+re_arg_ident = '&[a-zA-Z0-9_]*'
30
switch (s->float_2nan_prop_rule) {
49
+re_fld_ident = '%[a-zA-Z0-9_]*'
31
case float_2nan_prop_s_ab:
50
+re_fmt_ident = '@[a-zA-Z0-9_]*'
32
if (have_snan) {
51
+re_pat_ident = '[a-zA-Z0-9_]*'
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
52
34
* return the NaN with the positive sign bit (if any).
53
def error_with_file(file, lineno, *args):
35
*/
54
"""Print an error message from file:line and args and exit."""
36
if (is_snan(a->cls)) {
55
@@ -XXX,XX +XXX,XX @@ class ExcMultiPattern(MultiPattern):
37
- if (is_snan(b->cls)) {
56
def parse_field(lineno, name, toks):
38
- which = cmp > 0 ? 0 : 1;
57
"""Parse one instruction field from TOKS at LINENO"""
39
- } else {
58
global fields
40
+ if (!is_snan(b->cls)) {
59
- global re_ident
41
which = is_qnan(b->cls) ? 1 : 0;
60
global insnwidth
42
+ break;
61
43
}
62
# A "simple" field will have only one entry;
44
} else if (is_qnan(a->cls)) {
63
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
64
width = 0
46
which = 0;
65
func = None
47
- } else {
66
for t in toks:
48
- which = cmp > 0 ? 0 : 1;
67
- if re.fullmatch('!function=' + re_ident, t):
49
+ break;
68
+ if re.match('^!function=', t):
50
}
69
if func:
51
} else {
70
error(lineno, 'duplicate function')
52
which = 1;
71
func = t.split('=')
53
+ break;
72
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
54
}
73
def parse_arguments(lineno, name, toks):
55
+ cmp = frac_cmp(a, b);
74
"""Parse one argument set from TOKS at LINENO"""
56
+ if (cmp == 0) {
75
global arguments
57
+ cmp = a->sign < b->sign;
76
- global re_ident
58
+ }
77
+ global re_C_ident
59
+ which = cmp > 0 ? 0 : 1;
78
global anyextern
60
break;
79
61
default:
80
flds = []
62
g_assert_not_reached();
81
@@ -XXX,XX +XXX,XX @@ def parse_arguments(lineno, name, toks):
82
extern = True
83
anyextern = True
84
continue
85
- if not re.fullmatch(re_ident, t):
86
+ if not re.fullmatch(re_C_ident, t):
87
error(lineno, 'invalid argument set token "{0}"'.format(t))
88
if t in flds:
89
error(lineno, 'duplicate argument "{0}"'.format(t))
90
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
91
global arguments
92
global formats
93
global allpatterns
94
- global re_ident
95
+ global re_arg_ident
96
+ global re_fld_ident
97
+ global re_fmt_ident
98
+ global re_C_ident
99
global insnwidth
100
global insnmask
101
global variablewidth
102
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
103
fmt = None
104
for t in toks:
105
# '&Foo' gives a format an explcit argument set.
106
- if t[0] == '&':
107
+ if re.fullmatch(re_arg_ident, t):
108
tt = t[1:]
109
if arg:
110
error(lineno, 'multiple argument sets')
111
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
112
continue
113
114
# '@Foo' gives a pattern an explicit format.
115
- if t[0] == '@':
116
+ if re.fullmatch(re_fmt_ident, t):
117
tt = t[1:]
118
if fmt:
119
error(lineno, 'multiple formats')
120
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
121
continue
122
123
# '%Foo' imports a field.
124
- if t[0] == '%':
125
+ if re.fullmatch(re_fld_ident, t):
126
tt = t[1:]
127
flds = add_field_byname(lineno, flds, tt, tt)
128
continue
129
130
# 'Foo=%Bar' imports a field with a different name.
131
- if re.fullmatch(re_ident + '=%' + re_ident, t):
132
+ if re.fullmatch(re_C_ident + '=' + re_fld_ident, t):
133
(fname, iname) = t.split('=%')
134
flds = add_field_byname(lineno, flds, fname, iname)
135
continue
136
137
# 'Foo=number' sets an argument field to a constant value
138
- if re.fullmatch(re_ident + '=[+-]?[0-9]+', t):
139
+ if re.fullmatch(re_C_ident + '=[+-]?[0-9]+', t):
140
(fname, value) = t.split('=')
141
value = int(value)
142
flds = add_field(lineno, flds, fname, ConstField(value))
143
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
144
fixedmask = (fixedmask << shift) | fms
145
undefmask = (undefmask << shift) | ubm
146
# Otherwise, fieldname:fieldwidth
147
- elif re.fullmatch(re_ident + ':s?[0-9]+', t):
148
+ elif re.fullmatch(re_C_ident + ':s?[0-9]+', t):
149
(fname, flen) = t.split(':')
150
sign = False
151
if flen[0] == 's':
152
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
153
154
def parse_file(f, parent_pat):
155
"""Parse all of the patterns within a file"""
156
+ global re_arg_ident
157
+ global re_fld_ident
158
+ global re_fmt_ident
159
+ global re_pat_ident
160
161
# Read all of the lines of the file. Concatenate lines
162
# ending in backslash; discard empty lines and comments.
163
@@ -XXX,XX +XXX,XX @@ def parse_file(f, parent_pat):
164
continue
165
166
# Determine the type of object needing to be parsed.
167
- if name[0] == '%':
168
+ if re.fullmatch(re_fld_ident, name):
169
parse_field(start_lineno, name[1:], toks)
170
- elif name[0] == '&':
171
+ elif re.fullmatch(re_arg_ident, name):
172
parse_arguments(start_lineno, name[1:], toks)
173
- elif name[0] == '@':
174
+ elif re.fullmatch(re_fmt_ident, name):
175
parse_generic(start_lineno, None, name[1:], toks)
176
- else:
177
+ elif re.fullmatch(re_pat_ident, name):
178
parse_generic(start_lineno, parent_pat, name, toks)
179
+ else:
180
+ error(lineno, 'invalid token "{0}"'.format(name))
181
toks = []
182
183
if nesting != 0:
184
--
63
--
185
2.20.1
64
2.34.1
186
187
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Per the datasheet (DDI0407 r2p0):
3
Replace the "index" selecting between A and B with a result variable
4
of the proper type. This improves clarity within the function.
4
5
5
"The SCU connects one to four Cortex-A9 processors to
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
the memory system through the AXI interfaces."
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
8
Change the instance_init() handler to a device_realize()
9
one so we can verify the property is in range, and return
10
an error to the caller if not.
11
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200901144100.116742-2-f4bug@amsat.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
hw/misc/a9scu.c | 18 +++++++++++++-----
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
18
1 file changed, 13 insertions(+), 5 deletions(-)
12
1 file changed, 13 insertions(+), 15 deletions(-)
19
13
20
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/a9scu.c
16
--- a/fpu/softfloat-parts.c.inc
23
+++ b/hw/misc/a9scu.c
17
+++ b/fpu/softfloat-parts.c.inc
24
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
25
#include "hw/misc/a9scu.h"
19
float_status *s)
26
#include "hw/qdev-properties.h"
27
#include "migration/vmstate.h"
28
+#include "qapi/error.h"
29
#include "qemu/module.h"
30
31
+#define A9_SCU_CPU_MAX 4
32
+
33
static uint64_t a9_scu_read(void *opaque, hwaddr offset,
34
unsigned size)
35
{
20
{
36
@@ -XXX,XX +XXX,XX @@ static void a9_scu_reset(DeviceState *dev)
21
bool have_snan = false;
37
s->control = 0;
22
- int cmp, which;
23
+ FloatPartsN *ret;
24
+ int cmp;
25
26
if (is_snan(a->cls) || is_snan(b->cls)) {
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
29
switch (s->float_2nan_prop_rule) {
30
case float_2nan_prop_s_ab:
31
if (have_snan) {
32
- which = is_snan(a->cls) ? 0 : 1;
33
+ ret = is_snan(a->cls) ? a : b;
34
break;
35
}
36
/* fall through */
37
case float_2nan_prop_ab:
38
- which = is_nan(a->cls) ? 0 : 1;
39
+ ret = is_nan(a->cls) ? a : b;
40
break;
41
case float_2nan_prop_s_ba:
42
if (have_snan) {
43
- which = is_snan(b->cls) ? 1 : 0;
44
+ ret = is_snan(b->cls) ? b : a;
45
break;
46
}
47
/* fall through */
48
case float_2nan_prop_ba:
49
- which = is_nan(b->cls) ? 1 : 0;
50
+ ret = is_nan(b->cls) ? b : a;
51
break;
52
case float_2nan_prop_x87:
53
/*
54
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
55
*/
56
if (is_snan(a->cls)) {
57
if (!is_snan(b->cls)) {
58
- which = is_qnan(b->cls) ? 1 : 0;
59
+ ret = is_qnan(b->cls) ? b : a;
60
break;
61
}
62
} else if (is_qnan(a->cls)) {
63
if (is_snan(b->cls) || !is_qnan(b->cls)) {
64
- which = 0;
65
+ ret = a;
66
break;
67
}
68
} else {
69
- which = 1;
70
+ ret = b;
71
break;
72
}
73
cmp = frac_cmp(a, b);
74
if (cmp == 0) {
75
cmp = a->sign < b->sign;
76
}
77
- which = cmp > 0 ? 0 : 1;
78
+ ret = cmp > 0 ? a : b;
79
break;
80
default:
81
g_assert_not_reached();
82
}
83
84
- if (which) {
85
- a = b;
86
+ if (is_snan(ret->cls)) {
87
+ parts_silence_nan(ret, s);
88
}
89
- if (is_snan(a->cls)) {
90
- parts_silence_nan(a, s);
91
- }
92
- return a;
93
+ return ret;
38
}
94
}
39
95
40
-static void a9_scu_init(Object *obj)
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
41
+static void a9_scu_realize(DeviceState *dev, Error **errp)
42
{
43
- A9SCUState *s = A9_SCU(obj);
44
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
45
+ A9SCUState *s = A9_SCU(dev);
46
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
47
48
- memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
49
+ if (!s->num_cpu || s->num_cpu > A9_SCU_CPU_MAX) {
50
+ error_setg(errp, "Illegal CPU count: %u", s->num_cpu);
51
+ return;
52
+ }
53
+
54
+ memory_region_init_io(&s->iomem, OBJECT(s), &a9_scu_ops, s,
55
"a9-scu", 0x100);
56
sysbus_init_mmio(sbd, &s->iomem);
57
}
58
@@ -XXX,XX +XXX,XX @@ static void a9_scu_class_init(ObjectClass *klass, void *data)
59
device_class_set_props(dc, a9_scu_properties);
60
dc->vmsd = &vmstate_a9_scu;
61
dc->reset = a9_scu_reset;
62
+ dc->realize = a9_scu_realize;
63
}
64
65
static const TypeInfo a9_scu_info = {
66
.name = TYPE_A9_SCU,
67
.parent = TYPE_SYS_BUS_DEVICE,
68
.instance_size = sizeof(A9SCUState),
69
- .instance_init = a9_scu_init,
70
.class_init = a9_scu_class_init,
71
};
72
73
--
97
--
74
2.20.1
98
2.34.1
75
99
76
100
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Implement a device model for the System Global Control Registers in the
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
NPCM730 and NPCM750 BMC SoCs.
4
update my email address, and update the mailmap to match.
5
5
6
This is primarily used to enable SMP boot (the boot ROM spins reading
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
7
the SCRPAD register) and DDR memory initialization; other registers are
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
best effort for now.
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
9
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
The reset values of the MDLR and PWRON registers are determined by the
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
SoC variant (730 vs 750) and board straps respectively.
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
12
13
Reviewed-by: Joel Stanley <joel@jms.id.au>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Alexander Bulekov <alxndr@bu.edu>
18
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
19
Message-id: 20200911052101.2602693-2-hskinnemoen@google.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
13
---
22
include/hw/misc/npcm7xx_gcr.h | 43 ++++++
14
MAINTAINERS | 2 +-
23
hw/misc/npcm7xx_gcr.c | 269 ++++++++++++++++++++++++++++++++++
15
.mailmap | 5 +++--
24
MAINTAINERS | 8 +
16
2 files changed, 4 insertions(+), 3 deletions(-)
25
hw/arm/Kconfig | 3 +
26
hw/misc/meson.build | 3 +
27
hw/misc/trace-events | 4 +
28
6 files changed, 330 insertions(+)
29
create mode 100644 include/hw/misc/npcm7xx_gcr.h
30
create mode 100644 hw/misc/npcm7xx_gcr.c
31
17
32
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/npcm7xx_gcr.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * Nuvoton NPCM7xx System Global Control Registers.
40
+ *
41
+ * Copyright 2020 Google LLC
42
+ *
43
+ * This program is free software; you can redistribute it and/or modify it
44
+ * under the terms of the GNU General Public License as published by the
45
+ * Free Software Foundation; either version 2 of the License, or
46
+ * (at your option) any later version.
47
+ *
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51
+ * for more details.
52
+ */
53
+#ifndef NPCM7XX_GCR_H
54
+#define NPCM7XX_GCR_H
55
+
56
+#include "exec/memory.h"
57
+#include "hw/sysbus.h"
58
+
59
+/*
60
+ * Number of registers in our device state structure. Don't change this without
61
+ * incrementing the version_id in the vmstate.
62
+ */
63
+#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
64
+
65
+typedef struct NPCM7xxGCRState {
66
+ SysBusDevice parent;
67
+
68
+ MemoryRegion iomem;
69
+
70
+ uint32_t regs[NPCM7XX_GCR_NR_REGS];
71
+
72
+ uint32_t reset_pwron;
73
+ uint32_t reset_mdlr;
74
+ uint32_t reset_intcr3;
75
+} NPCM7xxGCRState;
76
+
77
+#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
78
+#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
79
+
80
+#endif /* NPCM7XX_GCR_H */
81
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
82
new file mode 100644
83
index XXXXXXX..XXXXXXX
84
--- /dev/null
85
+++ b/hw/misc/npcm7xx_gcr.c
86
@@ -XXX,XX +XXX,XX @@
87
+/*
88
+ * Nuvoton NPCM7xx System Global Control Registers.
89
+ *
90
+ * Copyright 2020 Google LLC
91
+ *
92
+ * This program is free software; you can redistribute it and/or modify it
93
+ * under the terms of the GNU General Public License as published by the
94
+ * Free Software Foundation; either version 2 of the License, or
95
+ * (at your option) any later version.
96
+ *
97
+ * This program is distributed in the hope that it will be useful, but WITHOUT
98
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
99
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
100
+ * for more details.
101
+ */
102
+
103
+#include "qemu/osdep.h"
104
+
105
+#include "hw/misc/npcm7xx_gcr.h"
106
+#include "hw/qdev-properties.h"
107
+#include "migration/vmstate.h"
108
+#include "qapi/error.h"
109
+#include "qemu/cutils.h"
110
+#include "qemu/log.h"
111
+#include "qemu/module.h"
112
+#include "qemu/units.h"
113
+
114
+#include "trace.h"
115
+
116
+#define NPCM7XX_GCR_MIN_DRAM_SIZE (128 * MiB)
117
+#define NPCM7XX_GCR_MAX_DRAM_SIZE (2 * GiB)
118
+
119
+enum NPCM7xxGCRRegisters {
120
+ NPCM7XX_GCR_PDID,
121
+ NPCM7XX_GCR_PWRON,
122
+ NPCM7XX_GCR_MFSEL1 = 0x0c / sizeof(uint32_t),
123
+ NPCM7XX_GCR_MFSEL2,
124
+ NPCM7XX_GCR_MISCPE,
125
+ NPCM7XX_GCR_SPSWC = 0x038 / sizeof(uint32_t),
126
+ NPCM7XX_GCR_INTCR,
127
+ NPCM7XX_GCR_INTSR,
128
+ NPCM7XX_GCR_HIFCR = 0x050 / sizeof(uint32_t),
129
+ NPCM7XX_GCR_INTCR2 = 0x060 / sizeof(uint32_t),
130
+ NPCM7XX_GCR_MFSEL3,
131
+ NPCM7XX_GCR_SRCNT,
132
+ NPCM7XX_GCR_RESSR,
133
+ NPCM7XX_GCR_RLOCKR1,
134
+ NPCM7XX_GCR_FLOCKR1,
135
+ NPCM7XX_GCR_DSCNT,
136
+ NPCM7XX_GCR_MDLR,
137
+ NPCM7XX_GCR_SCRPAD3,
138
+ NPCM7XX_GCR_SCRPAD2,
139
+ NPCM7XX_GCR_DAVCLVLR = 0x098 / sizeof(uint32_t),
140
+ NPCM7XX_GCR_INTCR3,
141
+ NPCM7XX_GCR_VSINTR = 0x0ac / sizeof(uint32_t),
142
+ NPCM7XX_GCR_MFSEL4,
143
+ NPCM7XX_GCR_CPBPNTR = 0x0c4 / sizeof(uint32_t),
144
+ NPCM7XX_GCR_CPCTL = 0x0d0 / sizeof(uint32_t),
145
+ NPCM7XX_GCR_CP2BST,
146
+ NPCM7XX_GCR_B2CPNT,
147
+ NPCM7XX_GCR_CPPCTL,
148
+ NPCM7XX_GCR_I2CSEGSEL,
149
+ NPCM7XX_GCR_I2CSEGCTL,
150
+ NPCM7XX_GCR_VSRCR,
151
+ NPCM7XX_GCR_MLOCKR,
152
+ NPCM7XX_GCR_SCRPAD = 0x013c / sizeof(uint32_t),
153
+ NPCM7XX_GCR_USB1PHYCTL,
154
+ NPCM7XX_GCR_USB2PHYCTL,
155
+ NPCM7XX_GCR_REGS_END,
156
+};
157
+
158
+static const uint32_t cold_reset_values[NPCM7XX_GCR_NR_REGS] = {
159
+ [NPCM7XX_GCR_PDID] = 0x04a92750, /* Poleg A1 */
160
+ [NPCM7XX_GCR_MISCPE] = 0x0000ffff,
161
+ [NPCM7XX_GCR_SPSWC] = 0x00000003,
162
+ [NPCM7XX_GCR_INTCR] = 0x0000035e,
163
+ [NPCM7XX_GCR_HIFCR] = 0x0000004e,
164
+ [NPCM7XX_GCR_INTCR2] = (1U << 19), /* DDR initialized */
165
+ [NPCM7XX_GCR_RESSR] = 0x80000000,
166
+ [NPCM7XX_GCR_DSCNT] = 0x000000c0,
167
+ [NPCM7XX_GCR_DAVCLVLR] = 0x5a00f3cf,
168
+ [NPCM7XX_GCR_SCRPAD] = 0x00000008,
169
+ [NPCM7XX_GCR_USB1PHYCTL] = 0x034730e4,
170
+ [NPCM7XX_GCR_USB2PHYCTL] = 0x034730e4,
171
+};
172
+
173
+static uint64_t npcm7xx_gcr_read(void *opaque, hwaddr offset, unsigned size)
174
+{
175
+ uint32_t reg = offset / sizeof(uint32_t);
176
+ NPCM7xxGCRState *s = opaque;
177
+
178
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
179
+ qemu_log_mask(LOG_GUEST_ERROR,
180
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
181
+ __func__, offset);
182
+ return 0;
183
+ }
184
+
185
+ trace_npcm7xx_gcr_read(offset, s->regs[reg]);
186
+
187
+ return s->regs[reg];
188
+}
189
+
190
+static void npcm7xx_gcr_write(void *opaque, hwaddr offset,
191
+ uint64_t v, unsigned size)
192
+{
193
+ uint32_t reg = offset / sizeof(uint32_t);
194
+ NPCM7xxGCRState *s = opaque;
195
+ uint32_t value = v;
196
+
197
+ trace_npcm7xx_gcr_write(offset, value);
198
+
199
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
200
+ qemu_log_mask(LOG_GUEST_ERROR,
201
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
202
+ __func__, offset);
203
+ return;
204
+ }
205
+
206
+ switch (reg) {
207
+ case NPCM7XX_GCR_PDID:
208
+ case NPCM7XX_GCR_PWRON:
209
+ case NPCM7XX_GCR_INTSR:
210
+ qemu_log_mask(LOG_GUEST_ERROR,
211
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
212
+ __func__, offset);
213
+ return;
214
+
215
+ case NPCM7XX_GCR_RESSR:
216
+ case NPCM7XX_GCR_CP2BST:
217
+ /* Write 1 to clear */
218
+ value = s->regs[reg] & ~value;
219
+ break;
220
+
221
+ case NPCM7XX_GCR_RLOCKR1:
222
+ case NPCM7XX_GCR_MDLR:
223
+ /* Write 1 to set */
224
+ value |= s->regs[reg];
225
+ break;
226
+ };
227
+
228
+ s->regs[reg] = value;
229
+}
230
+
231
+static const struct MemoryRegionOps npcm7xx_gcr_ops = {
232
+ .read = npcm7xx_gcr_read,
233
+ .write = npcm7xx_gcr_write,
234
+ .endianness = DEVICE_LITTLE_ENDIAN,
235
+ .valid = {
236
+ .min_access_size = 4,
237
+ .max_access_size = 4,
238
+ .unaligned = false,
239
+ },
240
+};
241
+
242
+static void npcm7xx_gcr_enter_reset(Object *obj, ResetType type)
243
+{
244
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
245
+
246
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
247
+
248
+ switch (type) {
249
+ case RESET_TYPE_COLD:
250
+ memcpy(s->regs, cold_reset_values, sizeof(s->regs));
251
+ s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
252
+ s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
253
+ s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
254
+ break;
255
+ }
256
+}
257
+
258
+static void npcm7xx_gcr_realize(DeviceState *dev, Error **errp)
259
+{
260
+ ERRP_GUARD();
261
+ NPCM7xxGCRState *s = NPCM7XX_GCR(dev);
262
+ uint64_t dram_size;
263
+ Object *obj;
264
+
265
+ obj = object_property_get_link(OBJECT(dev), "dram-mr", errp);
266
+ if (!obj) {
267
+ error_prepend(errp, "%s: required dram-mr link not found: ", __func__);
268
+ return;
269
+ }
270
+ dram_size = memory_region_size(MEMORY_REGION(obj));
271
+ if (!is_power_of_2(dram_size) ||
272
+ dram_size < NPCM7XX_GCR_MIN_DRAM_SIZE ||
273
+ dram_size > NPCM7XX_GCR_MAX_DRAM_SIZE) {
274
+ g_autofree char *sz = size_to_str(dram_size);
275
+ g_autofree char *min_sz = size_to_str(NPCM7XX_GCR_MIN_DRAM_SIZE);
276
+ g_autofree char *max_sz = size_to_str(NPCM7XX_GCR_MAX_DRAM_SIZE);
277
+ error_setg(errp, "%s: unsupported DRAM size %s", __func__, sz);
278
+ error_append_hint(errp,
279
+ "DRAM size must be a power of two between %s and %s,"
280
+ " inclusive.\n", min_sz, max_sz);
281
+ return;
282
+ }
283
+
284
+ /* Power-on reset value */
285
+ s->reset_intcr3 = 0x00001002;
286
+
287
+ /*
288
+ * The GMMAP (Graphics Memory Map) field is used by u-boot to detect the
289
+ * DRAM size, and is normally initialized by the boot block as part of DRAM
290
+ * training. However, since we don't have a complete emulation of the
291
+ * memory controller and try to make it look like it has already been
292
+ * initialized, the boot block will skip this initialization, and we need
293
+ * to make sure this field is set correctly up front.
294
+ *
295
+ * WARNING: some versions of u-boot only looks at bits 8 and 9, so 2 GiB of
296
+ * DRAM will be interpreted as 128 MiB.
297
+ *
298
+ * https://github.com/Nuvoton-Israel/u-boot/blob/2aef993bd2aafeb5408dbaad0f3ce099ee40c4aa/board/nuvoton/poleg/poleg.c#L244
299
+ */
300
+ s->reset_intcr3 |= ctz64(dram_size / NPCM7XX_GCR_MIN_DRAM_SIZE) << 8;
301
+}
302
+
303
+static void npcm7xx_gcr_init(Object *obj)
304
+{
305
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
306
+
307
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
308
+ TYPE_NPCM7XX_GCR, 4 * KiB);
309
+ sysbus_init_mmio(&s->parent, &s->iomem);
310
+}
311
+
312
+static const VMStateDescription vmstate_npcm7xx_gcr = {
313
+ .name = "npcm7xx-gcr",
314
+ .version_id = 0,
315
+ .minimum_version_id = 0,
316
+ .fields = (VMStateField[]) {
317
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxGCRState, NPCM7XX_GCR_NR_REGS),
318
+ VMSTATE_END_OF_LIST(),
319
+ },
320
+};
321
+
322
+static Property npcm7xx_gcr_properties[] = {
323
+ DEFINE_PROP_UINT32("disabled-modules", NPCM7xxGCRState, reset_mdlr, 0),
324
+ DEFINE_PROP_UINT32("power-on-straps", NPCM7xxGCRState, reset_pwron, 0),
325
+ DEFINE_PROP_END_OF_LIST(),
326
+};
327
+
328
+static void npcm7xx_gcr_class_init(ObjectClass *klass, void *data)
329
+{
330
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
331
+ DeviceClass *dc = DEVICE_CLASS(klass);
332
+
333
+ QEMU_BUILD_BUG_ON(NPCM7XX_GCR_REGS_END > NPCM7XX_GCR_NR_REGS);
334
+
335
+ dc->desc = "NPCM7xx System Global Control Registers";
336
+ dc->realize = npcm7xx_gcr_realize;
337
+ dc->vmsd = &vmstate_npcm7xx_gcr;
338
+ rc->phases.enter = npcm7xx_gcr_enter_reset;
339
+
340
+ device_class_set_props(dc, npcm7xx_gcr_properties);
341
+}
342
+
343
+static const TypeInfo npcm7xx_gcr_info = {
344
+ .name = TYPE_NPCM7XX_GCR,
345
+ .parent = TYPE_SYS_BUS_DEVICE,
346
+ .instance_size = sizeof(NPCM7xxGCRState),
347
+ .instance_init = npcm7xx_gcr_init,
348
+ .class_init = npcm7xx_gcr_class_init,
349
+};
350
+
351
+static void npcm7xx_gcr_register_type(void)
352
+{
353
+ type_register_static(&npcm7xx_gcr_info);
354
+}
355
+type_init(npcm7xx_gcr_register_type);
356
diff --git a/MAINTAINERS b/MAINTAINERS
18
diff --git a/MAINTAINERS b/MAINTAINERS
357
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
358
--- a/MAINTAINERS
20
--- a/MAINTAINERS
359
+++ b/MAINTAINERS
21
+++ b/MAINTAINERS
360
@@ -XXX,XX +XXX,XX @@ S: Odd Fixes
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
361
F: hw/arm/musicpal.c
23
SBSA-REF
362
F: docs/system/arm/musicpal.rst
24
M: Radoslaw Biernacki <rad@semihalf.com>
363
364
+Nuvoton NPCM7xx
365
+M: Havard Skinnemoen <hskinnemoen@google.com>
366
+M: Tyrone Ting <kfting@nuvoton.com>
367
+L: qemu-arm@nongnu.org
368
+S: Supported
369
+F: hw/*/npcm7xx*
370
+F: include/hw/*/npcm7xx*
371
+
372
nSeries
373
M: Andrzej Zaborowski <balrogg@gmail.com>
374
M: Peter Maydell <peter.maydell@linaro.org>
25
M: Peter Maydell <peter.maydell@linaro.org>
375
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
29
L: qemu-arm@nongnu.org
30
S: Maintained
31
diff --git a/.mailmap b/.mailmap
376
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
377
--- a/hw/arm/Kconfig
33
--- a/.mailmap
378
+++ b/hw/arm/Kconfig
34
+++ b/.mailmap
379
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
380
select VIRTIO_MMIO
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
381
select UNIMP
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
382
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
383
+config NPCM7XX
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
384
+ bool
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
385
+
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
386
config FSL_IMX25
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
387
bool
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
388
select IMX
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
389
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
390
index XXXXXXX..XXXXXXX 100644
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
391
--- a/hw/misc/meson.build
392
+++ b/hw/misc/meson.build
393
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
394
))
395
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
396
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
397
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
398
+ 'npcm7xx_gcr.c',
399
+))
400
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
401
'omap_clk.c',
402
'omap_gpmc.c',
403
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
404
index XXXXXXX..XXXXXXX 100644
405
--- a/hw/misc/trace-events
406
+++ b/hw/misc/trace-events
407
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
408
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
409
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
410
411
+# npcm7xx_gcr.c
412
+npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
413
+npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
414
+
415
# stm32f4xx_syscfg.c
416
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
417
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
418
--
47
--
419
2.20.1
48
2.34.1
420
49
421
50
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
2
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
5
6
Message-id: 1597278668-339715-5-git-send-email-fnu.vikram@xilinx.com
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
MAINTAINERS | 8 ++++++++
11
MAINTAINERS | 2 ++
10
1 file changed, 8 insertions(+)
12
1 file changed, 2 insertions(+)
11
13
12
diff --git a/MAINTAINERS b/MAINTAINERS
14
diff --git a/MAINTAINERS b/MAINTAINERS
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
16
--- a/MAINTAINERS
15
+++ b/MAINTAINERS
17
+++ b/MAINTAINERS
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
17
19
18
Devices
20
Xilinx CAN
19
-------
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
20
+Xilinx CAN
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
23
+S: Maintained
24
+F: hw/net/can/xlnx-*
25
+F: include/hw/net/xlnx-*
26
+F: tests/qtest/xlnx-can-test*
27
+
28
EDU
29
M: Jiri Slaby <jslaby@suse.cz>
30
S: Maintained
23
S: Maintained
24
F: hw/net/can/xlnx-*
25
F: include/hw/net/xlnx-*
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
27
CAN bus subsystem and hardware
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
31
S: Maintained
32
W: https://canbus.pages.fel.cvut.cz/
33
F: net/can/*
31
--
34
--
32
2.20.1
35
2.34.1
33
34
diff view generated by jsdifflib