1
The following changes since commit 35152940b78e478b97051a799cb6275ced03192e:
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
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 :-))
2
4
3
Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging (2024-10-14 17:05:25 +0100)
5
thanks
6
-- PMM
7
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
9
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241015
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
8
15
9
for you to fetch changes up to 9bb9833fd2ef30c5c7306c6f2a15dcc313305ccc:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
10
17
11
hw/arm/xilinx_zynq: Add various missing unimplemented devices (2024-10-15 11:29:47 +0100)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
target-arm queue:
21
target-arm queue:
15
* hw/arm/omap1: Remove unused omap_uwire_attach() method
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
16
* stm32f405: Add RCC device to stm32f405 SoC
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
17
* arm/gicv3: add missing casts
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
18
* hw/misc: Create STM32L4x5 SYSCFG clock
25
* fpu: Minor NaN-related cleanups
19
* hw/arm: Add SPI to Allwinner A10
26
* MAINTAINERS: email address updates
20
* hw/intc/omap_intc: Remove now-unnecessary abstract base class
21
* hw/char/pl011: Use correct masks for IBRD and FBRD
22
* docs/devel: Convert txt files to rST
23
* Remove MAX111X, MAX7310, DSCM-1XXXX, pcmcia devices (used only
24
by now-removed omap/pxa2xx boards)
25
* vl.c: Remove pxa2xx-specific -portrait and -rotate options
26
* dma: Fix function names in documentation
27
* hw/arm/xilinx_zynq: Add various missing unimplemented devices
28
27
29
----------------------------------------------------------------
28
----------------------------------------------------------------
30
Akihiko Odaki (1):
29
Bernhard Beschow (5):
31
dma: Fix function names in documentation
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
32
35
33
Alexandra Diupina (3):
36
Leif Lindholm (1):
34
hw/intc/arm_gicv3: Add cast to match the documentation
37
MAINTAINERS: update email address for Leif Lindholm
35
hw/intc/arm_gicv3: Add cast to match the documentation
36
hw/intc/arm_gicv3_cpuif: Add cast to match the documentation
37
38
38
Chao Liu (1):
39
Peter Maydell (54):
39
hw/arm/xilinx_zynq: Add various missing unimplemented devices
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
42
softfloat: Allow runtime choice of inf * 0 + NaN result
43
tests/fp: Explicitly set inf-zero-nan rule
44
target/arm: Set FloatInfZeroNaNRule explicitly
45
target/s390: Set FloatInfZeroNaNRule explicitly
46
target/ppc: Set FloatInfZeroNaNRule explicitly
47
target/mips: Set FloatInfZeroNaNRule explicitly
48
target/sparc: Set FloatInfZeroNaNRule explicitly
49
target/xtensa: Set FloatInfZeroNaNRule explicitly
50
target/x86: Set FloatInfZeroNaNRule explicitly
51
target/loongarch: Set FloatInfZeroNaNRule explicitly
52
target/hppa: Set FloatInfZeroNaNRule explicitly
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
40
94
41
Inès Varhol (3):
95
Richard Henderson (11):
42
hw/misc: Create STM32L4x5 SYSCFG clock
96
target/arm: Copy entire float_status in is_ebf
43
hw/clock: Expose 'qtest-clock-period' QOM property for QTests
97
softfloat: Inline pickNaNMulAdd
44
tests/qtest: Check STM32L4x5 clock connections
98
softfloat: Use goto for default nan case in pick_nan_muladd
99
softfloat: Remove which from parts_pick_nan_muladd
100
softfloat: Pad array size in pick_nan_muladd
101
softfloat: Move propagateFloatx80NaN to softfloat.c
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
103
softfloat: Inline pickNaN
104
softfloat: Share code between parts_pick_nan cases
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
106
softfloat: Replace WHICH with RET in parts_pick_nan
45
107
46
Peter Maydell (15):
108
Vikram Garhwal (1):
47
hw/intc/omap_intc: Remove now-unnecessary abstract base class
109
MAINTAINERS: Add correct email address for Vikram Garhwal
48
hw/char/pl011: Use correct masks for IBRD and FBRD
49
docs/devel/blkdebug: Convert to rST format
50
docs/devel/blkverify: Convert to rST format
51
docs/devel/lockcnt: Convert to rST format
52
docs/devel/multiple-iothreads: Convert to rST format
53
docs/devel/rcu: Convert to rST format
54
include: Move QemuLockCnt APIs to their own header
55
docs/devel/lockcnt: Include kernel-doc API documentation
56
hw/adc: Remove MAX111X device
57
hw/gpio: Remove MAX7310 device
58
hw/ide: Remove DSCM-1XXXX microdrive device model
59
hw: Remove PCMCIA subsystem
60
hw/block: Remove ecc
61
vl.c: Remove pxa2xx-specific -portrait and -rotate options
62
110
63
Philippe Mathieu-Daudé (1):
111
MAINTAINERS | 4 +-
64
hw/arm/omap1: Remove unused omap_uwire_attach() method
112
include/fpu/softfloat-helpers.h | 38 +++-
65
113
include/fpu/softfloat-types.h | 89 +++++++-
66
Román Cárdenas Rodríguez (2):
114
include/hw/net/imx_fec.h | 9 +-
67
hw/misc/stm32_rcc: Implement RCC device for STM32F4 SoCs
115
include/hw/net/lan9118_phy.h | 37 ++++
68
hw/arm/stm32f405: Add RCC device to stm32f405 SoC
116
include/hw/net/mii.h | 6 +
69
117
target/mips/fpu_helper.h | 20 ++
70
Strahinja Jankovic (2):
118
target/sparc/helper.h | 4 +-
71
hw/ssi: Allwinner A10 SPI emulation
119
fpu/softfloat.c | 19 ++
72
hw/arm: Add SPI to Allwinner A10
120
hw/net/imx_fec.c | 146 ++------------
73
121
hw/net/lan9118.c | 137 ++-----------
74
MAINTAINERS | 10 +-
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
75
docs/about/removed-features.rst | 23 +
123
linux-user/arm/nwfpe/fpa11.c | 5 +
76
docs/devel/blkdebug.txt | 162 ------
124
target/alpha/cpu.c | 2 +
77
docs/devel/clocks.rst | 6 +
125
target/arm/cpu.c | 10 +
78
docs/devel/index-api.rst | 1 +
126
target/arm/tcg/vec_helper.c | 20 +-
79
docs/devel/index-internals.rst | 2 +
127
target/hexagon/cpu.c | 2 +
80
docs/devel/{lockcnt.txt => lockcnt.rst} | 89 +--
128
target/hppa/fpu_helper.c | 12 ++
81
docs/devel/multiple-iothreads.rst | 139 +++++
129
target/i386/tcg/fpu_helper.c | 12 ++
82
docs/devel/multiple-iothreads.txt | 130 -----
130
target/loongarch/tcg/fpu_helper.c | 14 +-
83
docs/devel/{rcu.txt => rcu.rst} | 172 +++---
131
target/m68k/cpu.c | 14 +-
84
docs/devel/testing/blkdebug.rst | 177 ++++++
132
target/m68k/fpu_helper.c | 6 +-
85
.../devel/{blkverify.txt => testing/blkverify.rst} | 30 +-
133
target/m68k/helper.c | 6 +-
86
docs/devel/testing/index.rst | 2 +
134
target/microblaze/cpu.c | 2 +
87
docs/system/arm/cubieboard.rst | 1 +
135
target/mips/msa.c | 10 +
88
docs/system/arm/stm32.rst | 3 +-
136
target/openrisc/cpu.c | 2 +
89
include/block/aio.h | 1 +
137
target/ppc/cpu_init.c | 19 ++
90
include/hw/adc/max111x.h | 56 --
138
target/ppc/fpu_helper.c | 3 +-
91
include/hw/arm/allwinner-a10.h | 2 +
139
target/riscv/cpu.c | 2 +
92
include/hw/arm/omap.h | 10 +-
140
target/rx/cpu.c | 2 +
93
include/hw/arm/stm32f405_soc.h | 2 +
141
target/s390x/cpu.c | 5 +
94
include/hw/block/flash.h | 11 -
142
target/sh4/cpu.c | 2 +
95
include/hw/core/cpu.h | 1 +
143
target/sparc/cpu.c | 6 +
96
include/hw/misc/stm32_rcc.h | 91 +++
144
target/sparc/fop_helper.c | 8 +-
97
include/hw/misc/stm32l4x5_syscfg.h | 1 +
145
target/sparc/translate.c | 4 +-
98
include/hw/pcmcia.h | 66 ---
146
target/tricore/helper.c | 2 +
99
include/hw/ssi/allwinner-a10-spi.h | 57 ++
147
target/xtensa/cpu.c | 4 +
100
include/qemu/lockcnt.h | 130 +++++
148
target/xtensa/fpu_helper.c | 3 +-
101
include/qemu/thread.h | 111 ----
149
tests/fp/fp-bench.c | 7 +
102
include/sysemu/dma.h | 11 +-
150
tests/fp/fp-test-log2.c | 1 +
103
include/sysemu/sysemu.h | 1 -
151
tests/fp/fp-test.c | 7 +
104
tests/qtest/stm32l4x5.h | 42 ++
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
105
accel/accel-blocker.c | 1 +
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
106
hw/adc/max111x.c | 236 --------
154
.mailmap | 5 +-
107
hw/arm/allwinner-a10.c | 8 +
155
hw/net/Kconfig | 5 +
108
hw/arm/omap1.c | 29 +-
156
hw/net/meson.build | 1 +
109
hw/arm/stm32f405_soc.c | 12 +-
157
hw/net/trace-events | 10 +-
110
hw/arm/stm32l4x5_soc.c | 2 +
158
47 files changed, 778 insertions(+), 730 deletions(-)
111
hw/arm/xilinx_zynq.c | 70 +++
159
create mode 100644 include/hw/net/lan9118_phy.h
112
hw/block/ecc.c | 91 ---
160
create mode 100644 hw/net/lan9118_phy.c
113
hw/char/pl011.c | 4 +-
114
hw/core/clock.c | 16 +
115
hw/core/cpu-common.c | 1 +
116
hw/gpio/max7310.c | 217 -------
117
hw/ide/microdrive.c | 644 ---------------------
118
hw/intc/arm_gicv3_cpuif.c | 6 +-
119
hw/intc/omap_intc.c | 13 +-
120
hw/misc/stm32_rcc.c | 162 ++++++
121
hw/misc/stm32l4x5_syscfg.c | 19 +-
122
hw/pcmcia/pcmcia.c | 24 -
123
hw/ssi/allwinner-a10-spi.c | 561 ++++++++++++++++++
124
system/globals.c | 1 -
125
system/vl.c | 11 -
126
tests/qtest/stm32l4x5_gpio-test.c | 23 +
127
tests/qtest/stm32l4x5_syscfg-test.c | 20 +-
128
tests/qtest/stm32l4x5_usart-test.c | 26 +
129
ui/input.c | 36 --
130
util/aio-posix.c | 1 +
131
util/aio-win32.c | 1 +
132
util/async.c | 1 +
133
util/fdmon-epoll.c | 1 +
134
util/lockcnt.c | 1 +
135
hw/Kconfig | 1 -
136
hw/adc/Kconfig | 3 -
137
hw/adc/meson.build | 1 -
138
hw/arm/Kconfig | 3 +-
139
hw/block/Kconfig | 3 -
140
hw/block/meson.build | 1 -
141
hw/gpio/Kconfig | 4 -
142
hw/gpio/meson.build | 1 -
143
hw/ide/Kconfig | 6 -
144
hw/ide/meson.build | 1 -
145
hw/meson.build | 1 -
146
hw/misc/Kconfig | 4 +-
147
hw/misc/meson.build | 1 +
148
hw/misc/trace-events | 6 +
149
hw/pcmcia/Kconfig | 2 -
150
hw/pcmcia/meson.build | 1 -
151
hw/ssi/Kconfig | 4 +
152
hw/ssi/meson.build | 1 +
153
hw/ssi/trace-events | 10 +
154
qemu-options.hx | 16 -
155
81 files changed, 1800 insertions(+), 2048 deletions(-)
156
delete mode 100644 docs/devel/blkdebug.txt
157
rename docs/devel/{lockcnt.txt => lockcnt.rst} (75%)
158
create mode 100644 docs/devel/multiple-iothreads.rst
159
delete mode 100644 docs/devel/multiple-iothreads.txt
160
rename docs/devel/{rcu.txt => rcu.rst} (73%)
161
create mode 100644 docs/devel/testing/blkdebug.rst
162
rename docs/devel/{blkverify.txt => testing/blkverify.rst} (77%)
163
delete mode 100644 include/hw/adc/max111x.h
164
create mode 100644 include/hw/misc/stm32_rcc.h
165
delete mode 100644 include/hw/pcmcia.h
166
create mode 100644 include/hw/ssi/allwinner-a10-spi.h
167
create mode 100644 include/qemu/lockcnt.h
168
create mode 100644 tests/qtest/stm32l4x5.h
169
delete mode 100644 hw/adc/max111x.c
170
delete mode 100644 hw/block/ecc.c
171
delete mode 100644 hw/gpio/max7310.c
172
delete mode 100644 hw/ide/microdrive.c
173
create mode 100644 hw/misc/stm32_rcc.c
174
delete mode 100644 hw/pcmcia/pcmcia.c
175
create mode 100644 hw/ssi/allwinner-a10-spi.c
176
delete mode 100644 hw/pcmcia/Kconfig
177
delete mode 100644 hw/pcmcia/meson.build
178
diff view generated by jsdifflib
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
This patch implements Allwinner A10 SPI controller emulation.
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
Only master-mode functionality is implemented.
4
a common implementation by extracting a device model into its own files.
5
5
6
Since U-Boot and Linux SPI drivers for Allwinner A10 perform only
6
Some migration state has been moved into the new device model which breaks
7
byte-wide CPU access (no DMA) to the transmit and receive registers of
7
migration compatibility for the following machines:
8
the peripheral, the emulated controller does not implement DMA control,
8
* smdkc210
9
and supports only byte-wide access to transmit and receive registers
9
* realview-*
10
(half-word and word accesses will be treated as byte accesses).
10
* vexpress-*
11
* kzm
12
* mps2-*
11
13
12
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
14
While breaking migration ABI, fix the size of the MII registers to be 16 bit,
13
Message-id: 20241001221349.8319-2-strahinja.p.jankovic@gmail.com
15
as defined by IEEE 802.3u.
16
17
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
18
Tested-by: Guenter Roeck <linux@roeck-us.net>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
22
---
17
include/hw/ssi/allwinner-a10-spi.h | 57 +++
23
include/hw/net/lan9118_phy.h | 37 ++++++++
18
hw/ssi/allwinner-a10-spi.c | 561 +++++++++++++++++++++++++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
19
hw/ssi/Kconfig | 4 +
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
20
hw/ssi/meson.build | 1 +
26
hw/net/Kconfig | 4 +
21
hw/ssi/trace-events | 10 +
27
hw/net/meson.build | 1 +
22
5 files changed, 633 insertions(+)
28
5 files changed, 233 insertions(+), 115 deletions(-)
23
create mode 100644 include/hw/ssi/allwinner-a10-spi.h
29
create mode 100644 include/hw/net/lan9118_phy.h
24
create mode 100644 hw/ssi/allwinner-a10-spi.c
30
create mode 100644 hw/net/lan9118_phy.c
25
31
26
diff --git a/include/hw/ssi/allwinner-a10-spi.h b/include/hw/ssi/allwinner-a10-spi.h
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
27
new file mode 100644
33
new file mode 100644
28
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
29
--- /dev/null
35
--- /dev/null
30
+++ b/include/hw/ssi/allwinner-a10-spi.h
36
+++ b/include/hw/net/lan9118_phy.h
31
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
32
+/*
38
+/*
33
+ * Allwinner SPI Bus Serial Interface registers definition
39
+ * SMSC LAN9118 PHY emulation
34
+ *
40
+ *
35
+ * Copyright (C) 2024 Strahinja Jankovic. <strahinja.p.jankovic@gmail.com>
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
42
+ * Written by Paul Brook
36
+ *
43
+ *
37
+ * 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.
38
+ * under the terms of the GNU General Public License as published by the
45
+ * See the COPYING file in the top-level directory.
39
+ * Free Software Foundation; either version 2 of the License, or
40
+ * (at your option) any later version.
41
+ *
42
+ * This program is distributed in the hope that it will be useful, but WITHOUT
43
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
44
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
45
+ * for more details.
46
+ *
47
+ * You should have received a copy of the GNU General Public License along
48
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
49
+ *
50
+ * SPDX-License-Identifier: GPL-2.0-or-later
51
+ */
46
+ */
52
+
47
+
53
+#ifndef ALLWINNER_A10_SPI_H
48
+#ifndef HW_NET_LAN9118_PHY_H
54
+#define ALLWINNER_A10_SPI_H
49
+#define HW_NET_LAN9118_PHY_H
55
+
50
+
56
+#include "hw/ssi/ssi.h"
51
+#include "qom/object.h"
57
+#include "hw/sysbus.h"
52
+#include "hw/sysbus.h"
58
+#include "qemu/fifo8.h"
53
+
59
+#include "qom/object.h"
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
60
+
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
61
+/** Size of register I/O address space used by SPI device */
56
+
62
+#define AW_A10_SPI_IOSIZE (0x1000)
57
+typedef struct Lan9118PhyState {
63
+
64
+/** Total number of known registers */
65
+#define AW_A10_SPI_REGS_NUM (AW_A10_SPI_IOSIZE / sizeof(uint32_t))
66
+#define AW_A10_SPI_FIFO_SIZE (64)
67
+#define AW_A10_SPI_CS_LINES_NR (4)
68
+
69
+#define TYPE_AW_A10_SPI "allwinner.spi"
70
+OBJECT_DECLARE_SIMPLE_TYPE(AWA10SPIState, AW_A10_SPI)
71
+
72
+struct AWA10SPIState {
73
+ /*< private >*/
74
+ SysBusDevice parent_obj;
58
+ SysBusDevice parent_obj;
75
+
59
+
76
+ /*< public >*/
60
+ uint16_t status;
77
+ MemoryRegion iomem;
61
+ uint16_t control;
78
+ SSIBus *bus;
62
+ uint16_t advertise;
63
+ uint16_t ints;
64
+ uint16_t int_mask;
79
+ qemu_irq irq;
65
+ qemu_irq irq;
80
+ qemu_irq cs_lines[AW_A10_SPI_CS_LINES_NR];
66
+ bool link_down;
81
+
67
+} Lan9118PhyState;
82
+ uint32_t regs[AW_A10_SPI_REGS_NUM];
68
+
83
+
69
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down);
84
+ Fifo8 rx_fifo;
70
+void lan9118_phy_reset(Lan9118PhyState *s);
85
+ Fifo8 tx_fifo;
71
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg);
86
+};
72
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val);
87
+
73
+
88
+#endif /* ALLWINNER_A10_SPI_H */
74
+#endif
89
diff --git a/hw/ssi/allwinner-a10-spi.c b/hw/ssi/allwinner-a10-spi.c
75
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/net/lan9118.c
78
+++ b/hw/net/lan9118.c
79
@@ -XXX,XX +XXX,XX @@
80
#include "net/net.h"
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
90
new file mode 100644
312
new file mode 100644
91
index XXXXXXX..XXXXXXX
313
index XXXXXXX..XXXXXXX
92
--- /dev/null
314
--- /dev/null
93
+++ b/hw/ssi/allwinner-a10-spi.c
315
+++ b/hw/net/lan9118_phy.c
94
@@ -XXX,XX +XXX,XX @@
316
@@ -XXX,XX +XXX,XX @@
95
+/*
317
+/*
96
+ * Allwinner SPI Bus Serial Interface Emulation
318
+ * SMSC LAN9118 PHY emulation
97
+ *
319
+ *
98
+ * Copyright (C) 2024 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
321
+ * Written by Paul Brook
99
+ *
322
+ *
100
+ * This program is free software; you can redistribute it and/or modify it
323
+ * This code is licensed under the GNU GPL v2
101
+ * under the terms of the GNU General Public License as published by the
102
+ * Free Software Foundation; either version 2 of the License, or
103
+ * (at your option) any later version.
104
+ *
324
+ *
105
+ * 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
106
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
326
+ * GNU GPL, version 2 or (at your option) any later version.
107
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
108
+ * for more details.
109
+ *
110
+ * You should have received a copy of the GNU General Public License along
111
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
112
+ *
113
+ * SPDX-License-Identifier: GPL-2.0-or-later
114
+ */
327
+ */
115
+
328
+
116
+#include "qemu/osdep.h"
329
+#include "qemu/osdep.h"
330
+#include "hw/net/lan9118_phy.h"
117
+#include "hw/irq.h"
331
+#include "hw/irq.h"
118
+#include "hw/ssi/allwinner-a10-spi.h"
332
+#include "hw/resettable.h"
119
+#include "migration/vmstate.h"
333
+#include "migration/vmstate.h"
120
+#include "qemu/log.h"
334
+#include "qemu/log.h"
121
+#include "qemu/module.h"
335
+
122
+#include "trace.h"
336
+#define PHY_INT_ENERGYON (1 << 7)
123
+
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
124
+/* Allwinner SPI memory map */
338
+#define PHY_INT_FAULT (1 << 5)
125
+#define SPI_RXDATA_REG 0x00 /* receive data register */
339
+#define PHY_INT_DOWN (1 << 4)
126
+#define SPI_TXDATA_REG 0x04 /* transmit data register */
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
127
+#define SPI_CTL_REG 0x08 /* control register */
341
+#define PHY_INT_PARFAULT (1 << 2)
128
+#define SPI_INTCTL_REG 0x0c /* interrupt control register */
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
129
+#define SPI_INT_STA_REG 0x10 /* interrupt status register */
343
+
130
+#define SPI_DMACTL_REG 0x14 /* DMA control register */
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
131
+#define SPI_WAIT_REG 0x18 /* wait clock counter register */
345
+{
132
+#define SPI_CCTL_REG 0x1c /* clock rate control register */
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
133
+#define SPI_BC_REG 0x20 /* burst control register */
347
+}
134
+#define SPI_TC_REG 0x24 /* transmit counter register */
348
+
135
+#define SPI_FIFO_STA_REG 0x28 /* FIFO status register */
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
136
+
350
+{
137
+/* Data register */
351
+ uint16_t val;
138
+#define SPI_DATA_RESET 0
352
+
139
+
353
+ switch (reg) {
140
+/* Control register */
354
+ case 0: /* Basic Control */
141
+#define SPI_CTL_SDC (1 << 19)
355
+ return s->control;
142
+#define SPI_CTL_TP_EN (1 << 18)
356
+ case 1: /* Basic Status */
143
+#define SPI_CTL_SS_LEVEL (1 << 17)
357
+ return s->status;
144
+#define SPI_CTL_SS_CTRL (1 << 16)
358
+ case 2: /* ID1 */
145
+#define SPI_CTL_DHB (1 << 15)
359
+ return 0x0007;
146
+#define SPI_CTL_DDB (1 << 14)
360
+ case 3: /* ID2 */
147
+#define SPI_CTL_SS (3 << 12)
361
+ return 0xc0d1;
148
+#define SPI_CTL_SS_SHIFT 12
362
+ case 4: /* Auto-neg advertisement */
149
+#define SPI_CTL_RPSM (1 << 11)
363
+ return s->advertise;
150
+#define SPI_CTL_XCH (1 << 10)
364
+ case 5: /* Auto-neg Link Partner Ability */
151
+#define SPI_CTL_RF_RST (1 << 9)
365
+ return 0x0f71;
152
+#define SPI_CTL_TF_RST (1 << 8)
366
+ case 6: /* Auto-neg Expansion */
153
+#define SPI_CTL_SSCTL (1 << 7)
367
+ return 1;
154
+#define SPI_CTL_LMTF (1 << 6)
368
+ /* TODO 17, 18, 27, 29, 30, 31 */
155
+#define SPI_CTL_DMAMC (1 << 5)
369
+ case 29: /* Interrupt source. */
156
+#define SPI_CTL_SSPOL (1 << 4)
370
+ val = s->ints;
157
+#define SPI_CTL_POL (1 << 3)
371
+ s->ints = 0;
158
+#define SPI_CTL_PHA (1 << 2)
372
+ lan9118_phy_update_irq(s);
159
+#define SPI_CTL_MODE (1 << 1)
373
+ return val;
160
+#define SPI_CTL_EN (1 << 0)
374
+ case 30: /* Interrupt mask */
161
+#define SPI_CTL_MASK 0xFFFFFu
375
+ return s->int_mask;
162
+#define SPI_CTL_RESET 0x0002001Cu
163
+
164
+/* Interrupt control register */
165
+#define SPI_INTCTL_SS_INT_EN (1 << 17)
166
+#define SPI_INTCTL_TX_INT_EN (1 << 16)
167
+#define SPI_INTCTL_TF_UR_INT_EN (1 << 14)
168
+#define SPI_INTCTL_TF_OF_INT_EN (1 << 13)
169
+#define SPI_INTCTL_TF_E34_INT_EN (1 << 12)
170
+#define SPI_INTCTL_TF_E14_INT_EN (1 << 11)
171
+#define SPI_INTCTL_TF_FL_INT_EN (1 << 10)
172
+#define SPI_INTCTL_TF_HALF_EMP_INT_EN (1 << 9)
173
+#define SPI_INTCTL_TF_EMP_INT_EN (1 << 8)
174
+#define SPI_INTCTL_RF_UR_INT_EN (1 << 6)
175
+#define SPI_INTCTL_RF_OF_INT_EN (1 << 5)
176
+#define SPI_INTCTL_RF_E34_INT_EN (1 << 4)
177
+#define SPI_INTCTL_RF_E14_INT_EN (1 << 3)
178
+#define SPI_INTCTL_RF_FU_INT_EN (1 << 2)
179
+#define SPI_INTCTL_RF_HALF_FU_INT_EN (1 << 1)
180
+#define SPI_INTCTL_RF_RDY_INT_EN (1 << 0)
181
+#define SPI_INTCTL_MASK 0x37F7Fu
182
+#define SPI_INTCTL_RESET 0
183
+
184
+/* Interrupt status register */
185
+#define SPI_INT_STA_INT_CBF (1 << 31)
186
+#define SPI_INT_STA_SSI (1 << 17)
187
+#define SPI_INT_STA_TC (1 << 16)
188
+#define SPI_INT_STA_TU (1 << 14)
189
+#define SPI_INT_STA_TO (1 << 13)
190
+#define SPI_INT_STA_TE34 (1 << 12)
191
+#define SPI_INT_STA_TE14 (1 << 11)
192
+#define SPI_INT_STA_TF (1 << 10)
193
+#define SPI_INT_STA_THE (1 << 9)
194
+#define SPI_INT_STA_TE (1 << 8)
195
+#define SPI_INT_STA_RU (1 << 6)
196
+#define SPI_INT_STA_RO (1 << 5)
197
+#define SPI_INT_STA_RF34 (1 << 4)
198
+#define SPI_INT_STA_RF14 (1 << 3)
199
+#define SPI_INT_STA_RF (1 << 2)
200
+#define SPI_INT_STA_RHF (1 << 1)
201
+#define SPI_INT_STA_RR (1 << 0)
202
+#define SPI_INT_STA_MASK 0x80037F7Fu
203
+#define SPI_INT_STA_RESET 0x00001B00u
204
+
205
+/* DMA control register - not implemented */
206
+#define SPI_DMACTL_RESET 0
207
+
208
+/* Wait clock register */
209
+#define SPI_WAIT_REG_WCC_MASK 0xFFFFu
210
+#define SPI_WAIT_RESET 0
211
+
212
+/* Clock control register - not implemented */
213
+#define SPI_CCTL_RESET 2
214
+
215
+/* Burst count register */
216
+#define SPI_BC_BC_MASK 0xFFFFFFu
217
+#define SPI_BC_RESET 0
218
+
219
+/* Transmi counter register */
220
+#define SPI_TC_WTC_MASK 0xFFFFFFu
221
+#define SPI_TC_RESET 0
222
+
223
+/* FIFO status register */
224
+#define SPI_FIFO_STA_CNT_MASK 0x7F
225
+#define SPI_FIFO_STA_TF_CNT_SHIFT 16
226
+#define SPI_FIFO_STA_RF_CNT_SHIFT 0
227
+#define SPI_FIFO_STA_RESET 0
228
+
229
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
230
+
231
+
232
+static const char *allwinner_a10_spi_get_regname(unsigned offset)
233
+{
234
+ switch (offset) {
235
+ case SPI_RXDATA_REG:
236
+ return "RXDATA";
237
+ case SPI_TXDATA_REG:
238
+ return "TXDATA";
239
+ case SPI_CTL_REG:
240
+ return "CTL";
241
+ case SPI_INTCTL_REG:
242
+ return "INTCTL";
243
+ case SPI_INT_STA_REG:
244
+ return "INT_STA";
245
+ case SPI_DMACTL_REG:
246
+ return "DMACTL";
247
+ case SPI_WAIT_REG:
248
+ return "WAIT";
249
+ case SPI_CCTL_REG:
250
+ return "CCTL";
251
+ case SPI_BC_REG:
252
+ return "BC";
253
+ case SPI_TC_REG:
254
+ return "TC";
255
+ case SPI_FIFO_STA_REG:
256
+ return "FIFO_STA";
257
+ default:
376
+ default:
258
+ return "[?]";
377
+ qemu_log_mask(LOG_GUEST_ERROR,
378
+ "lan9118_phy_read: PHY read reg %d\n", reg);
379
+ return 0;
259
+ }
380
+ }
260
+}
381
+}
261
+
382
+
262
+static bool allwinner_a10_spi_is_enabled(AWA10SPIState *s)
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
263
+{
384
+{
264
+ return s->regs[REG_INDEX(SPI_CTL_REG)] & SPI_CTL_EN;
385
+ switch (reg) {
265
+}
386
+ case 0: /* Basic Control */
266
+
387
+ if (val & 0x8000) {
267
+static void allwinner_a10_spi_txfifo_reset(AWA10SPIState *s)
388
+ lan9118_phy_reset(s);
268
+{
269
+ fifo8_reset(&s->tx_fifo);
270
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= (SPI_INT_STA_TE | SPI_INT_STA_TE14 |
271
+ SPI_INT_STA_THE | SPI_INT_STA_TE34);
272
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~(SPI_INT_STA_TU | SPI_INT_STA_TO);
273
+}
274
+
275
+static void allwinner_a10_spi_rxfifo_reset(AWA10SPIState *s)
276
+{
277
+ fifo8_reset(&s->rx_fifo);
278
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &=
279
+ ~(SPI_INT_STA_RU | SPI_INT_STA_RO | SPI_INT_STA_RF | SPI_INT_STA_RR |
280
+ SPI_INT_STA_RHF | SPI_INT_STA_RF14 | SPI_INT_STA_RF34);
281
+}
282
+
283
+static uint8_t allwinner_a10_spi_selected_channel(AWA10SPIState *s)
284
+{
285
+ return (s->regs[REG_INDEX(SPI_CTL_REG)] & SPI_CTL_SS) >> SPI_CTL_SS_SHIFT;
286
+}
287
+
288
+static void allwinner_a10_spi_reset_hold(Object *obj, ResetType type)
289
+{
290
+ AWA10SPIState *s = AW_A10_SPI(obj);
291
+
292
+ s->regs[REG_INDEX(SPI_RXDATA_REG)] = SPI_DATA_RESET;
293
+ s->regs[REG_INDEX(SPI_TXDATA_REG)] = SPI_DATA_RESET;
294
+ s->regs[REG_INDEX(SPI_CTL_REG)] = SPI_CTL_RESET;
295
+ s->regs[REG_INDEX(SPI_INTCTL_REG)] = SPI_INTCTL_RESET;
296
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] = SPI_INT_STA_RESET;
297
+ s->regs[REG_INDEX(SPI_DMACTL_REG)] = SPI_DMACTL_RESET;
298
+ s->regs[REG_INDEX(SPI_WAIT_REG)] = SPI_WAIT_RESET;
299
+ s->regs[REG_INDEX(SPI_CCTL_REG)] = SPI_CCTL_RESET;
300
+ s->regs[REG_INDEX(SPI_BC_REG)] = SPI_BC_RESET;
301
+ s->regs[REG_INDEX(SPI_TC_REG)] = SPI_TC_RESET;
302
+ s->regs[REG_INDEX(SPI_FIFO_STA_REG)] = SPI_FIFO_STA_RESET;
303
+
304
+ allwinner_a10_spi_txfifo_reset(s);
305
+ allwinner_a10_spi_rxfifo_reset(s);
306
+}
307
+
308
+static void allwinner_a10_spi_update_irq(AWA10SPIState *s)
309
+{
310
+ bool level;
311
+
312
+ if (fifo8_is_empty(&s->rx_fifo)) {
313
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_RR;
314
+ } else {
315
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_RR;
316
+ }
317
+
318
+ if (fifo8_num_used(&s->rx_fifo) >= (AW_A10_SPI_FIFO_SIZE >> 2)) {
319
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_RF14;
320
+ } else {
321
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_RF14;
322
+ }
323
+
324
+ if (fifo8_num_used(&s->rx_fifo) >= (AW_A10_SPI_FIFO_SIZE >> 1)) {
325
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_RHF;
326
+ } else {
327
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_RHF;
328
+ }
329
+
330
+ if (fifo8_num_free(&s->rx_fifo) <= (AW_A10_SPI_FIFO_SIZE >> 2)) {
331
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_RF34;
332
+ } else {
333
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_RF34;
334
+ }
335
+
336
+ if (fifo8_is_full(&s->rx_fifo)) {
337
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_RF;
338
+ } else {
339
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_RF;
340
+ }
341
+
342
+ if (fifo8_is_empty(&s->tx_fifo)) {
343
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_TE;
344
+ } else {
345
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_TE;
346
+ }
347
+
348
+ if (fifo8_num_free(&s->tx_fifo) >= (AW_A10_SPI_FIFO_SIZE >> 2)) {
349
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_TE14;
350
+ } else {
351
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_TE14;
352
+ }
353
+
354
+ if (fifo8_num_free(&s->tx_fifo) >= (AW_A10_SPI_FIFO_SIZE >> 1)) {
355
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_THE;
356
+ } else {
357
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_THE;
358
+ }
359
+
360
+ if (fifo8_num_used(&s->tx_fifo) <= (AW_A10_SPI_FIFO_SIZE >> 2)) {
361
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_TE34;
362
+ } else {
363
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_TE34;
364
+ }
365
+
366
+ if (fifo8_is_full(&s->rx_fifo)) {
367
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_TF;
368
+ } else {
369
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~SPI_INT_STA_TF;
370
+ }
371
+
372
+ level = (s->regs[REG_INDEX(SPI_INT_STA_REG)] &
373
+ s->regs[REG_INDEX(SPI_INTCTL_REG)]) != 0;
374
+
375
+ qemu_set_irq(s->irq, level);
376
+
377
+ trace_allwinner_a10_spi_update_irq(level);
378
+}
379
+
380
+static void allwinner_a10_spi_flush_txfifo(AWA10SPIState *s)
381
+{
382
+ uint32_t burst_count = s->regs[REG_INDEX(SPI_BC_REG)];
383
+ uint32_t tx_burst = s->regs[REG_INDEX(SPI_TC_REG)];
384
+ trace_allwinner_a10_spi_burst_length(tx_burst);
385
+
386
+ trace_allwinner_a10_spi_flush_txfifo_begin(fifo8_num_used(&s->tx_fifo),
387
+ fifo8_num_used(&s->rx_fifo));
388
+
389
+ while (!fifo8_is_empty(&s->tx_fifo)) {
390
+ uint8_t tx = fifo8_pop(&s->tx_fifo);
391
+ uint8_t rx = 0;
392
+ bool fill_rx = true;
393
+
394
+ trace_allwinner_a10_spi_tx(tx);
395
+
396
+ /* Write one byte at a time */
397
+ rx = ssi_transfer(s->bus, tx);
398
+
399
+ trace_allwinner_a10_spi_rx(rx);
400
+
401
+ /* Check DHB here to determine if RX bytes should be stored */
402
+ if (s->regs[REG_INDEX(SPI_CTL_REG)] & SPI_CTL_DHB) {
403
+ /* Store rx bytes only after WTC transfers */
404
+ if (tx_burst > 0u) {
405
+ fill_rx = false;
406
+ tx_burst--;
407
+ }
408
+ }
409
+
410
+ if (fill_rx) {
411
+ if (fifo8_is_full(&s->rx_fifo)) {
412
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_RF;
413
+ } else {
414
+ fifo8_push(&s->rx_fifo, rx);
415
+ }
416
+ }
417
+
418
+ allwinner_a10_spi_update_irq(s);
419
+
420
+ burst_count--;
421
+
422
+ if (burst_count == 0) {
423
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_TC;
424
+ s->regs[REG_INDEX(SPI_CTL_REG)] &= ~SPI_CTL_XCH;
425
+ break;
389
+ break;
426
+ }
390
+ }
427
+ }
391
+ s->control = val & 0x7980;
428
+
392
+ /* Complete autonegotiation immediately. */
429
+ if (fifo8_is_empty(&s->tx_fifo)) {
393
+ if (val & 0x1000) {
430
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] |= SPI_INT_STA_TC;
394
+ s->status |= 0x0020;
431
+ s->regs[REG_INDEX(SPI_CTL_REG)] &= ~SPI_CTL_XCH;
432
+ }
433
+
434
+ trace_allwinner_a10_spi_flush_txfifo_end(fifo8_num_used(&s->tx_fifo),
435
+ fifo8_num_used(&s->rx_fifo));
436
+}
437
+
438
+static uint64_t allwinner_a10_spi_read(void *opaque, hwaddr offset,
439
+ unsigned size)
440
+{
441
+ uint32_t value = 0;
442
+ AWA10SPIState *s = opaque;
443
+ uint32_t index = offset >> 2;
444
+
445
+ if (offset > SPI_FIFO_STA_REG) {
446
+ qemu_log_mask(LOG_GUEST_ERROR,
447
+ "[%s]%s: Bad register at offset 0x%" HWADDR_PRIx "\n",
448
+ TYPE_AW_A10_SPI, __func__, offset);
449
+ return 0;
450
+ }
451
+
452
+ value = s->regs[index];
453
+
454
+ if (allwinner_a10_spi_is_enabled(s)) {
455
+ switch (offset) {
456
+ case SPI_RXDATA_REG:
457
+ if (fifo8_is_empty(&s->rx_fifo)) {
458
+ /* value is undefined */
459
+ value = 0xdeadbeef;
460
+ } else {
461
+ /* read from the RX FIFO */
462
+ value = fifo8_pop(&s->rx_fifo);
463
+ }
464
+ break;
465
+ case SPI_TXDATA_REG:
466
+ qemu_log_mask(LOG_GUEST_ERROR,
467
+ "[%s]%s: Trying to read from TX FIFO\n",
468
+ TYPE_AW_A10_SPI, __func__);
469
+
470
+ /* Reading from TXDATA gives 0 */
471
+ break;
472
+ case SPI_FIFO_STA_REG:
473
+ /* Read current tx/rx fifo data count */
474
+ value = fifo8_num_used(&s->tx_fifo) << SPI_FIFO_STA_TF_CNT_SHIFT |
475
+ fifo8_num_used(&s->rx_fifo) << SPI_FIFO_STA_RF_CNT_SHIFT;
476
+ break;
477
+ case SPI_CTL_REG:
478
+ case SPI_INTCTL_REG:
479
+ case SPI_INT_STA_REG:
480
+ case SPI_DMACTL_REG:
481
+ case SPI_WAIT_REG:
482
+ case SPI_CCTL_REG:
483
+ case SPI_BC_REG:
484
+ case SPI_TC_REG:
485
+ break;
486
+ default:
487
+ qemu_log_mask(LOG_GUEST_ERROR,
488
+ "%s: bad offset 0x%x\n", __func__,
489
+ (uint32_t)offset);
490
+ break;
491
+ }
492
+
493
+ allwinner_a10_spi_update_irq(s);
494
+ }
495
+ trace_allwinner_a10_spi_read(allwinner_a10_spi_get_regname(offset), value);
496
+
497
+ return value;
498
+}
499
+
500
+static bool allwinner_a10_spi_update_cs_level(AWA10SPIState *s, int cs_line_nr)
501
+{
502
+ if (cs_line_nr == allwinner_a10_spi_selected_channel(s)) {
503
+ return (s->regs[REG_INDEX(SPI_CTL_REG)] & SPI_CTL_SS_LEVEL) != 0;
504
+ } else {
505
+ return (s->regs[REG_INDEX(SPI_CTL_REG)] & SPI_CTL_SSPOL) != 0;
506
+ }
507
+}
508
+
509
+static void allwinner_a10_spi_write(void *opaque, hwaddr offset, uint64_t value,
510
+ unsigned size)
511
+{
512
+ AWA10SPIState *s = opaque;
513
+ uint32_t index = offset >> 2;
514
+ int i = 0;
515
+
516
+ if (offset > SPI_FIFO_STA_REG) {
517
+ qemu_log_mask(LOG_GUEST_ERROR,
518
+ "[%s]%s: Bad register at offset 0x%" HWADDR_PRIx "\n",
519
+ TYPE_AW_A10_SPI, __func__, offset);
520
+ return;
521
+ }
522
+
523
+ trace_allwinner_a10_spi_write(allwinner_a10_spi_get_regname(offset),
524
+ (uint32_t)value);
525
+
526
+ if (!allwinner_a10_spi_is_enabled(s)) {
527
+ /* Block is disabled */
528
+ if (offset != SPI_CTL_REG) {
529
+ /* Ignore access */
530
+ return;
531
+ }
532
+ }
533
+
534
+ switch (offset) {
535
+ case SPI_RXDATA_REG:
536
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to write to RX FIFO\n",
537
+ TYPE_AW_A10_SPI, __func__);
538
+ break;
539
+ case SPI_TXDATA_REG:
540
+ if (fifo8_is_full(&s->tx_fifo)) {
541
+ /* Ignore writes if queue is full */
542
+ break;
543
+ }
544
+
545
+ fifo8_push(&s->tx_fifo, (uint8_t)value);
546
+
547
+ break;
548
+ case SPI_INT_STA_REG:
549
+ /* Handle W1C bits - everything except SPI_INT_STA_INT_CBF. */
550
+ value &= ~SPI_INT_STA_INT_CBF;
551
+ s->regs[REG_INDEX(SPI_INT_STA_REG)] &= ~(value & SPI_INT_STA_MASK);
552
+ break;
553
+ case SPI_CTL_REG:
554
+ s->regs[REG_INDEX(SPI_CTL_REG)] = value;
555
+
556
+ for (i = 0; i < AW_A10_SPI_CS_LINES_NR; i++) {
557
+ qemu_set_irq(
558
+ s->cs_lines[i],
559
+ allwinner_a10_spi_update_cs_level(s, i));
560
+ }
561
+
562
+ if (s->regs[REG_INDEX(SPI_CTL_REG)] & SPI_CTL_XCH) {
563
+ /* Request to start emitting */
564
+ allwinner_a10_spi_flush_txfifo(s);
565
+ }
566
+ if (s->regs[REG_INDEX(SPI_CTL_REG)] & SPI_CTL_TF_RST) {
567
+ allwinner_a10_spi_txfifo_reset(s);
568
+ s->regs[REG_INDEX(SPI_CTL_REG)] &= ~SPI_CTL_TF_RST;
569
+ }
570
+ if (s->regs[REG_INDEX(SPI_CTL_REG)] & SPI_CTL_RF_RST) {
571
+ allwinner_a10_spi_rxfifo_reset(s);
572
+ s->regs[REG_INDEX(SPI_CTL_REG)] &= ~SPI_CTL_RF_RST;
573
+ }
395
+ }
574
+ break;
396
+ break;
575
+ case SPI_INTCTL_REG:
397
+ case 4: /* Auto-neg advertisement */
576
+ case SPI_DMACTL_REG:
398
+ s->advertise = (val & 0x2d7f) | 0x80;
577
+ case SPI_WAIT_REG:
399
+ break;
578
+ case SPI_CCTL_REG:
400
+ /* TODO 17, 18, 27, 31 */
579
+ case SPI_BC_REG:
401
+ case 30: /* Interrupt mask */
580
+ case SPI_TC_REG:
402
+ s->int_mask = val & 0xff;
581
+ case SPI_FIFO_STA_REG:
403
+ lan9118_phy_update_irq(s);
582
+ s->regs[index] = value;
583
+ break;
404
+ break;
584
+ default:
405
+ default:
585
+ qemu_log_mask(LOG_GUEST_ERROR,
406
+ qemu_log_mask(LOG_GUEST_ERROR,
586
+ "%s: bad offset 0x%x\n", __func__,
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
587
+ (uint32_t)offset);
588
+ break;
589
+ }
408
+ }
590
+
409
+}
591
+ allwinner_a10_spi_update_irq(s);
410
+
592
+}
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
593
+
412
+{
594
+static const MemoryRegionOps allwinner_a10_spi_ops = {
413
+ s->link_down = link_down;
595
+ .read = allwinner_a10_spi_read,
414
+
596
+ .write = allwinner_a10_spi_write,
415
+ /* Autonegotiation status mirrors link status. */
597
+ .valid.min_access_size = 1,
416
+ if (link_down) {
598
+ .valid.max_access_size = 4,
417
+ s->status &= ~0x0024;
599
+ .endianness = DEVICE_NATIVE_ENDIAN,
418
+ s->ints |= PHY_INT_DOWN;
600
+};
419
+ } else {
601
+
420
+ s->status |= 0x0024;
602
+static const VMStateDescription allwinner_a10_spi_vmstate = {
421
+ s->ints |= PHY_INT_ENERGYON;
603
+ .name = TYPE_AW_A10_SPI,
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",
604
+ .version_id = 1,
453
+ .version_id = 1,
605
+ .minimum_version_id = 1,
454
+ .minimum_version_id = 1,
606
+ .fields = (const VMStateField[]) {
455
+ .fields = (const VMStateField[]) {
607
+ VMSTATE_FIFO8(tx_fifo, AWA10SPIState),
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
608
+ VMSTATE_FIFO8(rx_fifo, AWA10SPIState),
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
609
+ VMSTATE_UINT32_ARRAY(regs, AWA10SPIState, AW_A10_SPI_REGS_NUM),
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
610
+ VMSTATE_END_OF_LIST()
462
+ VMSTATE_END_OF_LIST()
611
+ }
463
+ }
612
+};
464
+};
613
+
465
+
614
+static void allwinner_a10_spi_realize(DeviceState *dev, Error **errp)
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
615
+{
467
+{
616
+ AWA10SPIState *s = AW_A10_SPI(dev);
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
617
+ int i = 0;
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
618
+
470
+
619
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_a10_spi_ops, s,
471
+ rc->phases.hold = lan9118_phy_reset_hold;
620
+ TYPE_AW_A10_SPI, AW_A10_SPI_IOSIZE);
472
+ dc->vmsd = &vmstate_lan9118_phy;
621
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
473
+}
622
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
474
+
623
+
475
+static const TypeInfo types[] = {
624
+ s->bus = ssi_create_bus(dev, "spi");
476
+ {
625
+ for (i = 0; i < AW_A10_SPI_CS_LINES_NR; i++) {
477
+ .name = TYPE_LAN9118_PHY,
626
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->cs_lines[i]);
478
+ .parent = TYPE_SYS_BUS_DEVICE,
479
+ .instance_size = sizeof(Lan9118PhyState),
480
+ .instance_init = lan9118_phy_init,
481
+ .class_init = lan9118_phy_class_init,
627
+ }
482
+ }
628
+ fifo8_create(&s->tx_fifo, AW_A10_SPI_FIFO_SIZE);
629
+ fifo8_create(&s->rx_fifo, AW_A10_SPI_FIFO_SIZE);
630
+}
631
+
632
+static void allwinner_a10_spi_class_init(ObjectClass *klass, void *data)
633
+{
634
+ DeviceClass *dc = DEVICE_CLASS(klass);
635
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
636
+
637
+ rc->phases.hold = allwinner_a10_spi_reset_hold;
638
+ dc->vmsd = &allwinner_a10_spi_vmstate;
639
+ dc->realize = allwinner_a10_spi_realize;
640
+ dc->desc = "Allwinner A10 SPI Controller";
641
+}
642
+
643
+static const TypeInfo allwinner_a10_spi_type_info = {
644
+ .name = TYPE_AW_A10_SPI,
645
+ .parent = TYPE_SYS_BUS_DEVICE,
646
+ .instance_size = sizeof(AWA10SPIState),
647
+ .class_init = allwinner_a10_spi_class_init,
648
+};
483
+};
649
+
484
+
650
+static void allwinner_a10_spi_register_types(void)
485
+DEFINE_TYPES(types)
651
+{
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
652
+ type_register_static(&allwinner_a10_spi_type_info);
653
+}
654
+
655
+type_init(allwinner_a10_spi_register_types)
656
diff --git a/hw/ssi/Kconfig b/hw/ssi/Kconfig
657
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
658
--- a/hw/ssi/Kconfig
488
--- a/hw/net/Kconfig
659
+++ b/hw/ssi/Kconfig
489
+++ b/hw/net/Kconfig
660
@@ -XXX,XX +XXX,XX @@ config BCM2835_SPI
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
661
config PNV_SPI
491
config SMC91C111
662
bool
492
bool
663
select SSI
493
664
+
494
+config LAN9118_PHY
665
+config ALLWINNER_A10_SPI
666
+ bool
495
+ bool
667
+ select SSI
496
+
668
diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build
497
config LAN9118
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
669
index XXXXXXX..XXXXXXX 100644
504
index XXXXXXX..XXXXXXX 100644
670
--- a/hw/ssi/meson.build
505
--- a/hw/net/meson.build
671
+++ b/hw/ssi/meson.build
506
+++ b/hw/net/meson.build
672
@@ -XXX,XX +XXX,XX @@
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
673
+system_ss.add(when: 'CONFIG_ALLWINNER_A10_SPI', if_true: files('allwinner-a10-spi.c'))
508
674
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_smc.c'))
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
675
system_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-spi.c'))
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
676
system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_fiu.c', 'npcm_pspi.c'))
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
677
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
512
system_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c'))
678
index XXXXXXX..XXXXXXX 100644
513
system_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c'))
679
--- a/hw/ssi/trace-events
514
system_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c'))
680
+++ b/hw/ssi/trace-events
681
@@ -XXX,XX +XXX,XX @@ pnv_spi_rx_read_N2frame(void) ""
682
pnv_spi_shift_rx(uint8_t byte, uint32_t index) "byte = 0x%2.2x into RDR from payload index %d"
683
pnv_spi_sequencer_stop_requested(const char* reason) "due to %s"
684
pnv_spi_RDR_match(const char* result) "%s"
685
+
686
+# allwinner_a10_spi.c
687
+allwinner_a10_spi_update_irq(uint32_t level) "IRQ level is %d"
688
+allwinner_a10_spi_flush_txfifo_begin(uint32_t tx, uint32_t rx) "Begin: TX Fifo Size = %d, RX Fifo Size = %d"
689
+allwinner_a10_spi_flush_txfifo_end(uint32_t tx, uint32_t rx) "End: TX Fifo Size = %d, RX Fifo Size = %d"
690
+allwinner_a10_spi_burst_length(uint32_t len) "Burst length = %d"
691
+allwinner_a10_spi_tx(uint8_t byte) "write 0x%02x"
692
+allwinner_a10_spi_rx(uint8_t byte) "read 0x%02x"
693
+allwinner_a10_spi_read(const char* regname, uint32_t value) "reg[%s] => 0x%08x"
694
+allwinner_a10_spi_write(const char* regname, uint32_t value) "reg[%s] <= 0x%08x"
695
--
515
--
696
2.34.1
516
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
imx_fec having more logging and tracing. Merge these improvements into
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
6
7
Some migration state how resides in the new device model which breaks migration
8
compatibility for the following machines:
9
* imx25-pdk
10
* sabrelite
11
* mcimx7d-sabre
12
* mcimx6ul-evk
13
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 20241102125724.532843-3-shentey@gmail.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
include/hw/net/imx_fec.h | 9 ++-
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
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(-)
26
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/net/imx_fec.h
30
+++ b/include/hw/net/imx_fec.h
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
32
#define TYPE_IMX_ENET "imx.enet"
33
34
#include "hw/sysbus.h"
35
+#include "hw/net/lan9118_phy.h"
36
+#include "hw/irq.h"
37
#include "net/net.h"
38
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
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/net/imx_fec.c
57
+++ b/hw/net/imx_fec.c
58
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth_txdescs = {
59
60
static const VMStateDescription vmstate_imx_eth = {
61
.name = TYPE_IMX_FEC,
62
- .version_id = 2,
63
- .minimum_version_id = 2,
64
+ .version_id = 3,
65
+ .minimum_version_id = 3,
66
.fields = (const VMStateField[]) {
67
VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
68
VMSTATE_UINT32(rx_descriptor, IMXFECState),
69
VMSTATE_UINT32(tx_descriptor[0], IMXFECState),
70
- VMSTATE_UINT32(phy_status, IMXFECState),
71
- VMSTATE_UINT32(phy_control, IMXFECState),
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 = {
79
},
80
};
81
82
-#define PHY_INT_ENERGYON (1 << 7)
83
-#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
84
-#define PHY_INT_FAULT (1 << 5)
85
-#define PHY_INT_DOWN (1 << 4)
86
-#define PHY_INT_AUTONEG_LP (1 << 3)
87
-#define PHY_INT_PARFAULT (1 << 2)
88
-#define PHY_INT_AUTONEG_PAGE (1 << 1)
89
-
90
static void imx_eth_update(IMXFECState *s);
91
92
/*
93
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s);
94
* For now we don't handle any GPIO/interrupt line, so the OS will
95
* have to poll for the PHY status.
96
*/
97
-static void imx_phy_update_irq(IMXFECState *s)
98
+static void imx_phy_update_irq(void *opaque, int n, int level)
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;
260
+ }
261
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
262
+
263
qemu_macaddr_default_if_unset(&s->conf.macaddr);
264
265
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
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)
353
{
354
+ trace_lan9118_phy_write(val, reg);
355
+
356
switch (reg) {
357
case 0: /* Basic Control */
358
if (val & 0x8000) {
359
lan9118_phy_reset(s);
360
- break;
361
- }
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"
471
--
472
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
5
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
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/net/lan9118_phy.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/lan9118_phy.c
19
+++ b/hw/net/lan9118_phy.c
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
21
val = s->advertise;
22
break;
23
case 5: /* Auto-neg Link Partner Ability */
24
- val = 0x0f71;
25
+ val = 0x0fe1;
26
break;
27
case 6: /* Auto-neg Expansion */
28
val = 1;
29
--
30
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Prefer named constants over magic values for better readability.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20241102125724.532843-5-shentey@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/net/mii.h | 6 +++++
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
13
2 files changed, 46 insertions(+), 23 deletions(-)
14
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/net/mii.h
18
+++ b/include/hw/net/mii.h
19
@@ -XXX,XX +XXX,XX @@
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
21
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
22
23
+#define MII_ANAR_RFAULT (1 << 13) /* Say we can detect faults */
24
#define MII_ANAR_PAUSE_ASYM (1 << 11) /* Try for asymmetric pause */
25
#define MII_ANAR_PAUSE (1 << 10) /* Try for pause */
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
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/net/lan9118_phy.c
49
+++ b/hw/net/lan9118_phy.c
50
@@ -XXX,XX +XXX,XX @@
51
52
#include "qemu/osdep.h"
53
#include "hw/net/lan9118_phy.h"
54
+#include "hw/net/mii.h"
55
#include "hw/irq.h"
56
#include "hw/resettable.h"
57
#include "migration/vmstate.h"
58
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
59
uint16_t val;
60
61
switch (reg) {
62
- case 0: /* Basic Control */
63
+ case MII_BMCR:
64
val = s->control;
65
break;
66
- case 1: /* Basic Status */
67
+ case MII_BMSR:
68
val = s->status;
69
break;
70
- case 2: /* ID1 */
71
- val = 0x0007;
72
+ case MII_PHYID1:
73
+ val = SMSCLAN9118_PHYID1;
74
break;
75
- case 3: /* ID2 */
76
- val = 0xc0d1;
77
+ case MII_PHYID2:
78
+ val = SMSCLAN9118_PHYID2;
79
break;
80
- case 4: /* Auto-neg advertisement */
81
+ case MII_ANAR:
82
val = s->advertise;
83
break;
84
- case 5: /* Auto-neg Link Partner Ability */
85
- val = 0x0fe1;
86
+ case MII_ANLPAR:
87
+ val = MII_ANLPAR_PAUSEASY | MII_ANLPAR_PAUSE | MII_ANLPAR_T4 |
88
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
89
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
90
break;
91
- case 6: /* Auto-neg Expansion */
92
- val = 1;
93
+ case MII_ANER:
94
+ val = MII_ANER_NWAY;
95
break;
96
case 29: /* Interrupt source. */
97
val = s->ints;
98
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
99
trace_lan9118_phy_write(val, reg);
100
101
switch (reg) {
102
- case 0: /* Basic Control */
103
- if (val & 0x8000) {
104
+ case MII_BMCR:
105
+ if (val & MII_BMCR_RESET) {
106
lan9118_phy_reset(s);
107
} else {
108
- s->control = val & 0x7980;
109
+ s->control = val & (MII_BMCR_LOOPBACK | MII_BMCR_SPEED100 |
110
+ MII_BMCR_AUTOEN | MII_BMCR_PDOWN | MII_BMCR_FD |
111
+ MII_BMCR_CTST);
112
/* Complete autonegotiation immediately. */
113
- if (val & 0x1000) {
114
- s->status |= 0x0020;
115
+ if (val & MII_BMCR_AUTOEN) {
116
+ s->status |= MII_BMSR_AN_COMP;
117
}
118
}
119
break;
120
- case 4: /* Auto-neg advertisement */
121
- s->advertise = (val & 0x2d7f) | 0x80;
122
+ case MII_ANAR:
123
+ s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
124
+ MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
125
+ MII_ANAR_SELECT))
126
+ | MII_ANAR_TX;
127
break;
128
case 30: /* Interrupt mask */
129
s->int_mask = val & 0xff;
130
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
131
/* Autonegotiation status mirrors link status. */
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);
166
--
167
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
The real device advertises this mode and the device model already advertises
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
make the model more realistic.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/net/lan9118_phy.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/lan9118_phy.c
19
+++ b/hw/net/lan9118_phy.c
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
21
break;
22
case MII_ANAR:
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
25
- MII_ANAR_SELECT))
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
28
| MII_ANAR_TX;
29
break;
30
case 30: /* Interrupt mask */
31
--
32
2.34.1
diff view generated by jsdifflib
New patch
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.
1
6
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".
13
14
For Arm, this looks like it might be a behaviour change because we
15
used to set float_flag_invalid | float_flag_invalid_imz only if C is
16
a quiet NaN. However, it is not, because Arm target code never looks
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
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
37
---
38
fpu/softfloat-parts.c.inc | 13 +++++++------
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
40
2 files changed, 8 insertions(+), 34 deletions(-)
41
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
43
index XXXXXXX..XXXXXXX 100644
44
--- a/fpu/softfloat-parts.c.inc
45
+++ b/fpu/softfloat-parts.c.inc
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
47
int ab_mask, int abc_mask)
48
{
49
int which;
50
+ bool infzero = (ab_mask == float_cmask_infzero);
51
52
if (unlikely(abc_mask & float_cmask_snan)) {
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
54
}
55
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
57
- ab_mask == float_cmask_infzero, s);
58
+ if (infzero) {
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
61
+ }
62
+
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
64
65
if (s->default_nan_mode || which == 3) {
66
- /*
67
- * Note that this check is after pickNaNMulAdd so that function
68
- * has an opportunity to set the Invalid flag for infzero.
69
- */
70
parts_default_nan(a, s);
71
return a;
72
}
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
- }
112
+
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
114
if (is_snan(c_cls)) {
115
return 2;
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
117
* to return an input NaN if we have one (ie c) rather than generating
118
* a default NaN
119
*/
120
- if (infzero) {
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
122
- return 2;
123
- }
124
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
128
return 1;
129
}
130
#elif defined(TARGET_RISCV)
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
132
- if (infzero) {
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
134
- }
135
return 3; /* default NaN */
136
#elif defined(TARGET_S390X)
137
if (infzero) {
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
139
return 3;
140
}
141
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
143
return 2;
144
}
145
#elif defined(TARGET_SPARC)
146
- /* For (inf,0,nan) return c. */
147
- if (infzero) {
148
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
149
- return 2;
150
- }
151
/* Prefer SNaN over QNaN, order C, B, A. */
152
if (is_snan(c_cls)) {
153
return 2;
154
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
155
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
156
* an input NaN if we have one (ie c).
157
*/
158
- if (infzero) {
159
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
160
- return 2;
161
- }
162
if (status->use_first_nan) {
163
if (is_nan(a_cls)) {
164
return 0;
165
--
166
2.34.1
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
New patch
1
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
architectures thus do different things:
4
* some return the default NaN
5
* some return the input NaN
6
* Arm returns the default NaN if the input NaN is quiet,
7
and the input NaN if it is signalling
8
9
We want to make this logic be runtime selected rather than
10
hardcoded into the binary, because:
11
* this will let us have multiple targets in one QEMU binary
12
* the Arm FEAT_AFP architectural feature includes letting
13
the guest select a NaN propagation rule at runtime
14
15
In this commit we add an enum for the propagation rule, the field in
16
float_status, and the corresponding getters and setters. We change
17
pickNaNMulAdd to honour this, but because all targets still leave
18
this field at its default 0 value, the fallback logic will pick the
19
rule type with the old ifdef ladder.
20
21
Note that four architectures both use the muladd softfloat functions
22
and did not have a branch of the ifdef ladder to specify their
23
behaviour (and so were ending up with the "default" case, probably
24
wrongly): i386, HPPA, SH4 and Tricore. SH4 and Tricore both set
25
default_nan_mode, and so will never get into pickNaNMulAdd(). For
26
HPPA and i386 we retain the same behaviour as the old default-case,
27
which is to not ever return the default NaN. This might not be
28
correct but it is not a behaviour change.
29
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
33
---
34
include/fpu/softfloat-helpers.h | 11 ++++
35
include/fpu/softfloat-types.h | 23 +++++++++
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
37
3 files changed, 95 insertions(+), 30 deletions(-)
38
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/include/fpu/softfloat-helpers.h
42
+++ b/include/fpu/softfloat-helpers.h
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
44
status->float_2nan_prop_rule = rule;
45
}
46
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
76
+/*
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.
80
+ *
81
+ * You don't need to set this if default_nan_mode is enabled.
82
+ * When not in default-NaN mode, it is an error for the target
83
+ * not to set the rule in float_status if it uses muladd, and we
84
+ * will assert if we need to handle an input NaN and no rule was
85
+ * selected.
86
+ */
87
+typedef enum __attribute__((__packed__)) {
88
+ /* No propagation rule specified */
89
+ float_infzeronan_none = 0,
90
+ /* Result is never the default NaN (so always the input NaN) */
91
+ float_infzeronan_dnan_never,
92
+ /* Result is always the default NaN */
93
+ float_infzeronan_dnan_always,
94
+ /* Result is the default NaN if the input NaN is quiet */
95
+ float_infzeronan_dnan_if_qnan,
96
+} FloatInfZeroNaNRule;
97
+
98
/*
99
* Floating Point Status. Individual architectures may maintain
100
* several versions of float_status for different functions. The
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
102
FloatRoundMode float_rounding_mode;
103
FloatX80RoundPrec floatx80_rounding_precision;
104
Float2NaNPropRule float_2nan_prop_rule;
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
106
bool tininess_before_rounding;
107
/* should denormalised results go to zero and set the inexact flag? */
108
bool flush_to_zero;
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
110
index XXXXXXX..XXXXXXX 100644
111
--- a/fpu/softfloat-specialize.c.inc
112
+++ b/fpu/softfloat-specialize.c.inc
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
115
bool infzero, float_status *status)
116
{
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
118
+
119
/*
120
* We guarantee not to require the target to tell us how to
121
* pick a NaN if we're always returning the default NaN.
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
123
* specify.
124
*/
125
assert(!status->default_nan_mode);
126
+
127
+ if (rule == float_infzeronan_none) {
128
+ /*
129
+ * Temporarily fall back to ifdef ladder
130
+ */
131
#if defined(TARGET_ARM)
132
- /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
133
- * the default NaN
134
- */
135
- if (infzero && is_qnan(c_cls)) {
136
- return 3;
137
+ /*
138
+ * For ARM, the (inf,zero,qnan) case returns the default NaN,
139
+ * but (inf,zero,snan) returns the input NaN.
140
+ */
141
+ rule = float_infzeronan_dnan_if_qnan;
142
+#elif defined(TARGET_MIPS)
143
+ if (snan_bit_is_one(status)) {
144
+ /*
145
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
146
+ * case sets InvalidOp and returns the default NaN
147
+ */
148
+ rule = float_infzeronan_dnan_always;
149
+ } else {
150
+ /*
151
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
152
+ * case sets InvalidOp and returns the input value 'c'
153
+ */
154
+ rule = float_infzeronan_dnan_never;
155
+ }
156
+#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
157
+ defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
158
+ defined(TARGET_I386) || defined(TARGET_LOONGARCH)
159
+ /*
160
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
161
+ * case sets InvalidOp and returns the input value 'c'
162
+ */
163
+ /*
164
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
165
+ * to return an input NaN if we have one (ie c) rather than generating
166
+ * a default NaN
167
+ */
168
+ rule = float_infzeronan_dnan_never;
169
+#elif defined(TARGET_S390X)
170
+ rule = float_infzeronan_dnan_always;
171
+#endif
172
}
173
174
+ if (infzero) {
175
+ /*
176
+ * Inf * 0 + NaN -- some implementations return the default NaN here,
177
+ * and some return the input NaN.
178
+ */
179
+ switch (rule) {
180
+ case float_infzeronan_dnan_never:
181
+ return 2;
182
+ case float_infzeronan_dnan_always:
183
+ return 3;
184
+ case float_infzeronan_dnan_if_qnan:
185
+ return is_qnan(c_cls) ? 3 : 2;
186
+ default:
187
+ g_assert_not_reached();
188
+ }
189
+ }
190
+
191
+#if defined(TARGET_ARM)
192
+
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
195
*/
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
197
}
198
#elif defined(TARGET_MIPS)
199
if (snan_bit_is_one(status)) {
200
- /*
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
202
- * case sets InvalidOp and returns the default NaN
203
- */
204
- if (infzero) {
205
- return 3;
206
- }
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
208
if (is_snan(a_cls)) {
209
return 0;
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
211
return 2;
212
}
213
} else {
214
- /*
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
216
- * case sets InvalidOp and returns the input value 'c'
217
- */
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
219
if (is_snan(c_cls)) {
220
return 2;
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
222
}
223
}
224
#elif defined(TARGET_LOONGARCH64)
225
- /*
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
227
- * case sets InvalidOp and returns the input value 'c'
228
- */
229
-
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
231
if (is_snan(c_cls)) {
232
return 2;
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
234
return 1;
235
}
236
#elif defined(TARGET_PPC)
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
238
- * to return an input NaN if we have one (ie c) rather than generating
239
- * a default NaN
240
- */
241
-
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
244
*/
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
246
return 1;
247
}
248
#elif defined(TARGET_S390X)
249
- if (infzero) {
250
- return 3;
251
- }
252
-
253
if (is_snan(a_cls)) {
254
return 0;
255
} else if (is_snan(b_cls)) {
256
--
257
2.34.1
diff view generated by jsdifflib
1
From: Chao Liu <chao.liu@yeah.net>
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.
2
5
3
Add unimplemented-device blocks to the xilinx_zynq board
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
corresponding to various devices documented in the TRM
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
and in the device tree.
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(+)
6
13
7
See: ug585-Zynq-7000-TRM manual B.3 (Module Summary)
14
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
8
9
Signed-off-by: Chao Liu <chao.liu@yeah.net>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: tweaked commit message. Removed the clearing of
12
the ignore_memory_transaction_failures flag]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/arm/xilinx_zynq.c | 70 ++++++++++++++++++++++++++++++++++++++++++++
16
1 file changed, 70 insertions(+)
17
18
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/xilinx_zynq.c
16
--- a/tests/fp/fp-bench.c
21
+++ b/hw/arm/xilinx_zynq.c
17
+++ b/tests/fp/fp-bench.c
22
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
23
#include "hw/net/cadence_gem.h"
19
{
24
#include "hw/cpu/a9mpcore.h"
20
bench_func_t f;
25
#include "hw/qdev-clock.h"
26
+#include "hw/misc/unimp.h"
27
#include "sysemu/reset.h"
28
#include "qom/object.h"
29
#include "exec/tswap.h"
30
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
31
sysbus_connect_irq(busdev, 0, pic[40 - IRQ_OFFSET]);
32
sysbus_mmio_map(busdev, 0, 0xF8007000);
33
21
34
+ /*
22
+ /*
35
+ * Refer to the ug585-Zynq-7000-TRM manual B.3 (Module Summary) and
23
+ * These implementation-defined choices for various things IEEE
36
+ * the zynq-7000.dtsi. Add placeholders for unimplemented devices.
24
+ * doesn't specify match those used by the Arm architecture.
37
+ */
25
+ */
38
+ create_unimplemented_device("zynq.i2c0", 0xE0004000, 4 * KiB);
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
39
+ create_unimplemented_device("zynq.i2c1", 0xE0005000, 4 * KiB);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
40
+ create_unimplemented_device("zynq.can0", 0xE0008000, 4 * KiB);
28
41
+ create_unimplemented_device("zynq.can1", 0xE0009000, 4 * KiB);
29
f = bench_funcs[operation][precision];
42
+ create_unimplemented_device("zynq.gpio", 0xE000A000, 4 * KiB);
30
g_assert(f);
43
+ create_unimplemented_device("zynq.smcc", 0xE000E000, 4 * KiB);
31
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
44
+
32
index XXXXXXX..XXXXXXX 100644
45
+ /* Direct Memory Access Controller, PL330, Non-Secure Mode */
33
--- a/tests/fp/fp-test.c
46
+ create_unimplemented_device("zynq.dma_ns", 0xF8004000, 4 * KiB);
34
+++ b/tests/fp/fp-test.c
47
+
35
@@ -XXX,XX +XXX,XX @@ void run_test(void)
48
+ /* System Watchdog Timer Registers */
36
{
49
+ create_unimplemented_device("zynq.swdt", 0xF8005000, 4 * KiB);
37
unsigned int i;
50
+
38
51
+ /* DDR memory controller */
39
+ /*
52
+ create_unimplemented_device("zynq.ddrc", 0xF8006000, 4 * KiB);
40
+ * These implementation-defined choices for various things IEEE
53
+
41
+ * doesn't specify match those used by the Arm architecture.
54
+ /* AXI_HP Interface (AFI) */
42
+ */
55
+ create_unimplemented_device("zynq.axi_hp0", 0xF8008000, 0x28);
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
56
+ create_unimplemented_device("zynq.axi_hp1", 0xF8009000, 0x28);
44
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
57
+ create_unimplemented_device("zynq.axi_hp2", 0xF800A000, 0x28);
45
58
+ create_unimplemented_device("zynq.axi_hp3", 0xF800B000, 0x28);
46
genCases_setLevel(test_level);
59
+
47
verCases_maxErrorCount = n_max_errors;
60
+ create_unimplemented_device("zynq.efuse", 0xF800d000, 0x20);
61
+
62
+ /* Embedded Trace Buffer */
63
+ create_unimplemented_device("zynq.etb", 0xF8801000, 4 * KiB);
64
+
65
+ /* Cross Trigger Interface, ETB and TPIU */
66
+ create_unimplemented_device("zynq.cti_etb_tpiu", 0xF8802000, 4 * KiB);
67
+
68
+ /* Trace Port Interface Unit */
69
+ create_unimplemented_device("zynq.tpiu", 0xF8803000, 4 * KiB);
70
+
71
+ /* CoreSight Trace Funnel */
72
+ create_unimplemented_device("zynq.funnel", 0xF8804000, 4 * KiB);
73
+
74
+ /* Instrumentation Trace Macrocell */
75
+ create_unimplemented_device("zynq.itm", 0xF8805000, 4 * KiB);
76
+
77
+ /* Cross Trigger Interface, FTM */
78
+ create_unimplemented_device("zynq.cti_ftm", 0xF8809000, 4 * KiB);
79
+
80
+ /* Fabric Trace Macrocell */
81
+ create_unimplemented_device("zynq.ftm", 0xF880B000, 4 * KiB);
82
+
83
+ /* Cortex A9 Performance Monitoring Unit, CPU */
84
+ create_unimplemented_device("cortex-a9.pmu0", 0xF8891000, 4 * KiB);
85
+ create_unimplemented_device("cortex-a9.pmu1", 0xF8893000, 4 * KiB);
86
+
87
+ /* Cross Trigger Interface, CPU */
88
+ create_unimplemented_device("zynq.cpu_cti0", 0xF8898000, 4 * KiB);
89
+ create_unimplemented_device("zynq.cpu_cti1", 0xF8899000, 4 * KiB);
90
+
91
+ /* CoreSight PTM-A9, CPU */
92
+ create_unimplemented_device("cortex-a9.ptm0", 0xF889c000, 4 * KiB);
93
+ create_unimplemented_device("cortex-a9.ptm1", 0xF889d000, 4 * KiB);
94
+
95
+ /* AMBA NIC301 TrustZone */
96
+ create_unimplemented_device("zynq.trustZone", 0xF8900000, 0x20);
97
+
98
+ /* AMBA Network Interconnect Advanced Quality of Service (QoS-301) */
99
+ create_unimplemented_device("zynq.qos301_cpu", 0xF8946000, 0x130);
100
+ create_unimplemented_device("zynq.qos301_dmac", 0xF8947000, 0x130);
101
+ create_unimplemented_device("zynq.qos301_iou", 0xF8948000, 0x130);
102
+
103
zynq_binfo.ram_size = machine->ram_size;
104
zynq_binfo.board_id = 0xd32;
105
zynq_binfo.loader_start = 0;
106
--
48
--
107
2.34.1
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
1
The MAX111X ADC device was used only by the XScale-based
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
Zaurus machine types. Now they have all been removed, we can
2
so we can remove the ifdef from pickNaNMulAdd().
3
drop this device model too.
4
3
5
Because this device is an SSI device, in theory it could be created
4
As this is the last target to be converted to explicitly setting
6
by users on the command line for boards with a different SSI
5
the rule, we can remove the fallback code in pickNaNMulAdd()
7
controller, but we don't believe users are doing this -- it would be
6
entirely.
8
impossible on the command line to connect up the GPIO inputs which
9
correspond to ADC inputs, or the GPIO output which is an interrupt
10
line. The only example a web search produces for "device max1111" or
11
"device max1110" is our own bug report
12
https://gitlab.com/qemu-project/qemu/-/issues/2228
13
where it's used as an example of a bogus command that causes an
14
assertion in an aspeed machine type that wasn't expecting anything
15
other than flash devices on its SMC bus.
16
7
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
20
Message-id: 20241003140010.1653808-2-peter.maydell@linaro.org
21
---
11
---
22
include/hw/adc/max111x.h | 56 ----------
12
target/hppa/fpu_helper.c | 2 ++
23
hw/adc/max111x.c | 236 ---------------------------------------
13
fpu/softfloat-specialize.c.inc | 13 +------------
24
hw/adc/Kconfig | 3 -
14
2 files changed, 3 insertions(+), 12 deletions(-)
25
hw/adc/meson.build | 1 -
26
4 files changed, 296 deletions(-)
27
delete mode 100644 include/hw/adc/max111x.h
28
delete mode 100644 hw/adc/max111x.c
29
15
30
diff --git a/include/hw/adc/max111x.h b/include/hw/adc/max111x.h
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
31
deleted file mode 100644
17
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX
18
--- a/target/hppa/fpu_helper.c
33
--- a/include/hw/adc/max111x.h
19
+++ b/target/hppa/fpu_helper.c
34
+++ /dev/null
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
35
@@ -XXX,XX +XXX,XX @@
21
* HPPA does note implement a CPU reset method at all...
36
-/*
22
*/
37
- * Maxim MAX1110/1111 ADC chip emulation.
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
38
- *
24
+ /* For inf * 0 + NaN, return the input NaN */
39
- * Copyright (c) 2006 Openedhand Ltd.
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
40
- * Written by Andrzej Zaborowski <balrog@zabor.org>
26
}
41
- *
27
42
- * This code is licensed under the GNU GPLv2.
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
43
- *
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
44
- * Contributions after 2012-01-13 are licensed under the terms of the
30
index XXXXXXX..XXXXXXX 100644
45
- * GNU GPL, version 2 or (at your option) any later version.
31
--- a/fpu/softfloat-specialize.c.inc
46
- */
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;
47
-
38
-
48
-#ifndef HW_MISC_MAX111X_H
39
/*
49
-#define HW_MISC_MAX111X_H
40
* We guarantee not to require the target to tell us how to
50
-
41
* pick a NaN if we're always returning the default NaN.
51
-#include "hw/ssi/ssi.h"
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
52
-#include "qom/object.h"
43
*/
53
-
44
assert(!status->default_nan_mode);
54
-/*
45
55
- * This is a model of the Maxim MAX1110/1111 ADC chip, which for QEMU
46
- if (rule == float_infzeronan_none) {
56
- * is an SSI slave device. It has either 4 (max1110) or 8 (max1111)
47
- /*
57
- * 8-bit ADC channels.
48
- * Temporarily fall back to ifdef ladder
58
- *
49
- */
59
- * QEMU interface:
50
-#if defined(TARGET_HPPA)
60
- * + GPIO inputs 0..3 (for max1110) or 0..7 (for max1111): set the value
51
- rule = float_infzeronan_dnan_never;
61
- * of each ADC input, as an unsigned 8-bit value
62
- * + GPIO output 0: interrupt line
63
- * + Properties "input0" to "input3" (max1110) or "input0" to "input7"
64
- * (max1111): initial reset values for ADC inputs.
65
- *
66
- * Known bugs:
67
- * + the interrupt line is not correctly implemented, and will never
68
- * be lowered once it has been asserted.
69
- */
70
-struct MAX111xState {
71
- SSIPeripheral parent_obj;
72
-
73
- qemu_irq interrupt;
74
- /* Values of inputs at system reset (settable by QOM property) */
75
- uint8_t reset_input[8];
76
-
77
- uint8_t tb1, rb2, rb3;
78
- int cycle;
79
-
80
- uint8_t input[8];
81
- int inputs, com;
82
-};
83
-
84
-#define TYPE_MAX_111X "max111x"
85
-
86
-OBJECT_DECLARE_SIMPLE_TYPE(MAX111xState, MAX_111X)
87
-
88
-#define TYPE_MAX_1110 "max1110"
89
-#define TYPE_MAX_1111 "max1111"
90
-
91
-#endif
52
-#endif
92
diff --git a/hw/adc/max111x.c b/hw/adc/max111x.c
93
deleted file mode 100644
94
index XXXXXXX..XXXXXXX
95
--- a/hw/adc/max111x.c
96
+++ /dev/null
97
@@ -XXX,XX +XXX,XX @@
98
-/*
99
- * Maxim MAX1110/1111 ADC chip emulation.
100
- *
101
- * Copyright (c) 2006 Openedhand Ltd.
102
- * Written by Andrzej Zaborowski <balrog@zabor.org>
103
- *
104
- * This code is licensed under the GNU GPLv2.
105
- *
106
- * Contributions after 2012-01-13 are licensed under the terms of the
107
- * GNU GPL, version 2 or (at your option) any later version.
108
- */
109
-
110
-#include "qemu/osdep.h"
111
-#include "hw/adc/max111x.h"
112
-#include "hw/irq.h"
113
-#include "migration/vmstate.h"
114
-#include "qemu/module.h"
115
-#include "hw/qdev-properties.h"
116
-
117
-/* Control-byte bitfields */
118
-#define CB_PD0        (1 << 0)
119
-#define CB_PD1        (1 << 1)
120
-#define CB_SGL        (1 << 2)
121
-#define CB_UNI        (1 << 3)
122
-#define CB_SEL0        (1 << 4)
123
-#define CB_SEL1        (1 << 5)
124
-#define CB_SEL2        (1 << 6)
125
-#define CB_START    (1 << 7)
126
-
127
-#define CHANNEL_NUM(v, b0, b1, b2)    \
128
- ((((v) >> (2 + (b0))) & 4) |    \
129
- (((v) >> (3 + (b1))) & 2) |    \
130
- (((v) >> (4 + (b2))) & 1))
131
-
132
-static uint32_t max111x_read(MAX111xState *s)
133
-{
134
- if (!s->tb1)
135
- return 0;
136
-
137
- switch (s->cycle ++) {
138
- case 1:
139
- return s->rb2;
140
- case 2:
141
- return s->rb3;
142
- }
53
- }
143
-
54
-
144
- return 0;
55
if (infzero) {
145
-}
56
/*
146
-
57
* Inf * 0 + NaN -- some implementations return the default NaN here,
147
-/* Interpret a control-byte */
58
* and some return the input NaN.
148
-static void max111x_write(MAX111xState *s, uint32_t value)
59
*/
149
-{
60
- switch (rule) {
150
- int measure, chan;
61
+ switch (status->float_infzeronan_rule) {
151
-
62
case float_infzeronan_dnan_never:
152
- /* Ignore the value if START bit is zero */
63
return 2;
153
- if (!(value & CB_START))
64
case float_infzeronan_dnan_always:
154
- return;
155
-
156
- s->cycle = 0;
157
-
158
- if (!(value & CB_PD1)) {
159
- s->tb1 = 0;
160
- return;
161
- }
162
-
163
- s->tb1 = value;
164
-
165
- if (s->inputs == 8)
166
- chan = CHANNEL_NUM(value, 1, 0, 2);
167
- else
168
- chan = CHANNEL_NUM(value & ~CB_SEL0, 0, 1, 2);
169
-
170
- if (value & CB_SGL)
171
- measure = s->input[chan] - s->com;
172
- else
173
- measure = s->input[chan] - s->input[chan ^ 1];
174
-
175
- if (!(value & CB_UNI))
176
- measure ^= 0x80;
177
-
178
- s->rb2 = (measure >> 2) & 0x3f;
179
- s->rb3 = (measure << 6) & 0xc0;
180
-
181
- /* FIXME: When should the IRQ be lowered? */
182
- qemu_irq_raise(s->interrupt);
183
-}
184
-
185
-static uint32_t max111x_transfer(SSIPeripheral *dev, uint32_t value)
186
-{
187
- MAX111xState *s = MAX_111X(dev);
188
- max111x_write(s, value);
189
- return max111x_read(s);
190
-}
191
-
192
-static const VMStateDescription vmstate_max111x = {
193
- .name = "max111x",
194
- .version_id = 1,
195
- .minimum_version_id = 1,
196
- .fields = (const VMStateField[]) {
197
- VMSTATE_SSI_PERIPHERAL(parent_obj, MAX111xState),
198
- VMSTATE_UINT8(tb1, MAX111xState),
199
- VMSTATE_UINT8(rb2, MAX111xState),
200
- VMSTATE_UINT8(rb3, MAX111xState),
201
- VMSTATE_INT32_EQUAL(inputs, MAX111xState, NULL),
202
- VMSTATE_INT32(com, MAX111xState),
203
- VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs,
204
- vmstate_info_uint8, uint8_t),
205
- VMSTATE_END_OF_LIST()
206
- }
207
-};
208
-
209
-static void max111x_input_set(void *opaque, int line, int value)
210
-{
211
- MAX111xState *s = MAX_111X(opaque);
212
-
213
- assert(line >= 0 && line < s->inputs);
214
- s->input[line] = value;
215
-}
216
-
217
-static int max111x_init(SSIPeripheral *d, int inputs)
218
-{
219
- DeviceState *dev = DEVICE(d);
220
- MAX111xState *s = MAX_111X(dev);
221
-
222
- qdev_init_gpio_out(dev, &s->interrupt, 1);
223
- qdev_init_gpio_in(dev, max111x_input_set, inputs);
224
-
225
- s->inputs = inputs;
226
-
227
- return 0;
228
-}
229
-
230
-static void max1110_realize(SSIPeripheral *dev, Error **errp)
231
-{
232
- max111x_init(dev, 8);
233
-}
234
-
235
-static void max1111_realize(SSIPeripheral *dev, Error **errp)
236
-{
237
- max111x_init(dev, 4);
238
-}
239
-
240
-static void max111x_reset(DeviceState *dev)
241
-{
242
- MAX111xState *s = MAX_111X(dev);
243
- int i;
244
-
245
- for (i = 0; i < s->inputs; i++) {
246
- s->input[i] = s->reset_input[i];
247
- }
248
- s->com = 0;
249
- s->tb1 = 0;
250
- s->rb2 = 0;
251
- s->rb3 = 0;
252
- s->cycle = 0;
253
-}
254
-
255
-static Property max1110_properties[] = {
256
- /* Reset values for ADC inputs */
257
- DEFINE_PROP_UINT8("input0", MAX111xState, reset_input[0], 0xf0),
258
- DEFINE_PROP_UINT8("input1", MAX111xState, reset_input[1], 0xe0),
259
- DEFINE_PROP_UINT8("input2", MAX111xState, reset_input[2], 0xd0),
260
- DEFINE_PROP_UINT8("input3", MAX111xState, reset_input[3], 0xc0),
261
- DEFINE_PROP_END_OF_LIST(),
262
-};
263
-
264
-static Property max1111_properties[] = {
265
- /* Reset values for ADC inputs */
266
- DEFINE_PROP_UINT8("input0", MAX111xState, reset_input[0], 0xf0),
267
- DEFINE_PROP_UINT8("input1", MAX111xState, reset_input[1], 0xe0),
268
- DEFINE_PROP_UINT8("input2", MAX111xState, reset_input[2], 0xd0),
269
- DEFINE_PROP_UINT8("input3", MAX111xState, reset_input[3], 0xc0),
270
- DEFINE_PROP_UINT8("input4", MAX111xState, reset_input[4], 0xb0),
271
- DEFINE_PROP_UINT8("input5", MAX111xState, reset_input[5], 0xa0),
272
- DEFINE_PROP_UINT8("input6", MAX111xState, reset_input[6], 0x90),
273
- DEFINE_PROP_UINT8("input7", MAX111xState, reset_input[7], 0x80),
274
- DEFINE_PROP_END_OF_LIST(),
275
-};
276
-
277
-static void max111x_class_init(ObjectClass *klass, void *data)
278
-{
279
- SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
280
- DeviceClass *dc = DEVICE_CLASS(klass);
281
-
282
- k->transfer = max111x_transfer;
283
- device_class_set_legacy_reset(dc, max111x_reset);
284
- dc->vmsd = &vmstate_max111x;
285
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
286
-}
287
-
288
-static const TypeInfo max111x_info = {
289
- .name = TYPE_MAX_111X,
290
- .parent = TYPE_SSI_PERIPHERAL,
291
- .instance_size = sizeof(MAX111xState),
292
- .class_init = max111x_class_init,
293
- .abstract = true,
294
-};
295
-
296
-static void max1110_class_init(ObjectClass *klass, void *data)
297
-{
298
- SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
299
- DeviceClass *dc = DEVICE_CLASS(klass);
300
-
301
- k->realize = max1110_realize;
302
- device_class_set_props(dc, max1110_properties);
303
-}
304
-
305
-static const TypeInfo max1110_info = {
306
- .name = TYPE_MAX_1110,
307
- .parent = TYPE_MAX_111X,
308
- .class_init = max1110_class_init,
309
-};
310
-
311
-static void max1111_class_init(ObjectClass *klass, void *data)
312
-{
313
- SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
314
- DeviceClass *dc = DEVICE_CLASS(klass);
315
-
316
- k->realize = max1111_realize;
317
- device_class_set_props(dc, max1111_properties);
318
-}
319
-
320
-static const TypeInfo max1111_info = {
321
- .name = TYPE_MAX_1111,
322
- .parent = TYPE_MAX_111X,
323
- .class_init = max1111_class_init,
324
-};
325
-
326
-static void max111x_register_types(void)
327
-{
328
- type_register_static(&max111x_info);
329
- type_register_static(&max1110_info);
330
- type_register_static(&max1111_info);
331
-}
332
-
333
-type_init(max111x_register_types)
334
diff --git a/hw/adc/Kconfig b/hw/adc/Kconfig
335
index XXXXXXX..XXXXXXX 100644
336
--- a/hw/adc/Kconfig
337
+++ b/hw/adc/Kconfig
338
@@ -XXX,XX +XXX,XX @@
339
config STM32F2XX_ADC
340
bool
341
-
342
-config MAX111X
343
- bool
344
diff --git a/hw/adc/meson.build b/hw/adc/meson.build
345
index XXXXXXX..XXXXXXX 100644
346
--- a/hw/adc/meson.build
347
+++ b/hw/adc/meson.build
348
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
349
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_adc.c'))
350
system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
351
system_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq-xadc.c'))
352
-system_ss.add(when: 'CONFIG_MAX111X', if_true: files('max111x.c'))
353
--
65
--
354
2.34.1
66
2.34.1
355
356
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
New patch
1
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
result if both operands of a 3-operand fused multiply-add operation
3
are NaNs. As a result different architectures have ended up with
4
different rules for propagating NaNs.
5
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
We want to make the propagation rule instead be selectable at
9
runtime, because:
10
* this will let us have multiple targets in one QEMU binary
11
* the Arm FEAT_AFP architectural feature includes letting
12
the guest select a NaN propagation rule at runtime
13
14
In this commit we add an enum for the propagation rule, the field in
15
float_status, and the corresponding getters and setters. We change
16
pickNaNMulAdd to honour this, but because all targets still leave
17
this field at its default 0 value, the fallback logic will pick the
18
rule type with the old ifdef ladder.
19
20
It's valid not to set a propagation rule if default_nan_mode is
21
enabled, because in that case there's no need to pick a NaN; all the
22
callers of pickNaNMulAdd() catch this case and skip calling it.
23
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
27
---
28
include/fpu/softfloat-helpers.h | 11 +++
29
include/fpu/softfloat-types.h | 55 +++++++++++
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
31
3 files changed, 107 insertions(+), 126 deletions(-)
32
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/fpu/softfloat-helpers.h
36
+++ b/include/fpu/softfloat-helpers.h
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
38
status->float_2nan_prop_rule = rule;
39
}
40
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
42
+ float_status *status)
43
+{
44
+ status->float_3nan_prop_rule = rule;
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
63
index XXXXXXX..XXXXXXX 100644
64
--- a/include/fpu/softfloat-types.h
65
+++ b/include/fpu/softfloat-types.h
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
67
#ifndef SOFTFLOAT_TYPES_H
68
#define SOFTFLOAT_TYPES_H
69
70
+#include "hw/registerfields.h"
71
+
72
/*
73
* Software IEC/IEEE floating-point types.
74
*/
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
76
float_2nan_prop_x87,
77
} Float2NaNPropRule;
78
79
+/*
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.
84
+ *
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.
91
+ *
92
+ * The naming scheme for Float3NaNPropRule values is:
93
+ * float_3nan_prop_s_abc:
94
+ * = "Prefer SNaN over QNaN, then operand A over B over C"
95
+ * float_3nan_prop_abc:
96
+ * = "Prefer A over B over C regardless of SNaN vs QNAN"
97
+ *
98
+ * For QEMU, the multiply-add operation is A * B + C.
99
+ */
100
+
101
+/*
102
+ * We set the Float3NaNPropRule enum values up so we can select the
103
+ * right value in pickNaNMulAdd in a data driven way.
104
+ */
105
+FIELD(3NAN, 1ST, 0, 2) /* which operand is most preferred ? */
106
+FIELD(3NAN, 2ND, 2, 2) /* which operand is next most preferred ? */
107
+FIELD(3NAN, 3RD, 4, 2) /* which operand is least preferred ? */
108
+FIELD(3NAN, SNAN, 6, 1) /* do we prefer SNaN over QNaN ? */
109
+
110
+#define PROPRULE(X, Y, Z) \
111
+ ((X << R_3NAN_1ST_SHIFT) | (Y << R_3NAN_2ND_SHIFT) | (Z << R_3NAN_3RD_SHIFT))
112
+
113
+typedef enum __attribute__((__packed__)) {
114
+ float_3nan_prop_none = 0, /* No propagation rule specified */
115
+ float_3nan_prop_abc = PROPRULE(0, 1, 2),
116
+ float_3nan_prop_acb = PROPRULE(0, 2, 1),
117
+ float_3nan_prop_bac = PROPRULE(1, 0, 2),
118
+ float_3nan_prop_bca = PROPRULE(1, 2, 0),
119
+ float_3nan_prop_cab = PROPRULE(2, 0, 1),
120
+ float_3nan_prop_cba = PROPRULE(2, 1, 0),
121
+ float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,
122
+ float_3nan_prop_s_acb = float_3nan_prop_acb | R_3NAN_SNAN_MASK,
123
+ float_3nan_prop_s_bac = float_3nan_prop_bac | R_3NAN_SNAN_MASK,
124
+ float_3nan_prop_s_bca = float_3nan_prop_bca | R_3NAN_SNAN_MASK,
125
+ float_3nan_prop_s_cab = float_3nan_prop_cab | R_3NAN_SNAN_MASK,
126
+ float_3nan_prop_s_cba = float_3nan_prop_cba | R_3NAN_SNAN_MASK,
127
+} Float3NaNPropRule;
128
+
129
+#undef PROPRULE
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
321
+ }
322
+
323
+ assert(rule != float_3nan_prop_none);
324
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
325
+ /* We have at least one SNaN input and should prefer it */
326
+ do {
327
+ which = rule & R_3NAN_1ST_MASK;
328
+ rule >>= R_3NAN_1ST_LENGTH;
329
+ } while (!is_snan(cls[which]));
330
+ } else {
331
+ do {
332
+ which = rule & R_3NAN_1ST_MASK;
333
+ rule >>= R_3NAN_1ST_LENGTH;
334
+ } while (!is_nan(cls[which]));
335
+ }
336
+ return which;
337
}
338
339
/*----------------------------------------------------------------------------
340
--
341
2.34.1
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
1
Pull in the kernel-doc API documentation into the lockcnt docs.
1
Set the Float3NaNPropRule explicitly for SPARC, and remove the
2
This requires us to fix one rST markup syntax error in the
2
ifdef from pickNaNMulAdd().
3
header file comments.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20240816132212.3602106-8-peter.maydell@linaro.org
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-22-peter.maydell@linaro.org
7
---
7
---
8
docs/devel/lockcnt.rst | 2 +-
8
target/sparc/cpu.c | 2 ++
9
include/qemu/lockcnt.h | 2 +-
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
11
12
diff --git a/docs/devel/lockcnt.rst b/docs/devel/lockcnt.rst
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/devel/lockcnt.rst
14
--- a/target/sparc/cpu.c
15
+++ b/docs/devel/lockcnt.rst
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ three instructions in the critical path, two assignments and a ``smp_wmb()``.
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
``QemuLockCnt`` API
17
* the CPU state struct so it won't get zeroed on reset.
18
-------------------
18
*/
19
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
-The ``QemuLockCnt`` API is described in ``include/qemu/lockcnt.h``.
20
+ /* For fused-multiply add, prefer SNaN over QNaN, then C->B->A */
21
+.. kernel-doc:: include/qemu/lockcnt.h
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
22
22
/* For inf * 0 + NaN, return the input NaN */
23
23
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
``QemuLockCnt`` usage
24
25
diff --git a/include/qemu/lockcnt.h b/include/qemu/lockcnt.h
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/qemu/lockcnt.h
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/include/qemu/lockcnt.h
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ void qemu_lockcnt_destroy(QemuLockCnt *lockcnt);
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
* Because this function can wait on the mutex, it must not be
30
} else {
31
* called while the lockcnt's mutex is held by the current thread.
31
rule = float_3nan_prop_s_cab;
32
* For the same reason, qemu_lockcnt_inc can also contribute to
32
}
33
- * AB-BA deadlocks. This is a sample deadlock scenario:
33
-#elif defined(TARGET_SPARC)
34
+ * AB-BA deadlocks. This is a sample deadlock scenario::
34
- rule = float_3nan_prop_s_cba;
35
*
35
#elif defined(TARGET_XTENSA)
36
* thread 1 thread 2
36
if (status->use_first_nan) {
37
* -------------------------------------------------------
37
rule = float_3nan_prop_abc;
38
--
38
--
39
2.34.1
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
Convert docs/devel/lockcnt.txt to rST format.
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Message-id: 20240816132212.3602106-4-peter.maydell@linaro.org
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
5
---
7
---
6
MAINTAINERS | 2 +-
8
target/xtensa/fpu_helper.c | 2 ++
7
docs/devel/index-api.rst | 1 +
9
fpu/softfloat-specialize.c.inc | 8 --------
8
docs/devel/{lockcnt.txt => lockcnt.rst} | 89 +++++++++++++------------
10
2 files changed, 2 insertions(+), 8 deletions(-)
9
3 files changed, 47 insertions(+), 45 deletions(-)
10
rename docs/devel/{lockcnt.txt => lockcnt.rst} (74%)
11
11
12
diff --git a/MAINTAINERS b/MAINTAINERS
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
14
--- a/target/xtensa/fpu_helper.c
15
+++ b/MAINTAINERS
15
+++ b/target/xtensa/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ F: qapi/run-state.json
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
17
Read, Copy, Update (RCU)
17
set_use_first_nan(use_first, &env->fp_status);
18
M: Paolo Bonzini <pbonzini@redhat.com>
18
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
19
S: Maintained
19
&env->fp_status);
20
-F: docs/devel/lockcnt.txt
20
+ set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
21
+F: docs/devel/lockcnt.rst
21
+ &env->fp_status);
22
F: docs/devel/rcu.txt
22
}
23
F: include/qemu/rcu*.h
23
24
F: tests/unit/rcutorture.c
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
25
diff --git a/docs/devel/index-api.rst b/docs/devel/index-api.rst
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
27
--- a/docs/devel/index-api.rst
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/docs/devel/index-api.rst
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ generated from in-code annotations to function prototypes.
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
31
bitops
32
loads-stores
33
+ lockcnt
34
memory
35
modules
36
pci
37
diff --git a/docs/devel/lockcnt.txt b/docs/devel/lockcnt.rst
38
similarity index 74%
39
rename from docs/devel/lockcnt.txt
40
rename to docs/devel/lockcnt.rst
41
index XXXXXXX..XXXXXXX 100644
42
--- a/docs/devel/lockcnt.txt
43
+++ b/docs/devel/lockcnt.rst
44
@@ -XXX,XX +XXX,XX @@
45
-DOCUMENTATION FOR LOCKED COUNTERS (aka QemuLockCnt)
46
-===================================================
47
+Locked Counters (aka ``QemuLockCnt``)
48
+=====================================
49
50
QEMU often uses reference counts to track data structures that are being
51
accessed and should not be freed. For example, a loop that invoke
52
-callbacks like this is not safe:
53
+callbacks like this is not safe::
54
55
QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
56
if (ioh->revents & G_IO_OUT) {
57
@@ -XXX,XX +XXX,XX @@ callbacks like this is not safe:
58
}
59
}
30
}
60
31
61
-QLIST_FOREACH_SAFE protects against deletion of the current node (ioh)
32
if (rule == float_3nan_prop_none) {
62
-by stashing away its "next" pointer. However, ioh->fd_write could
33
-#if defined(TARGET_XTENSA)
63
+``QLIST_FOREACH_SAFE`` protects against deletion of the current node (``ioh``)
34
- if (status->use_first_nan) {
64
+by stashing away its ``next`` pointer. However, ``ioh->fd_write`` could
35
- rule = float_3nan_prop_abc;
65
actually delete the next node from the list. The simplest way to
36
- } else {
66
avoid this is to mark the node as deleted, and remove it from the
37
- rule = float_3nan_prop_cba;
67
-list in the above loop:
38
- }
68
+list in the above loop::
39
-#else
69
40
rule = float_3nan_prop_abc;
70
QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
41
-#endif
71
if (ioh->deleted) {
72
@@ -XXX,XX +XXX,XX @@ list in the above loop:
73
}
42
}
74
43
75
If however this loop must also be reentrant, i.e. it is possible that
44
assert(rule != float_3nan_prop_none);
76
-ioh->fd_write invokes the loop again, some kind of counting is needed:
77
+``ioh->fd_write`` invokes the loop again, some kind of counting is needed::
78
79
walking_handlers++;
80
QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
81
@@ -XXX,XX +XXX,XX @@ ioh->fd_write invokes the loop again, some kind of counting is needed:
82
}
83
walking_handlers--;
84
85
-One may think of using the RCU primitives, rcu_read_lock() and
86
-rcu_read_unlock(); effectively, the RCU nesting count would take
87
+One may think of using the RCU primitives, ``rcu_read_lock()`` and
88
+``rcu_read_unlock()``; effectively, the RCU nesting count would take
89
the place of the walking_handlers global variable. Indeed,
90
reference counting and RCU have similar purposes, but their usage in
91
general is complementary:
92
@@ -XXX,XX +XXX,XX @@ general is complementary:
93
this can improve performance, but also delay reclamation undesirably.
94
With reference counting, reclamation is deterministic.
95
96
-This file documents QemuLockCnt, an abstraction for using reference
97
+This file documents ``QemuLockCnt``, an abstraction for using reference
98
counting in code that has to be both thread-safe and reentrant.
99
100
101
-QemuLockCnt concepts
102
---------------------
103
+``QemuLockCnt`` concepts
104
+------------------------
105
106
-A QemuLockCnt comprises both a counter and a mutex; it has primitives
107
+A ``QemuLockCnt`` comprises both a counter and a mutex; it has primitives
108
to increment and decrement the counter, and to take and release the
109
mutex. The counter notes how many visits to the data structures are
110
taking place (the visits could be from different threads, or there could
111
@@ -XXX,XX +XXX,XX @@ not just frees, though there could be cases where this is not necessary.
112
113
Reads, instead, can be done without taking the mutex, as long as the
114
readers and writers use the same macros that are used for RCU, for
115
-example qatomic_rcu_read, qatomic_rcu_set, QLIST_FOREACH_RCU, etc. This is
116
-because the reads are done outside a lock and a set or QLIST_INSERT_HEAD
117
+example ``qatomic_rcu_read``, ``qatomic_rcu_set``, ``QLIST_FOREACH_RCU``,
118
+etc. This is because the reads are done outside a lock and a set
119
+or ``QLIST_INSERT_HEAD``
120
can happen concurrently with the read. The RCU API ensures that the
121
processor and the compiler see all required memory barriers.
122
123
This could be implemented simply by protecting the counter with the
124
-mutex, for example:
125
+mutex, for example::
126
127
// (1)
128
qemu_mutex_lock(&walking_handlers_mutex);
129
@@ -XXX,XX +XXX,XX @@ mutex, for example:
130
Here, no frees can happen in the code represented by the ellipsis.
131
If another thread is executing critical section (2), that part of
132
the code cannot be entered, because the thread will not be able
133
-to increment the walking_handlers variable. And of course
134
+to increment the ``walking_handlers`` variable. And of course
135
during the visit any other thread will see a nonzero value for
136
-walking_handlers, as in the single-threaded code.
137
+``walking_handlers``, as in the single-threaded code.
138
139
Note that it is possible for multiple concurrent accesses to delay
140
-the cleanup arbitrarily; in other words, for the walking_handlers
141
+the cleanup arbitrarily; in other words, for the ``walking_handlers``
142
counter to never become zero. For this reason, this technique is
143
more easily applicable if concurrent access to the structure is rare.
144
145
However, critical sections are easy to forget since you have to do
146
-them for each modification of the counter. QemuLockCnt ensures that
147
+them for each modification of the counter. ``QemuLockCnt`` ensures that
148
all modifications of the counter take the lock appropriately, and it
149
can also be more efficient in two ways:
150
151
- it avoids taking the lock for many operations (for example
152
incrementing the counter while it is non-zero);
153
154
-- on some platforms, one can implement QemuLockCnt to hold the lock
155
+- on some platforms, one can implement ``QemuLockCnt`` to hold the lock
156
and the mutex in a single word, making the fast path no more expensive
157
than simply managing a counter using atomic operations (see
158
- docs/devel/atomics.rst). This can be very helpful if concurrent access to
159
+ :doc:`atomics`). This can be very helpful if concurrent access to
160
the data structure is expected to be rare.
161
162
163
Using the same mutex for frees and writes can still incur some small
164
inefficiencies; for example, a visit can never start if the counter is
165
-zero and the mutex is taken---even if the mutex is taken by a write,
166
+zero and the mutex is taken -- even if the mutex is taken by a write,
167
which in principle need not block a visit of the data structure.
168
However, these are usually not a problem if any of the following
169
assumptions are valid:
170
@@ -XXX,XX +XXX,XX @@ assumptions are valid:
171
- writes are frequent, but this kind of write (e.g. appending to a
172
list) has a very small critical section.
173
174
-For example, QEMU uses QemuLockCnt to manage an AioContext's list of
175
+For example, QEMU uses ``QemuLockCnt`` to manage an ``AioContext``'s list of
176
bottom halves and file descriptor handlers. Modifications to the list
177
of file descriptor handlers are rare. Creation of a new bottom half is
178
frequent and can happen on a fast path; however: 1) it is almost never
179
concurrent with a visit to the list of bottom halves; 2) it only has
180
-three instructions in the critical path, two assignments and a smp_wmb().
181
+three instructions in the critical path, two assignments and a ``smp_wmb()``.
182
183
184
-QemuLockCnt API
185
----------------
186
+``QemuLockCnt`` API
187
+-------------------
188
189
-The QemuLockCnt API is described in include/qemu/thread.h.
190
+The ``QemuLockCnt`` API is described in ``include/qemu/thread.h``.
191
192
193
-QemuLockCnt usage
194
------------------
195
+``QemuLockCnt`` usage
196
+---------------------
197
198
-This section explains the typical usage patterns for QemuLockCnt functions.
199
+This section explains the typical usage patterns for ``QemuLockCnt`` functions.
200
201
Setting a variable to a non-NULL value can be done between
202
-qemu_lockcnt_lock and qemu_lockcnt_unlock:
203
+``qemu_lockcnt_lock`` and ``qemu_lockcnt_unlock``::
204
205
qemu_lockcnt_lock(&xyz_lockcnt);
206
if (!xyz) {
207
@@ -XXX,XX +XXX,XX @@ qemu_lockcnt_lock and qemu_lockcnt_unlock:
208
}
209
qemu_lockcnt_unlock(&xyz_lockcnt);
210
211
-Accessing the value can be done between qemu_lockcnt_inc and
212
-qemu_lockcnt_dec:
213
+Accessing the value can be done between ``qemu_lockcnt_inc`` and
214
+``qemu_lockcnt_dec``::
215
216
qemu_lockcnt_inc(&xyz_lockcnt);
217
if (xyz) {
218
@@ -XXX,XX +XXX,XX @@ qemu_lockcnt_dec:
219
}
220
qemu_lockcnt_dec(&xyz_lockcnt);
221
222
-Freeing the object can similarly use qemu_lockcnt_lock and
223
-qemu_lockcnt_unlock, but you also need to ensure that the count
224
-is zero (i.e. there is no concurrent visit). Because qemu_lockcnt_inc
225
-takes the QemuLockCnt's lock, the count cannot become non-zero while
226
-the object is being freed. Freeing an object looks like this:
227
+Freeing the object can similarly use ``qemu_lockcnt_lock`` and
228
+``qemu_lockcnt_unlock``, but you also need to ensure that the count
229
+is zero (i.e. there is no concurrent visit). Because ``qemu_lockcnt_inc``
230
+takes the ``QemuLockCnt``'s lock, the count cannot become non-zero while
231
+the object is being freed. Freeing an object looks like this::
232
233
qemu_lockcnt_lock(&xyz_lockcnt);
234
if (!qemu_lockcnt_count(&xyz_lockcnt)) {
235
@@ -XXX,XX +XXX,XX @@ the object is being freed. Freeing an object looks like this:
236
qemu_lockcnt_unlock(&xyz_lockcnt);
237
238
If an object has to be freed right after a visit, you can combine
239
-the decrement, the locking and the check on count as follows:
240
+the decrement, the locking and the check on count as follows::
241
242
qemu_lockcnt_inc(&xyz_lockcnt);
243
if (xyz) {
244
@@ -XXX,XX +XXX,XX @@ the decrement, the locking and the check on count as follows:
245
qemu_lockcnt_unlock(&xyz_lockcnt);
246
}
247
248
-QemuLockCnt can also be used to access a list as follows:
249
+``QemuLockCnt`` can also be used to access a list as follows::
250
251
qemu_lockcnt_inc(&io_handlers_lockcnt);
252
QLIST_FOREACH_RCU(ioh, &io_handlers, pioh) {
253
@@ -XXX,XX +XXX,XX @@ QemuLockCnt can also be used to access a list as follows:
254
}
255
256
Again, the RCU primitives are used because new items can be added to the
257
-list during the walk. QLIST_FOREACH_RCU ensures that the processor and
258
+list during the walk. ``QLIST_FOREACH_RCU`` ensures that the processor and
259
the compiler see the appropriate memory barriers.
260
261
-An alternative pattern uses qemu_lockcnt_dec_if_lock:
262
+An alternative pattern uses ``qemu_lockcnt_dec_if_lock``::
263
264
qemu_lockcnt_inc(&io_handlers_lockcnt);
265
QLIST_FOREACH_SAFE_RCU(ioh, &io_handlers, next, pioh) {
266
@@ -XXX,XX +XXX,XX @@ An alternative pattern uses qemu_lockcnt_dec_if_lock:
267
}
268
qemu_lockcnt_dec(&io_handlers_lockcnt);
269
270
-Here you can use qemu_lockcnt_dec instead of qemu_lockcnt_dec_and_lock,
271
+Here you can use ``qemu_lockcnt_dec`` instead of ``qemu_lockcnt_dec_and_lock``,
272
because there is no special task to do if the count goes from 1 to 0.
273
--
45
--
274
2.34.1
46
2.34.1
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
1
The MAX7310 GPIO controller was used only by the XScale-based Zaurus
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
machine types. Now they have been removed we can remove this device
2
ifdef from pickNaNMulAdd().
3
model as well.
4
3
5
Because this device is an I2C device, in theory it could be created
4
HPPA is the only target that was using the default branch of the
6
by users on the command line for boards with a different I2c
5
ifdef ladder (other targets either do not use muladd or set
7
controller, but we don't believe users are doing this -- it would be
6
default_nan_mode), so we can remove the ifdef fallback entirely now
8
impossible on the command line to connect up the GPIO inputs/outputs.
7
(allowing the "rule not set" case to fall into the default of the
9
The only example a web search produces for "device max7310" is a user
8
switch statement and assert).
10
trying to create this because they didn't realize that there was no
9
11
way to manipulate the GPIO lines.
10
We add a TODO note that the HPPA rule is probably wrong; this is
11
not a behavioural change for this refactoring.
12
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
16
Message-id: 20241003140010.1653808-3-peter.maydell@linaro.org
17
---
16
---
18
hw/gpio/max7310.c | 217 --------------------------------------------
17
target/hppa/fpu_helper.c | 8 ++++++++
19
hw/gpio/Kconfig | 4 -
18
fpu/softfloat-specialize.c.inc | 4 ----
20
hw/gpio/meson.build | 1 -
19
2 files changed, 8 insertions(+), 4 deletions(-)
21
3 files changed, 222 deletions(-)
22
delete mode 100644 hw/gpio/max7310.c
23
20
24
diff --git a/hw/gpio/max7310.c b/hw/gpio/max7310.c
21
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
25
deleted file mode 100644
22
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX
23
--- a/target/hppa/fpu_helper.c
27
--- a/hw/gpio/max7310.c
24
+++ b/target/hppa/fpu_helper.c
28
+++ /dev/null
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
29
@@ -XXX,XX +XXX,XX @@
26
* HPPA does note implement a CPU reset method at all...
30
-/*
27
*/
31
- * MAX7310 8-port GPIO expansion chip.
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
32
- *
29
+ /*
33
- * Copyright (c) 2006 Openedhand Ltd.
30
+ * TODO: The HPPA architecture reference only documents its NaN
34
- * Written by Andrzej Zaborowski <balrog@zabor.org>
31
+ * propagation rule for 2-operand operations. Testing on real hardware
35
- *
32
+ * might be necessary to confirm whether this order for muladd is correct.
36
- * This file is licensed under GNU GPL.
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
37
- */
34
+ * from the documented rules for 2-operand operations.
38
-
35
+ */
39
-#include "qemu/osdep.h"
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
40
-#include "hw/i2c/i2c.h"
37
/* For inf * 0 + NaN, return the input NaN */
41
-#include "hw/irq.h"
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
42
-#include "migration/vmstate.h"
39
}
43
-#include "qemu/log.h"
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
44
-#include "qemu/module.h"
41
index XXXXXXX..XXXXXXX 100644
45
-#include "qom/object.h"
42
--- a/fpu/softfloat-specialize.c.inc
46
-
43
+++ b/fpu/softfloat-specialize.c.inc
47
-#define TYPE_MAX7310 "max7310"
44
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
48
-OBJECT_DECLARE_SIMPLE_TYPE(MAX7310State, MAX7310)
45
}
49
-
46
}
50
-struct MAX7310State {
47
51
- I2CSlave parent_obj;
48
- if (rule == float_3nan_prop_none) {
52
-
49
- rule = float_3nan_prop_abc;
53
- int i2c_command_byte;
54
- int len;
55
-
56
- uint8_t level;
57
- uint8_t direction;
58
- uint8_t polarity;
59
- uint8_t status;
60
- uint8_t command;
61
- qemu_irq handler[8];
62
- qemu_irq *gpio_in;
63
-};
64
-
65
-static void max7310_reset(DeviceState *dev)
66
-{
67
- MAX7310State *s = MAX7310(dev);
68
-
69
- s->level &= s->direction;
70
- s->direction = 0xff;
71
- s->polarity = 0xf0;
72
- s->status = 0x01;
73
- s->command = 0x00;
74
-}
75
-
76
-static uint8_t max7310_rx(I2CSlave *i2c)
77
-{
78
- MAX7310State *s = MAX7310(i2c);
79
-
80
- switch (s->command) {
81
- case 0x00: /* Input port */
82
- return s->level ^ s->polarity;
83
-
84
- case 0x01: /* Output port */
85
- return s->level & ~s->direction;
86
-
87
- case 0x02: /* Polarity inversion */
88
- return s->polarity;
89
-
90
- case 0x03: /* Configuration */
91
- return s->direction;
92
-
93
- case 0x04: /* Timeout */
94
- return s->status;
95
-
96
- case 0xff: /* Reserved */
97
- return 0xff;
98
-
99
- default:
100
- qemu_log_mask(LOG_UNIMP, "%s: Unsupported register 0x02%" PRIx8 "\n",
101
- __func__, s->command);
102
- break;
103
- }
104
- return 0xff;
105
-}
106
-
107
-static int max7310_tx(I2CSlave *i2c, uint8_t data)
108
-{
109
- MAX7310State *s = MAX7310(i2c);
110
- uint8_t diff;
111
- int line;
112
-
113
- if (s->len ++ > 1) {
114
-#ifdef VERBOSE
115
- printf("%s: message too long (%i bytes)\n", __func__, s->len);
116
-#endif
117
- return 1;
118
- }
50
- }
119
-
51
-
120
- if (s->i2c_command_byte) {
52
assert(rule != float_3nan_prop_none);
121
- s->command = data;
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
122
- s->i2c_command_byte = 0;
54
/* We have at least one SNaN input and should prefer it */
123
- return 0;
124
- }
125
-
126
- switch (s->command) {
127
- case 0x01: /* Output port */
128
- for (diff = (data ^ s->level) & ~s->direction; diff;
129
- diff &= ~(1 << line)) {
130
- line = ctz32(diff);
131
- if (s->handler[line])
132
- qemu_set_irq(s->handler[line], (data >> line) & 1);
133
- }
134
- s->level = (s->level & s->direction) | (data & ~s->direction);
135
- break;
136
-
137
- case 0x02: /* Polarity inversion */
138
- s->polarity = data;
139
- break;
140
-
141
- case 0x03: /* Configuration */
142
- s->level &= ~(s->direction ^ data);
143
- s->direction = data;
144
- break;
145
-
146
- case 0x04: /* Timeout */
147
- s->status = data;
148
- break;
149
-
150
- case 0x00: /* Input port - ignore writes */
151
- break;
152
- default:
153
- qemu_log_mask(LOG_UNIMP, "%s: Unsupported register 0x02%" PRIx8 "\n",
154
- __func__, s->command);
155
- return 1;
156
- }
157
-
158
- return 0;
159
-}
160
-
161
-static int max7310_event(I2CSlave *i2c, enum i2c_event event)
162
-{
163
- MAX7310State *s = MAX7310(i2c);
164
- s->len = 0;
165
-
166
- switch (event) {
167
- case I2C_START_SEND:
168
- s->i2c_command_byte = 1;
169
- break;
170
- case I2C_FINISH:
171
-#ifdef VERBOSE
172
- if (s->len == 1)
173
- printf("%s: message too short (%i bytes)\n", __func__, s->len);
174
-#endif
175
- break;
176
- default:
177
- break;
178
- }
179
-
180
- return 0;
181
-}
182
-
183
-static const VMStateDescription vmstate_max7310 = {
184
- .name = "max7310",
185
- .version_id = 0,
186
- .minimum_version_id = 0,
187
- .fields = (const VMStateField[]) {
188
- VMSTATE_INT32(i2c_command_byte, MAX7310State),
189
- VMSTATE_INT32(len, MAX7310State),
190
- VMSTATE_UINT8(level, MAX7310State),
191
- VMSTATE_UINT8(direction, MAX7310State),
192
- VMSTATE_UINT8(polarity, MAX7310State),
193
- VMSTATE_UINT8(status, MAX7310State),
194
- VMSTATE_UINT8(command, MAX7310State),
195
- VMSTATE_I2C_SLAVE(parent_obj, MAX7310State),
196
- VMSTATE_END_OF_LIST()
197
- }
198
-};
199
-
200
-static void max7310_gpio_set(void *opaque, int line, int level)
201
-{
202
- MAX7310State *s = (MAX7310State *) opaque;
203
- assert(line >= 0 && line < ARRAY_SIZE(s->handler));
204
-
205
- if (level)
206
- s->level |= s->direction & (1 << line);
207
- else
208
- s->level &= ~(s->direction & (1 << line));
209
-}
210
-
211
-/* MAX7310 is SMBus-compatible (can be used with only SMBus protocols),
212
- * but also accepts sequences that are not SMBus so return an I2C device. */
213
-static void max7310_realize(DeviceState *dev, Error **errp)
214
-{
215
- MAX7310State *s = MAX7310(dev);
216
-
217
- qdev_init_gpio_in(dev, max7310_gpio_set, ARRAY_SIZE(s->handler));
218
- qdev_init_gpio_out(dev, s->handler, ARRAY_SIZE(s->handler));
219
-}
220
-
221
-static void max7310_class_init(ObjectClass *klass, void *data)
222
-{
223
- DeviceClass *dc = DEVICE_CLASS(klass);
224
- I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
225
-
226
- dc->realize = max7310_realize;
227
- k->event = max7310_event;
228
- k->recv = max7310_rx;
229
- k->send = max7310_tx;
230
- device_class_set_legacy_reset(dc, max7310_reset);
231
- dc->vmsd = &vmstate_max7310;
232
-}
233
-
234
-static const TypeInfo max7310_info = {
235
- .name = TYPE_MAX7310,
236
- .parent = TYPE_I2C_SLAVE,
237
- .instance_size = sizeof(MAX7310State),
238
- .class_init = max7310_class_init,
239
-};
240
-
241
-static void max7310_register_types(void)
242
-{
243
- type_register_static(&max7310_info);
244
-}
245
-
246
-type_init(max7310_register_types)
247
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/gpio/Kconfig
250
+++ b/hw/gpio/Kconfig
251
@@ -XXX,XX +XXX,XX @@
252
-config MAX7310
253
- bool
254
- depends on I2C
255
-
256
config PL061
257
bool
258
259
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
260
index XXXXXXX..XXXXXXX 100644
261
--- a/hw/gpio/meson.build
262
+++ b/hw/gpio/meson.build
263
@@ -XXX,XX +XXX,XX @@
264
system_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c'))
265
system_ss.add(when: 'CONFIG_GPIO_MPC8XXX', if_true: files('mpc8xxx.c'))
266
system_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.c'))
267
-system_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c'))
268
system_ss.add(when: 'CONFIG_PCA9552', if_true: files('pca9552.c'))
269
system_ss.add(when: 'CONFIG_PCA9554', if_true: files('pca9554.c'))
270
system_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c'))
271
--
55
--
272
2.34.1
56
2.34.1
273
274
diff view generated by jsdifflib
1
The ecc.c code was used only by the PXA2xx and OMAP2 SoC devices,
1
The use_first_nan field in float_status was an xtensa-specific way to
2
which we have removed, so it is now completely unused.
2
select at runtime from two different NaN propagation rules. Now that
3
3
xtensa is using the target-agnostic NaN propagation rule selection
4
Note that hw/misc/eccmemctl.c does not in fact use any of the
4
that we've just added, we can remove use_first_nan, because there is
5
code frome ecc.c, so that KConfig dependency was incorrect.
5
no longer any code that reads it.
6
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20241202131347.498124-27-peter.maydell@linaro.org
10
Message-id: 20241003140010.1653808-6-peter.maydell@linaro.org
11
---
10
---
12
include/hw/block/flash.h | 11 -----
11
include/fpu/softfloat-helpers.h | 5 -----
13
hw/block/ecc.c | 91 ----------------------------------------
12
include/fpu/softfloat-types.h | 1 -
14
hw/arm/Kconfig | 1 -
13
target/xtensa/fpu_helper.c | 1 -
15
hw/block/Kconfig | 3 --
14
3 files changed, 7 deletions(-)
16
hw/block/meson.build | 1 -
17
hw/misc/Kconfig | 1 -
18
6 files changed, 108 deletions(-)
19
delete mode 100644 hw/block/ecc.c
20
15
21
diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h
16
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/block/flash.h
18
--- a/include/fpu/softfloat-helpers.h
24
+++ b/include/hw/block/flash.h
19
+++ b/include/fpu/softfloat-helpers.h
25
@@ -XXX,XX +XXX,XX @@ uint32_t nand_getbuswidth(DeviceState *dev);
20
@@ -XXX,XX +XXX,XX @@ static inline void set_snan_bit_is_one(bool val, float_status *status)
26
#define NAND_MFR_HYNIX 0xad
21
status->snan_bit_is_one = val;
27
#define NAND_MFR_MICRON 0x2c
22
}
28
23
29
-/* ecc.c */
24
-static inline void set_use_first_nan(bool val, float_status *status)
30
-typedef struct {
31
- uint8_t cp; /* Column parity */
32
- uint16_t lp[2]; /* Line parity */
33
- uint16_t count;
34
-} ECCState;
35
-
36
-uint8_t ecc_digest(ECCState *s, uint8_t sample);
37
-void ecc_reset(ECCState *s);
38
-extern const VMStateDescription vmstate_ecc_state;
39
-
40
/* m25p80.c */
41
42
#define TYPE_M25P80 "m25p80-generic"
43
diff --git a/hw/block/ecc.c b/hw/block/ecc.c
44
deleted file mode 100644
45
index XXXXXXX..XXXXXXX
46
--- a/hw/block/ecc.c
47
+++ /dev/null
48
@@ -XXX,XX +XXX,XX @@
49
-/*
50
- * Calculate Error-correcting Codes. Used by NAND Flash controllers
51
- * (not by NAND chips).
52
- *
53
- * Copyright (c) 2006 Openedhand Ltd.
54
- * Written by Andrzej Zaborowski <balrog@zabor.org>
55
- *
56
- * This code is licensed under the GNU GPL v2.
57
- *
58
- * Contributions after 2012-01-13 are licensed under the terms of the
59
- * GNU GPL, version 2 or (at your option) any later version.
60
- */
61
-
62
-#include "qemu/osdep.h"
63
-#include "migration/vmstate.h"
64
-#include "hw/block/flash.h"
65
-
66
-/*
67
- * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
68
- */
69
-static const uint8_t nand_ecc_precalc_table[] = {
70
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
71
- 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
72
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
73
- 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
74
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
75
- 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
76
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
77
- 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
78
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
79
- 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
80
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
81
- 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
82
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
83
- 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
84
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
85
- 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
86
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
87
- 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
88
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
89
- 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
90
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
91
- 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
92
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
93
- 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
94
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
95
- 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
96
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
97
- 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
98
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
99
- 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
100
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
101
- 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
102
-};
103
-
104
-/* Update ECC parity count. */
105
-uint8_t ecc_digest(ECCState *s, uint8_t sample)
106
-{
25
-{
107
- uint8_t idx = nand_ecc_precalc_table[sample];
26
- status->use_first_nan = val;
108
-
109
- s->cp ^= idx & 0x3f;
110
- if (idx & 0x40) {
111
- s->lp[0] ^= ~s->count;
112
- s->lp[1] ^= s->count;
113
- }
114
- s->count ++;
115
-
116
- return sample;
117
-}
27
-}
118
-
28
-
119
-/* Reinitialise the counters. */
29
static inline void set_no_signaling_nans(bool val, float_status *status)
120
-void ecc_reset(ECCState *s)
30
{
121
-{
31
status->no_signaling_nans = val;
122
- s->lp[0] = 0x0000;
32
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
123
- s->lp[1] = 0x0000;
124
- s->cp = 0x00;
125
- s->count = 0;
126
-}
127
-
128
-/* Save/restore */
129
-const VMStateDescription vmstate_ecc_state = {
130
- .name = "ecc-state",
131
- .version_id = 0,
132
- .minimum_version_id = 0,
133
- .fields = (const VMStateField[]) {
134
- VMSTATE_UINT8(cp, ECCState),
135
- VMSTATE_UINT16_ARRAY(lp, ECCState, 2),
136
- VMSTATE_UINT16(count, ECCState),
137
- VMSTATE_END_OF_LIST(),
138
- },
139
-};
140
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
141
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
142
--- a/hw/arm/Kconfig
34
--- a/include/fpu/softfloat-types.h
143
+++ b/hw/arm/Kconfig
35
+++ b/include/fpu/softfloat-types.h
144
@@ -XXX,XX +XXX,XX @@ config OMAP
36
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
145
bool
37
* softfloat-specialize.inc.c)
146
select FRAMEBUFFER
38
*/
147
select I2C
39
bool snan_bit_is_one;
148
- select ECC
40
- bool use_first_nan;
149
select NAND
41
bool no_signaling_nans;
150
select PFLASH_CFI01
42
/* should overflowed results subtract re_bias to its exponent? */
151
select SD
43
bool rebias_overflow;
152
diff --git a/hw/block/Kconfig b/hw/block/Kconfig
44
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
153
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
154
--- a/hw/block/Kconfig
46
--- a/target/xtensa/fpu_helper.c
155
+++ b/hw/block/Kconfig
47
+++ b/target/xtensa/fpu_helper.c
156
@@ -XXX,XX +XXX,XX @@ config PFLASH_CFI01
48
@@ -XXX,XX +XXX,XX @@ static const struct {
157
config PFLASH_CFI02
49
158
bool
50
void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
159
51
{
160
-config ECC
52
- set_use_first_nan(use_first, &env->fp_status);
161
- bool
53
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
162
-
54
&env->fp_status);
163
config VIRTIO_BLK
55
set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
164
bool
165
default y
166
diff --git a/hw/block/meson.build b/hw/block/meson.build
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/block/meson.build
169
+++ b/hw/block/meson.build
170
@@ -XXX,XX +XXX,XX @@ system_ss.add(files(
171
'cdrom.c',
172
'hd-geometry.c'
173
))
174
-system_ss.add(when: 'CONFIG_ECC', if_true: files('ecc.c'))
175
system_ss.add(when: 'CONFIG_FDC', if_true: files('fdc.c'))
176
system_ss.add(when: 'CONFIG_FDC_ISA', if_true: files('fdc-isa.c'))
177
system_ss.add(when: 'CONFIG_FDC_SYSBUS', if_true: files('fdc-sysbus.c'))
178
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
179
index XXXXXXX..XXXXXXX 100644
180
--- a/hw/misc/Kconfig
181
+++ b/hw/misc/Kconfig
182
@@ -XXX,XX +XXX,XX @@ config IVSHMEM_DEVICE
183
184
config ECCMEMCTL
185
bool
186
- select ECC
187
188
config IMX
189
bool
190
--
56
--
191
2.34.1
57
2.34.1
192
193
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
From: Alexandra Diupina <adiupina@astralinux.ru>
1
We create our 128-bit default NaN by calling parts64_default_nan()
2
and then adjusting the result. We can do the same trick for creating
3
the floatx80 default NaN, which lets us drop a target ifdef.
2
4
3
The result of 1 << regbit with regbit==31 has a 1 in the 32nd bit.
5
floatx80 is used only by:
4
When cast to uint64_t (for further bitwise OR), the 32 most
6
i386
5
significant bits will be filled with 1s. However, the documentation
7
m68k
6
states that the upper 32 bits of ICH_AP[0/1]R<n>_EL2 are reserved.
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)
7
13
8
Add an explicit cast to match the documentation.
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
9
17
10
Found by Linux Verification Center (linuxtesting.org) with SVACE.
18
These are the same as the parts64_default_nan for these architectures.
11
19
12
Cc: qemu-stable@nongnu.org
20
This is technically a possible behaviour change for arm linux-user
13
Fixes: c3f21b065a ("hw/intc/arm_gicv3_cpuif: Support vLPIs")
21
nwfpe emulation emulation, because the default NaN will now have the
14
Signed-off-by: Alexandra Diupina <adiupina@astralinux.ru>
22
sign bit clear. But we were already generating a different floatx80
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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.
36
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
39
Message-id: 20241202131347.498124-29-peter.maydell@linaro.org
17
---
40
---
18
hw/intc/arm_gicv3_cpuif.c | 2 +-
41
fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
19
1 file changed, 1 insertion(+), 1 deletion(-)
42
1 file changed, 10 insertions(+), 10 deletions(-)
20
43
21
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
44
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
22
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/intc/arm_gicv3_cpuif.c
46
--- a/fpu/softfloat-specialize.c.inc
24
+++ b/hw/intc/arm_gicv3_cpuif.c
47
+++ b/fpu/softfloat-specialize.c.inc
25
@@ -XXX,XX +XXX,XX @@ static void icv_activate_vlpi(GICv3CPUState *cs)
48
@@ -XXX,XX +XXX,XX @@ static void parts128_silence_nan(FloatParts128 *p, float_status *status)
26
int regno = aprbit / 32;
49
floatx80 floatx80_default_nan(float_status *status)
27
int regbit = aprbit % 32;
50
{
28
51
floatx80 r;
29
- cs->ich_apr[cs->hppvlpi.grp][regno] |= (1 << regbit);
52
+ /*
30
+ cs->ich_apr[cs->hppvlpi.grp][regno] |= (1U << regbit);
53
+ * Extrapolate from the choices made by parts64_default_nan to fill
31
gicv3_redist_vlpi_pending(cs, cs->hppvlpi.irq, 0);
54
+ * in the floatx80 format. We assume that floatx80's explicit
55
+ * integer bit is always set (this is true for i386 and m68k,
56
+ * which are the only real users of this format).
57
+ */
58
+ FloatParts64 p64;
59
+ parts64_default_nan(&p64, status);
60
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;
32
}
74
}
33
75
34
--
76
--
35
2.34.1
77
2.34.1
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
The OMAP interrupt controller code used to have an omap-intc
1
In the helper functions flcmps and flcmpd we use a scratch float_status
2
class and an omap2-intc class, which shared common code via
2
so that we don't change the CPU state if the comparison raises any
3
the abstract class common-omap-intc. Now we have deleted
3
floating point exception flags. Instead of zero-initializing this
4
omap2-intc, we don't need the separate abstract base class;
4
scratch float_status, initialize it as a copy of env->fp_status. This
5
fold int into omap-intc.
5
avoids the need to explicitly initialize settings like the NaN
6
propagation rule or others we might add to softfloat in future.
6
7
7
Suggested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
To do this we need to pass the CPU env pointer in to the helper.
9
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241003135323.1653230-1-peter.maydell@linaro.org
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
11
---
13
---
12
include/hw/arm/omap.h | 2 +-
14
target/sparc/helper.h | 4 ++--
13
hw/intc/omap_intc.c | 13 +++----------
15
target/sparc/fop_helper.c | 8 ++++----
14
2 files changed, 4 insertions(+), 11 deletions(-)
16
target/sparc/translate.c | 4 ++--
17
3 files changed, 8 insertions(+), 8 deletions(-)
15
18
16
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/omap.h
21
--- a/target/sparc/helper.h
19
+++ b/include/hw/arm/omap.h
22
+++ b/target/sparc/helper.h
20
@@ -XXX,XX +XXX,XX @@ int64_t omap_clk_getrate(omap_clk clk);
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
21
void omap_clk_reparent(omap_clk clk, omap_clk parent);
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
22
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
23
/* omap_intc.c */
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
24
-#define TYPE_OMAP_INTC "common-omap-intc"
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
25
+#define TYPE_OMAP_INTC "omap-intc"
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
26
typedef struct OMAPIntcState OMAPIntcState;
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
27
DECLARE_INSTANCE_CHECKER(OMAPIntcState, OMAP_INTC, TYPE_OMAP_INTC)
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
28
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
29
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
32
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
30
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/omap_intc.c
36
--- a/target/sparc/fop_helper.c
32
+++ b/hw/intc/omap_intc.c
37
+++ b/target/sparc/fop_helper.c
33
@@ -XXX,XX +XXX,XX @@ static void omap_intc_class_init(ObjectClass *klass, void *data)
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
39
return finish_fcmp(env, r, GETPC());
34
}
40
}
35
41
36
static const TypeInfo omap_intc_info = {
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
37
- .name = "omap-intc",
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
38
- .parent = TYPE_OMAP_INTC,
39
+ .name = TYPE_OMAP_INTC,
40
+ .parent = TYPE_SYS_BUS_DEVICE,
41
+ .instance_size = sizeof(OMAPIntcState),
42
.instance_init = omap_intc_init,
43
.class_init = omap_intc_class_init,
44
};
45
46
-static const TypeInfo omap_intc_type_info = {
47
- .name = TYPE_OMAP_INTC,
48
- .parent = TYPE_SYS_BUS_DEVICE,
49
- .instance_size = sizeof(OMAPIntcState),
50
- .abstract = true,
51
-};
52
-
53
static void omap_intc_register_types(void)
54
{
44
{
55
- type_register_static(&omap_intc_type_info);
45
/*
56
type_register_static(&omap_intc_info);
46
* FLCMP never raises an exception nor modifies any FSR fields.
47
* Perform the comparison with a dummy fp environment.
48
*/
49
- float_status discard = { };
50
+ float_status discard = env->fp_status;
51
FloatRelation r;
52
53
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
54
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
55
g_assert_not_reached();
57
}
56
}
57
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
60
{
61
- float_status discard = { };
62
+ float_status discard = env->fp_status;
63
FloatRelation r;
64
65
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
66
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/sparc/translate.c
69
+++ b/target/sparc/translate.c
70
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
71
72
src1 = gen_load_fpr_F(dc, a->rs1);
73
src2 = gen_load_fpr_F(dc, a->rs2);
74
- gen_helper_flcmps(cpu_fcc[a->cc], src1, src2);
75
+ gen_helper_flcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
76
return advance_pc(dc);
77
}
78
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
80
81
src1 = gen_load_fpr_D(dc, a->rs1);
82
src2 = gen_load_fpr_D(dc, a->rs2);
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
85
return advance_pc(dc);
86
}
58
87
59
--
88
--
60
2.34.1
89
2.34.1
61
62
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: Inès Varhol <ines.varhol@telecom-paris.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This commit creates a clock in STM32L4x5 SYSCFG and wires it up to the
3
Now that float_status has a bunch of fp parameters,
4
corresponding clock from STM32L4x5 RCC.
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.
5
8
6
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
9
Reviewed-by: Luc Michel <luc@lmichel.fr>
10
Message-id: 20241003081105.40836-2-ines.varhol@telecom-paris.fr
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
14
---
13
include/hw/misc/stm32l4x5_syscfg.h | 1 +
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
14
hw/arm/stm32l4x5_soc.c | 2 ++
16
1 file changed, 7 insertions(+), 13 deletions(-)
15
hw/misc/stm32l4x5_syscfg.c | 19 +++++++++++++++++--
16
3 files changed, 20 insertions(+), 2 deletions(-)
17
17
18
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/misc/stm32l4x5_syscfg.h
20
--- a/target/arm/tcg/vec_helper.c
21
+++ b/include/hw/misc/stm32l4x5_syscfg.h
21
+++ b/target/arm/tcg/vec_helper.c
22
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SyscfgState {
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
23
uint32_t swpr2;
23
* no effect on AArch32 instructions.
24
24
*/
25
qemu_irq gpio_out[GPIO_NUM_PINS];
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
26
+ Clock *clk;
26
- *statusp = (float_status){
27
};
27
- .tininess_before_rounding = float_tininess_before_rounding,
28
28
- .float_rounding_mode = float_round_to_odd_inf,
29
#endif
29
- .flush_to_zero = true,
30
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
30
- .flush_inputs_to_zero = true,
31
index XXXXXXX..XXXXXXX 100644
31
- .default_nan_mode = true,
32
--- a/hw/arm/stm32l4x5_soc.c
32
- };
33
+++ b/hw/arm/stm32l4x5_soc.c
33
+
34
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
34
+ *statusp = env->vfp.fp_status;
35
35
+ set_default_nan_mode(true, statusp);
36
/* System configuration controller */
36
37
busdev = SYS_BUS_DEVICE(&s->syscfg);
37
if (ebf) {
38
+ qdev_connect_clock_in(DEVICE(&s->syscfg), "clk",
38
- float_status *fpst = &env->vfp.fp_status;
39
+ qdev_get_clock_out(DEVICE(&(s->rcc)), "syscfg-out"));
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
40
if (!sysbus_realize(busdev, errp)) {
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
41
return;
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
42
-
43
/* EBF=1 needs to do a step with round-to-odd semantics */
44
*oddstatusp = *statusp;
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
46
+ } else {
47
+ set_flush_to_zero(true, statusp);
48
+ set_flush_inputs_to_zero(true, statusp);
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
42
}
50
}
43
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
51
-
44
index XXXXXXX..XXXXXXX 100644
52
return ebf;
45
--- a/hw/misc/stm32l4x5_syscfg.c
46
+++ b/hw/misc/stm32l4x5_syscfg.c
47
@@ -XXX,XX +XXX,XX @@
48
#include "trace.h"
49
#include "hw/irq.h"
50
#include "migration/vmstate.h"
51
+#include "hw/clock.h"
52
+#include "hw/qdev-clock.h"
53
+#include "qapi/error.h"
54
#include "hw/misc/stm32l4x5_syscfg.h"
55
#include "hw/gpio/stm32l4x5_gpio.h"
56
57
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_syscfg_init(Object *obj)
58
qdev_init_gpio_in(DEVICE(obj), stm32l4x5_syscfg_set_irq,
59
GPIO_NUM_PINS * NUM_GPIOS);
60
qdev_init_gpio_out(DEVICE(obj), s->gpio_out, GPIO_NUM_PINS);
61
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
62
+}
63
+
64
+static void stm32l4x5_syscfg_realize(DeviceState *dev, Error **errp)
65
+{
66
+ Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(dev);
67
+ if (!clock_has_source(s->clk)) {
68
+ error_setg(errp, "SYSCFG: clk input must be connected");
69
+ return;
70
+ }
71
}
53
}
72
73
static const VMStateDescription vmstate_stm32l4x5_syscfg = {
74
.name = TYPE_STM32L4X5_SYSCFG,
75
- .version_id = 1,
76
- .minimum_version_id = 1,
77
+ .version_id = 2,
78
+ .minimum_version_id = 2,
79
.fields = (VMStateField[]) {
80
VMSTATE_UINT32(memrmp, Stm32l4x5SyscfgState),
81
VMSTATE_UINT32(cfgr1, Stm32l4x5SyscfgState),
82
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stm32l4x5_syscfg = {
83
VMSTATE_UINT32(swpr, Stm32l4x5SyscfgState),
84
VMSTATE_UINT32(skr, Stm32l4x5SyscfgState),
85
VMSTATE_UINT32(swpr2, Stm32l4x5SyscfgState),
86
+ VMSTATE_CLOCK(clk, Stm32l4x5SyscfgState),
87
VMSTATE_END_OF_LIST()
88
}
89
};
90
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_syscfg_class_init(ObjectClass *klass, void *data)
91
ResettableClass *rc = RESETTABLE_CLASS(klass);
92
93
dc->vmsd = &vmstate_stm32l4x5_syscfg;
94
+ dc->realize = stm32l4x5_syscfg_realize;
95
rc->phases.hold = stm32l4x5_syscfg_hold_reset;
96
}
97
54
98
--
55
--
99
2.34.1
56
2.34.1
100
57
101
58
diff view generated by jsdifflib
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
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
For USART, GPIO and SYSCFG devices, check that clock frequency before
7
Add a field to float_status to specify the default NaN value; fall
4
and after enabling the peripheral clock in RCC is correct.
8
back to the old ifdef behaviour if these are not set.
5
9
6
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
10
The default NaN value is specified by setting a uint8_t to a
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
pattern corresponding to the sign and upper fraction parts of
8
Reviewed-by: Luc Michel <luc@lmichel.fr>
12
the NaN; the lower bits of the fraction are set from bit 0 of
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
the pattern.
10
Message-id: 20241003081105.40836-4-ines.varhol@telecom-paris.fr
14
11
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
12
---
18
---
13
tests/qtest/stm32l4x5.h | 42 +++++++++++++++++++++++++++++
19
include/fpu/softfloat-helpers.h | 11 +++++++
14
tests/qtest/stm32l4x5_gpio-test.c | 23 ++++++++++++++++
20
include/fpu/softfloat-types.h | 10 ++++++
15
tests/qtest/stm32l4x5_syscfg-test.c | 20 ++++++++++++--
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
16
tests/qtest/stm32l4x5_usart-test.c | 26 ++++++++++++++++++
22
3 files changed, 54 insertions(+), 22 deletions(-)
17
4 files changed, 109 insertions(+), 2 deletions(-)
18
create mode 100644 tests/qtest/stm32l4x5.h
19
23
20
diff --git a/tests/qtest/stm32l4x5.h b/tests/qtest/stm32l4x5.h
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
21
new file mode 100644
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX
26
--- a/include/fpu/softfloat-helpers.h
23
--- /dev/null
27
+++ b/include/fpu/softfloat-helpers.h
24
+++ b/tests/qtest/stm32l4x5.h
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
25
@@ -XXX,XX +XXX,XX @@
29
status->float_infzeronan_rule = rule;
26
+/*
30
}
27
+ * QTest testcase header for STM32L4X5 :
31
28
+ * used for consolidating common objects in stm32l4x5_*-test.c
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
29
+ *
33
+ float_status *status)
30
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
31
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
32
+ *
33
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
34
+ * See the COPYING file in the top-level directory.
35
+ */
36
+
37
+#include "libqtest.h"
38
+
39
+/* copied from clock.h */
40
+#define CLOCK_PERIOD_1SEC (1000000000llu << 32)
41
+#define CLOCK_PERIOD_FROM_HZ(hz) (((hz) != 0) ? CLOCK_PERIOD_1SEC / (hz) : 0u)
42
+/*
43
+ * MSI (4 MHz) is used as system clock source after startup
44
+ * from Reset.
45
+ * AHB, APB1 and APB2 prescalers are set to 1 at reset.
46
+ */
47
+#define SYSCLK_PERIOD CLOCK_PERIOD_FROM_HZ(4000000)
48
+#define RCC_AHB2ENR 0x4002104C
49
+#define RCC_APB1ENR1 0x40021058
50
+#define RCC_APB1ENR2 0x4002105C
51
+#define RCC_APB2ENR 0x40021060
52
+
53
+
54
+static inline uint64_t get_clock_period(QTestState *qts, const char *path)
55
+{
34
+{
56
+ uint64_t clock_period = 0;
35
+ status->default_nan_pattern = dnan_pattern;
57
+ QDict *r;
58
+
59
+ r = qtest_qmp(qts, "{ 'execute': 'qom-get', 'arguments':"
60
+ " { 'path': %s, 'property': 'qtest-clock-period'} }", path);
61
+ g_assert_false(qdict_haskey(r, "error"));
62
+ clock_period = qdict_get_int(r, "return");
63
+ qobject_unref(r);
64
+ return clock_period;
65
+}
36
+}
66
+
37
+
67
+
38
static inline void set_flush_to_zero(bool val, float_status *status)
68
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
39
{
69
index XXXXXXX..XXXXXXX 100644
40
status->flush_to_zero = val;
70
--- a/tests/qtest/stm32l4x5_gpio-test.c
41
@@ -XXX,XX +XXX,XX @@ static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status
71
+++ b/tests/qtest/stm32l4x5_gpio-test.c
42
return status->float_infzeronan_rule;
72
@@ -XXX,XX +XXX,XX @@
73
74
#include "qemu/osdep.h"
75
#include "libqtest-single.h"
76
+#include "stm32l4x5.h"
77
78
#define GPIO_BASE_ADDR 0x48000000
79
#define GPIO_SIZE 0x400
80
@@ -XXX,XX +XXX,XX @@ static void test_bsrr_brr(const void *data)
81
gpio_writel(gpio, ODR, reset(gpio, ODR));
82
}
43
}
83
44
84
+static void test_clock_enable(void)
45
+static inline uint8_t get_float_default_nan_pattern(float_status *status)
85
+{
46
+{
86
+ /*
47
+ return status->default_nan_pattern;
87
+ * For each GPIO, enable its clock in RCC
88
+ * and check that its clock period changes to SYSCLK_PERIOD
89
+ */
90
+ unsigned int gpio_id;
91
+
92
+ for (uint32_t gpio = GPIO_A; gpio <= GPIO_H; gpio += GPIO_B - GPIO_A) {
93
+ gpio_id = get_gpio_id(gpio);
94
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c/clk",
95
+ gpio_id + 'a');
96
+ g_assert_cmpuint(get_clock_period(global_qtest, path), ==, 0);
97
+ /* Enable the gpio clock */
98
+ writel(RCC_AHB2ENR, readl(RCC_AHB2ENR) | (0x1 << gpio_id));
99
+ g_assert_cmpuint(get_clock_period(global_qtest, path), ==,
100
+ SYSCLK_PERIOD);
101
+ }
102
+}
48
+}
103
+
49
+
104
int main(int argc, char **argv)
50
static inline bool get_flush_to_zero(float_status *status)
105
{
51
{
106
int ret;
52
return status->flush_to_zero;
107
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
108
qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
109
test_data(GPIO_D, 0),
110
test_bsrr_brr);
111
+ qtest_add_func("stm32l4x5/gpio/test_clock_enable",
112
+ test_clock_enable);
113
114
qtest_start("-machine b-l475e-iot01a");
115
ret = g_test_run();
116
diff --git a/tests/qtest/stm32l4x5_syscfg-test.c b/tests/qtest/stm32l4x5_syscfg-test.c
117
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
118
--- a/tests/qtest/stm32l4x5_syscfg-test.c
55
--- a/include/fpu/softfloat-types.h
119
+++ b/tests/qtest/stm32l4x5_syscfg-test.c
56
+++ b/include/fpu/softfloat-types.h
120
@@ -XXX,XX +XXX,XX @@
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
121
58
/* should denormalised inputs go to zero and set the input_denormal flag? */
122
#include "qemu/osdep.h"
59
bool flush_inputs_to_zero;
123
#include "libqtest-single.h"
60
bool default_nan_mode;
124
+#include "stm32l4x5.h"
61
+ /*
125
62
+ * The pattern to use for the default NaN. Here the high bit specifies
126
#define SYSCFG_BASE_ADDR 0x40010000
63
+ * the default NaN's sign bit, and bits 6..0 specify the high bits of the
127
#define SYSCFG_MEMRMP 0x00
64
+ * fractional part. The low bits of the fractional part are copies of bit 0.
128
@@ -XXX,XX +XXX,XX @@
65
+ * The exponent of the default NaN is (as for any NaN) always all 1s.
129
#define INVALID_ADDR 0x2C
66
+ * Note that a value of 0 here is not a valid NaN. The target must set
130
67
+ * this to the correct non-zero value, or we will assert when trying to
131
/* SoC forwards GPIOs to SysCfg */
68
+ * create a default NaN.
132
-#define SYSCFG "/machine/soc"
69
+ */
133
+#define SOC "/machine/soc"
70
+ uint8_t default_nan_pattern;
134
+#define SYSCFG "/machine/soc/syscfg"
71
/*
135
+#define SYSCFG_CLK "/machine/soc/syscfg/clk"
72
* The flags below are not used on all specializations and may
136
#define EXTI "/machine/soc/exti"
73
* constant fold away (see snan_bit_is_one()/no_signalling_nans() in
137
74
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
138
static void syscfg_writel(unsigned int offset, uint32_t value)
75
index XXXXXXX..XXXXXXX 100644
139
@@ -XXX,XX +XXX,XX @@ static uint32_t syscfg_readl(unsigned int offset)
76
--- a/fpu/softfloat-specialize.c.inc
140
77
+++ b/fpu/softfloat-specialize.c.inc
141
static void syscfg_set_irq(int num, int level)
78
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
142
{
79
{
143
- qtest_set_irq_in(global_qtest, SYSCFG, NULL, num, level);
80
bool sign = 0;
144
+ qtest_set_irq_in(global_qtest, SOC, NULL, num, level);
81
uint64_t frac;
145
}
82
+ uint8_t dnan_pattern = status->default_nan_pattern;
146
83
147
static void system_reset(void)
84
+ if (dnan_pattern == 0) {
148
@@ -XXX,XX +XXX,XX @@ static void test_irq_gpio_multiplexer(void)
85
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
149
syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
86
- /* !snan_bit_is_one, set all bits */
150
}
87
- frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
151
88
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
152
+static void test_clock_enable(void)
89
+ /* Sign bit clear, all frac bits set */
153
+{
90
+ dnan_pattern = 0b01111111;
154
+ g_assert_cmpuint(get_clock_period(global_qtest, SYSCFG_CLK), ==, 0);
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);
155
+
136
+
156
+ /* Enable SYSCFG clock */
137
+ sign = dnan_pattern >> 7;
157
+ writel(RCC_APB2ENR, readl(RCC_APB2ENR) | (0x1 << 0));
158
+
159
+ g_assert_cmpuint(get_clock_period(global_qtest, SYSCFG_CLK), ==,
160
+ SYSCLK_PERIOD);
161
+}
162
+
163
int main(int argc, char **argv)
164
{
165
int ret;
166
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
167
test_irq_pin_multiplexer);
168
qtest_add_func("stm32l4x5/syscfg/test_irq_gpio_multiplexer",
169
test_irq_gpio_multiplexer);
170
+ qtest_add_func("stm32l4x5/syscfg/test_clock_enable",
171
+ test_clock_enable);
172
173
qtest_start("-machine b-l475e-iot01a");
174
ret = g_test_run();
175
diff --git a/tests/qtest/stm32l4x5_usart-test.c b/tests/qtest/stm32l4x5_usart-test.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/tests/qtest/stm32l4x5_usart-test.c
178
+++ b/tests/qtest/stm32l4x5_usart-test.c
179
@@ -XXX,XX +XXX,XX @@
180
#include "libqtest.h"
181
#include "hw/misc/stm32l4x5_rcc_internals.h"
182
#include "hw/registerfields.h"
183
+#include "stm32l4x5.h"
184
185
#define RCC_BASE_ADDR 0x40021000
186
/* Use USART 1 ADDR, assume the others work the same */
187
@@ -XXX,XX +XXX,XX @@ static void test_ack(void)
188
qtest_quit(qts);
189
}
190
191
+static void check_clock(QTestState *qts, const char *path, uint32_t rcc_reg,
192
+ uint32_t reg_offset)
193
+{
194
+ g_assert_cmpuint(get_clock_period(qts, path), ==, 0);
195
+ qtest_writel(qts, rcc_reg, qtest_readl(qts, rcc_reg) | (0x1 << reg_offset));
196
+ g_assert_cmpuint(get_clock_period(qts, path), ==, SYSCLK_PERIOD);
197
+}
198
+
199
+static void test_clock_enable(void)
200
+{
201
+ /*
138
+ /*
202
+ * For each USART device, enable its clock in RCC
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
203
+ * and check that its clock frequency is SYSCLK_PERIOD
140
+ * and replecate bit [0] down into [55:0]
204
+ */
141
+ */
205
+ QTestState *qts = qtest_init("-M b-l475e-iot01a");
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
206
+
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
207
+ check_clock(qts, "machine/soc/usart[0]/clk", RCC_APB2ENR, 14);
144
208
+ check_clock(qts, "machine/soc/usart[1]/clk", RCC_APB1ENR1, 17);
145
*p = (FloatParts64) {
209
+ check_clock(qts, "machine/soc/usart[2]/clk", RCC_APB1ENR1, 18);
146
.cls = float_class_qnan,
210
+ check_clock(qts, "machine/soc/uart[0]/clk", RCC_APB1ENR1, 19);
211
+ check_clock(qts, "machine/soc/uart[1]/clk", RCC_APB1ENR1, 20);
212
+ check_clock(qts, "machine/soc/lpuart1/clk", RCC_APB1ENR2, 0);
213
+}
214
+
215
int main(int argc, char **argv)
216
{
217
int ret;
218
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
219
qtest_add_func("stm32l4x5/usart/receive_str", test_receive_str);
220
qtest_add_func("stm32l4x5/usart/send_str", test_send_str);
221
qtest_add_func("stm32l4x5/usart/ack", test_ack);
222
+ qtest_add_func("stm32l4x5/usart/clock_enable", test_clock_enable);
223
ret = g_test_run();
224
225
return ret;
226
--
147
--
227
2.34.1
148
2.34.1
228
229
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
From: Akihiko Odaki <akihiko.odaki@daynix.com>
1
Set the default NaN pattern explicitly for the arm target.
2
This includes setting it for the old linux-user nwfpe emulation.
3
For nwfpe, our default doesn't match the real kernel, but we
4
avoid making a behaviour change in this commit.
2
5
3
Ensure the function names match.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-41-peter.maydell@linaro.org
9
---
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
11
target/arm/cpu.c | 2 ++
12
2 files changed, 7 insertions(+)
4
13
5
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
6
Message-id: 20241012-dma-v2-1-6afddf5f3c8d@daynix.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
include/sysemu/dma.h | 11 +++++------
11
1 file changed, 5 insertions(+), 6 deletions(-)
12
13
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/sysemu/dma.h
16
--- a/linux-user/arm/nwfpe/fpa11.c
16
+++ b/include/sysemu/dma.h
17
+++ b/linux-user/arm/nwfpe/fpa11.c
17
@@ -XXX,XX +XXX,XX @@ static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr,
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
19
* this late date.
20
*/
21
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
22
+ /*
23
+ * Use the same default NaN value as Arm VFP. This doesn't match
24
+ * the Linux kernel's nwfpe emulation, which uses an all-1s value.
25
+ */
26
+ set_float_default_nan_pattern(0b01000000, &fpa11->fp_status);
18
}
27
}
19
28
20
/**
29
void SetRoundingMode(const unsigned int opcode)
21
- * address_space_write: Write to address space from DMA controller.
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
+ * dma_memory_write: Write to address space from DMA controller.
31
index XXXXXXX..XXXXXXX 100644
23
*
32
--- a/target/arm/cpu.c
24
* Return a MemTxResult indicating whether the operation succeeded
33
+++ b/target/arm/cpu.c
25
* or failed (eg unassigned memory, device rejected the transaction,
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
26
@@ -XXX,XX +XXX,XX @@ MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr,
35
* the pseudocode function the arguments are in the order c, a, b.
27
uint8_t c, dma_addr_t len, MemTxAttrs attrs);
36
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
28
37
* and the input NaN if it is signalling
29
/**
38
+ * * Default NaN has sign bit clear, msb frac bit set
30
- * address_space_map: Map a physical memory region into a host virtual address.
39
*/
31
+ * dma_memory_map: Map a physical memory region into a host virtual address.
40
static void arm_set_default_fp_behaviours(float_status *s)
32
*
41
{
33
* May map a subset of the requested range, given by and returned in @plen.
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
34
* May return %NULL and set *@plen to zero(0), if resources needed to perform
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
35
@@ -XXX,XX +XXX,XX @@ static inline void *dma_memory_map(AddressSpace *as,
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);
36
}
47
}
37
48
38
/**
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
39
- * address_space_unmap: Unmaps a memory region previously mapped
40
- * by dma_memory_map()
41
+ * dma_memory_unmap: Unmaps a memory region previously mapped by dma_memory_map()
42
*
43
* Will also mark the memory as dirty if @dir == %DMA_DIRECTION_FROM_DEVICE.
44
* @access_len gives the amount of memory that was actually read or written
45
* by the caller.
46
*
47
* @as: #AddressSpace used
48
- * @buffer: host pointer as returned by address_space_map()
49
- * @len: buffer length as returned by address_space_map()
50
+ * @buffer: host pointer as returned by dma_memory_map()
51
+ * @len: buffer length as returned by dma_memory_map()
52
* @dir: indicates the transfer direction
53
* @access_len: amount of data actually transferred
54
*/
55
--
50
--
56
2.34.1
51
2.34.1
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
New patch
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).
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-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(+)
13
14
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/mips/fpu_helper.h
17
+++ b/target/mips/fpu_helper.h
18
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
20
nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
21
set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
22
+ /*
23
+ * With nan2008, the default NaN value has the sign bit clear and the
24
+ * frac msb set; with the older mode, the sign bit is clear, and all
25
+ * frac bits except the msb are set.
26
+ */
27
+ set_float_default_nan_pattern(nan2008 ? 0b01000000 : 0b00111111,
28
+ &env->active_fpu.fp_status);
29
30
}
31
32
diff --git a/target/mips/msa.c b/target/mips/msa.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/mips/msa.c
35
+++ b/target/mips/msa.c
36
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
37
/* Inf * 0 + NaN returns the input NaN */
38
set_float_infzeronan_rule(float_infzeronan_dnan_never,
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
}
44
--
45
2.34.1
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
New patch
1
Set the default NaN pattern explicitly for ppc.
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-46-peter.maydell@linaro.org
6
---
7
target/ppc/cpu_init.c | 4 ++++
8
1 file changed, 4 insertions(+)
9
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/ppc/cpu_init.c
13
+++ b/target/ppc/cpu_init.c
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
17
18
+ /* Default NaN: sign bit clear, set frac msb */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
21
+
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
23
ppc_spr_t *spr = &env->spr_cb[i];
24
25
--
26
2.34.1
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
New patch
1
Set the default NaN pattern explicitly for rx.
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-48-peter.maydell@linaro.org
6
---
7
target/rx/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/rx/cpu.c
13
+++ b/target/rx/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
18
+ /* Default NaN value: sign bit clear, set frac msb */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
}
21
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for s390x.
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-49-peter.maydell@linaro.org
6
---
7
target/s390x/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/s390x/cpu.c
13
+++ b/target/s390x/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
15
set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
16
set_float_infzeronan_rule(float_infzeronan_dnan_always,
17
&env->fpu_status);
18
+ /* Default NaN value: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fpu_status);
20
/* fall through */
21
case RESET_TYPE_S390_CPU_NORMAL:
22
env->psw.mask &= ~PSW_MASK_RI;
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for SPARC, and remove
2
the ifdef from 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-50-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 5 +----
10
2 files changed, 3 insertions(+), 4 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
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &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 value: sign bit clear, all frac bits set */
21
+ set_float_default_nan_pattern(0b01111111, &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 void parts64_default_nan(FloatParts64 *p, float_status *status)
30
uint8_t dnan_pattern = status->default_nan_pattern;
31
32
if (dnan_pattern == 0) {
33
-#if defined(TARGET_SPARC)
34
- /* Sign bit clear, all frac bits set */
35
- dnan_pattern = 0b01111111;
36
-#elif defined(TARGET_HEXAGON)
37
+#if defined(TARGET_HEXAGON)
38
/* Sign bit set, all frac bits set. */
39
dnan_pattern = 0b11111111;
40
#else
41
--
42
2.34.1
diff view generated by jsdifflib
1
From: Alexandra Diupina <adiupina@astralinux.ru>
1
Set the default NaN pattern explicitly for xtensa.
2
2
3
The result of 1 << regbit with regbit==31 has a 1 in the 32nd bit.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
When cast to uint64_t (for further bitwise OR), the 32 most
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
significant bits will be filled with 1s. However, the documentation
5
Message-id: 20241202131347.498124-51-peter.maydell@linaro.org
6
states that the upper 32 bits of ICH_AP[0/1]R<n>_EL2 are reserved.
6
---
7
target/xtensa/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
7
9
8
Add an explicit cast to match the documentation.
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
9
10
Found by Linux Verification Center (linuxtesting.org) with SVACE.
11
12
Cc: qemu-stable@nongnu.org
13
Fixes: d2c0c6aab6 ("hw/intc/arm_gicv3: Handle icv_nmiar1_read() for icc_nmiar1_read()")
14
Signed-off-by: Alexandra Diupina <adiupina@astralinux.ru>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/intc/arm_gicv3_cpuif.c | 2 +-
19
1 file changed, 1 insertion(+), 1 deletion(-)
20
21
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
22
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/intc/arm_gicv3_cpuif.c
12
--- a/target/xtensa/cpu.c
24
+++ b/hw/intc/arm_gicv3_cpuif.c
13
+++ b/target/xtensa/cpu.c
25
@@ -XXX,XX +XXX,XX @@ static void icv_activate_irq(GICv3CPUState *cs, int idx, int grp)
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
26
if (nmi) {
15
/* For inf * 0 + NaN, return the input NaN */
27
cs->ich_apr[grp][regno] |= ICV_AP1R_EL1_NMI;
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
28
} else {
17
set_no_signaling_nans(!dfpu, &env->fp_status);
29
- cs->ich_apr[grp][regno] |= (1 << regbit);
18
+ /* Default NaN value: sign bit clear, set frac msb */
30
+ cs->ich_apr[grp][regno] |= (1U << regbit);
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
31
}
20
xtensa_use_first_nan(env, !dfpu);
32
}
21
}
33
22
34
--
23
--
35
2.34.1
24
2.34.1
diff view generated by jsdifflib
1
Convert docs/devel/rcu.txt to rST format.
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
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Message-id: 20240816132212.3602106-6-peter.maydell@linaro.org
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-52-peter.maydell@linaro.org
5
---
8
---
6
MAINTAINERS | 2 +-
9
target/hexagon/cpu.c | 2 ++
7
docs/devel/index-internals.rst | 1 +
10
fpu/softfloat-specialize.c.inc | 5 -----
8
docs/devel/{rcu.txt => rcu.rst} | 172 +++++++++++++++-----------------
11
2 files changed, 2 insertions(+), 5 deletions(-)
9
3 files changed, 82 insertions(+), 93 deletions(-)
10
rename docs/devel/{rcu.txt => rcu.rst} (73%)
11
12
12
diff --git a/MAINTAINERS b/MAINTAINERS
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
15
--- a/target/hexagon/cpu.c
15
+++ b/MAINTAINERS
16
+++ b/target/hexagon/cpu.c
16
@@ -XXX,XX +XXX,XX @@ Read, Copy, Update (RCU)
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
17
M: Paolo Bonzini <pbonzini@redhat.com>
18
18
S: Maintained
19
set_default_nan_mode(1, &env->fp_status);
19
F: docs/devel/lockcnt.rst
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
20
-F: docs/devel/rcu.txt
21
+ /* Default NaN value: sign bit set, all frac bits set */
21
+F: docs/devel/rcu.rst
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
22
F: include/qemu/rcu*.h
23
}
23
F: tests/unit/rcutorture.c
24
24
F: tests/unit/test-rcu-*.c
25
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
25
diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst
26
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
27
--- a/docs/devel/index-internals.rst
28
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/docs/devel/index-internals.rst
29
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ Details about QEMU's various subsystems including how to add features to them.
30
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
31
uint8_t dnan_pattern = status->default_nan_pattern;
31
qom
32
32
atomics
33
if (dnan_pattern == 0) {
33
+ rcu
34
-#if defined(TARGET_HEXAGON)
34
block-coroutine-wrapper
35
- /* Sign bit set, all frac bits set. */
35
clocks
36
- dnan_pattern = 0b11111111;
36
ebpf_rss
37
-#else
37
diff --git a/docs/devel/rcu.txt b/docs/devel/rcu.rst
38
/*
38
similarity index 73%
39
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
39
rename from docs/devel/rcu.txt
40
* S390, SH4, TriCore, and Xtensa. Our other supported targets
40
rename to docs/devel/rcu.rst
41
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
41
index XXXXXXX..XXXXXXX 100644
42
/* sign bit clear, set frac msb */
42
--- a/docs/devel/rcu.txt
43
dnan_pattern = 0b01000000;
43
+++ b/docs/devel/rcu.rst
44
@@ -XXX,XX +XXX,XX @@ for the execution of all *currently running* critical sections before
45
proceeding, or before asynchronously executing a callback.
46
47
The key point here is that only the currently running critical sections
48
-are waited for; critical sections that are started _after_ the beginning
49
+are waited for; critical sections that are started **after** the beginning
50
of the wait do not extend the wait, despite running concurrently with
51
the updater. This is the reason why RCU is more scalable than,
52
for example, reader-writer locks. It is so much more scalable that
53
@@ -XXX,XX +XXX,XX @@ do not matter; as soon as all previous critical sections have finished,
54
there cannot be any readers who hold references to the data structure,
55
and these can now be safely reclaimed (e.g., freed or unref'ed).
56
57
-Here is a picture:
58
+Here is a picture::
59
60
thread 1 thread 2 thread 3
61
------------------- ------------------------ -------------------
62
@@ -XXX,XX +XXX,XX @@ that critical section.
63
64
65
RCU API
66
-=======
67
+-------
68
69
The core RCU API is small:
70
71
- void rcu_read_lock(void);
72
-
73
+``void rcu_read_lock(void);``
74
Used by a reader to inform the reclaimer that the reader is
75
entering an RCU read-side critical section.
76
77
- void rcu_read_unlock(void);
78
-
79
+``void rcu_read_unlock(void);``
80
Used by a reader to inform the reclaimer that the reader is
81
exiting an RCU read-side critical section. Note that RCU
82
read-side critical sections may be nested and/or overlapping.
83
84
- void synchronize_rcu(void);
85
-
86
+``void synchronize_rcu(void);``
87
Blocks until all pre-existing RCU read-side critical sections
88
on all threads have completed. This marks the end of the removal
89
phase and the beginning of reclamation phase.
90
91
Note that it would be valid for another update to come while
92
- synchronize_rcu is running. Because of this, it is better that
93
+ ``synchronize_rcu`` is running. Because of this, it is better that
94
the updater releases any locks it may hold before calling
95
- synchronize_rcu. If this is not possible (for example, because
96
- the updater is protected by the BQL), you can use call_rcu.
97
+ ``synchronize_rcu``. If this is not possible (for example, because
98
+ the updater is protected by the BQL), you can use ``call_rcu``.
99
100
- void call_rcu1(struct rcu_head * head,
101
- void (*func)(struct rcu_head *head));
102
-
103
- This function invokes func(head) after all pre-existing RCU
104
+``void call_rcu1(struct rcu_head * head, void (*func)(struct rcu_head *head));``
105
+ This function invokes ``func(head)`` after all pre-existing RCU
106
read-side critical sections on all threads have completed. This
107
marks the end of the removal phase, with func taking care
108
asynchronously of the reclamation phase.
109
110
- The foo struct needs to have an rcu_head structure added,
111
- perhaps as follows:
112
+ The ``foo`` struct needs to have an ``rcu_head`` structure added,
113
+ perhaps as follows::
114
115
struct foo {
116
struct rcu_head rcu;
117
@@ -XXX,XX +XXX,XX @@ The core RCU API is small:
118
long c;
119
};
120
121
- so that the reclaimer function can fetch the struct foo address
122
- and free it:
123
+ so that the reclaimer function can fetch the ``struct foo`` address
124
+ and free it::
125
126
call_rcu1(&foo.rcu, foo_reclaim);
127
128
@@ -XXX,XX +XXX,XX @@ The core RCU API is small:
129
g_free(fp);
130
}
131
132
- For the common case where the rcu_head member is the first of the
133
- struct, you can use the following macro.
134
+ ``call_rcu1`` is typically used via either the ``call_rcu`` or
135
+ ``g_free_rcu`` macros, which handle the common case where the
136
+ ``rcu_head`` member is the first of the struct.
137
138
- void call_rcu(T *p,
139
- void (*func)(T *p),
140
- field-name);
141
- void g_free_rcu(T *p,
142
- field-name);
143
+``void call_rcu(T *p, void (*func)(T *p), field-name);``
144
+ If the ``struct rcu_head`` is the first field in the struct, you can
145
+ use this macro instead of ``call_rcu1``.
146
147
- call_rcu1 is typically used through these macro, in the common case
148
- where the "struct rcu_head" is the first field in the struct. If
149
- the callback function is g_free, in particular, g_free_rcu can be
150
- used. In the above case, one could have written simply:
151
+``void g_free_rcu(T *p, field-name);``
152
+ This is a special-case version of ``call_rcu`` where the callback
153
+ function is ``g_free``.
154
+ In the example given in ``call_rcu1``, one could have written simply::
155
156
g_free_rcu(&foo, rcu);
157
158
- typeof(*p) qatomic_rcu_read(p);
159
+``typeof(*p) qatomic_rcu_read(p);``
160
+ ``qatomic_rcu_read()`` is similar to ``qatomic_load_acquire()``, but
161
+ it makes some assumptions on the code that calls it. This allows a
162
+ more optimized implementation.
163
164
- qatomic_rcu_read() is similar to qatomic_load_acquire(), but it makes
165
- some assumptions on the code that calls it. This allows a more
166
- optimized implementation.
167
-
168
- qatomic_rcu_read assumes that whenever a single RCU critical
169
+ ``qatomic_rcu_read`` assumes that whenever a single RCU critical
170
section reads multiple shared data, these reads are either
171
data-dependent or need no ordering. This is almost always the
172
case when using RCU, because read-side critical sections typically
173
@@ -XXX,XX +XXX,XX @@ The core RCU API is small:
174
every update) until reaching a data structure of interest,
175
and then read from there.
176
177
- RCU read-side critical sections must use qatomic_rcu_read() to
178
+ RCU read-side critical sections must use ``qatomic_rcu_read()`` to
179
read data, unless concurrent writes are prevented by another
180
synchronization mechanism.
181
182
@@ -XXX,XX +XXX,XX @@ The core RCU API is small:
183
data structure in a single direction, opposite to the direction
184
in which the updater initializes it.
185
186
- void qatomic_rcu_set(p, typeof(*p) v);
187
+``void qatomic_rcu_set(p, typeof(*p) v);``
188
+ ``qatomic_rcu_set()`` is similar to ``qatomic_store_release()``,
189
+ though it also makes assumptions on the code that calls it in
190
+ order to allow a more optimized implementation.
191
192
- qatomic_rcu_set() is similar to qatomic_store_release(), though it also
193
- makes assumptions on the code that calls it in order to allow a more
194
- optimized implementation.
195
-
196
- In particular, qatomic_rcu_set() suffices for synchronization
197
+ In particular, ``qatomic_rcu_set()`` suffices for synchronization
198
with readers, if the updater never mutates a field within a
199
data item that is already accessible to readers. This is the
200
case when initializing a new copy of the RCU-protected data
201
- structure; just ensure that initialization of *p is carried out
202
- before qatomic_rcu_set() makes the data item visible to readers.
203
+ structure; just ensure that initialization of ``*p`` is carried out
204
+ before ``qatomic_rcu_set()`` makes the data item visible to readers.
205
If this rule is observed, writes will happen in the opposite
206
order as reads in the RCU read-side critical sections (or if
207
there is just one update), and there will be no need for other
208
@@ -XXX,XX +XXX,XX @@ The core RCU API is small:
209
210
The following APIs must be used before RCU is used in a thread:
211
212
- void rcu_register_thread(void);
213
-
214
+``void rcu_register_thread(void);``
215
Mark a thread as taking part in the RCU mechanism. Such a thread
216
will have to report quiescent points regularly, either manually
217
- or through the QemuCond/QemuSemaphore/QemuEvent APIs.
218
-
219
- void rcu_unregister_thread(void);
220
+ or through the ``QemuCond``/``QemuSemaphore``/``QemuEvent`` APIs.
221
222
+``void rcu_unregister_thread(void);``
223
Mark a thread as not taking part anymore in the RCU mechanism.
224
It is not a problem if such a thread reports quiescent points,
225
- either manually or by using the QemuCond/QemuSemaphore/QemuEvent
226
- APIs.
227
+ either manually or by using the
228
+ ``QemuCond``/``QemuSemaphore``/``QemuEvent`` APIs.
229
230
-Note that these APIs are relatively heavyweight, and should _not_ be
231
+Note that these APIs are relatively heavyweight, and should **not** be
232
nested.
233
234
Convenience macros
235
-==================
236
+------------------
237
238
Two macros are provided that automatically release the read lock at the
239
end of the scope.
240
241
- RCU_READ_LOCK_GUARD()
242
-
243
+``RCU_READ_LOCK_GUARD()``
244
Takes the lock and will release it at the end of the block it's
245
used in.
246
247
- WITH_RCU_READ_LOCK_GUARD() { code }
248
-
249
+``WITH_RCU_READ_LOCK_GUARD() { code }``
250
Is used at the head of a block to protect the code within the block.
251
252
-Note that 'goto'ing out of the guarded block will also drop the lock.
253
+Note that a ``goto`` out of the guarded block will also drop the lock.
254
255
-DIFFERENCES WITH LINUX
256
-======================
257
+Differences with Linux
258
+----------------------
259
260
- Waiting on a mutex is possible, though discouraged, within an RCU critical
261
section. This is because spinlocks are rarely (if ever) used in userspace
262
programming; not allowing this would prevent upgrading an RCU read-side
263
critical section to become an updater.
264
265
-- qatomic_rcu_read and qatomic_rcu_set replace rcu_dereference and
266
- rcu_assign_pointer. They take a _pointer_ to the variable being accessed.
267
+- ``qatomic_rcu_read`` and ``qatomic_rcu_set`` replace ``rcu_dereference`` and
268
+ ``rcu_assign_pointer``. They take a **pointer** to the variable being accessed.
269
270
-- call_rcu is a macro that has an extra argument (the name of the first
271
- field in the struct, which must be a struct rcu_head), and expects the
272
+- ``call_rcu`` is a macro that has an extra argument (the name of the first
273
+ field in the struct, which must be a struct ``rcu_head``), and expects the
274
type of the callback's argument to be the type of the first argument.
275
- call_rcu1 is the same as Linux's call_rcu.
276
+ ``call_rcu1`` is the same as Linux's ``call_rcu``.
277
278
279
-RCU PATTERNS
280
-============
281
+RCU Patterns
282
+------------
283
284
Many patterns using read-writer locks translate directly to RCU, with
285
the advantages of higher scalability and deadlock immunity.
286
@@ -XXX,XX +XXX,XX @@ Here are some frequently-used RCU idioms that are worth noting.
287
288
289
RCU list processing
290
--------------------
291
+^^^^^^^^^^^^^^^^^^^
292
293
TBD (not yet used in QEMU)
294
295
296
RCU reference counting
297
-----------------------
298
+^^^^^^^^^^^^^^^^^^^^^^
299
300
Because grace periods are not allowed to complete while there is an RCU
301
read-side critical section in progress, the RCU read-side primitives
302
may be used as a restricted reference-counting mechanism. For example,
303
-consider the following code fragment:
304
+consider the following code fragment::
305
306
rcu_read_lock();
307
p = qatomic_rcu_read(&foo);
308
/* do something with p. */
309
rcu_read_unlock();
310
311
-The RCU read-side critical section ensures that the value of "p" remains
312
-valid until after the rcu_read_unlock(). In some sense, it is acquiring
313
-a reference to p that is later released when the critical section ends.
314
-The write side looks simply like this (with appropriate locking):
315
+The RCU read-side critical section ensures that the value of ``p`` remains
316
+valid until after the ``rcu_read_unlock()``. In some sense, it is acquiring
317
+a reference to ``p`` that is later released when the critical section ends.
318
+The write side looks simply like this (with appropriate locking)::
319
320
qemu_mutex_lock(&foo_mutex);
321
old = foo;
322
@@ -XXX,XX +XXX,XX @@ The write side looks simply like this (with appropriate locking):
323
free(old);
324
325
If the processing cannot be done purely within the critical section, it
326
-is possible to combine this idiom with a "real" reference count:
327
+is possible to combine this idiom with a "real" reference count::
328
329
rcu_read_lock();
330
p = qatomic_rcu_read(&foo);
331
@@ -XXX,XX +XXX,XX @@ is possible to combine this idiom with a "real" reference count:
332
/* do something with p. */
333
foo_unref(p);
334
335
-The write side can be like this:
336
+The write side can be like this::
337
338
qemu_mutex_lock(&foo_mutex);
339
old = foo;
340
@@ -XXX,XX +XXX,XX @@ The write side can be like this:
341
synchronize_rcu();
342
foo_unref(old);
343
344
-or with call_rcu:
345
+or with ``call_rcu``::
346
347
qemu_mutex_lock(&foo_mutex);
348
old = foo;
349
@@ -XXX,XX +XXX,XX @@ or with call_rcu:
350
call_rcu(foo_unref, old, rcu);
351
352
In both cases, the write side only performs removal. Reclamation
353
-happens when the last reference to a "foo" object is dropped.
354
-Using synchronize_rcu() is undesirably expensive, because the
355
+happens when the last reference to a ``foo`` object is dropped.
356
+Using ``synchronize_rcu()`` is undesirably expensive, because the
357
last reference may be dropped on the read side. Hence you can
358
-use call_rcu() instead:
359
+use ``call_rcu()`` instead::
360
361
foo_unref(struct foo *p) {
362
if (qatomic_fetch_dec(&p->refcount) == 1) {
363
@@ -XXX,XX +XXX,XX @@ use call_rcu() instead:
364
365
366
Note that the same idioms would be possible with reader/writer
367
-locks:
368
+locks::
369
370
read_lock(&foo_rwlock); write_mutex_lock(&foo_rwlock);
371
p = foo; p = foo;
372
@@ -XXX,XX +XXX,XX @@ locks:
373
foo_unref(p);
374
read_unlock(&foo_rwlock);
375
376
-foo_unref could use a mechanism such as bottom halves to move deallocation
377
+``foo_unref`` could use a mechanism such as bottom halves to move deallocation
378
out of the write-side critical section.
379
380
381
RCU resizable arrays
382
---------------------
383
+^^^^^^^^^^^^^^^^^^^^
384
385
Resizable arrays can be used with RCU. The expensive RCU synchronization
386
-(or call_rcu) only needs to take place when the array is resized.
387
+(or ``call_rcu``) only needs to take place when the array is resized.
388
The two items to take care of are:
389
390
- ensuring that the old version of the array is available between removal
391
@@ -XXX,XX +XXX,XX @@ The two items to take care of are:
392
- avoiding mismatches in the read side between the array data and the
393
array size.
394
395
-The first problem is avoided simply by not using realloc. Instead,
396
+The first problem is avoided simply by not using ``realloc``. Instead,
397
each resize will allocate a new array and copy the old data into it.
398
The second problem would arise if the size and the data pointers were
399
-two members of a larger struct:
400
+two members of a larger struct::
401
402
struct mystuff {
403
...
404
@@ -XXX,XX +XXX,XX @@ two members of a larger struct:
405
...
406
};
407
408
-Instead, we store the size of the array with the array itself:
409
+Instead, we store the size of the array with the array itself::
410
411
struct arr {
412
int size;
413
@@ -XXX,XX +XXX,XX @@ Instead, we store the size of the array with the array itself:
414
}
44
}
415
45
-#endif
416
46
}
417
-SOURCES
47
assert(dnan_pattern != 0);
418
-=======
48
419
+References
420
+----------
421
422
-* Documentation/RCU/ from the Linux kernel
423
+* The `Linux kernel RCU documentation <https://docs.kernel.org/RCU/>`__
424
--
49
--
425
2.34.1
50
2.34.1
diff view generated by jsdifflib
1
Convert docs/devel/multiple-iothreads.txt to rST format.
1
Set the default NaN pattern explicitly for riscv.
2
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Message-id: 20240816132212.3602106-5-peter.maydell@linaro.org
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-53-peter.maydell@linaro.org
5
---
6
---
6
docs/devel/index-internals.rst | 1 +
7
target/riscv/cpu.c | 2 ++
7
docs/devel/multiple-iothreads.rst | 139 ++++++++++++++++++++++++++++++
8
1 file changed, 2 insertions(+)
8
docs/devel/multiple-iothreads.txt | 130 ----------------------------
9
3 files changed, 140 insertions(+), 130 deletions(-)
10
create mode 100644 docs/devel/multiple-iothreads.rst
11
delete mode 100644 docs/devel/multiple-iothreads.txt
12
9
13
diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/docs/devel/index-internals.rst
12
--- a/target/riscv/cpu.c
16
+++ b/docs/devel/index-internals.rst
13
+++ b/target/riscv/cpu.c
17
@@ -XXX,XX +XXX,XX @@ Details about QEMU's various subsystems including how to add features to them.
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
18
writing-monitor-commands
15
cs->exception_index = RISCV_EXCP_NONE;
19
virtio-backends
16
env->load_res = -1;
20
crypto
17
set_default_nan_mode(1, &env->fp_status);
21
+ multiple-iothreads
18
+ /* Default NaN value: sign bit clear, frac msb set */
22
diff --git a/docs/devel/multiple-iothreads.rst b/docs/devel/multiple-iothreads.rst
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
23
new file mode 100644
20
env->vill = true;
24
index XXXXXXX..XXXXXXX
21
25
--- /dev/null
22
#ifndef CONFIG_USER_ONLY
26
+++ b/docs/devel/multiple-iothreads.rst
27
@@ -XXX,XX +XXX,XX @@
28
+Using Multiple ``IOThread``\ s
29
+==============================
30
+
31
+..
32
+ Copyright (c) 2014-2017 Red Hat Inc.
33
+
34
+ This work is licensed under the terms of the GNU GPL, version 2 or later. See
35
+ the COPYING file in the top-level directory.
36
+
37
+
38
+This document explains the ``IOThread`` feature and how to write code that runs
39
+outside the BQL.
40
+
41
+The main loop and ``IOThread``\ s
42
+---------------------------------
43
+QEMU is an event-driven program that can do several things at once using an
44
+event loop. The VNC server and the QMP monitor are both processed from the
45
+same event loop, which monitors their file descriptors until they become
46
+readable and then invokes a callback.
47
+
48
+The default event loop is called the main loop (see ``main-loop.c``). It is
49
+possible to create additional event loop threads using
50
+``-object iothread,id=my-iothread``.
51
+
52
+Side note: The main loop and ``IOThread`` are both event loops but their code is
53
+not shared completely. Sometimes it is useful to remember that although they
54
+are conceptually similar they are currently not interchangeable.
55
+
56
+Why ``IOThread``\ s are useful
57
+------------------------------
58
+``IOThread``\ s allow the user to control the placement of work. The main loop is a
59
+scalability bottleneck on hosts with many CPUs. Work can be spread across
60
+several ``IOThread``\ s instead of just one main loop. When set up correctly this
61
+can improve I/O latency and reduce jitter seen by the guest.
62
+
63
+The main loop is also deeply associated with the BQL, which is a
64
+scalability bottleneck in itself. vCPU threads and the main loop use the BQL
65
+to serialize execution of QEMU code. This mutex is necessary because a lot of
66
+QEMU's code historically was not thread-safe.
67
+
68
+The fact that all I/O processing is done in a single main loop and that the
69
+BQL is contended by all vCPU threads and the main loop explain
70
+why it is desirable to place work into ``IOThread``\ s.
71
+
72
+The experimental ``virtio-blk`` data-plane implementation has been benchmarked and
73
+shows these effects:
74
+ftp://public.dhe.ibm.com/linux/pdfs/KVM_Virtualized_IO_Performance_Paper.pdf
75
+
76
+.. _how-to-program:
77
+
78
+How to program for ``IOThread``\ s
79
+----------------------------------
80
+The main difference between legacy code and new code that can run in an
81
+``IOThread`` is dealing explicitly with the event loop object, ``AioContext``
82
+(see ``include/block/aio.h``). Code that only works in the main loop
83
+implicitly uses the main loop's ``AioContext``. Code that supports running
84
+in ``IOThread``\ s must be aware of its ``AioContext``.
85
+
86
+AioContext supports the following services:
87
+ * File descriptor monitoring (read/write/error on POSIX hosts)
88
+ * Event notifiers (inter-thread signalling)
89
+ * Timers
90
+ * Bottom Halves (BH) deferred callbacks
91
+
92
+There are several old APIs that use the main loop AioContext:
93
+ * LEGACY ``qemu_aio_set_fd_handler()`` - monitor a file descriptor
94
+ * LEGACY ``qemu_aio_set_event_notifier()`` - monitor an event notifier
95
+ * LEGACY ``timer_new_ms()`` - create a timer
96
+ * LEGACY ``qemu_bh_new()`` - create a BH
97
+ * LEGACY ``qemu_bh_new_guarded()`` - create a BH with a device re-entrancy guard
98
+ * LEGACY ``qemu_aio_wait()`` - run an event loop iteration
99
+
100
+Since they implicitly work on the main loop they cannot be used in code that
101
+runs in an ``IOThread``. They might cause a crash or deadlock if called from an
102
+``IOThread`` since the BQL is not held.
103
+
104
+Instead, use the ``AioContext`` functions directly (see ``include/block/aio.h``):
105
+ * ``aio_set_fd_handler()`` - monitor a file descriptor
106
+ * ``aio_set_event_notifier()`` - monitor an event notifier
107
+ * ``aio_timer_new()`` - create a timer
108
+ * ``aio_bh_new()`` - create a BH
109
+ * ``aio_bh_new_guarded()`` - create a BH with a device re-entrancy guard
110
+ * ``aio_poll()`` - run an event loop iteration
111
+
112
+The ``qemu_bh_new_guarded``/``aio_bh_new_guarded`` APIs accept a
113
+``MemReentrancyGuard``
114
+argument, which is used to check for and prevent re-entrancy problems. For
115
+BHs associated with devices, the reentrancy-guard is contained in the
116
+corresponding ``DeviceState`` and named ``mem_reentrancy_guard``.
117
+
118
+The ``AioContext`` can be obtained from the ``IOThread`` using
119
+``iothread_get_aio_context()`` or for the main loop using
120
+``qemu_get_aio_context()``. Code that takes an ``AioContext`` argument
121
+works both in ``IOThread``\ s or the main loop, depending on which ``AioContext``
122
+instance the caller passes in.
123
+
124
+How to synchronize with an ``IOThread``
125
+---------------------------------------
126
+Variables that can be accessed by multiple threads require some form of
127
+synchronization such as ``qemu_mutex_lock()``, ``rcu_read_lock()``, etc.
128
+
129
+``AioContext`` functions like ``aio_set_fd_handler()``,
130
+``aio_set_event_notifier()``, ``aio_bh_new()``, and ``aio_timer_new()``
131
+are thread-safe. They can be used to trigger activity in an ``IOThread``.
132
+
133
+Side note: the best way to schedule a function call across threads is to call
134
+``aio_bh_schedule_oneshot()``.
135
+
136
+The main loop thread can wait synchronously for a condition using
137
+``AIO_WAIT_WHILE()``.
138
+
139
+``AioContext`` and the block layer
140
+----------------------------------
141
+The ``AioContext`` originates from the QEMU block layer, even though nowadays
142
+``AioContext`` is a generic event loop that can be used by any QEMU subsystem.
143
+
144
+The block layer has support for ``AioContext`` integrated. Each
145
+``BlockDriverState`` is associated with an ``AioContext`` using
146
+``bdrv_try_change_aio_context()`` and ``bdrv_get_aio_context()``.
147
+This allows block layer code to process I/O inside the
148
+right ``AioContext``. Other subsystems may wish to follow a similar approach.
149
+
150
+Block layer code must therefore expect to run in an ``IOThread`` and avoid using
151
+old APIs that implicitly use the main loop. See
152
+`How to program for IOThreads`_ for information on how to do that.
153
+
154
+Code running in the monitor typically needs to ensure that past
155
+requests from the guest are completed. When a block device is running
156
+in an ``IOThread``, the ``IOThread`` can also process requests from the guest
157
+(via ioeventfd). To achieve both objects, wrap the code between
158
+``bdrv_drained_begin()`` and ``bdrv_drained_end()``, thus creating a "drained
159
+section".
160
+
161
+Long-running jobs (usually in the form of coroutines) are often scheduled in
162
+the ``BlockDriverState``'s ``AioContext``. The functions
163
+``bdrv_add``/``remove_aio_context_notifier``, or alternatively
164
+``blk_add``/``remove_aio_context_notifier`` if you use ``BlockBackends``,
165
+can be used to get a notification whenever ``bdrv_try_change_aio_context()``
166
+moves a ``BlockDriverState`` to a different ``AioContext``.
167
diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
168
deleted file mode 100644
169
index XXXXXXX..XXXXXXX
170
--- a/docs/devel/multiple-iothreads.txt
171
+++ /dev/null
172
@@ -XXX,XX +XXX,XX @@
173
-Copyright (c) 2014-2017 Red Hat Inc.
174
-
175
-This work is licensed under the terms of the GNU GPL, version 2 or later. See
176
-the COPYING file in the top-level directory.
177
-
178
-
179
-This document explains the IOThread feature and how to write code that runs
180
-outside the BQL.
181
-
182
-The main loop and IOThreads
183
----------------------------
184
-QEMU is an event-driven program that can do several things at once using an
185
-event loop. The VNC server and the QMP monitor are both processed from the
186
-same event loop, which monitors their file descriptors until they become
187
-readable and then invokes a callback.
188
-
189
-The default event loop is called the main loop (see main-loop.c). It is
190
-possible to create additional event loop threads using -object
191
-iothread,id=my-iothread.
192
-
193
-Side note: The main loop and IOThread are both event loops but their code is
194
-not shared completely. Sometimes it is useful to remember that although they
195
-are conceptually similar they are currently not interchangeable.
196
-
197
-Why IOThreads are useful
198
-------------------------
199
-IOThreads allow the user to control the placement of work. The main loop is a
200
-scalability bottleneck on hosts with many CPUs. Work can be spread across
201
-several IOThreads instead of just one main loop. When set up correctly this
202
-can improve I/O latency and reduce jitter seen by the guest.
203
-
204
-The main loop is also deeply associated with the BQL, which is a
205
-scalability bottleneck in itself. vCPU threads and the main loop use the BQL
206
-to serialize execution of QEMU code. This mutex is necessary because a lot of
207
-QEMU's code historically was not thread-safe.
208
-
209
-The fact that all I/O processing is done in a single main loop and that the
210
-BQL is contended by all vCPU threads and the main loop explain
211
-why it is desirable to place work into IOThreads.
212
-
213
-The experimental virtio-blk data-plane implementation has been benchmarked and
214
-shows these effects:
215
-ftp://public.dhe.ibm.com/linux/pdfs/KVM_Virtualized_IO_Performance_Paper.pdf
216
-
217
-How to program for IOThreads
218
-----------------------------
219
-The main difference between legacy code and new code that can run in an
220
-IOThread is dealing explicitly with the event loop object, AioContext
221
-(see include/block/aio.h). Code that only works in the main loop
222
-implicitly uses the main loop's AioContext. Code that supports running
223
-in IOThreads must be aware of its AioContext.
224
-
225
-AioContext supports the following services:
226
- * File descriptor monitoring (read/write/error on POSIX hosts)
227
- * Event notifiers (inter-thread signalling)
228
- * Timers
229
- * Bottom Halves (BH) deferred callbacks
230
-
231
-There are several old APIs that use the main loop AioContext:
232
- * LEGACY qemu_aio_set_fd_handler() - monitor a file descriptor
233
- * LEGACY qemu_aio_set_event_notifier() - monitor an event notifier
234
- * LEGACY timer_new_ms() - create a timer
235
- * LEGACY qemu_bh_new() - create a BH
236
- * LEGACY qemu_bh_new_guarded() - create a BH with a device re-entrancy guard
237
- * LEGACY qemu_aio_wait() - run an event loop iteration
238
-
239
-Since they implicitly work on the main loop they cannot be used in code that
240
-runs in an IOThread. They might cause a crash or deadlock if called from an
241
-IOThread since the BQL is not held.
242
-
243
-Instead, use the AioContext functions directly (see include/block/aio.h):
244
- * aio_set_fd_handler() - monitor a file descriptor
245
- * aio_set_event_notifier() - monitor an event notifier
246
- * aio_timer_new() - create a timer
247
- * aio_bh_new() - create a BH
248
- * aio_bh_new_guarded() - create a BH with a device re-entrancy guard
249
- * aio_poll() - run an event loop iteration
250
-
251
-The qemu_bh_new_guarded/aio_bh_new_guarded APIs accept a "MemReentrancyGuard"
252
-argument, which is used to check for and prevent re-entrancy problems. For
253
-BHs associated with devices, the reentrancy-guard is contained in the
254
-corresponding DeviceState and named "mem_reentrancy_guard".
255
-
256
-The AioContext can be obtained from the IOThread using
257
-iothread_get_aio_context() or for the main loop using qemu_get_aio_context().
258
-Code that takes an AioContext argument works both in IOThreads or the main
259
-loop, depending on which AioContext instance the caller passes in.
260
-
261
-How to synchronize with an IOThread
262
------------------------------------
263
-Variables that can be accessed by multiple threads require some form of
264
-synchronization such as qemu_mutex_lock(), rcu_read_lock(), etc.
265
-
266
-AioContext functions like aio_set_fd_handler(), aio_set_event_notifier(),
267
-aio_bh_new(), and aio_timer_new() are thread-safe. They can be used to trigger
268
-activity in an IOThread.
269
-
270
-Side note: the best way to schedule a function call across threads is to call
271
-aio_bh_schedule_oneshot().
272
-
273
-The main loop thread can wait synchronously for a condition using
274
-AIO_WAIT_WHILE().
275
-
276
-AioContext and the block layer
277
-------------------------------
278
-The AioContext originates from the QEMU block layer, even though nowadays
279
-AioContext is a generic event loop that can be used by any QEMU subsystem.
280
-
281
-The block layer has support for AioContext integrated. Each BlockDriverState
282
-is associated with an AioContext using bdrv_try_change_aio_context() and
283
-bdrv_get_aio_context(). This allows block layer code to process I/O inside the
284
-right AioContext. Other subsystems may wish to follow a similar approach.
285
-
286
-Block layer code must therefore expect to run in an IOThread and avoid using
287
-old APIs that implicitly use the main loop. See the "How to program for
288
-IOThreads" above for information on how to do that.
289
-
290
-Code running in the monitor typically needs to ensure that past
291
-requests from the guest are completed. When a block device is running
292
-in an IOThread, the IOThread can also process requests from the guest
293
-(via ioeventfd). To achieve both objects, wrap the code between
294
-bdrv_drained_begin() and bdrv_drained_end(), thus creating a "drained
295
-section".
296
-
297
-Long-running jobs (usually in the form of coroutines) are often scheduled in
298
-the BlockDriverState's AioContext. The functions
299
-bdrv_add/remove_aio_context_notifier, or alternatively
300
-blk_add/remove_aio_context_notifier if you use BlockBackends, can be used to
301
-get a notification whenever bdrv_try_change_aio_context() moves a
302
-BlockDriverState to a different AioContext.
303
--
23
--
304
2.34.1
24
2.34.1
diff view generated by jsdifflib
1
Currently the QemuLockCnt data structure and associated functions are
1
Set the default NaN pattern explicitly for tricore.
2
in the include/qemu/thread.h header. Move them to their own
3
qemu/lockcnt.h. The main reason for doing this is that it means we
4
can autogenerate the documentation comments into the docs/devel
5
documentation.
6
7
The copyright/author in the new header is drawn from lockcnt.c,
8
since the header changes were added in the same commit as
9
lockcnt.c; since neither thread.h nor lockcnt.c state an explicit
10
license, the standard default of GPL-2-or-later applies.
11
12
We include the new header (and the .c file, which was accidentally
13
omitted previously) in the "RCU" part of MAINTAINERS, since that
14
is where the lockcnt.rst documentation is categorized.
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: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-id: 20241202131347.498124-54-peter.maydell@linaro.org
19
Message-id: 20240816132212.3602106-7-peter.maydell@linaro.org
20
---
6
---
21
MAINTAINERS | 2 +
7
target/tricore/helper.c | 2 ++
22
docs/devel/lockcnt.rst | 2 +-
8
1 file changed, 2 insertions(+)
23
include/block/aio.h | 1 +
24
include/hw/core/cpu.h | 1 +
25
include/qemu/lockcnt.h | 130 +++++++++++++++++++++++++++++++++++++++++
26
include/qemu/thread.h | 111 -----------------------------------
27
accel/accel-blocker.c | 1 +
28
hw/core/cpu-common.c | 1 +
29
util/aio-posix.c | 1 +
30
util/aio-win32.c | 1 +
31
util/async.c | 1 +
32
util/fdmon-epoll.c | 1 +
33
util/lockcnt.c | 1 +
34
13 files changed, 142 insertions(+), 112 deletions(-)
35
create mode 100644 include/qemu/lockcnt.h
36
9
37
diff --git a/MAINTAINERS b/MAINTAINERS
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
38
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
39
--- a/MAINTAINERS
12
--- a/target/tricore/helper.c
40
+++ b/MAINTAINERS
13
+++ b/target/tricore/helper.c
41
@@ -XXX,XX +XXX,XX @@ S: Maintained
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
42
F: docs/devel/lockcnt.rst
15
set_flush_to_zero(1, &env->fp_status);
43
F: docs/devel/rcu.rst
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
44
F: include/qemu/rcu*.h
17
set_default_nan_mode(1, &env->fp_status);
45
+F: include/qemu/lockcnt.h
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
46
F: tests/unit/rcutorture.c
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
47
F: tests/unit/test-rcu-*.c
48
+F: util/lockcnt.c
49
F: util/rcu.c
50
51
Human Monitor (HMP)
52
diff --git a/docs/devel/lockcnt.rst b/docs/devel/lockcnt.rst
53
index XXXXXXX..XXXXXXX 100644
54
--- a/docs/devel/lockcnt.rst
55
+++ b/docs/devel/lockcnt.rst
56
@@ -XXX,XX +XXX,XX @@ three instructions in the critical path, two assignments and a ``smp_wmb()``.
57
``QemuLockCnt`` API
58
-------------------
59
60
-The ``QemuLockCnt`` API is described in ``include/qemu/thread.h``.
61
+The ``QemuLockCnt`` API is described in ``include/qemu/lockcnt.h``.
62
63
64
``QemuLockCnt`` usage
65
diff --git a/include/block/aio.h b/include/block/aio.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/include/block/aio.h
68
+++ b/include/block/aio.h
69
@@ -XXX,XX +XXX,XX @@
70
#include "qemu/coroutine-core.h"
71
#include "qemu/queue.h"
72
#include "qemu/event_notifier.h"
73
+#include "qemu/lockcnt.h"
74
#include "qemu/thread.h"
75
#include "qemu/timer.h"
76
#include "block/graph-lock.h"
77
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
78
index XXXXXXX..XXXXXXX 100644
79
--- a/include/hw/core/cpu.h
80
+++ b/include/hw/core/cpu.h
81
@@ -XXX,XX +XXX,XX @@
82
#include "qemu/bitmap.h"
83
#include "qemu/rcu_queue.h"
84
#include "qemu/queue.h"
85
+#include "qemu/lockcnt.h"
86
#include "qemu/thread.h"
87
#include "qom/object.h"
88
89
diff --git a/include/qemu/lockcnt.h b/include/qemu/lockcnt.h
90
new file mode 100644
91
index XXXXXXX..XXXXXXX
92
--- /dev/null
93
+++ b/include/qemu/lockcnt.h
94
@@ -XXX,XX +XXX,XX @@
95
+/* SPDX-License-Identifier: GPL-2.0-or-later */
96
+/*
97
+ * QemuLockCnt implementation
98
+ *
99
+ * Copyright Red Hat, Inc. 2017
100
+ *
101
+ * Author:
102
+ * Paolo Bonzini <pbonzini@redhat.com>
103
+ *
104
+ */
105
+
106
+#ifndef QEMU_LOCKCNT_H
107
+#define QEMU_LOCKCNT_H
108
+
109
+#include "qemu/thread.h"
110
+
111
+typedef struct QemuLockCnt QemuLockCnt;
112
+
113
+struct QemuLockCnt {
114
+#ifndef CONFIG_LINUX
115
+ QemuMutex mutex;
116
+#endif
117
+ unsigned count;
118
+};
119
+
120
+/**
121
+ * qemu_lockcnt_init: initialize a QemuLockcnt
122
+ * @lockcnt: the lockcnt to initialize
123
+ *
124
+ * Initialize lockcnt's counter to zero and prepare its mutex
125
+ * for usage.
126
+ */
127
+void qemu_lockcnt_init(QemuLockCnt *lockcnt);
128
+
129
+/**
130
+ * qemu_lockcnt_destroy: destroy a QemuLockcnt
131
+ * @lockcnt: the lockcnt to destruct
132
+ *
133
+ * Destroy lockcnt's mutex.
134
+ */
135
+void qemu_lockcnt_destroy(QemuLockCnt *lockcnt);
136
+
137
+/**
138
+ * qemu_lockcnt_inc: increment a QemuLockCnt's counter
139
+ * @lockcnt: the lockcnt to operate on
140
+ *
141
+ * If the lockcnt's count is zero, wait for critical sections
142
+ * to finish and increment lockcnt's count to 1. If the count
143
+ * is not zero, just increment it.
144
+ *
145
+ * Because this function can wait on the mutex, it must not be
146
+ * called while the lockcnt's mutex is held by the current thread.
147
+ * For the same reason, qemu_lockcnt_inc can also contribute to
148
+ * AB-BA deadlocks. This is a sample deadlock scenario:
149
+ *
150
+ * thread 1 thread 2
151
+ * -------------------------------------------------------
152
+ * qemu_lockcnt_lock(&lc1);
153
+ * qemu_lockcnt_lock(&lc2);
154
+ * qemu_lockcnt_inc(&lc2);
155
+ * qemu_lockcnt_inc(&lc1);
156
+ */
157
+void qemu_lockcnt_inc(QemuLockCnt *lockcnt);
158
+
159
+/**
160
+ * qemu_lockcnt_dec: decrement a QemuLockCnt's counter
161
+ * @lockcnt: the lockcnt to operate on
162
+ */
163
+void qemu_lockcnt_dec(QemuLockCnt *lockcnt);
164
+
165
+/**
166
+ * qemu_lockcnt_dec_and_lock: decrement a QemuLockCnt's counter and
167
+ * possibly lock it.
168
+ * @lockcnt: the lockcnt to operate on
169
+ *
170
+ * Decrement lockcnt's count. If the new count is zero, lock
171
+ * the mutex and return true. Otherwise, return false.
172
+ */
173
+bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt);
174
+
175
+/**
176
+ * qemu_lockcnt_dec_if_lock: possibly decrement a QemuLockCnt's counter and
177
+ * lock it.
178
+ * @lockcnt: the lockcnt to operate on
179
+ *
180
+ * If the count is 1, decrement the count to zero, lock
181
+ * the mutex and return true. Otherwise, return false.
182
+ */
183
+bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt);
184
+
185
+/**
186
+ * qemu_lockcnt_lock: lock a QemuLockCnt's mutex.
187
+ * @lockcnt: the lockcnt to operate on
188
+ *
189
+ * Remember that concurrent visits are not blocked unless the count is
190
+ * also zero. You can use qemu_lockcnt_count to check for this inside a
191
+ * critical section.
192
+ */
193
+void qemu_lockcnt_lock(QemuLockCnt *lockcnt);
194
+
195
+/**
196
+ * qemu_lockcnt_unlock: release a QemuLockCnt's mutex.
197
+ * @lockcnt: the lockcnt to operate on.
198
+ */
199
+void qemu_lockcnt_unlock(QemuLockCnt *lockcnt);
200
+
201
+/**
202
+ * qemu_lockcnt_inc_and_unlock: combined unlock/increment on a QemuLockCnt.
203
+ * @lockcnt: the lockcnt to operate on.
204
+ *
205
+ * This is the same as
206
+ *
207
+ * qemu_lockcnt_unlock(lockcnt);
208
+ * qemu_lockcnt_inc(lockcnt);
209
+ *
210
+ * but more efficient.
211
+ */
212
+void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt);
213
+
214
+/**
215
+ * qemu_lockcnt_count: query a LockCnt's count.
216
+ * @lockcnt: the lockcnt to query.
217
+ *
218
+ * Note that the count can change at any time. Still, while the
219
+ * lockcnt is locked, one can usefully check whether the count
220
+ * is non-zero.
221
+ */
222
+unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt);
223
+
224
+#endif
225
diff --git a/include/qemu/thread.h b/include/qemu/thread.h
226
index XXXXXXX..XXXXXXX 100644
227
--- a/include/qemu/thread.h
228
+++ b/include/qemu/thread.h
229
@@ -XXX,XX +XXX,XX @@ static inline void qemu_spin_unlock(QemuSpin *spin)
230
#endif
231
}
20
}
232
21
233
-struct QemuLockCnt {
22
uint32_t psw_read(CPUTriCoreState *env)
234
-#ifndef CONFIG_LINUX
235
- QemuMutex mutex;
236
-#endif
237
- unsigned count;
238
-};
239
-
240
-/**
241
- * qemu_lockcnt_init: initialize a QemuLockcnt
242
- * @lockcnt: the lockcnt to initialize
243
- *
244
- * Initialize lockcnt's counter to zero and prepare its mutex
245
- * for usage.
246
- */
247
-void qemu_lockcnt_init(QemuLockCnt *lockcnt);
248
-
249
-/**
250
- * qemu_lockcnt_destroy: destroy a QemuLockcnt
251
- * @lockcnt: the lockcnt to destruct
252
- *
253
- * Destroy lockcnt's mutex.
254
- */
255
-void qemu_lockcnt_destroy(QemuLockCnt *lockcnt);
256
-
257
-/**
258
- * qemu_lockcnt_inc: increment a QemuLockCnt's counter
259
- * @lockcnt: the lockcnt to operate on
260
- *
261
- * If the lockcnt's count is zero, wait for critical sections
262
- * to finish and increment lockcnt's count to 1. If the count
263
- * is not zero, just increment it.
264
- *
265
- * Because this function can wait on the mutex, it must not be
266
- * called while the lockcnt's mutex is held by the current thread.
267
- * For the same reason, qemu_lockcnt_inc can also contribute to
268
- * AB-BA deadlocks. This is a sample deadlock scenario:
269
- *
270
- * thread 1 thread 2
271
- * -------------------------------------------------------
272
- * qemu_lockcnt_lock(&lc1);
273
- * qemu_lockcnt_lock(&lc2);
274
- * qemu_lockcnt_inc(&lc2);
275
- * qemu_lockcnt_inc(&lc1);
276
- */
277
-void qemu_lockcnt_inc(QemuLockCnt *lockcnt);
278
-
279
-/**
280
- * qemu_lockcnt_dec: decrement a QemuLockCnt's counter
281
- * @lockcnt: the lockcnt to operate on
282
- */
283
-void qemu_lockcnt_dec(QemuLockCnt *lockcnt);
284
-
285
-/**
286
- * qemu_lockcnt_dec_and_lock: decrement a QemuLockCnt's counter and
287
- * possibly lock it.
288
- * @lockcnt: the lockcnt to operate on
289
- *
290
- * Decrement lockcnt's count. If the new count is zero, lock
291
- * the mutex and return true. Otherwise, return false.
292
- */
293
-bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt);
294
-
295
-/**
296
- * qemu_lockcnt_dec_if_lock: possibly decrement a QemuLockCnt's counter and
297
- * lock it.
298
- * @lockcnt: the lockcnt to operate on
299
- *
300
- * If the count is 1, decrement the count to zero, lock
301
- * the mutex and return true. Otherwise, return false.
302
- */
303
-bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt);
304
-
305
-/**
306
- * qemu_lockcnt_lock: lock a QemuLockCnt's mutex.
307
- * @lockcnt: the lockcnt to operate on
308
- *
309
- * Remember that concurrent visits are not blocked unless the count is
310
- * also zero. You can use qemu_lockcnt_count to check for this inside a
311
- * critical section.
312
- */
313
-void qemu_lockcnt_lock(QemuLockCnt *lockcnt);
314
-
315
-/**
316
- * qemu_lockcnt_unlock: release a QemuLockCnt's mutex.
317
- * @lockcnt: the lockcnt to operate on.
318
- */
319
-void qemu_lockcnt_unlock(QemuLockCnt *lockcnt);
320
-
321
-/**
322
- * qemu_lockcnt_inc_and_unlock: combined unlock/increment on a QemuLockCnt.
323
- * @lockcnt: the lockcnt to operate on.
324
- *
325
- * This is the same as
326
- *
327
- * qemu_lockcnt_unlock(lockcnt);
328
- * qemu_lockcnt_inc(lockcnt);
329
- *
330
- * but more efficient.
331
- */
332
-void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt);
333
-
334
-/**
335
- * qemu_lockcnt_count: query a LockCnt's count.
336
- * @lockcnt: the lockcnt to query.
337
- *
338
- * Note that the count can change at any time. Still, while the
339
- * lockcnt is locked, one can usefully check whether the count
340
- * is non-zero.
341
- */
342
-unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt);
343
-
344
#endif
345
diff --git a/accel/accel-blocker.c b/accel/accel-blocker.c
346
index XXXXXXX..XXXXXXX 100644
347
--- a/accel/accel-blocker.c
348
+++ b/accel/accel-blocker.c
349
@@ -XXX,XX +XXX,XX @@
350
*/
351
352
#include "qemu/osdep.h"
353
+#include "qemu/lockcnt.h"
354
#include "qemu/thread.h"
355
#include "qemu/main-loop.h"
356
#include "hw/core/cpu.h"
357
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
358
index XXXXXXX..XXXXXXX 100644
359
--- a/hw/core/cpu-common.c
360
+++ b/hw/core/cpu-common.c
361
@@ -XXX,XX +XXX,XX @@
362
#include "sysemu/hw_accel.h"
363
#include "qemu/log.h"
364
#include "qemu/main-loop.h"
365
+#include "qemu/lockcnt.h"
366
#include "exec/log.h"
367
#include "exec/gdbstub.h"
368
#include "sysemu/tcg.h"
369
diff --git a/util/aio-posix.c b/util/aio-posix.c
370
index XXXXXXX..XXXXXXX 100644
371
--- a/util/aio-posix.c
372
+++ b/util/aio-posix.c
373
@@ -XXX,XX +XXX,XX @@
374
#include "block/block.h"
375
#include "block/thread-pool.h"
376
#include "qemu/main-loop.h"
377
+#include "qemu/lockcnt.h"
378
#include "qemu/rcu.h"
379
#include "qemu/rcu_queue.h"
380
#include "qemu/sockets.h"
381
diff --git a/util/aio-win32.c b/util/aio-win32.c
382
index XXXXXXX..XXXXXXX 100644
383
--- a/util/aio-win32.c
384
+++ b/util/aio-win32.c
385
@@ -XXX,XX +XXX,XX @@
386
#include "qemu/osdep.h"
387
#include "block/block.h"
388
#include "qemu/main-loop.h"
389
+#include "qemu/lockcnt.h"
390
#include "qemu/queue.h"
391
#include "qemu/sockets.h"
392
#include "qapi/error.h"
393
diff --git a/util/async.c b/util/async.c
394
index XXXXXXX..XXXXXXX 100644
395
--- a/util/async.c
396
+++ b/util/async.c
397
@@ -XXX,XX +XXX,XX @@
398
#include "block/graph-lock.h"
399
#include "qemu/main-loop.h"
400
#include "qemu/atomic.h"
401
+#include "qemu/lockcnt.h"
402
#include "qemu/rcu_queue.h"
403
#include "block/raw-aio.h"
404
#include "qemu/coroutine_int.h"
405
diff --git a/util/fdmon-epoll.c b/util/fdmon-epoll.c
406
index XXXXXXX..XXXXXXX 100644
407
--- a/util/fdmon-epoll.c
408
+++ b/util/fdmon-epoll.c
409
@@ -XXX,XX +XXX,XX @@
410
411
#include "qemu/osdep.h"
412
#include <sys/epoll.h>
413
+#include "qemu/lockcnt.h"
414
#include "qemu/rcu_queue.h"
415
#include "aio-posix.h"
416
417
diff --git a/util/lockcnt.c b/util/lockcnt.c
418
index XXXXXXX..XXXXXXX 100644
419
--- a/util/lockcnt.c
420
+++ b/util/lockcnt.c
421
@@ -XXX,XX +XXX,XX @@
422
* Paolo Bonzini <pbonzini@redhat.com>
423
*/
424
#include "qemu/osdep.h"
425
+#include "qemu/lockcnt.h"
426
#include "qemu/thread.h"
427
#include "qemu/atomic.h"
428
#include "trace.h"
429
--
23
--
430
2.34.1
24
2.34.1
431
432
diff view generated by jsdifflib
1
Convert blkverify.txt to rST format.
1
Now that all our targets have bene converted to explicitly specify
2
their pattern for the default NaN value we can remove the remaining
3
fallback code in parts64_default_nan().
2
4
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20240816132212.3602106-3-peter.maydell@linaro.org
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
6
---
8
---
7
MAINTAINERS | 1 +
9
fpu/softfloat-specialize.c.inc | 14 --------------
8
.../{blkverify.txt => testing/blkverify.rst} | 30 +++++++++++--------
10
1 file changed, 14 deletions(-)
9
docs/devel/testing/index.rst | 1 +
10
3 files changed, 19 insertions(+), 13 deletions(-)
11
rename docs/devel/{blkverify.txt => testing/blkverify.rst} (77%)
12
11
13
diff --git a/MAINTAINERS b/MAINTAINERS
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/MAINTAINERS
14
--- a/fpu/softfloat-specialize.c.inc
16
+++ b/MAINTAINERS
15
+++ b/fpu/softfloat-specialize.c.inc
17
@@ -XXX,XX +XXX,XX @@ M: Stefan Hajnoczi <stefanha@redhat.com>
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
18
L: qemu-block@nongnu.org
17
uint64_t frac;
19
S: Supported
18
uint8_t dnan_pattern = status->default_nan_pattern;
20
F: block/blkverify.c
19
21
+F: docs/devel/blkverify.rst
20
- if (dnan_pattern == 0) {
22
21
- /*
23
bochs
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
24
M: Stefan Hajnoczi <stefanha@redhat.com>
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
25
diff --git a/docs/devel/blkverify.txt b/docs/devel/testing/blkverify.rst
24
- * do not have floating-point.
26
similarity index 77%
25
- */
27
rename from docs/devel/blkverify.txt
26
- if (snan_bit_is_one(status)) {
28
rename to docs/devel/testing/blkverify.rst
27
- /* sign bit clear, set all frac bits other than msb */
29
index XXXXXXX..XXXXXXX 100644
28
- dnan_pattern = 0b00111111;
30
--- a/docs/devel/blkverify.txt
29
- } else {
31
+++ b/docs/devel/testing/blkverify.rst
30
- /* sign bit clear, set frac msb */
32
@@ -XXX,XX +XXX,XX @@
31
- dnan_pattern = 0b01000000;
33
-= Block driver correctness testing with blkverify =
32
- }
34
+Block driver correctness testing with ``blkverify``
33
- }
35
+===================================================
34
assert(dnan_pattern != 0);
36
35
37
-== Introduction ==
36
sign = dnan_pattern >> 7;
38
+Introduction
39
+------------
40
41
-This document describes how to use the blkverify protocol to test that a block
42
+This document describes how to use the ``blkverify`` protocol to test that a block
43
driver is operating correctly.
44
45
It is difficult to test and debug block drivers against real guests. Often
46
@@ -XXX,XX +XXX,XX @@ of the executable. Other times obscure errors are raised by a program inside
47
the guest. These issues are extremely hard to trace back to bugs in the block
48
driver.
49
50
-Blkverify solves this problem by catching data corruption inside QEMU the first
51
+``blkverify`` solves this problem by catching data corruption inside QEMU the first
52
time bad data is read and reporting the disk sector that is corrupted.
53
54
-== How it works ==
55
+How it works
56
+------------
57
58
-The blkverify protocol has two child block devices, the "test" device and the
59
+The ``blkverify`` protocol has two child block devices, the "test" device and the
60
"raw" device. Read/write operations are mirrored to both devices so their
61
state should always be in sync.
62
63
@@ -XXX,XX +XXX,XX @@ contents to the "test" image. The idea is that the "raw" device will handle
64
read/write operations correctly and not corrupt data. It can be used as a
65
reference for comparison against the "test" device.
66
67
-After a mirrored read operation completes, blkverify will compare the data and
68
+After a mirrored read operation completes, ``blkverify`` will compare the data and
69
raise an error if it is not identical. This makes it possible to catch the
70
first instance where corrupt data is read.
71
72
-== Example ==
73
+Example
74
+-------
75
76
-Imagine raw.img has 0xcd repeated throughout its first sector:
77
+Imagine raw.img has 0xcd repeated throughout its first sector::
78
79
$ ./qemu-io -c 'read -v 0 512' raw.img
80
00000000: cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd ................
81
@@ -XXX,XX +XXX,XX @@ Imagine raw.img has 0xcd repeated throughout its first sector:
82
read 512/512 bytes at offset 0
83
512.000000 bytes, 1 ops; 0.0000 sec (97.656 MiB/sec and 200000.0000 ops/sec)
84
85
-And test.img is corrupt, its first sector is zeroed when it shouldn't be:
86
+And test.img is corrupt, its first sector is zeroed when it shouldn't be::
87
88
$ ./qemu-io -c 'read -v 0 512' test.img
89
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90
@@ -XXX,XX +XXX,XX @@ And test.img is corrupt, its first sector is zeroed when it shouldn't be:
91
read 512/512 bytes at offset 0
92
512.000000 bytes, 1 ops; 0.0000 sec (81.380 MiB/sec and 166666.6667 ops/sec)
93
94
-This error is caught by blkverify:
95
+This error is caught by ``blkverify``::
96
97
$ ./qemu-io -c 'read 0 512' blkverify:a.img:b.img
98
blkverify: read sector_num=0 nb_sectors=4 contents mismatch in sector 0
99
100
-A more realistic scenario is verifying the installation of a guest OS:
101
+A more realistic scenario is verifying the installation of a guest OS::
102
103
$ ./qemu-img create raw.img 16G
104
$ ./qemu-img create -f qcow2 test.qcow2 16G
105
$ ./qemu-system-x86_64 -cdrom debian.iso \
106
-drive file=blkverify:raw.img:test.qcow2
107
108
-If the installation is aborted when blkverify detects corruption, use qemu-io
109
+If the installation is aborted when ``blkverify`` detects corruption, use ``qemu-io``
110
to explore the contents of the disk image at the sector in question.
111
diff --git a/docs/devel/testing/index.rst b/docs/devel/testing/index.rst
112
index XXXXXXX..XXXXXXX 100644
113
--- a/docs/devel/testing/index.rst
114
+++ b/docs/devel/testing/index.rst
115
@@ -XXX,XX +XXX,XX @@ testing infrastructure.
116
ci
117
fuzzing
118
blkdebug
119
+ blkverify
120
--
37
--
121
2.34.1
38
2.34.1
diff view generated by jsdifflib
1
The only PCMCIA subsystem was the PXA2xx SoC and the machines
1
From: Richard Henderson <richard.henderson@linaro.org>
2
using it, which have now been removed. Although in theory
3
we have a few machine types which have PCMCIA (e.g. kzm,
4
the strongarm machines, sh4's sh7750), none of those machines
5
implement their PCMCIA controller, and they're all old and
6
no longer very interesting machine types.
7
2
8
Rather than keeping all the PCMCIA code in-tree without any
3
Inline pickNaNMulAdd into its only caller. This makes
9
active users of it, delete it. If we need PCMCIA in future
4
one assert redundant with the immediately preceding IF.
10
we can always resurrect it.
11
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
9
[PMM: keep comment from old code in new location]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241003140010.1653808-5-peter.maydell@linaro.org
16
---
11
---
17
include/hw/pcmcia.h | 63 -------------------------------------------
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
18
hw/pcmcia/pcmcia.c | 24 -----------------
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
19
hw/Kconfig | 1 -
14
2 files changed, 40 insertions(+), 55 deletions(-)
20
hw/meson.build | 1 -
21
hw/pcmcia/Kconfig | 2 --
22
hw/pcmcia/meson.build | 1 -
23
6 files changed, 92 deletions(-)
24
delete mode 100644 include/hw/pcmcia.h
25
delete mode 100644 hw/pcmcia/pcmcia.c
26
delete mode 100644 hw/pcmcia/Kconfig
27
delete mode 100644 hw/pcmcia/meson.build
28
15
29
diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
30
deleted file mode 100644
17
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX
18
--- a/fpu/softfloat-parts.c.inc
32
--- a/include/hw/pcmcia.h
19
+++ b/fpu/softfloat-parts.c.inc
33
+++ /dev/null
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
34
@@ -XXX,XX +XXX,XX @@
21
}
35
-#ifndef HW_PCMCIA_H
22
36
-#define HW_PCMCIA_H
23
if (s->default_nan_mode) {
24
+ /*
25
+ * We guarantee not to require the target to tell us how to
26
+ * pick a NaN if we're always returning the default NaN.
27
+ * But if we're not in default-NaN mode then the target must
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,
75
}
76
}
77
78
-/*----------------------------------------------------------------------------
79
-| Select which NaN to propagate for a three-input operation.
80
-| For the moment we assume that no CPU needs the 'larger significand'
81
-| information.
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
83
-*----------------------------------------------------------------------------*/
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
85
- bool infzero, bool have_snan, float_status *status)
86
-{
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
89
- int which;
37
-
90
-
38
-/* PCMCIA/Cardbus */
91
- /*
92
- * We guarantee not to require the target to tell us how to
93
- * pick a NaN if we're always returning the default NaN.
94
- * But if we're not in default-NaN mode then the target must
95
- * specify.
96
- */
97
- assert(!status->default_nan_mode);
39
-
98
-
40
-#include "hw/qdev-core.h"
99
- if (infzero) {
41
-#include "qom/object.h"
100
- /*
101
- * Inf * 0 + NaN -- some implementations return the default NaN here,
102
- * and some return the input NaN.
103
- */
104
- switch (status->float_infzeronan_rule) {
105
- case float_infzeronan_dnan_never:
106
- return 2;
107
- case float_infzeronan_dnan_always:
108
- return 3;
109
- case float_infzeronan_dnan_if_qnan:
110
- return is_qnan(c_cls) ? 3 : 2;
111
- default:
112
- g_assert_not_reached();
113
- }
114
- }
42
-
115
-
43
-typedef struct PCMCIASocket {
116
- assert(rule != float_3nan_prop_none);
44
- qemu_irq irq;
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
45
- bool attached;
118
- /* We have at least one SNaN input and should prefer it */
46
-} PCMCIASocket;
119
- do {
47
-
120
- which = rule & R_3NAN_1ST_MASK;
48
-#define TYPE_PCMCIA_CARD "pcmcia-card"
121
- rule >>= R_3NAN_1ST_LENGTH;
49
-OBJECT_DECLARE_TYPE(PCMCIACardState, PCMCIACardClass, PCMCIA_CARD)
122
- } while (!is_snan(cls[which]));
50
-
123
- } else {
51
-struct PCMCIACardState {
124
- do {
52
- /*< private >*/
125
- which = rule & R_3NAN_1ST_MASK;
53
- DeviceState parent_obj;
126
- rule >>= R_3NAN_1ST_LENGTH;
54
- /*< public >*/
127
- } while (!is_nan(cls[which]));
55
-
128
- }
56
- PCMCIASocket *slot;
129
- return which;
57
-};
58
-
59
-struct PCMCIACardClass {
60
- /*< private >*/
61
- DeviceClass parent_class;
62
- /*< public >*/
63
-
64
- int (*attach)(PCMCIACardState *state);
65
- int (*detach)(PCMCIACardState *state);
66
-
67
- const uint8_t *cis;
68
- int cis_len;
69
-
70
- /* Only valid if attached */
71
- uint8_t (*attr_read)(PCMCIACardState *card, uint32_t address);
72
- void (*attr_write)(PCMCIACardState *card, uint32_t address, uint8_t value);
73
- uint16_t (*common_read)(PCMCIACardState *card, uint32_t address);
74
- void (*common_write)(PCMCIACardState *card,
75
- uint32_t address, uint16_t value);
76
- uint16_t (*io_read)(PCMCIACardState *card, uint32_t address);
77
- void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value);
78
-};
79
-
80
-#define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */
81
-#define CISTPL_NO_LINK 0x14 /* No Link Tuple */
82
-#define CISTPL_VERS_1 0x15 /* Level 1 Version Tuple */
83
-#define CISTPL_JEDEC_C 0x18 /* JEDEC ID Tuple */
84
-#define CISTPL_JEDEC_A 0x19 /* JEDEC ID Tuple */
85
-#define CISTPL_CONFIG 0x1a /* Configuration Tuple */
86
-#define CISTPL_CFTABLE_ENTRY 0x1b /* 16-bit PCCard Configuration */
87
-#define CISTPL_DEVICE_OC 0x1c /* Additional Device Information */
88
-#define CISTPL_DEVICE_OA 0x1d /* Additional Device Information */
89
-#define CISTPL_DEVICE_GEO 0x1e /* Additional Device Information */
90
-#define CISTPL_DEVICE_GEO_A 0x1f /* Additional Device Information */
91
-#define CISTPL_MANFID 0x20 /* Manufacture ID Tuple */
92
-#define CISTPL_FUNCID 0x21 /* Function ID Tuple */
93
-#define CISTPL_FUNCE 0x22 /* Function Extension Tuple */
94
-#define CISTPL_END 0xff /* Tuple End */
95
-#define CISTPL_ENDMARK 0xff
96
-
97
-#endif
98
diff --git a/hw/pcmcia/pcmcia.c b/hw/pcmcia/pcmcia.c
99
deleted file mode 100644
100
index XXXXXXX..XXXXXXX
101
--- a/hw/pcmcia/pcmcia.c
102
+++ /dev/null
103
@@ -XXX,XX +XXX,XX @@
104
-/*
105
- * PCMCIA emulation
106
- *
107
- * Copyright 2013 SUSE LINUX Products GmbH
108
- */
109
-
110
-#include "qemu/osdep.h"
111
-#include "qemu/module.h"
112
-#include "hw/pcmcia.h"
113
-
114
-static const TypeInfo pcmcia_card_type_info = {
115
- .name = TYPE_PCMCIA_CARD,
116
- .parent = TYPE_DEVICE,
117
- .instance_size = sizeof(PCMCIACardState),
118
- .abstract = true,
119
- .class_size = sizeof(PCMCIACardClass),
120
-};
121
-
122
-static void pcmcia_register_types(void)
123
-{
124
- type_register_static(&pcmcia_card_type_info);
125
-}
130
-}
126
-
131
-
127
-type_init(pcmcia_register_types)
132
/*----------------------------------------------------------------------------
128
diff --git a/hw/Kconfig b/hw/Kconfig
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
129
index XXXXXXX..XXXXXXX 100644
134
| NaN; otherwise returns 0.
130
--- a/hw/Kconfig
131
+++ b/hw/Kconfig
132
@@ -XXX,XX +XXX,XX @@ source nvme/Kconfig
133
source nvram/Kconfig
134
source pci-bridge/Kconfig
135
source pci-host/Kconfig
136
-source pcmcia/Kconfig
137
source pci/Kconfig
138
source remote/Kconfig
139
source rtc/Kconfig
140
diff --git a/hw/meson.build b/hw/meson.build
141
index XXXXXXX..XXXXXXX 100644
142
--- a/hw/meson.build
143
+++ b/hw/meson.build
144
@@ -XXX,XX +XXX,XX @@ subdir('nvram')
145
subdir('pci')
146
subdir('pci-bridge')
147
subdir('pci-host')
148
-subdir('pcmcia')
149
subdir('rtc')
150
subdir('scsi')
151
subdir('sd')
152
diff --git a/hw/pcmcia/Kconfig b/hw/pcmcia/Kconfig
153
deleted file mode 100644
154
index XXXXXXX..XXXXXXX
155
--- a/hw/pcmcia/Kconfig
156
+++ /dev/null
157
@@ -XXX,XX +XXX,XX @@
158
-config PCMCIA
159
- bool
160
diff --git a/hw/pcmcia/meson.build b/hw/pcmcia/meson.build
161
deleted file mode 100644
162
index XXXXXXX..XXXXXXX
163
--- a/hw/pcmcia/meson.build
164
+++ /dev/null
165
@@ -1 +0,0 @@
166
-system_ss.add(when: 'CONFIG_PCMCIA', if_true: files('pcmcia.c'))
167
--
135
--
168
2.34.1
136
2.34.1
169
137
170
138
diff view generated by jsdifflib
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Expose the clock period via the QOM 'qtest-clock-period' property so it
3
Remove "3" as a special case for which and simply
4
can be used in QTests. This property is only accessible in QTests (not
4
branch to return the desired value.
5
via HMP).
6
5
7
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20241003081105.40836-3-ines.varhol@telecom-paris.fr
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
docs/devel/clocks.rst | 6 ++++++
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
15
hw/core/clock.c | 16 ++++++++++++++++
12
1 file changed, 10 insertions(+), 10 deletions(-)
16
2 files changed, 22 insertions(+)
17
13
18
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
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/docs/devel/clocks.rst
16
--- a/fpu/softfloat-parts.c.inc
21
+++ b/docs/devel/clocks.rst
17
+++ b/fpu/softfloat-parts.c.inc
22
@@ -XXX,XX +XXX,XX @@ humans (for instance in debugging), use ``clock_display_freq()``,
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
23
which returns a prettified string-representation, e.g. "33.3 MHz".
19
* But if we're not in default-NaN mode then the target must
24
The caller must free the string with g_free() after use.
20
* specify.
25
21
*/
26
+It's also possible to retrieve the clock period from a QTest by
22
- which = 3;
27
+accessing QOM property ``qtest-clock-period`` using a QMP command.
23
+ goto default_nan;
28
+This property is only present when the device is being run under
24
} else if (infzero) {
29
+the ``qtest`` accelerator; it is not available when QEMU is
25
/*
30
+being run normally.
26
* Inf * 0 + NaN -- some implementations return the
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
28
*/
29
switch (s->float_infzeronan_rule) {
30
case float_infzeronan_dnan_never:
31
- which = 2;
32
break;
33
case float_infzeronan_dnan_always:
34
- which = 3;
35
- break;
36
+ goto default_nan;
37
case float_infzeronan_dnan_if_qnan:
38
- which = is_qnan(c->cls) ? 3 : 2;
39
+ if (is_qnan(c->cls)) {
40
+ goto default_nan;
41
+ }
42
break;
43
default:
44
g_assert_not_reached();
45
}
46
+ which = 2;
47
} else {
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
51
}
52
}
53
54
- if (which == 3) {
55
- parts_default_nan(a, s);
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;
31
+
66
+
32
Calculating expiry deadlines
67
+ default_nan:
33
----------------------------
68
+ parts_default_nan(a, s);
34
69
+ return a;
35
diff --git a/hw/core/clock.c b/hw/core/clock.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/core/clock.c
38
+++ b/hw/core/clock.c
39
@@ -XXX,XX +XXX,XX @@
40
41
#include "qemu/osdep.h"
42
#include "qemu/cutils.h"
43
+#include "qapi/visitor.h"
44
+#include "sysemu/qtest.h"
45
#include "hw/clock.h"
46
#include "trace.h"
47
48
@@ -XXX,XX +XXX,XX @@ bool clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider)
49
return true;
50
}
70
}
51
71
52
+static void clock_period_prop_get(Object *obj, Visitor *v, const char *name,
72
/*
53
+ void *opaque, Error **errp)
54
+{
55
+ Clock *clk = CLOCK(obj);
56
+ uint64_t period = clock_get(clk);
57
+ visit_type_uint64(v, name, &period, errp);
58
+}
59
+
60
+
61
static void clock_initfn(Object *obj)
62
{
63
Clock *clk = CLOCK(obj);
64
@@ -XXX,XX +XXX,XX @@ static void clock_initfn(Object *obj)
65
clk->divider = 1;
66
67
QLIST_INIT(&clk->children);
68
+
69
+ if (qtest_enabled()) {
70
+ object_property_add(obj, "qtest-clock-period", "uint64",
71
+ clock_period_prop_get, NULL, NULL, NULL);
72
+ }
73
}
74
75
static void clock_finalizefn(Object *obj)
76
--
73
--
77
2.34.1
74
2.34.1
78
75
79
76
diff view generated by jsdifflib
1
From: Román Cárdenas Rodríguez <rcardenas.rod@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add the reset and clock controller device to the stm32f405 SoC.
3
Assign the pointer return value to 'a' directly,
4
rather than going through an intermediary index.
4
5
5
Signed-off-by: Roman Cardenas Rodriguez <rcardenas.rod@gmail.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
[PMM: tweak commit message]
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
docs/system/arm/stm32.rst | 3 ++-
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
11
include/hw/arm/stm32f405_soc.h | 2 ++
12
1 file changed, 10 insertions(+), 22 deletions(-)
12
hw/arm/stm32f405_soc.c | 12 +++++++++++-
13
hw/arm/Kconfig | 1 +
14
4 files changed, 16 insertions(+), 2 deletions(-)
15
13
16
diff --git a/docs/system/arm/stm32.rst b/docs/system/arm/stm32.rst
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/system/arm/stm32.rst
16
--- a/fpu/softfloat-parts.c.inc
19
+++ b/docs/system/arm/stm32.rst
17
+++ b/fpu/softfloat-parts.c.inc
20
@@ -XXX,XX +XXX,XX @@ Supported devices
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
* SPI controller
19
FloatPartsN *c, float_status *s,
22
* System configuration (SYSCFG)
20
int ab_mask, int abc_mask)
23
* Timer controller (TIMER)
21
{
24
+ * Reset and Clock Controller (RCC) (STM32F4 only, reset and enable only)
22
- int which;
25
23
bool infzero = (ab_mask == float_cmask_infzero);
26
Missing devices
24
bool have_snan = (abc_mask & float_cmask_snan);
27
---------------
25
+ FloatPartsN *ret;
28
@@ -XXX,XX +XXX,XX @@ Missing devices
26
29
* Power supply configuration (PWR)
27
if (unlikely(have_snan)) {
30
* Random Number Generator (RNG)
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
31
* Real-Time Clock (RTC) controller
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
32
- * Reset and Clock Controller (RCC)
30
default:
33
+ * Reset and Clock Controller (RCC) (other features than reset and enable)
31
g_assert_not_reached();
34
* Secure Digital Input/Output (SDIO) interface
32
}
35
* USB OTG
33
- which = 2;
36
* Watchdog controller (IWDG, WWDG)
34
+ ret = c;
37
diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
35
} else {
38
index XXXXXXX..XXXXXXX 100644
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
39
--- a/include/hw/arm/stm32f405_soc.h
37
+ FloatPartsN *val[3] = { a, b, c };
40
+++ b/include/hw/arm/stm32f405_soc.h
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
41
@@ -XXX,XX +XXX,XX @@
39
42
#ifndef HW_ARM_STM32F405_SOC_H
40
assert(rule != float_3nan_prop_none);
43
#define HW_ARM_STM32F405_SOC_H
41
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
44
42
/* We have at least one SNaN input and should prefer it */
45
+#include "hw/misc/stm32_rcc.h"
43
do {
46
#include "hw/misc/stm32f4xx_syscfg.h"
44
- which = rule & R_3NAN_1ST_MASK;
47
#include "hw/timer/stm32f2xx_timer.h"
45
+ ret = val[rule & R_3NAN_1ST_MASK];
48
#include "hw/char/stm32f2xx_usart.h"
46
rule >>= R_3NAN_1ST_LENGTH;
49
@@ -XXX,XX +XXX,XX @@ struct STM32F405State {
47
- } while (!is_snan(cls[which]));
50
48
+ } while (!is_snan(ret->cls));
51
ARMv7MState armv7m;
49
} else {
52
50
do {
53
+ STM32RccState rcc;
51
- which = rule & R_3NAN_1ST_MASK;
54
STM32F4xxSyscfgState syscfg;
52
+ ret = val[rule & R_3NAN_1ST_MASK];
55
STM32F4xxExtiState exti;
53
rule >>= R_3NAN_1ST_LENGTH;
56
STM32F2XXUsartState usart[STM_NUM_USARTS];
54
- } while (!is_nan(cls[which]));
57
diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
55
+ } while (!is_nan(ret->cls));
58
index XXXXXXX..XXXXXXX 100644
56
}
59
--- a/hw/arm/stm32f405_soc.c
60
+++ b/hw/arm/stm32f405_soc.c
61
@@ -XXX,XX +XXX,XX @@
62
#include "hw/qdev-clock.h"
63
#include "hw/misc/unimp.h"
64
65
+#define RCC_ADDR 0x40023800
66
#define SYSCFG_ADD 0x40013800
67
static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
68
0x40004C00, 0x40005000, 0x40011400,
69
@@ -XXX,XX +XXX,XX @@ static void stm32f405_soc_initfn(Object *obj)
70
71
object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M);
72
73
+ object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32_RCC);
74
+
75
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32F4XX_SYSCFG);
76
77
for (i = 0; i < STM_NUM_USARTS; i++) {
78
@@ -XXX,XX +XXX,XX @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
79
return;
80
}
57
}
81
58
82
+ /* Reset and clock controller */
59
- switch (which) {
83
+ dev = DEVICE(&s->rcc);
60
- case 0:
84
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->rcc), errp)) {
61
- break;
85
+ return;
62
- case 1:
86
+ }
63
- a = b;
87
+ busdev = SYS_BUS_DEVICE(dev);
64
- break;
88
+ sysbus_mmio_map(busdev, 0, RCC_ADDR);
65
- case 2:
89
+
66
- a = c;
90
/* System configuration controller */
67
- break;
91
dev = DEVICE(&s->syscfg);
68
- default:
92
if (!sysbus_realize(SYS_BUS_DEVICE(&s->syscfg), errp)) {
69
- g_assert_not_reached();
93
@@ -XXX,XX +XXX,XX @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
70
+ if (is_snan(ret->cls)) {
94
create_unimplemented_device("GPIOH", 0x40021C00, 0x400);
71
+ parts_silence_nan(ret, s);
95
create_unimplemented_device("GPIOI", 0x40022000, 0x400);
72
}
96
create_unimplemented_device("CRC", 0x40023000, 0x400);
73
- if (is_snan(a->cls)) {
97
- create_unimplemented_device("RCC", 0x40023800, 0x400);
74
- parts_silence_nan(a, s);
98
create_unimplemented_device("Flash Int", 0x40023C00, 0x400);
75
- }
99
create_unimplemented_device("BKPSRAM", 0x40024000, 0x400);
76
- return a;
100
create_unimplemented_device("DMA1", 0x40026000, 0x400);
77
+ return ret;
101
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
78
102
index XXXXXXX..XXXXXXX 100644
79
default_nan:
103
--- a/hw/arm/Kconfig
80
parts_default_nan(a, s);
104
+++ b/hw/arm/Kconfig
105
@@ -XXX,XX +XXX,XX @@ config STM32F405_SOC
106
bool
107
select ARM_V7M
108
select OR_IRQ
109
+ select STM32_RCC
110
select STM32F4XX_SYSCFG
111
select STM32F4XX_EXTI
112
113
--
81
--
114
2.34.1
82
2.34.1
115
83
116
84
diff view generated by jsdifflib
1
In commit b88cfee90268cad we defined masks for the IBRD and FBRD
1
From: Richard Henderson <richard.henderson@linaro.org>
2
integer and fractional baud rate divider registers, to prevent the
3
guest from writing invalid values which could cause division-by-zero.
4
Unfortunately we got the mask values the wrong way around: the FBRD
5
register is six bits and the IBRD register is 16 bits, not
6
vice-versa.
7
2
8
You would only run into this bug if you programmed the UART to a baud
3
While all indices into val[] should be in [0-2], the mask
9
rate of less than 9600, because for 9600 baud and above the IBRD
4
applied is two bits. To help static analysis see there is
10
value will fit into 6 bits, as per the table in
5
no possibility of read beyond the end of the array, pad the
11
https://developer.arm.com/documentation/ddi0183/g/programmers-model/register-descriptions/fractional-baud-rate-register--uartfbrd
6
array to 4 entries, with the final being (implicitly) NULL.
12
7
13
The only visible effects would be that the value read back from
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
the register by the guest would be truncated, and we would
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
print an incorrect baud rate in the debug logs.
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
fpu/softfloat-parts.c.inc | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
16
15
17
Cc: qemu-stable@nongnu.org
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
Fixes: b88cfee90268 ("hw/char/pl011: Avoid division-by-zero in pl011_get_baudrate()")
19
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2610
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
23
Reviewed-by: Gavin Shan <gshan@redhat.com>
24
Message-id: 20241007144732.2491331-1-peter.maydell@linaro.org
25
---
26
hw/char/pl011.c | 4 ++--
27
1 file changed, 2 insertions(+), 2 deletions(-)
28
29
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
30
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/char/pl011.c
18
--- a/fpu/softfloat-parts.c.inc
32
+++ b/hw/char/pl011.c
19
+++ b/fpu/softfloat-parts.c.inc
33
@@ -XXX,XX +XXX,XX @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
34
#define CR_UARTEN (1 << 0)
21
}
35
22
ret = c;
36
/* Integer Baud Rate Divider, UARTIBRD */
23
} else {
37
-#define IBRD_MASK 0x3f
24
- FloatPartsN *val[3] = { a, b, c };
38
+#define IBRD_MASK 0xffff
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
39
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
40
/* Fractional Baud Rate Divider, UARTFBRD */
27
41
-#define FBRD_MASK 0xffff
28
assert(rule != float_3nan_prop_none);
42
+#define FBRD_MASK 0x3f
43
44
static const unsigned char pl011_id_arm[8] =
45
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
46
--
29
--
47
2.34.1
30
2.34.1
48
31
49
32
diff view generated by jsdifflib
1
The DSCM-1XXXX microdrive device model was used only by the
1
From: Richard Henderson <richard.henderson@linaro.org>
2
XScale-based Zaurus machine types. Now they have been removed, we
3
can delete this device too.
4
2
3
This function is part of the public interface and
4
is not "specialized" to any target in any way.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-7-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241003140010.1653808-4-peter.maydell@linaro.org
9
---
10
---
10
include/hw/pcmcia.h | 3 -
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
11
hw/ide/microdrive.c | 644 --------------------------------------------
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
12
hw/ide/Kconfig | 6 -
13
2 files changed, 52 insertions(+), 52 deletions(-)
13
hw/ide/meson.build | 1 -
14
4 files changed, 654 deletions(-)
15
delete mode 100644 hw/ide/microdrive.c
16
14
17
diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/pcmcia.h
17
--- a/fpu/softfloat.c
20
+++ b/include/hw/pcmcia.h
18
+++ b/fpu/softfloat.c
21
@@ -XXX,XX +XXX,XX @@ struct PCMCIACardClass {
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
22
#define CISTPL_END 0xff /* Tuple End */
20
*zExpPtr = 1 - shiftCount;
23
#define CISTPL_ENDMARK 0xff
21
}
24
22
25
-/* dscm1xxxx.c */
23
+/*----------------------------------------------------------------------------
26
-PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv);
24
+| Takes two extended double-precision floating-point values `a' and `b', one
25
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
26
+| `b' is a signaling NaN, the invalid exception is raised.
27
+*----------------------------------------------------------------------------*/
28
+
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
30
+{
31
+ bool aIsLargerSignificand;
32
+ FloatClass a_cls, b_cls;
33
+
34
+ /* This is not complete, but is good enough for pickNaN. */
35
+ a_cls = (!floatx80_is_any_nan(a)
36
+ ? float_class_normal
37
+ : floatx80_is_signaling_nan(a, status)
38
+ ? float_class_snan
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);
45
+
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
47
+ float_raise(float_flag_invalid, status);
48
+ }
49
+
50
+ if (status->default_nan_mode) {
51
+ return floatx80_default_nan(status);
52
+ }
53
+
54
+ if (a.low < b.low) {
55
+ aIsLargerSignificand = 0;
56
+ } else if (b.low < a.low) {
57
+ aIsLargerSignificand = 1;
58
+ } else {
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
60
+ }
61
+
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
63
+ if (is_snan(b_cls)) {
64
+ return floatx80_silence_nan(b, status);
65
+ }
66
+ return b;
67
+ } else {
68
+ if (is_snan(a_cls)) {
69
+ return floatx80_silence_nan(a, status);
70
+ }
71
+ return a;
72
+ }
73
+}
74
+
75
/*----------------------------------------------------------------------------
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
79
index XXXXXXX..XXXXXXX 100644
80
--- a/fpu/softfloat-specialize.c.inc
81
+++ b/fpu/softfloat-specialize.c.inc
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
83
return a;
84
}
85
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
-*----------------------------------------------------------------------------*/
27
-
91
-
28
#endif
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
29
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
93
-{
30
deleted file mode 100644
94
- bool aIsLargerSignificand;
31
index XXXXXXX..XXXXXXX
95
- FloatClass a_cls, b_cls;
32
--- a/hw/ide/microdrive.c
33
+++ /dev/null
34
@@ -XXX,XX +XXX,XX @@
35
-/*
36
- * QEMU IDE Emulation: microdrive (CF / PCMCIA)
37
- *
38
- * Copyright (c) 2003 Fabrice Bellard
39
- * Copyright (c) 2006 Openedhand Ltd.
40
- *
41
- * Permission is hereby granted, free of charge, to any person obtaining a copy
42
- * of this software and associated documentation files (the "Software"), to deal
43
- * in the Software without restriction, including without limitation the rights
44
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
- * copies of the Software, and to permit persons to whom the Software is
46
- * furnished to do so, subject to the following conditions:
47
- *
48
- * The above copyright notice and this permission notice shall be included in
49
- * all copies or substantial portions of the Software.
50
- *
51
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
54
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
- * THE SOFTWARE.
58
- */
59
-
96
-
60
-#include "qemu/osdep.h"
97
- /* This is not complete, but is good enough for pickNaN. */
61
-#include "hw/pcmcia.h"
98
- a_cls = (!floatx80_is_any_nan(a)
62
-#include "migration/vmstate.h"
99
- ? float_class_normal
63
-#include "qapi/error.h"
100
- : floatx80_is_signaling_nan(a, status)
64
-#include "qemu/module.h"
101
- ? float_class_snan
65
-#include "sysemu/dma.h"
102
- : float_class_qnan);
66
-#include "hw/irq.h"
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);
67
-
108
-
68
-#include "qom/object.h"
109
- if (is_snan(a_cls) || is_snan(b_cls)) {
69
-#include "ide-internal.h"
110
- float_raise(float_flag_invalid, status);
70
-
71
-#define TYPE_MICRODRIVE "microdrive"
72
-OBJECT_DECLARE_SIMPLE_TYPE(MicroDriveState, MICRODRIVE)
73
-
74
-/***********************************************************/
75
-/* CF-ATA Microdrive */
76
-
77
-#define METADATA_SIZE 0x20
78
-
79
-/* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */
80
-
81
-struct MicroDriveState {
82
- /*< private >*/
83
- PCMCIACardState parent_obj;
84
- /*< public >*/
85
-
86
- IDEBus bus;
87
- uint32_t attr_base;
88
- uint32_t io_base;
89
-
90
- /* Card state */
91
- uint8_t opt;
92
- uint8_t stat;
93
- uint8_t pins;
94
-
95
- uint8_t ctrl;
96
- uint16_t io;
97
- uint8_t cycle;
98
-};
99
-
100
-/* Register bitfields */
101
-enum md_opt {
102
- OPT_MODE_MMAP = 0,
103
- OPT_MODE_IOMAP16 = 1,
104
- OPT_MODE_IOMAP1 = 2,
105
- OPT_MODE_IOMAP2 = 3,
106
- OPT_MODE = 0x3f,
107
- OPT_LEVIREQ = 0x40,
108
- OPT_SRESET = 0x80,
109
-};
110
-enum md_cstat {
111
- STAT_INT = 0x02,
112
- STAT_PWRDWN = 0x04,
113
- STAT_XE = 0x10,
114
- STAT_IOIS8 = 0x20,
115
- STAT_SIGCHG = 0x40,
116
- STAT_CHANGED = 0x80,
117
-};
118
-enum md_pins {
119
- PINS_MRDY = 0x02,
120
- PINS_CRDY = 0x20,
121
-};
122
-enum md_ctrl {
123
- CTRL_IEN = 0x02,
124
- CTRL_SRST = 0x04,
125
-};
126
-
127
-static inline void md_interrupt_update(MicroDriveState *s)
128
-{
129
- PCMCIACardState *card = PCMCIA_CARD(s);
130
-
131
- if (card->slot == NULL) {
132
- return;
133
- }
111
- }
134
-
112
-
135
- qemu_set_irq(card->slot->irq,
113
- if (status->default_nan_mode) {
136
- !(s->stat & STAT_INT) && /* Inverted */
114
- return floatx80_default_nan(status);
137
- !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
138
- !(s->opt & OPT_SRESET));
139
-}
140
-
141
-static void md_set_irq(void *opaque, int irq, int level)
142
-{
143
- MicroDriveState *s = opaque;
144
-
145
- if (level) {
146
- s->stat |= STAT_INT;
147
- } else {
148
- s->stat &= ~STAT_INT;
149
- }
115
- }
150
-
116
-
151
- md_interrupt_update(s);
117
- if (a.low < b.low) {
152
-}
118
- aIsLargerSignificand = 0;
153
-
119
- } else if (b.low < a.low) {
154
-static void md_reset(DeviceState *dev)
120
- aIsLargerSignificand = 1;
155
-{
121
- } else {
156
- MicroDriveState *s = MICRODRIVE(dev);
122
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
157
-
158
- s->opt = OPT_MODE_MMAP;
159
- s->stat = 0;
160
- s->pins = 0;
161
- s->cycle = 0;
162
- s->ctrl = 0;
163
- ide_bus_reset(&s->bus);
164
-}
165
-
166
-static uint8_t md_attr_read(PCMCIACardState *card, uint32_t at)
167
-{
168
- MicroDriveState *s = MICRODRIVE(card);
169
- PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
170
-
171
- if (at < s->attr_base) {
172
- if (at < pcc->cis_len) {
173
- return pcc->cis[at];
174
- } else {
175
- return 0x00;
176
- }
177
- }
123
- }
178
-
124
-
179
- at -= s->attr_base;
125
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
180
-
126
- if (is_snan(b_cls)) {
181
- switch (at) {
127
- return floatx80_silence_nan(b, status);
182
- case 0x00: /* Configuration Option Register */
183
- return s->opt;
184
- case 0x02: /* Card Configuration Status Register */
185
- if (s->ctrl & CTRL_IEN) {
186
- return s->stat & ~STAT_INT;
187
- } else {
188
- return s->stat;
189
- }
128
- }
190
- case 0x04: /* Pin Replacement Register */
129
- return b;
191
- return (s->pins & PINS_CRDY) | 0x0c;
130
- } else {
192
- case 0x06: /* Socket and Copy Register */
131
- if (is_snan(a_cls)) {
193
- return 0x00;
132
- return floatx80_silence_nan(a, status);
194
-#ifdef VERBOSE
195
- default:
196
- printf("%s: Bad attribute space register %02x\n", __func__, at);
197
-#endif
198
- }
199
-
200
- return 0;
201
-}
202
-
203
-static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
204
-{
205
- MicroDriveState *s = MICRODRIVE(card);
206
-
207
- at -= s->attr_base;
208
-
209
- switch (at) {
210
- case 0x00: /* Configuration Option Register */
211
- s->opt = value & 0xcf;
212
- if (value & OPT_SRESET) {
213
- device_cold_reset(DEVICE(s));
214
- }
133
- }
215
- md_interrupt_update(s);
134
- return a;
216
- break;
217
- case 0x02: /* Card Configuration Status Register */
218
- if ((s->stat ^ value) & STAT_PWRDWN) {
219
- s->pins |= PINS_CRDY;
220
- }
221
- s->stat &= 0x82;
222
- s->stat |= value & 0x74;
223
- md_interrupt_update(s);
224
- /* Word 170 in Identify Device must be equal to STAT_XE */
225
- break;
226
- case 0x04: /* Pin Replacement Register */
227
- s->pins &= PINS_CRDY;
228
- s->pins |= value & PINS_MRDY;
229
- break;
230
- case 0x06: /* Socket and Copy Register */
231
- break;
232
- default:
233
- printf("%s: Bad attribute space register %02x\n", __func__, at);
234
- }
135
- }
235
-}
136
-}
236
-
137
-
237
-static uint16_t md_common_read(PCMCIACardState *card, uint32_t at)
138
/*----------------------------------------------------------------------------
238
-{
139
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
239
- MicroDriveState *s = MICRODRIVE(card);
140
| NaN; otherwise returns 0.
240
- IDEState *ifs;
241
- uint16_t ret;
242
- at -= s->io_base;
243
-
244
- switch (s->opt & OPT_MODE) {
245
- case OPT_MODE_MMAP:
246
- if ((at & ~0x3ff) == 0x400) {
247
- at = 0;
248
- }
249
- break;
250
- case OPT_MODE_IOMAP16:
251
- at &= 0xf;
252
- break;
253
- case OPT_MODE_IOMAP1:
254
- if ((at & ~0xf) == 0x3f0) {
255
- at -= 0x3e8;
256
- } else if ((at & ~0xf) == 0x1f0) {
257
- at -= 0x1f0;
258
- }
259
- break;
260
- case OPT_MODE_IOMAP2:
261
- if ((at & ~0xf) == 0x370) {
262
- at -= 0x368;
263
- } else if ((at & ~0xf) == 0x170) {
264
- at -= 0x170;
265
- }
266
- }
267
-
268
- switch (at) {
269
- case 0x0: /* Even RD Data */
270
- case 0x8:
271
- return ide_data_readw(&s->bus, 0);
272
-
273
- /* TODO: 8-bit accesses */
274
- if (s->cycle) {
275
- ret = s->io >> 8;
276
- } else {
277
- s->io = ide_data_readw(&s->bus, 0);
278
- ret = s->io & 0xff;
279
- }
280
- s->cycle = !s->cycle;
281
- return ret;
282
- case 0x9: /* Odd RD Data */
283
- return s->io >> 8;
284
- case 0xd: /* Error */
285
- return ide_ioport_read(&s->bus, 0x1);
286
- case 0xe: /* Alternate Status */
287
- ifs = ide_bus_active_if(&s->bus);
288
- if (ifs->blk) {
289
- return ifs->status;
290
- } else {
291
- return 0;
292
- }
293
- case 0xf: /* Device Address */
294
- ifs = ide_bus_active_if(&s->bus);
295
- return 0xc2 | ((~ifs->select << 2) & 0x3c);
296
- default:
297
- return ide_ioport_read(&s->bus, at);
298
- }
299
-
300
- return 0;
301
-}
302
-
303
-static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
304
-{
305
- MicroDriveState *s = MICRODRIVE(card);
306
- at -= s->io_base;
307
-
308
- switch (s->opt & OPT_MODE) {
309
- case OPT_MODE_MMAP:
310
- if ((at & ~0x3ff) == 0x400) {
311
- at = 0;
312
- }
313
- break;
314
- case OPT_MODE_IOMAP16:
315
- at &= 0xf;
316
- break;
317
- case OPT_MODE_IOMAP1:
318
- if ((at & ~0xf) == 0x3f0) {
319
- at -= 0x3e8;
320
- } else if ((at & ~0xf) == 0x1f0) {
321
- at -= 0x1f0;
322
- }
323
- break;
324
- case OPT_MODE_IOMAP2:
325
- if ((at & ~0xf) == 0x370) {
326
- at -= 0x368;
327
- } else if ((at & ~0xf) == 0x170) {
328
- at -= 0x170;
329
- }
330
- }
331
-
332
- switch (at) {
333
- case 0x0: /* Even WR Data */
334
- case 0x8:
335
- ide_data_writew(&s->bus, 0, value);
336
- break;
337
-
338
- /* TODO: 8-bit accesses */
339
- if (s->cycle) {
340
- ide_data_writew(&s->bus, 0, s->io | (value << 8));
341
- } else {
342
- s->io = value & 0xff;
343
- }
344
- s->cycle = !s->cycle;
345
- break;
346
- case 0x9:
347
- s->io = value & 0xff;
348
- s->cycle = !s->cycle;
349
- break;
350
- case 0xd: /* Features */
351
- ide_ioport_write(&s->bus, 0x1, value);
352
- break;
353
- case 0xe: /* Device Control */
354
- s->ctrl = value;
355
- if (value & CTRL_SRST) {
356
- device_cold_reset(DEVICE(s));
357
- }
358
- md_interrupt_update(s);
359
- break;
360
- default:
361
- if (s->stat & STAT_PWRDWN) {
362
- s->pins |= PINS_CRDY;
363
- s->stat &= ~STAT_PWRDWN;
364
- }
365
- ide_ioport_write(&s->bus, at, value);
366
- }
367
-}
368
-
369
-static const VMStateDescription vmstate_microdrive = {
370
- .name = "microdrive",
371
- .version_id = 3,
372
- .minimum_version_id = 0,
373
- .fields = (const VMStateField[]) {
374
- VMSTATE_UINT8(opt, MicroDriveState),
375
- VMSTATE_UINT8(stat, MicroDriveState),
376
- VMSTATE_UINT8(pins, MicroDriveState),
377
- VMSTATE_UINT8(ctrl, MicroDriveState),
378
- VMSTATE_UINT16(io, MicroDriveState),
379
- VMSTATE_UINT8(cycle, MicroDriveState),
380
- VMSTATE_IDE_BUS(bus, MicroDriveState),
381
- VMSTATE_IDE_DRIVES(bus.ifs, MicroDriveState),
382
- VMSTATE_END_OF_LIST()
383
- }
384
-};
385
-
386
-static const uint8_t dscm1xxxx_cis[0x14a] = {
387
- [0x000] = CISTPL_DEVICE, /* 5V Device Information */
388
- [0x002] = 0x03, /* Tuple length = 4 bytes */
389
- [0x004] = 0xdb, /* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
390
- [0x006] = 0x01, /* Size = 2K bytes */
391
- [0x008] = CISTPL_ENDMARK,
392
-
393
- [0x00a] = CISTPL_DEVICE_OC, /* Additional Device Information */
394
- [0x00c] = 0x04, /* Tuple length = 4 byest */
395
- [0x00e] = 0x03, /* Conditions: Ext = 0, Vcc 3.3V, MWAIT = 1 */
396
- [0x010] = 0xdb, /* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
397
- [0x012] = 0x01, /* Size = 2K bytes */
398
- [0x014] = CISTPL_ENDMARK,
399
-
400
- [0x016] = CISTPL_JEDEC_C, /* JEDEC ID */
401
- [0x018] = 0x02, /* Tuple length = 2 bytes */
402
- [0x01a] = 0xdf, /* PC Card ATA with no Vpp required */
403
- [0x01c] = 0x01,
404
-
405
- [0x01e] = CISTPL_MANFID, /* Manufacture ID */
406
- [0x020] = 0x04, /* Tuple length = 4 bytes */
407
- [0x022] = 0xa4, /* TPLMID_MANF = 00a4 (IBM) */
408
- [0x024] = 0x00,
409
- [0x026] = 0x00, /* PLMID_CARD = 0000 */
410
- [0x028] = 0x00,
411
-
412
- [0x02a] = CISTPL_VERS_1, /* Level 1 Version */
413
- [0x02c] = 0x12, /* Tuple length = 23 bytes */
414
- [0x02e] = 0x04, /* Major Version = JEIDA 4.2 / PCMCIA 2.1 */
415
- [0x030] = 0x01, /* Minor Version = 1 */
416
- [0x032] = 'I',
417
- [0x034] = 'B',
418
- [0x036] = 'M',
419
- [0x038] = 0x00,
420
- [0x03a] = 'm',
421
- [0x03c] = 'i',
422
- [0x03e] = 'c',
423
- [0x040] = 'r',
424
- [0x042] = 'o',
425
- [0x044] = 'd',
426
- [0x046] = 'r',
427
- [0x048] = 'i',
428
- [0x04a] = 'v',
429
- [0x04c] = 'e',
430
- [0x04e] = 0x00,
431
- [0x050] = CISTPL_ENDMARK,
432
-
433
- [0x052] = CISTPL_FUNCID, /* Function ID */
434
- [0x054] = 0x02, /* Tuple length = 2 bytes */
435
- [0x056] = 0x04, /* TPLFID_FUNCTION = Fixed Disk */
436
- [0x058] = 0x01, /* TPLFID_SYSINIT: POST = 1, ROM = 0 */
437
-
438
- [0x05a] = CISTPL_FUNCE, /* Function Extension */
439
- [0x05c] = 0x02, /* Tuple length = 2 bytes */
440
- [0x05e] = 0x01, /* TPLFE_TYPE = Disk Device Interface */
441
- [0x060] = 0x01, /* TPLFE_DATA = PC Card ATA Interface */
442
-
443
- [0x062] = CISTPL_FUNCE, /* Function Extension */
444
- [0x064] = 0x03, /* Tuple length = 3 bytes */
445
- [0x066] = 0x02, /* TPLFE_TYPE = Basic PC Card ATA Interface */
446
- [0x068] = 0x08, /* TPLFE_DATA: Rotating, Unique, Single */
447
- [0x06a] = 0x0f, /* TPLFE_DATA: Sleep, Standby, Idle, Auto */
448
-
449
- [0x06c] = CISTPL_CONFIG, /* Configuration */
450
- [0x06e] = 0x05, /* Tuple length = 5 bytes */
451
- [0x070] = 0x01, /* TPCC_RASZ = 2 bytes, TPCC_RMSZ = 1 byte */
452
- [0x072] = 0x07, /* TPCC_LAST = 7 */
453
- [0x074] = 0x00, /* TPCC_RADR = 0200 */
454
- [0x076] = 0x02,
455
- [0x078] = 0x0f, /* TPCC_RMSK = 200, 202, 204, 206 */
456
-
457
- [0x07a] = CISTPL_CFTABLE_ENTRY, /* 16-bit PC Card Configuration */
458
- [0x07c] = 0x0b, /* Tuple length = 11 bytes */
459
- [0x07e] = 0xc0, /* TPCE_INDX = Memory Mode, Default, Iface */
460
- [0x080] = 0xc0, /* TPCE_IF = Memory, no BVDs, no WP, READY */
461
- [0x082] = 0xa1, /* TPCE_FS = Vcc only, no I/O, Memory, Misc */
462
- [0x084] = 0x27, /* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
463
- [0x086] = 0x55, /* NomV: 5.0 V */
464
- [0x088] = 0x4d, /* MinV: 4.5 V */
465
- [0x08a] = 0x5d, /* MaxV: 5.5 V */
466
- [0x08c] = 0x4e, /* Peakl: 450 mA */
467
- [0x08e] = 0x08, /* TPCE_MS = 1 window, 1 byte, Host address */
468
- [0x090] = 0x00, /* Window descriptor: Window length = 0 */
469
- [0x092] = 0x20, /* TPCE_MI: support power down mode, RW */
470
-
471
- [0x094] = CISTPL_CFTABLE_ENTRY, /* 16-bit PC Card Configuration */
472
- [0x096] = 0x06, /* Tuple length = 6 bytes */
473
- [0x098] = 0x00, /* TPCE_INDX = Memory Mode, no Default */
474
- [0x09a] = 0x01, /* TPCE_FS = Vcc only, no I/O, no Memory */
475
- [0x09c] = 0x21, /* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
476
- [0x09e] = 0xb5, /* NomV: 3.3 V */
477
- [0x0a0] = 0x1e,
478
- [0x0a2] = 0x3e, /* Peakl: 350 mA */
479
-
480
- [0x0a4] = CISTPL_CFTABLE_ENTRY, /* 16-bit PC Card Configuration */
481
- [0x0a6] = 0x0d, /* Tuple length = 13 bytes */
482
- [0x0a8] = 0xc1, /* TPCE_INDX = I/O and Memory Mode, Default */
483
- [0x0aa] = 0x41, /* TPCE_IF = I/O and Memory, no BVD, no WP */
484
- [0x0ac] = 0x99, /* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
485
- [0x0ae] = 0x27, /* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
486
- [0x0b0] = 0x55, /* NomV: 5.0 V */
487
- [0x0b2] = 0x4d, /* MinV: 4.5 V */
488
- [0x0b4] = 0x5d, /* MaxV: 5.5 V */
489
- [0x0b6] = 0x4e, /* Peakl: 450 mA */
490
- [0x0b8] = 0x64, /* TPCE_IO = 16-byte boundary, 16/8 accesses */
491
- [0x0ba] = 0xf0, /* TPCE_IR = MASK, Level, Pulse, Share */
492
- [0x0bc] = 0xff, /* IRQ0..IRQ7 supported */
493
- [0x0be] = 0xff, /* IRQ8..IRQ15 supported */
494
- [0x0c0] = 0x20, /* TPCE_MI = support power down mode */
495
-
496
- [0x0c2] = CISTPL_CFTABLE_ENTRY, /* 16-bit PC Card Configuration */
497
- [0x0c4] = 0x06, /* Tuple length = 6 bytes */
498
- [0x0c6] = 0x01, /* TPCE_INDX = I/O and Memory Mode */
499
- [0x0c8] = 0x01, /* TPCE_FS = Vcc only, no I/O, no Memory */
500
- [0x0ca] = 0x21, /* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
501
- [0x0cc] = 0xb5, /* NomV: 3.3 V */
502
- [0x0ce] = 0x1e,
503
- [0x0d0] = 0x3e, /* Peakl: 350 mA */
504
-
505
- [0x0d2] = CISTPL_CFTABLE_ENTRY, /* 16-bit PC Card Configuration */
506
- [0x0d4] = 0x12, /* Tuple length = 18 bytes */
507
- [0x0d6] = 0xc2, /* TPCE_INDX = I/O Primary Mode */
508
- [0x0d8] = 0x41, /* TPCE_IF = I/O and Memory, no BVD, no WP */
509
- [0x0da] = 0x99, /* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
510
- [0x0dc] = 0x27, /* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
511
- [0x0de] = 0x55, /* NomV: 5.0 V */
512
- [0x0e0] = 0x4d, /* MinV: 4.5 V */
513
- [0x0e2] = 0x5d, /* MaxV: 5.5 V */
514
- [0x0e4] = 0x4e, /* Peakl: 450 mA */
515
- [0x0e6] = 0xea, /* TPCE_IO = 1K boundary, 16/8 access, Range */
516
- [0x0e8] = 0x61, /* Range: 2 fields, 2 bytes addr, 1 byte len */
517
- [0x0ea] = 0xf0, /* Field 1 address = 0x01f0 */
518
- [0x0ec] = 0x01,
519
- [0x0ee] = 0x07, /* Address block length = 8 */
520
- [0x0f0] = 0xf6, /* Field 2 address = 0x03f6 */
521
- [0x0f2] = 0x03,
522
- [0x0f4] = 0x01, /* Address block length = 2 */
523
- [0x0f6] = 0xee, /* TPCE_IR = IRQ E, Level, Pulse, Share */
524
- [0x0f8] = 0x20, /* TPCE_MI = support power down mode */
525
-
526
- [0x0fa] = CISTPL_CFTABLE_ENTRY, /* 16-bit PC Card Configuration */
527
- [0x0fc] = 0x06, /* Tuple length = 6 bytes */
528
- [0x0fe] = 0x02, /* TPCE_INDX = I/O Primary Mode, no Default */
529
- [0x100] = 0x01, /* TPCE_FS = Vcc only, no I/O, no Memory */
530
- [0x102] = 0x21, /* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
531
- [0x104] = 0xb5, /* NomV: 3.3 V */
532
- [0x106] = 0x1e,
533
- [0x108] = 0x3e, /* Peakl: 350 mA */
534
-
535
- [0x10a] = CISTPL_CFTABLE_ENTRY, /* 16-bit PC Card Configuration */
536
- [0x10c] = 0x12, /* Tuple length = 18 bytes */
537
- [0x10e] = 0xc3, /* TPCE_INDX = I/O Secondary Mode, Default */
538
- [0x110] = 0x41, /* TPCE_IF = I/O and Memory, no BVD, no WP */
539
- [0x112] = 0x99, /* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
540
- [0x114] = 0x27, /* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
541
- [0x116] = 0x55, /* NomV: 5.0 V */
542
- [0x118] = 0x4d, /* MinV: 4.5 V */
543
- [0x11a] = 0x5d, /* MaxV: 5.5 V */
544
- [0x11c] = 0x4e, /* Peakl: 450 mA */
545
- [0x11e] = 0xea, /* TPCE_IO = 1K boundary, 16/8 access, Range */
546
- [0x120] = 0x61, /* Range: 2 fields, 2 byte addr, 1 byte len */
547
- [0x122] = 0x70, /* Field 1 address = 0x0170 */
548
- [0x124] = 0x01,
549
- [0x126] = 0x07, /* Address block length = 8 */
550
- [0x128] = 0x76, /* Field 2 address = 0x0376 */
551
- [0x12a] = 0x03,
552
- [0x12c] = 0x01, /* Address block length = 2 */
553
- [0x12e] = 0xee, /* TPCE_IR = IRQ E, Level, Pulse, Share */
554
- [0x130] = 0x20, /* TPCE_MI = support power down mode */
555
-
556
- [0x132] = CISTPL_CFTABLE_ENTRY, /* 16-bit PC Card Configuration */
557
- [0x134] = 0x06, /* Tuple length = 6 bytes */
558
- [0x136] = 0x03, /* TPCE_INDX = I/O Secondary Mode */
559
- [0x138] = 0x01, /* TPCE_FS = Vcc only, no I/O, no Memory */
560
- [0x13a] = 0x21, /* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
561
- [0x13c] = 0xb5, /* NomV: 3.3 V */
562
- [0x13e] = 0x1e,
563
- [0x140] = 0x3e, /* Peakl: 350 mA */
564
-
565
- [0x142] = CISTPL_NO_LINK, /* No Link */
566
- [0x144] = 0x00, /* Tuple length = 0 bytes */
567
-
568
- [0x146] = CISTPL_END, /* Tuple End */
569
-};
570
-
571
-#define TYPE_DSCM1XXXX "dscm1xxxx"
572
-
573
-static int dscm1xxxx_attach(PCMCIACardState *card)
574
-{
575
- MicroDriveState *md = MICRODRIVE(card);
576
- PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
577
-
578
- md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
579
- md->io_base = 0x0;
580
-
581
- device_cold_reset(DEVICE(md));
582
- md_interrupt_update(md);
583
-
584
- return 0;
585
-}
586
-
587
-static int dscm1xxxx_detach(PCMCIACardState *card)
588
-{
589
- MicroDriveState *md = MICRODRIVE(card);
590
-
591
- device_cold_reset(DEVICE(md));
592
- return 0;
593
-}
594
-
595
-PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
596
-{
597
- MicroDriveState *md;
598
-
599
- md = MICRODRIVE(object_new(TYPE_DSCM1XXXX));
600
- qdev_realize(DEVICE(md), NULL, &error_fatal);
601
-
602
- if (dinfo != NULL) {
603
- ide_bus_create_drive(&md->bus, 0, dinfo);
604
- }
605
- md->bus.ifs[0].drive_kind = IDE_CFATA;
606
- md->bus.ifs[0].mdata_size = METADATA_SIZE;
607
- md->bus.ifs[0].mdata_storage = g_malloc0(METADATA_SIZE);
608
-
609
- return PCMCIA_CARD(md);
610
-}
611
-
612
-static void dscm1xxxx_class_init(ObjectClass *oc, void *data)
613
-{
614
- PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
615
- DeviceClass *dc = DEVICE_CLASS(oc);
616
-
617
- pcc->cis = dscm1xxxx_cis;
618
- pcc->cis_len = sizeof(dscm1xxxx_cis);
619
-
620
- pcc->attach = dscm1xxxx_attach;
621
- pcc->detach = dscm1xxxx_detach;
622
- /* Reason: Needs to be wired-up in code, see dscm1xxxx_init() */
623
- dc->user_creatable = false;
624
-}
625
-
626
-static const TypeInfo dscm1xxxx_type_info = {
627
- .name = TYPE_DSCM1XXXX,
628
- .parent = TYPE_MICRODRIVE,
629
- .class_init = dscm1xxxx_class_init,
630
-};
631
-
632
-static void microdrive_realize(DeviceState *dev, Error **errp)
633
-{
634
- MicroDriveState *md = MICRODRIVE(dev);
635
-
636
- ide_bus_init_output_irq(&md->bus, qemu_allocate_irq(md_set_irq, md, 0));
637
-}
638
-
639
-static void microdrive_init(Object *obj)
640
-{
641
- MicroDriveState *md = MICRODRIVE(obj);
642
-
643
- ide_bus_init(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1);
644
-}
645
-
646
-static void microdrive_class_init(ObjectClass *oc, void *data)
647
-{
648
- DeviceClass *dc = DEVICE_CLASS(oc);
649
- PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
650
-
651
- pcc->attr_read = md_attr_read;
652
- pcc->attr_write = md_attr_write;
653
- pcc->common_read = md_common_read;
654
- pcc->common_write = md_common_write;
655
- pcc->io_read = md_common_read;
656
- pcc->io_write = md_common_write;
657
-
658
- dc->realize = microdrive_realize;
659
- device_class_set_legacy_reset(dc, md_reset);
660
- dc->vmsd = &vmstate_microdrive;
661
-}
662
-
663
-static const TypeInfo microdrive_type_info = {
664
- .name = TYPE_MICRODRIVE,
665
- .parent = TYPE_PCMCIA_CARD,
666
- .instance_size = sizeof(MicroDriveState),
667
- .instance_init = microdrive_init,
668
- .abstract = true,
669
- .class_init = microdrive_class_init,
670
-};
671
-
672
-static void microdrive_register_types(void)
673
-{
674
- type_register_static(&microdrive_type_info);
675
- type_register_static(&dscm1xxxx_type_info);
676
-}
677
-
678
-type_init(microdrive_register_types)
679
diff --git a/hw/ide/Kconfig b/hw/ide/Kconfig
680
index XXXXXXX..XXXXXXX 100644
681
--- a/hw/ide/Kconfig
682
+++ b/hw/ide/Kconfig
683
@@ -XXX,XX +XXX,XX @@ config IDE_VIA
684
bool
685
select IDE_PCI
686
687
-config MICRODRIVE
688
- bool
689
- select IDE_BUS
690
- select IDE_DEV
691
- depends on PCMCIA
692
-
693
config AHCI
694
bool
695
select IDE_BUS
696
diff --git a/hw/ide/meson.build b/hw/ide/meson.build
697
index XXXXXXX..XXXXXXX 100644
698
--- a/hw/ide/meson.build
699
+++ b/hw/ide/meson.build
700
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_IDE_PCI', if_true: files('pci.c'))
701
system_ss.add(when: 'CONFIG_IDE_PIIX', if_true: files('piix.c', 'ioport.c'))
702
system_ss.add(when: 'CONFIG_IDE_SII3112', if_true: files('sii3112.c'))
703
system_ss.add(when: 'CONFIG_IDE_VIA', if_true: files('via.c'))
704
-system_ss.add(when: 'CONFIG_MICRODRIVE', if_true: files('microdrive.c'))
705
--
141
--
706
2.34.1
142
2.34.1
707
708
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Unpacking and repacking the parts may be slightly more work
4
than we did before, but we get to reuse more code. For a
5
code path handling exceptional values, this is an improvement.
6
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(-)
14
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/fpu/softfloat.c
18
+++ b/fpu/softfloat.c
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
20
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
22
{
23
- bool aIsLargerSignificand;
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);
47
}
48
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
/*----------------------------------------------------------------------------
73
--
74
2.34.1
diff view generated by jsdifflib
1
The ``-portrait`` and ``-rotate`` options were documented as only
1
From: Richard Henderson <richard.henderson@linaro.org>
2
working with the PXA LCD device, and all the machine types using
2
3
that display device were removed in 9.2.
3
Inline pickNaN into its only caller. This makes one assert
4
4
redundant with the immediately preceding IF.
5
These options were intended to simulate a mobile device being
5
6
rotated by the user, and had three effects:
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
* the display output was rotated by 90, 180 or 270 degrees
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
(implemented in the PXA display device models)
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
9
* the mouse/trackpad input was rotated the opposite way
10
(implemented in generic code)
11
* the machine model would signal to the guest about its
12
orientation
13
(implemented by e.g. the spitz machine model)
14
15
Of these three things, the input-rotation was coded without being
16
restricted to boards which supported the full set of device-rotation
17
handling, so in theory the options were usable on other machine
18
models with odd effects (rotating input but not display output). But
19
this was never intended or documented behaviour, so we can reasonably
20
drop these command line arguments without a formal deprecate-and-drop
21
cycle for them.
22
23
Remove the options, and their implementation and documentation.
24
Describe the removal in removed-features.rst.
25
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
29
Message-id: 20241003140010.1653808-7-peter.maydell@linaro.org
30
---
10
---
31
docs/about/removed-features.rst | 23 +++++++++++++++++++++
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
32
include/sysemu/sysemu.h | 1 -
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
33
system/globals.c | 1 -
13
2 files changed, 73 insertions(+), 105 deletions(-)
34
system/vl.c | 11 ----------
14
35
ui/input.c | 36 ---------------------------------
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
36
qemu-options.hx | 16 ---------------
37
6 files changed, 23 insertions(+), 65 deletions(-)
38
39
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
40
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
41
--- a/docs/about/removed-features.rst
17
--- a/fpu/softfloat-parts.c.inc
42
+++ b/docs/about/removed-features.rst
18
+++ b/fpu/softfloat-parts.c.inc
43
@@ -XXX,XX +XXX,XX @@ security model option, or switch to ``virtiofs``. The virtiofs daemon
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
44
``virtiofsd`` uses vhost to eliminate the high latency costs of the 9p
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
45
``proxy`` backend.
21
float_status *s)
46
22
{
47
+``-portrait`` and ``-rotate`` (since 9.2)
23
+ int cmp, which;
48
+'''''''''''''''''''''''''''''''''''''''''
49
+
24
+
50
+The ``-portrait`` and ``-rotate`` options were documented as only
25
if (is_snan(a->cls) || is_snan(b->cls)) {
51
+working with the PXA LCD device, and all the machine types using
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
52
+that display device were removed in 9.2, so these options also
27
}
53
+have been dropped.
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
+ }
54
+
46
+
55
+These options were intended to simulate a mobile device being
47
+ switch (s->float_2nan_prop_rule) {
56
+rotated by the user, and had three effects:
48
+ case float_2nan_prop_s_ab:
49
if (is_snan(a->cls)) {
50
- parts_silence_nan(a, s);
51
+ which = 0;
52
+ } else if (is_snan(b->cls)) {
53
+ which = 1;
54
+ } else if (is_qnan(a->cls)) {
55
+ which = 0;
56
+ } else {
57
+ which = 1;
58
}
59
+ break;
60
+ case float_2nan_prop_s_ba:
61
+ if (is_snan(b->cls)) {
62
+ which = 1;
63
+ } else if (is_snan(a->cls)) {
64
+ which = 0;
65
+ } else if (is_qnan(b->cls)) {
66
+ which = 1;
67
+ } else {
68
+ which = 0;
69
+ }
70
+ break;
71
+ case float_2nan_prop_ab:
72
+ which = is_nan(a->cls) ? 0 : 1;
73
+ break;
74
+ case float_2nan_prop_ba:
75
+ which = is_nan(b->cls) ? 1 : 0;
76
+ break;
77
+ case float_2nan_prop_x87:
78
+ /*
79
+ * This implements x87 NaN propagation rules:
80
+ * SNaN + QNaN => return the QNaN
81
+ * two SNaNs => return the one with the larger significand, silenced
82
+ * two QNaNs => return the one with the larger significand
83
+ * SNaN and a non-NaN => return the SNaN, silenced
84
+ * QNaN and a non-NaN => return the QNaN
85
+ *
86
+ * If we get down to comparing significands and they are the same,
87
+ * return the NaN with the positive sign bit (if any).
88
+ */
89
+ if (is_snan(a->cls)) {
90
+ if (is_snan(b->cls)) {
91
+ which = cmp > 0 ? 0 : 1;
92
+ } else {
93
+ which = is_qnan(b->cls) ? 1 : 0;
94
+ }
95
+ } else if (is_qnan(a->cls)) {
96
+ if (is_snan(b->cls) || !is_qnan(b->cls)) {
97
+ which = 0;
98
+ } else {
99
+ which = cmp > 0 ? 0 : 1;
100
+ }
101
+ } else {
102
+ which = 1;
103
+ }
104
+ break;
105
+ default:
106
+ g_assert_not_reached();
107
+ }
57
+
108
+
58
+* the display output was rotated by 90, 180 or 270 degrees
109
+ if (which) {
59
+* the mouse/trackpad input was rotated the opposite way
110
+ a = b;
60
+* the machine model would signal to the guest about its
111
+ }
61
+ orientation
112
+ if (is_snan(a->cls)) {
62
+
113
+ parts_silence_nan(a, s);
63
+Of these three things, the input-rotation was coded without being
114
}
64
+restricted to boards which supported the full set of device-rotation
115
return a;
65
+handling, so in theory the options were usable on other machine models
116
}
66
+to produce an odd effect (rotating input but not display output). But
117
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
67
+this was never intended or documented behaviour, so we have dropped
68
+the options along with the machine models they were intended for.
69
+
70
User-mode emulator command line arguments
71
-----------------------------------------
72
73
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
74
index XXXXXXX..XXXXXXX 100644
118
index XXXXXXX..XXXXXXX 100644
75
--- a/include/sysemu/sysemu.h
119
--- a/fpu/softfloat-specialize.c.inc
76
+++ b/include/sysemu/sysemu.h
120
+++ b/fpu/softfloat-specialize.c.inc
77
@@ -XXX,XX +XXX,XX @@ extern int graphic_height;
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
78
extern int graphic_depth;
122
}
79
extern int display_opengl;
80
extern const char *keyboard_layout;
81
-extern int graphic_rotate;
82
extern int old_param;
83
extern uint8_t *boot_splash_filedata;
84
extern bool enable_mlock;
85
diff --git a/system/globals.c b/system/globals.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/system/globals.c
88
+++ b/system/globals.c
89
@@ -XXX,XX +XXX,XX @@ int autostart = 1;
90
int vga_interface_type = VGA_NONE;
91
bool vga_interface_created;
92
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
93
-int graphic_rotate;
94
QEMUOptionRom option_rom[MAX_OPTION_ROMS];
95
int nb_option_roms;
96
int old_param;
97
diff --git a/system/vl.c b/system/vl.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/system/vl.c
100
+++ b/system/vl.c
101
@@ -XXX,XX +XXX,XX @@ void qemu_init(int argc, char **argv)
102
nographic = true;
103
dpy.type = DISPLAY_TYPE_NONE;
104
break;
105
- case QEMU_OPTION_portrait:
106
- graphic_rotate = 90;
107
- break;
108
- case QEMU_OPTION_rotate:
109
- graphic_rotate = strtol(optarg, (char **) &optarg, 10);
110
- if (graphic_rotate != 0 && graphic_rotate != 90 &&
111
- graphic_rotate != 180 && graphic_rotate != 270) {
112
- error_report("only 90, 180, 270 deg rotation is available");
113
- exit(1);
114
- }
115
- break;
116
case QEMU_OPTION_kernel:
117
qdict_put_str(machine_opts_dict, "kernel", optarg);
118
break;
119
diff --git a/ui/input.c b/ui/input.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/ui/input.c
122
+++ b/ui/input.c
123
@@ -XXX,XX +XXX,XX @@ void qmp_input_send_event(const char *device,
124
qemu_input_event_sync();
125
}
123
}
126
124
127
-static int qemu_input_transform_invert_abs_value(int value)
125
-/*----------------------------------------------------------------------------
126
-| Select which NaN to propagate for a two-input operation.
127
-| IEEE754 doesn't specify all the details of this, so the
128
-| algorithm is target-specific.
129
-| The routine is passed various bits of information about the
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
131
-| Note that signalling NaNs are always squashed to quiet NaNs
132
-| by the caller, by calling floatXX_silence_nan() before
133
-| returning them.
134
-|
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
136
-| of some kind, and is true if a has the larger significand,
137
-| or if both a and b have the same significand but a is
138
-| positive but b is negative. It is only needed for the x87
139
-| tie-break rule.
140
-*----------------------------------------------------------------------------*/
141
-
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
143
- bool aIsLargerSignificand, float_status *status)
128
-{
144
-{
129
- return (int64_t)INPUT_EVENT_ABS_MAX - value + INPUT_EVENT_ABS_MIN;
145
- /*
130
-}
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);
131
-
152
-
132
-static void qemu_input_transform_abs_rotate(InputEvent *evt)
153
- switch (status->float_2nan_prop_rule) {
133
-{
154
- case float_2nan_prop_s_ab:
134
- InputMoveEvent *move = evt->u.abs.data;
155
- if (is_snan(a_cls)) {
135
- switch (graphic_rotate) {
156
- return 0;
136
- case 90:
157
- } else if (is_snan(b_cls)) {
137
- if (move->axis == INPUT_AXIS_X) {
158
- return 1;
138
- move->axis = INPUT_AXIS_Y;
159
- } else if (is_qnan(a_cls)) {
139
- } else if (move->axis == INPUT_AXIS_Y) {
160
- return 0;
140
- move->axis = INPUT_AXIS_X;
161
- } else {
141
- move->value = qemu_input_transform_invert_abs_value(move->value);
162
- return 1;
142
- }
163
- }
143
- break;
164
- break;
144
- case 180:
165
- case float_2nan_prop_s_ba:
145
- move->value = qemu_input_transform_invert_abs_value(move->value);
166
- if (is_snan(b_cls)) {
146
- break;
167
- return 1;
147
- case 270:
168
- } else if (is_snan(a_cls)) {
148
- if (move->axis == INPUT_AXIS_X) {
169
- return 0;
149
- move->axis = INPUT_AXIS_Y;
170
- } else if (is_qnan(b_cls)) {
150
- move->value = qemu_input_transform_invert_abs_value(move->value);
171
- return 1;
151
- } else if (move->axis == INPUT_AXIS_Y) {
172
- } else {
152
- move->axis = INPUT_AXIS_X;
173
- return 0;
153
- }
174
- }
154
- break;
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();
155
- }
218
- }
156
-}
219
-}
157
-
220
-
158
static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
221
/*----------------------------------------------------------------------------
159
{
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
160
const char *name;
223
| NaN; otherwise returns 0.
161
@@ -XXX,XX +XXX,XX @@ void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt)
162
163
qemu_input_event_trace(src, evt);
164
165
- /* pre processing */
166
- if (graphic_rotate && (evt->type == INPUT_EVENT_KIND_ABS)) {
167
- qemu_input_transform_abs_rotate(evt);
168
- }
169
-
170
/* send event */
171
s = qemu_input_find_handler(1 << evt->type, src);
172
if (!s) {
173
diff --git a/qemu-options.hx b/qemu-options.hx
174
index XXXXXXX..XXXXXXX 100644
175
--- a/qemu-options.hx
176
+++ b/qemu-options.hx
177
@@ -XXX,XX +XXX,XX @@ SRST
178
pick the first available. (Since 2.9)
179
ERST
180
181
-DEF("portrait", 0, QEMU_OPTION_portrait,
182
- "-portrait rotate graphical output 90 deg left (only PXA LCD)\n",
183
- QEMU_ARCH_ALL)
184
-SRST
185
-``-portrait``
186
- Rotate graphical output 90 deg left (only PXA LCD).
187
-ERST
188
-
189
-DEF("rotate", HAS_ARG, QEMU_OPTION_rotate,
190
- "-rotate <deg> rotate graphical output some deg left (only PXA LCD)\n",
191
- QEMU_ARCH_ALL)
192
-SRST
193
-``-rotate deg``
194
- Rotate graphical output some deg left (only PXA LCD).
195
-ERST
196
-
197
DEF("vga", HAS_ARG, QEMU_OPTION_vga,
198
"-vga [std|cirrus|vmware|qxl|xenfb|tcx|cg3|virtio|none]\n"
199
" select video card type\n", QEMU_ARCH_ALL)
200
--
224
--
201
2.34.1
225
2.34.1
202
226
203
227
diff view generated by jsdifflib
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Allwinner A10 SPI controller is added to the Allwinner A10
3
Remember if there was an SNaN, and use that to simplify
4
description, so it is available when Cubieboard is emulated.
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
Update the documentation for Cubieboard to indicate SPI availability.
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
8
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
9
Message-id: 20241001221349.8319-3-strahinja.p.jankovic@gmail.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
docs/system/arm/cubieboard.rst | 1 +
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
14
include/hw/arm/allwinner-a10.h | 2 ++
15
1 file changed, 12 insertions(+), 20 deletions(-)
15
hw/arm/allwinner-a10.c | 8 ++++++++
16
hw/arm/Kconfig | 1 +
17
4 files changed, 12 insertions(+)
18
16
19
diff --git a/docs/system/arm/cubieboard.rst b/docs/system/arm/cubieboard.rst
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/arm/cubieboard.rst
19
--- a/fpu/softfloat-parts.c.inc
22
+++ b/docs/system/arm/cubieboard.rst
20
+++ b/fpu/softfloat-parts.c.inc
23
@@ -XXX,XX +XXX,XX @@ Emulated devices:
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
24
- USB controller
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
25
- SATA controller
23
float_status *s)
26
- TWI (I2C) controller
24
{
27
+- SPI controller
25
+ bool have_snan = false;
28
- Watchdog timer
26
int cmp, which;
29
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
27
30
index XXXXXXX..XXXXXXX 100644
28
if (is_snan(a->cls) || is_snan(b->cls)) {
31
--- a/include/hw/arm/allwinner-a10.h
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
32
+++ b/include/hw/arm/allwinner-a10.h
30
+ have_snan = true;
33
@@ -XXX,XX +XXX,XX @@
31
}
34
#include "hw/misc/allwinner-a10-ccm.h"
32
35
#include "hw/misc/allwinner-a10-dramc.h"
33
if (s->default_nan_mode) {
36
#include "hw/i2c/allwinner-i2c.h"
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
37
+#include "hw/ssi/allwinner-a10-spi.h"
35
38
#include "hw/watchdog/allwinner-wdt.h"
36
switch (s->float_2nan_prop_rule) {
39
#include "sysemu/block-backend.h"
37
case float_2nan_prop_s_ab:
40
38
- if (is_snan(a->cls)) {
41
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
39
- which = 0;
42
AllwinnerAHCIState sata;
40
- } else if (is_snan(b->cls)) {
43
AwSdHostState mmc0;
41
- which = 1;
44
AWI2CState i2c0;
42
- } else if (is_qnan(a->cls)) {
45
+ AWA10SPIState spi0;
43
- which = 0;
46
AwRtcState rtc;
44
- } else {
47
AwWdtState wdt;
45
- which = 1;
48
MemoryRegion sram_a;
46
+ if (have_snan) {
49
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
47
+ which = is_snan(a->cls) ? 0 : 1;
50
index XXXXXXX..XXXXXXX 100644
48
+ break;
51
--- a/hw/arm/allwinner-a10.c
49
}
52
+++ b/hw/arm/allwinner-a10.c
50
- break;
53
@@ -XXX,XX +XXX,XX @@
51
- case float_2nan_prop_s_ba:
54
#define AW_A10_PIC_REG_BASE 0x01c20400
52
- if (is_snan(b->cls)) {
55
#define AW_A10_PIT_REG_BASE 0x01c20c00
53
- which = 1;
56
#define AW_A10_UART0_REG_BASE 0x01c28000
54
- } else if (is_snan(a->cls)) {
57
+#define AW_A10_SPI0_BASE 0x01c05000
55
- which = 0;
58
#define AW_A10_EMAC_BASE 0x01c0b000
56
- } else if (is_qnan(b->cls)) {
59
#define AW_A10_EHCI_BASE 0x01c14000
57
- which = 1;
60
#define AW_A10_OHCI_BASE 0x01c14400
58
- } else {
61
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
59
- which = 0;
62
60
- }
63
object_initialize_child(obj, "i2c0", &s->i2c0, TYPE_AW_I2C);
61
- break;
64
62
+ /* fall through */
65
+ object_initialize_child(obj, "spi0", &s->spi0, TYPE_AW_A10_SPI);
63
case float_2nan_prop_ab:
66
+
64
which = is_nan(a->cls) ? 0 : 1;
67
for (size_t i = 0; i < AW_A10_NUM_USB; i++) {
65
break;
68
object_initialize_child(obj, "ehci[*]", &s->ehci[i],
66
+ case float_2nan_prop_s_ba:
69
TYPE_PLATFORM_EHCI);
67
+ if (have_snan) {
70
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
68
+ which = is_snan(b->cls) ? 1 : 0;
71
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, AW_A10_I2C0_BASE);
69
+ break;
72
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0, qdev_get_gpio_in(dev, 7));
70
+ }
73
71
+ /* fall through */
74
+ /* SPI */
72
case float_2nan_prop_ba:
75
+ sysbus_realize(SYS_BUS_DEVICE(&s->spi0), &error_fatal);
73
which = is_nan(b->cls) ? 1 : 0;
76
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi0), 0, AW_A10_SPI0_BASE);
74
break;
77
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi0), 0, qdev_get_gpio_in(dev, 10));
78
+
79
/* WDT */
80
sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_fatal);
81
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->wdt), 0, AW_A10_WDT_BASE, 1);
82
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
83
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/arm/Kconfig
85
+++ b/hw/arm/Kconfig
86
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
87
select ALLWINNER_WDT
88
select ALLWINNER_EMAC
89
select ALLWINNER_I2C
90
+ select ALLWINNER_A10_SPI
91
select AXP2XX_PMU
92
select SERIAL_MM
93
select UNIMP
94
--
75
--
95
2.34.1
76
2.34.1
diff view generated by jsdifflib
1
From: Alexandra Diupina <adiupina@astralinux.ru>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The result of 1 << regbit with regbit==31 has a 1 in the 32nd bit.
3
Move the fractional comparison to the end of the
4
When cast to uint64_t (for further bitwise OR), the 32 most
4
float_2nan_prop_x87 case. This is not required for
5
significant bits will be filled with 1s. However, the documentation
5
any other 2nan propagation rule. Reorganize the
6
states that the upper 32 bits of ICC_AP[0/1]R<n>_EL2 are reserved.
6
x87 case itself to break out of the switch when the
7
fractional comparison is not required.
7
8
8
Add an explicit cast to match the documentation.
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
10
Found by Linux Verification Center (linuxtesting.org) with SVACE.
11
12
Cc: qemu-stable@nongnu.org
13
Fixes: 28cca59c46 ("hw/intc/arm_gicv3: Add NMI handling CPU interface registers")
14
Signed-off-by: Alexandra Diupina <adiupina@astralinux.ru>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
13
---
18
hw/intc/arm_gicv3_cpuif.c | 2 +-
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
19
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 9 insertions(+), 10 deletions(-)
20
16
21
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/intc/arm_gicv3_cpuif.c
19
--- a/fpu/softfloat-parts.c.inc
24
+++ b/hw/intc/arm_gicv3_cpuif.c
20
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static void icc_activate_irq(GICv3CPUState *cs, int irq)
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
26
if (nmi) {
22
return a;
27
cs->icc_apr[cs->hppi.grp][regno] |= ICC_AP1R_EL1_NMI;
28
} else {
29
- cs->icc_apr[cs->hppi.grp][regno] |= (1 << regbit);
30
+ cs->icc_apr[cs->hppi.grp][regno] |= (1U << regbit);
31
}
23
}
32
24
33
if (irq < GIC_INTERNAL) {
25
- cmp = frac_cmp(a, b);
26
- if (cmp == 0) {
27
- cmp = a->sign < b->sign;
28
- }
29
-
30
switch (s->float_2nan_prop_rule) {
31
case float_2nan_prop_s_ab:
32
if (have_snan) {
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
34
* return the NaN with the positive sign bit (if any).
35
*/
36
if (is_snan(a->cls)) {
37
- if (is_snan(b->cls)) {
38
- which = cmp > 0 ? 0 : 1;
39
- } else {
40
+ if (!is_snan(b->cls)) {
41
which = is_qnan(b->cls) ? 1 : 0;
42
+ break;
43
}
44
} else if (is_qnan(a->cls)) {
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
46
which = 0;
47
- } else {
48
- which = cmp > 0 ? 0 : 1;
49
+ break;
50
}
51
} else {
52
which = 1;
53
+ break;
54
}
55
+ cmp = frac_cmp(a, b);
56
+ if (cmp == 0) {
57
+ cmp = a->sign < b->sign;
58
+ }
59
+ which = cmp > 0 ? 0 : 1;
60
break;
61
default:
62
g_assert_not_reached();
34
--
63
--
35
2.34.1
64
2.34.1
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The recently removed 'cheetah' machine was the single user
3
Replace the "index" selecting between A and B with a result variable
4
of the omap_uwire_attach() method. Remove it altogether with
4
of the proper type. This improves clarity within the function.
5
the uWireSlave structure. Replace the send/receive callbacks
6
by Unimplemented logging.
7
5
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
include/hw/arm/omap.h | 8 --------
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
13
hw/arm/omap1.c | 29 ++++++++---------------------
12
1 file changed, 13 insertions(+), 15 deletions(-)
14
2 files changed, 8 insertions(+), 29 deletions(-)
15
13
16
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/omap.h
16
--- a/fpu/softfloat-parts.c.inc
19
+++ b/include/hw/arm/omap.h
17
+++ b/fpu/softfloat-parts.c.inc
20
@@ -XXX,XX +XXX,XX @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
21
void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
19
float_status *s)
22
void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
23
24
-typedef struct uWireSlave {
25
- uint16_t (*receive)(void *opaque);
26
- void (*send)(void *opaque, uint16_t data);
27
- void *opaque;
28
-} uWireSlave;
29
-
30
struct omap_uwire_s;
31
-void omap_uwire_attach(struct omap_uwire_s *s,
32
- uWireSlave *slave, int chipselect);
33
34
struct I2SCodec {
35
void *opaque;
36
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/omap1.c
39
+++ b/hw/arm/omap1.c
40
@@ -XXX,XX +XXX,XX @@ struct omap_uwire_s {
41
uint16_t rxbuf;
42
uint16_t control;
43
uint16_t setup[5];
44
-
45
- uWireSlave *chip[4];
46
};
47
48
static void omap_uwire_transfer_start(struct omap_uwire_s *s)
49
{
20
{
50
int chipselect = (s->control >> 10) & 3;        /* INDEX */
21
bool have_snan = false;
51
- uWireSlave *slave = s->chip[chipselect];
22
- int cmp, which;
52
23
+ FloatPartsN *ret;
53
if ((s->control >> 5) & 0x1f) {            /* NB_BITS_WR */
24
+ int cmp;
54
- if (s->control & (1 << 12))            /* CS_CMD */
25
55
- if (slave && slave->send)
26
if (is_snan(a->cls) || is_snan(b->cls)) {
56
- slave->send(slave->opaque,
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
57
- s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
58
+ if (s->control & (1 << 12)) { /* CS_CMD */
29
switch (s->float_2nan_prop_rule) {
59
+ qemu_log_mask(LOG_UNIMP, "uWireSlave TX CS:%d data:0x%04x\n",
30
case float_2nan_prop_s_ab:
60
+ chipselect,
31
if (have_snan) {
61
+ s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
32
- which = is_snan(a->cls) ? 0 : 1;
62
+ }
33
+ ret = is_snan(a->cls) ? a : b;
63
s->control &= ~(1 << 14);            /* CSRB */
34
break;
64
/* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
35
}
65
* a DRQ. When is the level IRQ supposed to be reset? */
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();
66
}
82
}
67
83
68
if ((s->control >> 0) & 0x1f) {            /* NB_BITS_RD */
84
- if (which) {
69
- if (s->control & (1 << 12))            /* CS_CMD */
85
- a = b;
70
- if (slave && slave->receive)
86
+ if (is_snan(ret->cls)) {
71
- s->rxbuf = slave->receive(slave->opaque);
87
+ parts_silence_nan(ret, s);
72
+ if (s->control & (1 << 12)) { /* CS_CMD */
88
}
73
+ qemu_log_mask(LOG_UNIMP, "uWireSlave RX CS:%d\n", chipselect);
89
- if (is_snan(a->cls)) {
74
+ }
90
- parts_silence_nan(a, s);
75
s->control |= 1 << 15;                /* RDRB */
91
- }
76
/* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
92
- return a;
77
* a DRQ. When is the level IRQ supposed to be reset? */
93
+ return ret;
78
@@ -XXX,XX +XXX,XX @@ static struct omap_uwire_s *omap_uwire_init(MemoryRegion *system_memory,
79
return s;
80
}
94
}
81
95
82
-void omap_uwire_attach(struct omap_uwire_s *s,
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
83
- uWireSlave *slave, int chipselect)
84
-{
85
- if (chipselect < 0 || chipselect > 3) {
86
- error_report("%s: Bad chipselect %i", __func__, chipselect);
87
- exit(-1);
88
- }
89
-
90
- s->chip[chipselect] = slave;
91
-}
92
-
93
/* Pseudonoise Pulse-Width Light Modulator */
94
struct omap_pwl_s {
95
MemoryRegion iomem;
96
--
97
--
97
2.34.1
98
2.34.1
98
99
99
100
diff view generated by jsdifflib
1
From: Román Cárdenas Rodríguez <rcardenas.rod@gmail.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Generic RCC class for STM32 devices. It can be used for most of
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
the STM32 chips. Note that it only implements enable and reset
4
update my email address, and update the mailmap to match.
5
capabilities.
6
5
7
Signed-off-by: Roman Cardenas Rodriguez <rcardenas.rod@gmail.com>
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
8
[PMM: tweaked commit message, added MAINTAINERS lines]
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
MAINTAINERS | 2 +
14
MAINTAINERS | 2 +-
13
include/hw/misc/stm32_rcc.h | 91 ++++++++++++++++++++
15
.mailmap | 5 +++--
14
hw/misc/stm32_rcc.c | 162 ++++++++++++++++++++++++++++++++++++
16
2 files changed, 4 insertions(+), 3 deletions(-)
15
hw/misc/Kconfig | 3 +
16
hw/misc/meson.build | 1 +
17
hw/misc/trace-events | 6 ++
18
6 files changed, 265 insertions(+)
19
create mode 100644 include/hw/misc/stm32_rcc.h
20
create mode 100644 hw/misc/stm32_rcc.c
21
17
22
diff --git a/MAINTAINERS b/MAINTAINERS
18
diff --git a/MAINTAINERS b/MAINTAINERS
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/MAINTAINERS
20
--- a/MAINTAINERS
25
+++ b/MAINTAINERS
21
+++ b/MAINTAINERS
26
@@ -XXX,XX +XXX,XX @@ S: Maintained
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
27
F: hw/arm/stm32f405_soc.c
23
SBSA-REF
28
F: hw/misc/stm32f4xx_syscfg.c
24
M: Radoslaw Biernacki <rad@semihalf.com>
29
F: hw/misc/stm32f4xx_exti.c
25
M: Peter Maydell <peter.maydell@linaro.org>
30
+F: hw/misc/stm32_rcc.c
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
31
+F: include/hw/misc/stm32_rcc.h
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
32
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
33
Netduino 2
29
L: qemu-arm@nongnu.org
34
M: Alistair Francis <alistair@alistair23.me>
30
S: Maintained
35
diff --git a/include/hw/misc/stm32_rcc.h b/include/hw/misc/stm32_rcc.h
31
diff --git a/.mailmap b/.mailmap
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/include/hw/misc/stm32_rcc.h
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * STM32 RCC (only reset and enable registers are implemented)
43
+ *
44
+ * Copyright (c) 2024 Román Cárdenas <rcardenas.rod@gmail.com>
45
+ *
46
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
47
+ * of this software and associated documentation files (the "Software"), to deal
48
+ * in the Software without restriction, including without limitation the rights
49
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
50
+ * copies of the Software, and to permit persons to whom the Software is
51
+ * furnished to do so, subject to the following conditions:
52
+ *
53
+ * The above copyright notice and this permission notice shall be included in
54
+ * all copies or substantial portions of the Software.
55
+ *
56
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
58
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
59
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
60
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
61
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
62
+ * THE SOFTWARE.
63
+ */
64
+
65
+#ifndef HW_STM32_RCC_H
66
+#define HW_STM32_RCC_H
67
+
68
+#include "hw/sysbus.h"
69
+#include "qom/object.h"
70
+
71
+#define STM32_RCC_CR 0x00
72
+#define STM32_RCC_PLL_CFGR 0x04
73
+#define STM32_RCC_CFGR 0x08
74
+#define STM32_RCC_CIR 0x0C
75
+#define STM32_RCC_AHB1_RSTR 0x10
76
+#define STM32_RCC_AHB2_RSTR 0x14
77
+#define STM32_RCC_AHB3_RSTR 0x18
78
+
79
+#define STM32_RCC_APB1_RSTR 0x20
80
+#define STM32_RCC_APB2_RSTR 0x24
81
+
82
+#define STM32_RCC_AHB1_ENR 0x30
83
+#define STM32_RCC_AHB2_ENR 0x34
84
+#define STM32_RCC_AHB3_ENR 0x38
85
+
86
+#define STM32_RCC_APB1_ENR 0x40
87
+#define STM32_RCC_APB2_ENR 0x44
88
+
89
+#define STM32_RCC_AHB1_LPENR 0x50
90
+#define STM32_RCC_AHB2_LPENR 0x54
91
+#define STM32_RCC_AHB3_LPENR 0x58
92
+
93
+#define STM32_RCC_APB1_LPENR 0x60
94
+#define STM32_RCC_APB2_LPENR 0x64
95
+
96
+#define STM32_RCC_BDCR 0x70
97
+#define STM32_RCC_CSR 0x74
98
+
99
+#define STM32_RCC_SSCGR 0x80
100
+#define STM32_RCC_PLLI2SCFGR 0x84
101
+#define STM32_RCC_PLLSAI_CFGR 0x88
102
+#define STM32_RCC_DCKCFGR 0x8C
103
+#define STM32_RCC_CKGATENR 0x90
104
+#define STM32_RCC_DCKCFGR2 0x94
105
+
106
+#define STM32_RCC_NREGS ((STM32_RCC_DCKCFGR2 >> 2) + 1)
107
+#define STM32_RCC_PERIPHERAL_SIZE 0x400
108
+#define STM32_RCC_NIRQS (32 * 5) /* 32 bits per reg, 5 en/rst regs */
109
+
110
+#define STM32_RCC_GPIO_IRQ_OFFSET 0
111
+
112
+#define TYPE_STM32_RCC "stm32.rcc"
113
+
114
+typedef struct STM32RccState STM32RccState;
115
+
116
+DECLARE_INSTANCE_CHECKER(STM32RccState, STM32_RCC, TYPE_STM32_RCC)
117
+
118
+#define NUM_GPIO_EVENT_IN_LINES 16
119
+
120
+struct STM32RccState {
121
+ SysBusDevice parent_obj;
122
+
123
+ MemoryRegion mmio;
124
+
125
+ uint32_t regs[STM32_RCC_NREGS];
126
+
127
+ qemu_irq enable_irq[STM32_RCC_NIRQS];
128
+ qemu_irq reset_irq[STM32_RCC_NIRQS];
129
+};
130
+
131
+#endif /* HW_STM32_RCC_H */
132
diff --git a/hw/misc/stm32_rcc.c b/hw/misc/stm32_rcc.c
133
new file mode 100644
134
index XXXXXXX..XXXXXXX
135
--- /dev/null
136
+++ b/hw/misc/stm32_rcc.c
137
@@ -XXX,XX +XXX,XX @@
138
+/*
139
+ * STM32 RCC (only reset and enable registers are implemented)
140
+ *
141
+ * Copyright (c) 2024 Román Cárdenas <rcardenas.rod@gmail.com>
142
+ *
143
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
144
+ * of this software and associated documentation files (the "Software"), to deal
145
+ * in the Software without restriction, including without limitation the rights
146
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
147
+ * copies of the Software, and to permit persons to whom the Software is
148
+ * furnished to do so, subject to the following conditions:
149
+ *
150
+ * The above copyright notice and this permission notice shall be included in
151
+ * all copies or substantial portions of the Software.
152
+ *
153
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
155
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
156
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
157
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
158
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
159
+ * THE SOFTWARE.
160
+ */
161
+
162
+#include "qemu/osdep.h"
163
+#include "qemu/log.h"
164
+#include "trace.h"
165
+#include "hw/irq.h"
166
+#include "migration/vmstate.h"
167
+#include "hw/misc/stm32_rcc.h"
168
+
169
+static void stm32_rcc_reset(DeviceState *dev)
170
+{
171
+ STM32RccState *s = STM32_RCC(dev);
172
+
173
+ for (int i = 0; i < STM32_RCC_NREGS; i++) {
174
+ s->regs[i] = 0;
175
+ }
176
+}
177
+
178
+static uint64_t stm32_rcc_read(void *opaque, hwaddr addr, unsigned int size)
179
+{
180
+ STM32RccState *s = STM32_RCC(opaque);
181
+
182
+ uint32_t value = 0;
183
+ if (addr > STM32_RCC_DCKCFGR2) {
184
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
185
+ __func__, addr);
186
+ } else {
187
+ value = s->regs[addr >> 2];
188
+ }
189
+ trace_stm32_rcc_read(addr, value);
190
+ return value;
191
+}
192
+
193
+static void stm32_rcc_write(void *opaque, hwaddr addr,
194
+ uint64_t val64, unsigned int size)
195
+{
196
+ STM32RccState *s = STM32_RCC(opaque);
197
+ uint32_t value = val64;
198
+ uint32_t prev_value, new_value, irq_offset;
199
+
200
+ trace_stm32_rcc_write(value, addr);
201
+
202
+ if (addr > STM32_RCC_DCKCFGR2) {
203
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
204
+ __func__, addr);
205
+ return;
206
+ }
207
+
208
+ switch (addr) {
209
+ case STM32_RCC_AHB1_RSTR...STM32_RCC_APB2_RSTR:
210
+ prev_value = s->regs[addr / 4];
211
+ s->regs[addr / 4] = value;
212
+
213
+ irq_offset = ((addr - STM32_RCC_AHB1_RSTR) / 4) * 32;
214
+ for (int i = 0; i < 32; i++) {
215
+ new_value = extract32(value, i, 1);
216
+ if (extract32(prev_value, i, 1) && !new_value) {
217
+ trace_stm32_rcc_pulse_reset(irq_offset + i, new_value);
218
+ qemu_set_irq(s->reset_irq[irq_offset + i], new_value);
219
+ }
220
+ }
221
+ return;
222
+ case STM32_RCC_AHB1_ENR...STM32_RCC_APB2_ENR:
223
+ prev_value = s->regs[addr / 4];
224
+ s->regs[addr / 4] = value;
225
+
226
+ irq_offset = ((addr - STM32_RCC_AHB1_ENR) / 4) * 32;
227
+ for (int i = 0; i < 32; i++) {
228
+ new_value = extract32(value, i, 1);
229
+ if (!extract32(prev_value, i, 1) && new_value) {
230
+ trace_stm32_rcc_pulse_enable(irq_offset + i, new_value);
231
+ qemu_set_irq(s->enable_irq[irq_offset + i], new_value);
232
+ }
233
+ }
234
+ return;
235
+ default:
236
+ qemu_log_mask(
237
+ LOG_UNIMP,
238
+ "%s: The RCC peripheral only supports enable and reset in QEMU\n",
239
+ __func__
240
+ );
241
+ s->regs[addr >> 2] = value;
242
+ }
243
+}
244
+
245
+static const MemoryRegionOps stm32_rcc_ops = {
246
+ .read = stm32_rcc_read,
247
+ .write = stm32_rcc_write,
248
+ .endianness = DEVICE_NATIVE_ENDIAN,
249
+};
250
+
251
+static void stm32_rcc_init(Object *obj)
252
+{
253
+ STM32RccState *s = STM32_RCC(obj);
254
+
255
+ memory_region_init_io(&s->mmio, obj, &stm32_rcc_ops, s,
256
+ TYPE_STM32_RCC, STM32_RCC_PERIPHERAL_SIZE);
257
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
258
+
259
+ qdev_init_gpio_out(DEVICE(obj), s->reset_irq, STM32_RCC_NIRQS);
260
+ qdev_init_gpio_out(DEVICE(obj), s->enable_irq, STM32_RCC_NIRQS);
261
+
262
+ for (int i = 0; i < STM32_RCC_NIRQS; i++) {
263
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->reset_irq[i]);
264
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->enable_irq[i]);
265
+ }
266
+}
267
+
268
+static const VMStateDescription vmstate_stm32_rcc = {
269
+ .name = TYPE_STM32_RCC,
270
+ .version_id = 1,
271
+ .minimum_version_id = 1,
272
+ .fields = (const VMStateField[]) {
273
+ VMSTATE_UINT32_ARRAY(regs, STM32RccState, STM32_RCC_NREGS),
274
+ VMSTATE_END_OF_LIST()
275
+ }
276
+};
277
+
278
+static void stm32_rcc_class_init(ObjectClass *klass, void *data)
279
+{
280
+ DeviceClass *dc = DEVICE_CLASS(klass);
281
+
282
+ dc->vmsd = &vmstate_stm32_rcc;
283
+ device_class_set_legacy_reset(dc, stm32_rcc_reset);
284
+}
285
+
286
+static const TypeInfo stm32_rcc_info = {
287
+ .name = TYPE_STM32_RCC,
288
+ .parent = TYPE_SYS_BUS_DEVICE,
289
+ .instance_size = sizeof(STM32RccState),
290
+ .instance_init = stm32_rcc_init,
291
+ .class_init = stm32_rcc_class_init,
292
+};
293
+
294
+static void stm32_rcc_register_types(void)
295
+{
296
+ type_register_static(&stm32_rcc_info);
297
+}
298
+
299
+type_init(stm32_rcc_register_types)
300
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
301
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
302
--- a/hw/misc/Kconfig
33
--- a/.mailmap
303
+++ b/hw/misc/Kconfig
34
+++ b/.mailmap
304
@@ -XXX,XX +XXX,XX @@ config IMX
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
305
select SSI
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
306
select USB_EHCI_SYSBUS
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
307
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
308
+config STM32_RCC
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
309
+ bool
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
310
+
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
311
config STM32F2XX_SYSCFG
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
312
bool
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
313
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
314
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
315
index XXXXXXX..XXXXXXX 100644
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
316
--- a/hw/misc/meson.build
317
+++ b/hw/misc/meson.build
318
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
319
system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files(
320
'xlnx-versal-trng.c',
321
))
322
+system_ss.add(when: 'CONFIG_STM32_RCC', if_true: files('stm32_rcc.c'))
323
system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
324
system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
325
system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
326
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
327
index XXXXXXX..XXXXXXX 100644
328
--- a/hw/misc/trace-events
329
+++ b/hw/misc/trace-events
330
@@ -XXX,XX +XXX,XX @@ npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0
331
npcm7xx_pwm_update_freq(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Freq: old_freq: %u, new_freq: %u"
332
npcm7xx_pwm_update_duty(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Duty: old_duty: %u, new_duty: %u"
333
334
+# stm32_rcc.c
335
+stm32_rcc_read(uint64_t addr, uint64_t data) "reg read: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
336
+stm32_rcc_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
337
+stm32_rcc_pulse_enable(int line, int level) "Enable: %d to %d"
338
+stm32_rcc_pulse_reset(int line, int level) "Reset: %d to %d"
339
+
340
# stm32f4xx_syscfg.c
341
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interrupt: GPIO: %d, Line: %d; Level: %d"
342
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
343
--
47
--
344
2.34.1
48
2.34.1
345
49
346
50
diff view generated by jsdifflib
1
Convert blkdebug.txt to rST format. We put it into index-build.rst
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
because it falls under the "test" part of "QEMU Build and Test
3
System".
4
2
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
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
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Thomas Huth <thuth@redhat.com>
7
Message-id: 20240816132212.3602106-2-peter.maydell@linaro.org
8
---
10
---
9
MAINTAINERS | 1 +
11
MAINTAINERS | 2 ++
10
docs/devel/blkdebug.txt | 162 -----------------------------
12
1 file changed, 2 insertions(+)
11
docs/devel/testing/blkdebug.rst | 177 ++++++++++++++++++++++++++++++++
12
docs/devel/testing/index.rst | 1 +
13
4 files changed, 179 insertions(+), 162 deletions(-)
14
delete mode 100644 docs/devel/blkdebug.txt
15
create mode 100644 docs/devel/testing/blkdebug.rst
16
13
17
diff --git a/MAINTAINERS b/MAINTAINERS
14
diff --git a/MAINTAINERS b/MAINTAINERS
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/MAINTAINERS
16
--- a/MAINTAINERS
20
+++ b/MAINTAINERS
17
+++ b/MAINTAINERS
21
@@ -XXX,XX +XXX,XX @@ M: Hanna Reitz <hreitz@redhat.com>
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
22
L: qemu-block@nongnu.org
19
23
S: Supported
20
Xilinx CAN
24
F: block/blkdebug.c
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
25
+F: docs/devel/blkdebug.rst
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
26
23
S: Maintained
27
vpc
24
F: hw/net/can/xlnx-*
28
M: Kevin Wolf <kwolf@redhat.com>
25
F: include/hw/net/xlnx-*
29
diff --git a/docs/devel/blkdebug.txt b/docs/devel/blkdebug.txt
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
30
deleted file mode 100644
27
CAN bus subsystem and hardware
31
index XXXXXXX..XXXXXXX
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
32
--- a/docs/devel/blkdebug.txt
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
33
+++ /dev/null
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
34
@@ -XXX,XX +XXX,XX @@
31
S: Maintained
35
-Block I/O error injection using blkdebug
32
W: https://canbus.pages.fel.cvut.cz/
36
-----------------------------------------
33
F: net/can/*
37
-Copyright (C) 2014-2015 Red Hat Inc
38
-
39
-This work is licensed under the terms of the GNU GPL, version 2 or later. See
40
-the COPYING file in the top-level directory.
41
-
42
-The blkdebug block driver is a rule-based error injection engine. It can be
43
-used to exercise error code paths in block drivers including ENOSPC (out of
44
-space) and EIO.
45
-
46
-This document gives an overview of the features available in blkdebug.
47
-
48
-Background
49
-----------
50
-Block drivers have many error code paths that handle I/O errors. Image formats
51
-are especially complex since metadata I/O errors during cluster allocation or
52
-while updating tables happen halfway through request processing and require
53
-discipline to keep image files consistent.
54
-
55
-Error injection allows test cases to trigger I/O errors at specific points.
56
-This way, all error paths can be tested to make sure they are correct.
57
-
58
-Rules
59
------
60
-The blkdebug block driver takes a list of "rules" that tell the error injection
61
-engine when to fail an I/O request.
62
-
63
-Each I/O request is evaluated against the rules. If a rule matches the request
64
-then its "action" is executed.
65
-
66
-Rules can be placed in a configuration file; the configuration file
67
-follows the same .ini-like format used by QEMU's -readconfig option, and
68
-each section of the file represents a rule.
69
-
70
-The following configuration file defines a single rule:
71
-
72
- $ cat blkdebug.conf
73
- [inject-error]
74
- event = "read_aio"
75
- errno = "28"
76
-
77
-This rule fails all aio read requests with ENOSPC (28). Note that the errno
78
-value depends on the host. On Linux, see
79
-/usr/include/asm-generic/errno-base.h for errno values.
80
-
81
-Invoke QEMU as follows:
82
-
83
- $ qemu-system-x86_64
84
- -drive if=none,cache=none,file=blkdebug:blkdebug.conf:test.img,id=drive0 \
85
- -device virtio-blk-pci,drive=drive0,id=virtio-blk-pci0
86
-
87
-Rules support the following attributes:
88
-
89
- event - which type of operation to match (e.g. read_aio, write_aio,
90
- flush_to_os, flush_to_disk). See the "Events" section for
91
- information on events.
92
-
93
- state - (optional) the engine must be in this state number in order for this
94
- rule to match. See the "State transitions" section for information
95
- on states.
96
-
97
- errno - the numeric errno value to return when a request matches this rule.
98
- The errno values depend on the host since the numeric values are not
99
- standardized in the POSIX specification.
100
-
101
- sector - (optional) a sector number that the request must overlap in order to
102
- match this rule
103
-
104
- once - (optional, default "off") only execute this action on the first
105
- matching request
106
-
107
- immediately - (optional, default "off") return a NULL BlockAIOCB
108
- pointer and fail without an errno instead. This
109
- exercises the code path where BlockAIOCB fails and the
110
- caller's BlockCompletionFunc is not invoked.
111
-
112
-Events
113
-------
114
-Block drivers provide information about the type of I/O request they are about
115
-to make so rules can match specific types of requests. For example, the qcow2
116
-block driver tells blkdebug when it accesses the L1 table so rules can match
117
-only L1 table accesses and not other metadata or guest data requests.
118
-
119
-The core events are:
120
-
121
- read_aio - guest data read
122
-
123
- write_aio - guest data write
124
-
125
- flush_to_os - write out unwritten block driver state (e.g. cached metadata)
126
-
127
- flush_to_disk - flush the host block device's disk cache
128
-
129
-See qapi/block-core.json:BlkdebugEvent for the full list of events.
130
-You may need to grep block driver source code to understand the
131
-meaning of specific events.
132
-
133
-State transitions
134
------------------
135
-There are cases where more power is needed to match a particular I/O request in
136
-a longer sequence of requests. For example:
137
-
138
- write_aio
139
- flush_to_disk
140
- write_aio
141
-
142
-How do we match the 2nd write_aio but not the first? This is where state
143
-transitions come in.
144
-
145
-The error injection engine has an integer called the "state" that always starts
146
-initialized to 1. The state integer is internal to blkdebug and cannot be
147
-observed from outside but rules can interact with it for powerful matching
148
-behavior.
149
-
150
-Rules can be conditional on the current state and they can transition to a new
151
-state.
152
-
153
-When a rule's "state" attribute is non-zero then the current state must equal
154
-the attribute in order for the rule to match.
155
-
156
-For example, to match the 2nd write_aio:
157
-
158
- [set-state]
159
- event = "write_aio"
160
- state = "1"
161
- new_state = "2"
162
-
163
- [inject-error]
164
- event = "write_aio"
165
- state = "2"
166
- errno = "5"
167
-
168
-The first write_aio request matches the set-state rule and transitions from
169
-state 1 to state 2. Once state 2 has been entered, the set-state rule no
170
-longer matches since it requires state 1. But the inject-error rule now
171
-matches the next write_aio request and injects EIO (5).
172
-
173
-State transition rules support the following attributes:
174
-
175
- event - which type of operation to match (e.g. read_aio, write_aio,
176
- flush_to_os, flush_to_disk). See the "Events" section for
177
- information on events.
178
-
179
- state - (optional) the engine must be in this state number in order for this
180
- rule to match
181
-
182
- new_state - transition to this state number
183
-
184
-Suspend and resume
185
-------------------
186
-Exercising code paths in block drivers may require specific ordering amongst
187
-concurrent requests. The "breakpoint" feature allows requests to be halted on
188
-a blkdebug event and resumed later. This makes it possible to achieve
189
-deterministic ordering when multiple requests are in flight.
190
-
191
-Breakpoints on blkdebug events are associated with a user-defined "tag" string.
192
-This tag serves as an identifier by which the request can be resumed at a later
193
-point.
194
-
195
-See the qemu-io(1) break, resume, remove_break, and wait_break commands for
196
-details.
197
diff --git a/docs/devel/testing/blkdebug.rst b/docs/devel/testing/blkdebug.rst
198
new file mode 100644
199
index XXXXXXX..XXXXXXX
200
--- /dev/null
201
+++ b/docs/devel/testing/blkdebug.rst
202
@@ -XXX,XX +XXX,XX @@
203
+Block I/O error injection using ``blkdebug``
204
+============================================
205
+
206
+..
207
+ Copyright (C) 2014-2015 Red Hat Inc
208
+
209
+ This work is licensed under the terms of the GNU GPL, version 2 or later. See
210
+ the COPYING file in the top-level directory.
211
+
212
+The ``blkdebug`` block driver is a rule-based error injection engine. It can be
213
+used to exercise error code paths in block drivers including ``ENOSPC`` (out of
214
+space) and ``EIO``.
215
+
216
+This document gives an overview of the features available in ``blkdebug``.
217
+
218
+Background
219
+----------
220
+Block drivers have many error code paths that handle I/O errors. Image formats
221
+are especially complex since metadata I/O errors during cluster allocation or
222
+while updating tables happen halfway through request processing and require
223
+discipline to keep image files consistent.
224
+
225
+Error injection allows test cases to trigger I/O errors at specific points.
226
+This way, all error paths can be tested to make sure they are correct.
227
+
228
+Rules
229
+-----
230
+The ``blkdebug`` block driver takes a list of "rules" that tell the error injection
231
+engine when to fail an I/O request.
232
+
233
+Each I/O request is evaluated against the rules. If a rule matches the request
234
+then its "action" is executed.
235
+
236
+Rules can be placed in a configuration file; the configuration file
237
+follows the same .ini-like format used by QEMU's ``-readconfig`` option, and
238
+each section of the file represents a rule.
239
+
240
+The following configuration file defines a single rule::
241
+
242
+ $ cat blkdebug.conf
243
+ [inject-error]
244
+ event = "read_aio"
245
+ errno = "28"
246
+
247
+This rule fails all aio read requests with ``ENOSPC`` (28). Note that the errno
248
+value depends on the host. On Linux, see
249
+``/usr/include/asm-generic/errno-base.h`` for errno values.
250
+
251
+Invoke QEMU as follows::
252
+
253
+ $ qemu-system-x86_64
254
+ -drive if=none,cache=none,file=blkdebug:blkdebug.conf:test.img,id=drive0 \
255
+ -device virtio-blk-pci,drive=drive0,id=virtio-blk-pci0
256
+
257
+Rules support the following attributes:
258
+
259
+``event``
260
+ which type of operation to match (e.g. ``read_aio``, ``write_aio``,
261
+ ``flush_to_os``, ``flush_to_disk``). See `Events`_ for
262
+ information on events.
263
+
264
+``state``
265
+ (optional) the engine must be in this state number in order for this
266
+ rule to match. See `State transitions`_ for information
267
+ on states.
268
+
269
+``errno``
270
+ the numeric errno value to return when a request matches this rule.
271
+ The errno values depend on the host since the numeric values are not
272
+ standardized in the POSIX specification.
273
+
274
+``sector``
275
+ (optional) a sector number that the request must overlap in order to
276
+ match this rule
277
+
278
+``once``
279
+ (optional, default ``off``) only execute this action on the first
280
+ matching request
281
+
282
+``immediately``
283
+ (optional, default ``off``) return a NULL ``BlockAIOCB``
284
+ pointer and fail without an errno instead. This
285
+ exercises the code path where ``BlockAIOCB`` fails and the
286
+ caller's ``BlockCompletionFunc`` is not invoked.
287
+
288
+Events
289
+------
290
+Block drivers provide information about the type of I/O request they are about
291
+to make so rules can match specific types of requests. For example, the ``qcow2``
292
+block driver tells ``blkdebug`` when it accesses the L1 table so rules can match
293
+only L1 table accesses and not other metadata or guest data requests.
294
+
295
+The core events are:
296
+
297
+``read_aio``
298
+ guest data read
299
+
300
+``write_aio``
301
+ guest data write
302
+
303
+``flush_to_os``
304
+ write out unwritten block driver state (e.g. cached metadata)
305
+
306
+``flush_to_disk``
307
+ flush the host block device's disk cache
308
+
309
+See ``qapi/block-core.json:BlkdebugEvent`` for the full list of events.
310
+You may need to grep block driver source code to understand the
311
+meaning of specific events.
312
+
313
+State transitions
314
+-----------------
315
+There are cases where more power is needed to match a particular I/O request in
316
+a longer sequence of requests. For example::
317
+
318
+ write_aio
319
+ flush_to_disk
320
+ write_aio
321
+
322
+How do we match the 2nd ``write_aio`` but not the first? This is where state
323
+transitions come in.
324
+
325
+The error injection engine has an integer called the "state" that always starts
326
+initialized to 1. The state integer is internal to ``blkdebug`` and cannot be
327
+observed from outside but rules can interact with it for powerful matching
328
+behavior.
329
+
330
+Rules can be conditional on the current state and they can transition to a new
331
+state.
332
+
333
+When a rule's "state" attribute is non-zero then the current state must equal
334
+the attribute in order for the rule to match.
335
+
336
+For example, to match the 2nd write_aio::
337
+
338
+ [set-state]
339
+ event = "write_aio"
340
+ state = "1"
341
+ new_state = "2"
342
+
343
+ [inject-error]
344
+ event = "write_aio"
345
+ state = "2"
346
+ errno = "5"
347
+
348
+The first ``write_aio`` request matches the ``set-state`` rule and transitions from
349
+state 1 to state 2. Once state 2 has been entered, the ``set-state`` rule no
350
+longer matches since it requires state 1. But the ``inject-error`` rule now
351
+matches the next ``write_aio`` request and injects ``EIO`` (5).
352
+
353
+State transition rules support the following attributes:
354
+
355
+``event``
356
+ which type of operation to match (e.g. ``read_aio``, ``write_aio``,
357
+ ``flush_to_os`, ``flush_to_disk``). See `Events`_ for
358
+ information on events.
359
+
360
+``state``
361
+ (optional) the engine must be in this state number in order for this
362
+ rule to match
363
+
364
+``new_state``
365
+ transition to this state number
366
+
367
+Suspend and resume
368
+------------------
369
+Exercising code paths in block drivers may require specific ordering amongst
370
+concurrent requests. The "breakpoint" feature allows requests to be halted on
371
+a ``blkdebug`` event and resumed later. This makes it possible to achieve
372
+deterministic ordering when multiple requests are in flight.
373
+
374
+Breakpoints on ``blkdebug`` events are associated with a user-defined ``tag`` string.
375
+This tag serves as an identifier by which the request can be resumed at a later
376
+point.
377
+
378
+See the ``qemu-io(1)`` ``break``, ``resume``, ``remove_break``, and ``wait_break``
379
+commands for details.
380
diff --git a/docs/devel/testing/index.rst b/docs/devel/testing/index.rst
381
index XXXXXXX..XXXXXXX 100644
382
--- a/docs/devel/testing/index.rst
383
+++ b/docs/devel/testing/index.rst
384
@@ -XXX,XX +XXX,XX @@ testing infrastructure.
385
acpi-bits
386
ci
387
fuzzing
388
+ blkdebug
389
--
34
--
390
2.34.1
35
2.34.1
diff view generated by jsdifflib