1
The following changes since commit 977542ded7e6b28d2bc077bcda24568c716e393c:
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 'pull-testing-updates-120124-2' of https://gitlab.com/stsquad/qemu into staging (2024-01-12 14:02:53 +0000)
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-20240116
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 7ec39730a9cc443c752d4cad2bf1c00467551ef5:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
10
17
11
load_elf: fix iterator's type for elf file processing (2024-01-15 17:14:22 +0000)
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
* docs/devel/docs: Document .hx file syntax
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
16
* arm_pamax() no longer needs to do feature propagation
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
17
* docs/system/arm/virt.rst: Improve 'highmem' option docs
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
18
* STM32L4x5 Implement SYSCFG and EXTI devices
25
* fpu: Minor NaN-related cleanups
19
* Nuvoton: Implement PCI Mailbox module
26
* MAINTAINERS: email address updates
20
* Nuvoton: Implement GMAC module
21
* hw/timer: fix systick trace message
22
* hw/arm/virt: Consolidate valid CPU types
23
* load_elf: fix iterator's type for elf file processing
24
27
25
----------------------------------------------------------------
28
----------------------------------------------------------------
26
Anastasia Belova (1):
29
Bernhard Beschow (5):
27
load_elf: fix iterator's type for elf file processing
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
28
35
29
Gavin Shan (1):
36
Leif Lindholm (1):
30
hw/arm/virt: Consolidate valid CPU types
37
MAINTAINERS: update email address for Leif Lindholm
31
38
32
Hao Wu (3):
39
Peter Maydell (54):
33
hw/misc: Add Nuvoton's PCI Mailbox Module
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
34
hw/misc: Add qtest for NPCM7xx PCI Mailbox
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
35
hw/arm: Add GMAC devices to NPCM7XX SoC
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
36
94
37
Inès Varhol (6):
95
Richard Henderson (11):
38
hw/misc: Implement STM32L4x5 EXTI
96
target/arm: Copy entire float_status in is_ebf
39
hw/arm: Connect STM32L4x5 EXTI to STM32L4x5 SoC
97
softfloat: Inline pickNaNMulAdd
40
tests/qtest: Add STM32L4x5 EXTI QTest testcase
98
softfloat: Use goto for default nan case in pick_nan_muladd
41
hw/misc: Implement STM32L4x5 SYSCFG
99
softfloat: Remove which from parts_pick_nan_muladd
42
hw/arm: Connect STM32L4x5 SYSCFG to STM32L4x5 SoC
100
softfloat: Pad array size in pick_nan_muladd
43
tests/qtest: Add STM32L4x5 SYSCFG QTest testcase
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
44
107
45
Nabih Estefan Diaz (4):
108
Vikram Garhwal (1):
46
tests/qtest: Creating qtest for GMAC Module
109
MAINTAINERS: Add correct email address for Vikram Garhwal
47
hw/net: GMAC Rx Implementation
48
hw/net: GMAC Tx Implementation
49
tests/qtest: Adding PCS Module test to GMAC Qtest
50
110
51
Peter Maydell (5):
111
MAINTAINERS | 4 +-
52
docs/devel/docs: Document .hx file syntax
112
include/fpu/softfloat-helpers.h | 38 +++-
53
target/arm: arm_pamax() no longer needs to do feature propagation
113
include/fpu/softfloat-types.h | 89 +++++++-
54
docs/system/arm/virt.rst: Improve 'highmem' option docs
114
include/hw/net/imx_fec.h | 9 +-
55
hw/arm: Add PCI mailbox module to Nuvoton SoC
115
include/hw/net/lan9118_phy.h | 37 ++++
56
hw/net: Add NPCMXXX GMAC device
116
include/hw/net/mii.h | 6 +
57
117
target/mips/fpu_helper.h | 20 ++
58
Samuel Tardieu (1):
118
target/sparc/helper.h | 4 +-
59
hw/timer: fix systick trace message
119
fpu/softfloat.c | 19 ++
60
120
hw/net/imx_fec.c | 146 ++------------
61
MAINTAINERS | 1 +
121
hw/net/lan9118.c | 137 ++-----------
62
docs/devel/docs.rst | 60 +++
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
63
docs/devel/index-build.rst | 1 +
123
linux-user/arm/nwfpe/fpa11.c | 5 +
64
docs/system/arm/b-l475e-iot01a.rst | 7 +-
124
target/alpha/cpu.c | 2 +
65
docs/system/arm/nuvoton.rst | 2 +
125
target/arm/cpu.c | 10 +
66
docs/system/arm/virt.rst | 8 +-
126
target/arm/tcg/vec_helper.c | 20 +-
67
include/hw/arm/npcm7xx.h | 4 +
127
target/hexagon/cpu.c | 2 +
68
include/hw/arm/stm32l4x5_soc.h | 5 +
128
target/hppa/fpu_helper.c | 12 ++
69
include/hw/elf_ops.h | 2 +-
129
target/i386/tcg/fpu_helper.c | 12 ++
70
include/hw/misc/npcm7xx_pci_mbox.h | 81 ++++
130
target/loongarch/tcg/fpu_helper.c | 14 +-
71
include/hw/misc/stm32l4x5_exti.h | 51 ++
131
target/m68k/cpu.c | 14 +-
72
include/hw/misc/stm32l4x5_syscfg.h | 54 +++
132
target/m68k/fpu_helper.c | 6 +-
73
include/hw/net/npcm_gmac.h | 340 +++++++++++++
133
target/m68k/helper.c | 6 +-
74
hw/arm/npcm7xx.c | 53 +-
134
target/microblaze/cpu.c | 2 +
75
hw/arm/stm32l4x5_soc.c | 73 ++-
135
target/mips/msa.c | 10 +
76
hw/arm/virt.c | 8 +-
136
target/openrisc/cpu.c | 2 +
77
hw/misc/npcm7xx_pci_mbox.c | 324 +++++++++++++
137
target/ppc/cpu_init.c | 19 ++
78
hw/misc/stm32l4x5_exti.c | 290 +++++++++++
138
target/ppc/fpu_helper.c | 3 +-
79
hw/misc/stm32l4x5_syscfg.c | 266 ++++++++++
139
target/riscv/cpu.c | 2 +
80
hw/net/npcm_gmac.c | 939 ++++++++++++++++++++++++++++++++++++
140
target/rx/cpu.c | 2 +
81
target/arm/ptw.c | 14 +-
141
target/s390x/cpu.c | 5 +
82
tests/qtest/npcm7xx_pci_mbox-test.c | 238 +++++++++
142
target/sh4/cpu.c | 2 +
83
tests/qtest/npcm_gmac-test.c | 341 +++++++++++++
143
target/sparc/cpu.c | 6 +
84
tests/qtest/stm32l4x5_exti-test.c | 524 ++++++++++++++++++++
144
target/sparc/fop_helper.c | 8 +-
85
tests/qtest/stm32l4x5_syscfg-test.c | 331 +++++++++++++
145
target/sparc/translate.c | 4 +-
86
hmp-commands-info.hx | 10 +-
146
target/tricore/helper.c | 2 +
87
hmp-commands.hx | 10 +-
147
target/xtensa/cpu.c | 4 +
88
hw/arm/Kconfig | 2 +
148
target/xtensa/fpu_helper.c | 3 +-
89
hw/misc/Kconfig | 6 +
149
tests/fp/fp-bench.c | 7 +
90
hw/misc/meson.build | 3 +
150
tests/fp/fp-test-log2.c | 1 +
91
hw/misc/trace-events | 16 +
151
tests/fp/fp-test.c | 7 +
92
hw/net/meson.build | 2 +-
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
93
hw/net/trace-events | 19 +
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
94
hw/timer/trace-events | 2 +-
154
.mailmap | 5 +-
95
qemu-img-cmds.hx | 2 +
155
hw/net/Kconfig | 5 +
96
qemu-options.hx | 2 +
156
hw/net/meson.build | 1 +
97
tests/qtest/meson.build | 8 +
157
hw/net/trace-events | 10 +-
98
37 files changed, 4066 insertions(+), 33 deletions(-)
158
47 files changed, 778 insertions(+), 730 deletions(-)
99
create mode 100644 docs/devel/docs.rst
159
create mode 100644 include/hw/net/lan9118_phy.h
100
create mode 100644 include/hw/misc/npcm7xx_pci_mbox.h
160
create mode 100644 hw/net/lan9118_phy.c
101
create mode 100644 include/hw/misc/stm32l4x5_exti.h
102
create mode 100644 include/hw/misc/stm32l4x5_syscfg.h
103
create mode 100644 include/hw/net/npcm_gmac.h
104
create mode 100644 hw/misc/npcm7xx_pci_mbox.c
105
create mode 100644 hw/misc/stm32l4x5_exti.c
106
create mode 100644 hw/misc/stm32l4x5_syscfg.c
107
create mode 100644 hw/net/npcm_gmac.c
108
create mode 100644 tests/qtest/npcm7xx_pci_mbox-test.c
109
create mode 100644 tests/qtest/npcm_gmac-test.c
110
create mode 100644 tests/qtest/stm32l4x5_exti-test.c
111
create mode 100644 tests/qtest/stm32l4x5_syscfg-test.c
112
diff view generated by jsdifflib
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Acked-by: Alistair Francis <alistair.francis@wdc.com>
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
a common implementation by extracting a device model into its own files.
5
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
6
Message-id: 20240109194438.70934-2-ines.varhol@telecom-paris.fr
6
Some migration state has been moved into the new device model which breaks
7
migration compatibility for the following machines:
8
* smdkc210
9
* realview-*
10
* vexpress-*
11
* kzm
12
* mps2-*
13
14
While breaking migration ABI, fix the size of the MII registers to be 16 bit,
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>
7
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
22
---
10
docs/system/arm/b-l475e-iot01a.rst | 2 +-
23
include/hw/net/lan9118_phy.h | 37 ++++++++
11
include/hw/misc/stm32l4x5_syscfg.h | 54 ++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
12
hw/misc/stm32l4x5_syscfg.c | 266 +++++++++++++++++++++++++++++
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
13
hw/misc/Kconfig | 3 +
26
hw/net/Kconfig | 4 +
14
hw/misc/meson.build | 1 +
27
hw/net/meson.build | 1 +
15
hw/misc/trace-events | 6 +
28
5 files changed, 233 insertions(+), 115 deletions(-)
16
6 files changed, 331 insertions(+), 1 deletion(-)
29
create mode 100644 include/hw/net/lan9118_phy.h
17
create mode 100644 include/hw/misc/stm32l4x5_syscfg.h
30
create mode 100644 hw/net/lan9118_phy.c
18
create mode 100644 hw/misc/stm32l4x5_syscfg.c
19
31
20
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/docs/system/arm/b-l475e-iot01a.rst
23
+++ b/docs/system/arm/b-l475e-iot01a.rst
24
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
25
26
- Cortex-M4F based STM32L4x5 SoC
27
- STM32L4x5 EXTI (Extended interrupts and events controller)
28
+- STM32L4x5 SYSCFG (System configuration controller)
29
30
Missing devices
31
"""""""""""""""
32
@@ -XXX,XX +XXX,XX @@ The B-L475E-IOT01A does *not* support the following devices:
33
34
- Reset and clock control (RCC)
35
- Serial ports (UART)
36
-- System configuration controller (SYSCFG)
37
- General-purpose I/Os (GPIO)
38
- Analog to Digital Converter (ADC)
39
- SPI controller
40
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
41
new file mode 100644
33
new file mode 100644
42
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
43
--- /dev/null
35
--- /dev/null
44
+++ b/include/hw/misc/stm32l4x5_syscfg.h
36
+++ b/include/hw/net/lan9118_phy.h
45
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
46
+/*
38
+/*
47
+ * STM32L4x5 SYSCFG (System Configuration Controller)
39
+ * SMSC LAN9118 PHY emulation
48
+ *
40
+ *
49
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
50
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
42
+ * Written by Paul Brook
51
+ *
52
+ * SPDX-License-Identifier: GPL-2.0-or-later
53
+ *
43
+ *
54
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
55
+ * See the COPYING file in the top-level directory.
45
+ * See the COPYING file in the top-level directory.
56
+ *
57
+ * This work is based on the stm32f4xx_syscfg by Alistair Francis.
58
+ * Original code is licensed under the MIT License:
59
+ *
60
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
61
+ */
46
+ */
62
+
47
+
63
+/*
48
+#ifndef HW_NET_LAN9118_PHY_H
64
+ * The reference used is the STMicroElectronics RM0351 Reference manual
49
+#define HW_NET_LAN9118_PHY_H
65
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
50
+
66
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
51
+#include "qom/object.h"
67
+ */
68
+
69
+#ifndef HW_STM32L4X5_SYSCFG_H
70
+#define HW_STM32L4X5_SYSCFG_H
71
+
72
+#include "hw/sysbus.h"
52
+#include "hw/sysbus.h"
73
+#include "qom/object.h"
53
+
74
+
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
75
+#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
76
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
56
+
77
+
57
+typedef struct Lan9118PhyState {
78
+#define NUM_GPIOS 8
79
+#define GPIO_NUM_PINS 16
80
+#define SYSCFG_NUM_EXTICR 4
81
+
82
+struct Stm32l4x5SyscfgState {
83
+ SysBusDevice parent_obj;
58
+ SysBusDevice parent_obj;
84
+
59
+
85
+ MemoryRegion mmio;
60
+ uint16_t status;
86
+
61
+ uint16_t control;
87
+ uint32_t memrmp;
62
+ uint16_t advertise;
88
+ uint32_t cfgr1;
63
+ uint16_t ints;
89
+ uint32_t exticr[SYSCFG_NUM_EXTICR];
64
+ uint16_t int_mask;
90
+ uint32_t scsr;
65
+ qemu_irq irq;
91
+ uint32_t cfgr2;
66
+ bool link_down;
92
+ uint32_t swpr;
67
+} Lan9118PhyState;
93
+ uint32_t skr;
68
+
94
+ uint32_t swpr2;
69
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down);
95
+
70
+void lan9118_phy_reset(Lan9118PhyState *s);
96
+ qemu_irq gpio_out[GPIO_NUM_PINS];
71
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg);
97
+};
72
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val);
98
+
73
+
99
+#endif
74
+#endif
100
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.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
101
new file mode 100644
312
new file mode 100644
102
index XXXXXXX..XXXXXXX
313
index XXXXXXX..XXXXXXX
103
--- /dev/null
314
--- /dev/null
104
+++ b/hw/misc/stm32l4x5_syscfg.c
315
+++ b/hw/net/lan9118_phy.c
105
@@ -XXX,XX +XXX,XX @@
316
@@ -XXX,XX +XXX,XX @@
106
+/*
317
+/*
107
+ * STM32L4x5 SYSCFG (System Configuration Controller)
318
+ * SMSC LAN9118 PHY emulation
108
+ *
319
+ *
109
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
110
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
321
+ * Written by Paul Brook
111
+ *
322
+ *
112
+ * SPDX-License-Identifier: GPL-2.0-or-later
323
+ * This code is licensed under the GNU GPL v2
113
+ *
324
+ *
114
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
115
+ * See the COPYING file in the top-level directory.
326
+ * GNU GPL, version 2 or (at your option) any later version.
116
+ *
117
+ * This work is based on the stm32f4xx_syscfg by Alistair Francis.
118
+ * Original code is licensed under the MIT License:
119
+ *
120
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
121
+ */
327
+ */
122
+
328
+
123
+/*
124
+ * The reference used is the STMicroElectronics RM0351 Reference manual
125
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
126
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
127
+ */
128
+
129
+#include "qemu/osdep.h"
329
+#include "qemu/osdep.h"
330
+#include "hw/net/lan9118_phy.h"
331
+#include "hw/irq.h"
332
+#include "hw/resettable.h"
333
+#include "migration/vmstate.h"
130
+#include "qemu/log.h"
334
+#include "qemu/log.h"
131
+#include "trace.h"
335
+
132
+#include "hw/irq.h"
336
+#define PHY_INT_ENERGYON (1 << 7)
133
+#include "migration/vmstate.h"
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
134
+#include "hw/misc/stm32l4x5_syscfg.h"
338
+#define PHY_INT_FAULT (1 << 5)
135
+
339
+#define PHY_INT_DOWN (1 << 4)
136
+#define SYSCFG_MEMRMP 0x00
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
137
+#define SYSCFG_CFGR1 0x04
341
+#define PHY_INT_PARFAULT (1 << 2)
138
+#define SYSCFG_EXTICR1 0x08
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
139
+#define SYSCFG_EXTICR2 0x0C
343
+
140
+#define SYSCFG_EXTICR3 0x10
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
141
+#define SYSCFG_EXTICR4 0x14
345
+{
142
+#define SYSCFG_SCSR 0x18
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
143
+#define SYSCFG_CFGR2 0x1C
347
+}
144
+#define SYSCFG_SWPR 0x20
348
+
145
+#define SYSCFG_SKR 0x24
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
146
+#define SYSCFG_SWPR2 0x28
350
+{
147
+
351
+ uint16_t val;
148
+/* 00000000_00000000_00000001_00000111 */
352
+
149
+#define ACTIVABLE_BITS_MEMRP 0x00000107
353
+ switch (reg) {
150
+
354
+ case 0: /* Basic Control */
151
+/* 11111100_11111111_00000001_00000000 */
355
+ return s->control;
152
+#define ACTIVABLE_BITS_CFGR1 0xFCFF0100
356
+ case 1: /* Basic Status */
153
+/* 00000000_00000000_00000000_00000001 */
357
+ return s->status;
154
+#define FIREWALL_DISABLE_CFGR1 0x00000001
358
+ case 2: /* ID1 */
155
+
359
+ return 0x0007;
156
+/* 00000000_00000000_11111111_11111111 */
360
+ case 3: /* ID2 */
157
+#define ACTIVABLE_BITS_EXTICR 0x0000FFFF
361
+ return 0xc0d1;
158
+
362
+ case 4: /* Auto-neg advertisement */
159
+/* 00000000_00000000_00000000_00000011 */
363
+ return s->advertise;
160
+/* #define ACTIVABLE_BITS_SCSR 0x00000003 */
364
+ case 5: /* Auto-neg Link Partner Ability */
161
+
365
+ return 0x0f71;
162
+/* 00000000_00000000_00000000_00001111 */
366
+ case 6: /* Auto-neg Expansion */
163
+#define ECC_LOCK_CFGR2 0x0000000F
367
+ return 1;
164
+/* 00000000_00000000_00000001_00000000 */
368
+ /* TODO 17, 18, 27, 29, 30, 31 */
165
+#define SRAM2_PARITY_ERROR_FLAG_CFGR2 0x00000100
369
+ case 29: /* Interrupt source. */
166
+
370
+ val = s->ints;
167
+/* 00000000_00000000_00000000_11111111 */
371
+ s->ints = 0;
168
+#define ACTIVABLE_BITS_SKR 0x000000FF
372
+ lan9118_phy_update_irq(s);
169
+
373
+ return val;
170
+#define NUM_LINES_PER_EXTICR_REG 4
374
+ case 30: /* Interrupt mask */
171
+
375
+ return s->int_mask;
172
+static void stm32l4x5_syscfg_hold_reset(Object *obj)
173
+{
174
+ Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
175
+
176
+ s->memrmp = 0x00000000;
177
+ s->cfgr1 = 0x7C000001;
178
+ s->exticr[0] = 0x00000000;
179
+ s->exticr[1] = 0x00000000;
180
+ s->exticr[2] = 0x00000000;
181
+ s->exticr[3] = 0x00000000;
182
+ s->scsr = 0x00000000;
183
+ s->cfgr2 = 0x00000000;
184
+ s->swpr = 0x00000000;
185
+ s->skr = 0x00000000;
186
+ s->swpr2 = 0x00000000;
187
+}
188
+
189
+static void stm32l4x5_syscfg_set_irq(void *opaque, int irq, int level)
190
+{
191
+ Stm32l4x5SyscfgState *s = opaque;
192
+ const uint8_t gpio = irq / GPIO_NUM_PINS;
193
+ const int line = irq % GPIO_NUM_PINS;
194
+
195
+ const int exticr_reg = line / NUM_LINES_PER_EXTICR_REG;
196
+ const int startbit = (line % NUM_LINES_PER_EXTICR_REG) * 4;
197
+
198
+ g_assert(gpio < NUM_GPIOS);
199
+ trace_stm32l4x5_syscfg_set_irq(gpio, line, level);
200
+
201
+ if (extract32(s->exticr[exticr_reg], startbit, 4) == gpio) {
202
+ trace_stm32l4x5_syscfg_forward_exti(line);
203
+ qemu_set_irq(s->gpio_out[line], level);
204
+ }
205
+}
206
+
207
+static uint64_t stm32l4x5_syscfg_read(void *opaque, hwaddr addr,
208
+ unsigned int size)
209
+{
210
+ Stm32l4x5SyscfgState *s = opaque;
211
+
212
+ trace_stm32l4x5_syscfg_read(addr);
213
+
214
+ switch (addr) {
215
+ case SYSCFG_MEMRMP:
216
+ return s->memrmp;
217
+ case SYSCFG_CFGR1:
218
+ return s->cfgr1;
219
+ case SYSCFG_EXTICR1...SYSCFG_EXTICR4:
220
+ return s->exticr[(addr - SYSCFG_EXTICR1) / 4];
221
+ case SYSCFG_SCSR:
222
+ return s->scsr;
223
+ case SYSCFG_CFGR2:
224
+ return s->cfgr2;
225
+ case SYSCFG_SWPR:
226
+ return s->swpr;
227
+ case SYSCFG_SKR:
228
+ return s->skr;
229
+ case SYSCFG_SWPR2:
230
+ return s->swpr2;
231
+ default:
376
+ default:
232
+ qemu_log_mask(LOG_GUEST_ERROR,
377
+ qemu_log_mask(LOG_GUEST_ERROR,
233
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
378
+ "lan9118_phy_read: PHY read reg %d\n", reg);
234
+ return 0;
379
+ return 0;
235
+ }
380
+ }
236
+}
381
+}
237
+static void stm32l4x5_syscfg_write(void *opaque, hwaddr addr,
382
+
238
+ uint64_t value, unsigned int size)
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
239
+{
384
+{
240
+ Stm32l4x5SyscfgState *s = opaque;
385
+ switch (reg) {
241
+
386
+ case 0: /* Basic Control */
242
+ trace_stm32l4x5_syscfg_write(addr, value);
387
+ if (val & 0x8000) {
243
+
388
+ lan9118_phy_reset(s);
244
+ switch (addr) {
389
+ break;
245
+ case SYSCFG_MEMRMP:
390
+ }
246
+ qemu_log_mask(LOG_UNIMP,
391
+ s->control = val & 0x7980;
247
+ "%s: Changing the memory mapping isn't supported\n",
392
+ /* Complete autonegotiation immediately. */
248
+ __func__);
393
+ if (val & 0x1000) {
249
+ s->memrmp = value & ACTIVABLE_BITS_MEMRP;
394
+ s->status |= 0x0020;
250
+ return;
395
+ }
251
+ case SYSCFG_CFGR1:
396
+ break;
252
+ qemu_log_mask(LOG_UNIMP,
397
+ case 4: /* Auto-neg advertisement */
253
+ "%s: Functions in CFGRx aren't supported\n",
398
+ s->advertise = (val & 0x2d7f) | 0x80;
254
+ __func__);
399
+ break;
255
+ /* bit 0 (firewall dis.) is cleared by software, set only by reset. */
400
+ /* TODO 17, 18, 27, 31 */
256
+ s->cfgr1 = (s->cfgr1 & value & FIREWALL_DISABLE_CFGR1) |
401
+ case 30: /* Interrupt mask */
257
+ (value & ACTIVABLE_BITS_CFGR1);
402
+ s->int_mask = val & 0xff;
258
+ return;
403
+ lan9118_phy_update_irq(s);
259
+ case SYSCFG_EXTICR1...SYSCFG_EXTICR4:
404
+ break;
260
+ s->exticr[(addr - SYSCFG_EXTICR1) / 4] =
261
+ (value & ACTIVABLE_BITS_EXTICR);
262
+ return;
263
+ case SYSCFG_SCSR:
264
+ qemu_log_mask(LOG_UNIMP,
265
+ "%s: Erasing SRAM2 isn't supported\n",
266
+ __func__);
267
+ /*
268
+ * only non reserved bits are :
269
+ * bit 0 (write-protected by a passkey), bit 1 (meant to be read)
270
+ * so it serves no purpose yet to add :
271
+ * s->scsr = value & 0x3;
272
+ */
273
+ return;
274
+ case SYSCFG_CFGR2:
275
+ qemu_log_mask(LOG_UNIMP,
276
+ "%s: Functions in CFGRx aren't supported\n",
277
+ __func__);
278
+ /* bit 8 (SRAM2 PEF) is cleared by software by writing a '1'.*/
279
+ /* bits[3:0] (ECC Lock) are set by software, cleared only by reset.*/
280
+ s->cfgr2 = (s->cfgr2 | (value & ECC_LOCK_CFGR2)) &
281
+ ~(value & SRAM2_PARITY_ERROR_FLAG_CFGR2);
282
+ return;
283
+ case SYSCFG_SWPR:
284
+ qemu_log_mask(LOG_UNIMP,
285
+ "%s: Write protecting SRAM2 isn't supported\n",
286
+ __func__);
287
+ /* These bits are set by software and cleared only by reset.*/
288
+ s->swpr |= value;
289
+ return;
290
+ case SYSCFG_SKR:
291
+ qemu_log_mask(LOG_UNIMP,
292
+ "%s: Erasing SRAM2 isn't supported\n",
293
+ __func__);
294
+ s->skr = value & ACTIVABLE_BITS_SKR;
295
+ return;
296
+ case SYSCFG_SWPR2:
297
+ qemu_log_mask(LOG_UNIMP,
298
+ "%s: Write protecting SRAM2 isn't supported\n",
299
+ __func__);
300
+ /* These bits are set by software and cleared only by reset.*/
301
+ s->swpr2 |= value;
302
+ return;
303
+ default:
405
+ default:
304
+ qemu_log_mask(LOG_GUEST_ERROR,
406
+ qemu_log_mask(LOG_GUEST_ERROR,
305
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
306
+ }
408
+ }
307
+}
409
+}
308
+
410
+
309
+static const MemoryRegionOps stm32l4x5_syscfg_ops = {
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
310
+ .read = stm32l4x5_syscfg_read,
412
+{
311
+ .write = stm32l4x5_syscfg_write,
413
+ s->link_down = link_down;
312
+ .endianness = DEVICE_NATIVE_ENDIAN,
414
+
313
+ .impl.min_access_size = 4,
415
+ /* Autonegotiation status mirrors link status. */
314
+ .impl.max_access_size = 4,
416
+ if (link_down) {
315
+ .impl.unaligned = false,
417
+ s->status &= ~0x0024;
316
+ .valid.min_access_size = 4,
418
+ s->ints |= PHY_INT_DOWN;
317
+ .valid.max_access_size = 4,
419
+ } else {
318
+ .valid.unaligned = false,
420
+ s->status |= 0x0024;
319
+};
421
+ s->ints |= PHY_INT_ENERGYON;
320
+
422
+ s->ints |= PHY_INT_AUTONEG_COMPLETE;
321
+static void stm32l4x5_syscfg_init(Object *obj)
423
+ }
322
+{
424
+ lan9118_phy_update_irq(s);
323
+ Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
425
+}
324
+
426
+
325
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_syscfg_ops, s,
427
+void lan9118_phy_reset(Lan9118PhyState *s)
326
+ TYPE_STM32L4X5_SYSCFG, 0x400);
428
+{
327
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
429
+ s->control = 0x3000;
328
+
430
+ s->status = 0x7809;
329
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_syscfg_set_irq,
431
+ s->advertise = 0x01e1;
330
+ GPIO_NUM_PINS * NUM_GPIOS);
432
+ s->int_mask = 0;
331
+ qdev_init_gpio_out(DEVICE(obj), s->gpio_out, GPIO_NUM_PINS);
433
+ s->ints = 0;
332
+}
434
+ lan9118_phy_update_link(s, s->link_down);
333
+
435
+}
334
+static const VMStateDescription vmstate_stm32l4x5_syscfg = {
436
+
335
+ .name = TYPE_STM32L4X5_SYSCFG,
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",
336
+ .version_id = 1,
453
+ .version_id = 1,
337
+ .minimum_version_id = 1,
454
+ .minimum_version_id = 1,
338
+ .fields = (VMStateField[]) {
455
+ .fields = (const VMStateField[]) {
339
+ VMSTATE_UINT32(memrmp, Stm32l4x5SyscfgState),
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
340
+ VMSTATE_UINT32(cfgr1, Stm32l4x5SyscfgState),
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
341
+ VMSTATE_UINT32_ARRAY(exticr, Stm32l4x5SyscfgState,
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
342
+ SYSCFG_NUM_EXTICR),
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
343
+ VMSTATE_UINT32(scsr, Stm32l4x5SyscfgState),
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
344
+ VMSTATE_UINT32(cfgr2, Stm32l4x5SyscfgState),
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
345
+ VMSTATE_UINT32(swpr, Stm32l4x5SyscfgState),
346
+ VMSTATE_UINT32(skr, Stm32l4x5SyscfgState),
347
+ VMSTATE_UINT32(swpr2, Stm32l4x5SyscfgState),
348
+ VMSTATE_END_OF_LIST()
462
+ VMSTATE_END_OF_LIST()
349
+ }
463
+ }
350
+};
464
+};
351
+
465
+
352
+static void stm32l4x5_syscfg_class_init(ObjectClass *klass, void *data)
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
353
+{
467
+{
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
354
+ DeviceClass *dc = DEVICE_CLASS(klass);
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
355
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
470
+
356
+
471
+ rc->phases.hold = lan9118_phy_reset_hold;
357
+ dc->vmsd = &vmstate_stm32l4x5_syscfg;
472
+ dc->vmsd = &vmstate_lan9118_phy;
358
+ rc->phases.hold = stm32l4x5_syscfg_hold_reset;
473
+}
359
+}
474
+
360
+
475
+static const TypeInfo types[] = {
361
+static const TypeInfo stm32l4x5_syscfg_info[] = {
362
+ {
476
+ {
363
+ .name = TYPE_STM32L4X5_SYSCFG,
477
+ .name = TYPE_LAN9118_PHY,
364
+ .parent = TYPE_SYS_BUS_DEVICE,
478
+ .parent = TYPE_SYS_BUS_DEVICE,
365
+ .instance_size = sizeof(Stm32l4x5SyscfgState),
479
+ .instance_size = sizeof(Lan9118PhyState),
366
+ .instance_init = stm32l4x5_syscfg_init,
480
+ .instance_init = lan9118_phy_init,
367
+ .class_init = stm32l4x5_syscfg_class_init,
481
+ .class_init = lan9118_phy_class_init,
368
+ }
482
+ }
369
+};
483
+};
370
+
484
+
371
+DEFINE_TYPES(stm32l4x5_syscfg_info)
485
+DEFINE_TYPES(types)
372
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
373
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
374
--- a/hw/misc/Kconfig
488
--- a/hw/net/Kconfig
375
+++ b/hw/misc/Kconfig
489
+++ b/hw/net/Kconfig
376
@@ -XXX,XX +XXX,XX @@ config STM32F4XX_EXTI
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
377
config STM32L4X5_EXTI
491
config SMC91C111
378
bool
492
bool
379
493
380
+config STM32L4X5_SYSCFG
494
+config LAN9118_PHY
381
+ bool
495
+ bool
382
+
496
+
383
config MIPS_ITU
497
config LAN9118
384
bool
498
bool
385
499
+ select LAN9118_PHY
386
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
500
select PTIMER
501
502
config NE2000_ISA
503
diff --git a/hw/net/meson.build b/hw/net/meson.build
387
index XXXXXXX..XXXXXXX 100644
504
index XXXXXXX..XXXXXXX 100644
388
--- a/hw/misc/meson.build
505
--- a/hw/net/meson.build
389
+++ b/hw/misc/meson.build
506
+++ b/hw/net/meson.build
390
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
391
system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
508
392
system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
393
system_ss.add(when: 'CONFIG_STM32L4X5_EXTI', if_true: files('stm32l4x5_exti.c'))
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
394
+system_ss.add(when: 'CONFIG_STM32L4X5_SYSCFG', if_true: files('stm32l4x5_syscfg.c'))
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
395
system_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c'))
512
system_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c'))
396
system_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c'))
513
system_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c'))
397
514
system_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c'))
398
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
399
index XXXXXXX..XXXXXXX 100644
400
--- a/hw/misc/trace-events
401
+++ b/hw/misc/trace-events
402
@@ -XXX,XX +XXX,XX @@ stm32f4xx_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
403
stm32f4xx_exti_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
404
stm32f4xx_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
405
406
+# stm32l4x5_syscfg.c
407
+stm32l4x5_syscfg_set_irq(int gpio, int line, int level) "irq from GPIO: %d, line: %d, level: %d"
408
+stm32l4x5_syscfg_forward_exti(int irq) "irq %d forwarded to EXTI"
409
+stm32l4x5_syscfg_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
410
+stm32l4x5_syscfg_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
411
+
412
# stm32l4x5_exti.c
413
stm32l4x5_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
414
stm32l4x5_exti_read(uint64_t addr, uint64_t data) "reg read: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
415
--
515
--
416
2.34.1
516
2.34.1
417
418
diff view generated by jsdifflib
1
This patch implements the basic registers of GMAC device and sets
1
From: Bernhard Beschow <shentey@gmail.com>
2
registers for networking functionalities.
3
2
4
Tested:
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
5
The following message shows up with the change:
4
imx_fec having more logging and tracing. Merge these improvements into
6
Broadcom BCM54612E stmmac-0:00: attached PHY driver [Broadcom BCM54612E] (mii_bus:phy_addr=stmmac-0:00, irq=POLL)
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
7
stmmaceth f0802000.eth eth0: Link is Up - 1Gbps/Full - flow control rx/tx
8
6
9
Change-Id: If71c6d486b95edcccba109ba454870714d7e0940
7
Some migration state how resides in the new device model which breaks migration
10
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
compatibility for the following machines:
11
Signed-off-by: Nabih Estefan Diaz <nabihestefan@google.com>
9
* imx25-pdk
12
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
10
* sabrelite
13
Message-id: 20240110234232.4116804-5-nabihestefan@google.com
11
* mcimx7d-sabre
14
[PMM: Squashed another patch into this one to avoid compilation failure]
12
* mcimx6ul-evk
13
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 20241102125724.532843-3-shentey@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
19
---
18
include/hw/net/npcm_gmac.h | 340 +++++++++++++++++++++++++++
20
include/hw/net/imx_fec.h | 9 ++-
19
hw/net/npcm_gmac.c | 464 +++++++++++++++++++++++++++++++++++++
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
20
hw/net/meson.build | 2 +-
22
hw/net/lan9118_phy.c | 82 ++++++++++++++++------
21
hw/net/trace-events | 12 +
23
hw/net/Kconfig | 1 +
22
4 files changed, 817 insertions(+), 1 deletion(-)
24
hw/net/trace-events | 10 +--
23
create mode 100644 include/hw/net/npcm_gmac.h
25
5 files changed, 85 insertions(+), 163 deletions(-)
24
create mode 100644 hw/net/npcm_gmac.c
25
26
26
diff --git a/include/hw/net/npcm_gmac.h b/include/hw/net/npcm_gmac.h
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
27
new file mode 100644
28
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX
29
--- a/include/hw/net/imx_fec.h
29
--- /dev/null
30
+++ b/include/hw/net/imx_fec.h
30
+++ b/include/hw/net/npcm_gmac.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
31
@@ -XXX,XX +XXX,XX @@
270
@@ -XXX,XX +XXX,XX @@
32
+/*
271
* Copyright (c) 2009 CodeSourcery, LLC.
33
+ * Nuvoton NPCM7xx/8xx GMAC Module
272
* Written by Paul Brook
273
*
274
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
34
+ *
275
+ *
35
+ * Copyright 2022 Google LLC
276
* This code is licensed under the GNU GPL v2
36
+ *
277
*
37
+ * This program is free software; you can redistribute it and/or modify it
278
* Contributions after 2012-01-13 are licensed under the terms of the
38
+ * under the terms of the GNU General Public License as published by the
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
+
48
+#ifndef NPCM_GMAC_H
49
+#define NPCM_GMAC_H
50
+
51
+#include "hw/irq.h"
52
+#include "hw/sysbus.h"
53
+#include "net/net.h"
54
+
55
+#define NPCM_GMAC_NR_REGS (0x1060 / sizeof(uint32_t))
56
+
57
+#define NPCM_GMAC_MAX_PHYS 32
58
+#define NPCM_GMAC_MAX_PHY_REGS 32
59
+
60
+struct NPCMGMACRxDesc {
61
+ uint32_t rdes0;
62
+ uint32_t rdes1;
63
+ uint32_t rdes2;
64
+ uint32_t rdes3;
65
+};
66
+
67
+/* NPCMGMACRxDesc.flags values */
68
+/* RDES2 and RDES3 are buffer addresses */
69
+/* Owner: 0 = software, 1 = dma */
70
+#define RX_DESC_RDES0_OWN BIT(31)
71
+/* Destination Address Filter Fail */
72
+#define RX_DESC_RDES0_DEST_ADDR_FILT_FAIL BIT(30)
73
+/* Frame length */
74
+#define RX_DESC_RDES0_FRAME_LEN_MASK(word) extract32(word, 16, 14)
75
+/* Frame length Shift*/
76
+#define RX_DESC_RDES0_FRAME_LEN_SHIFT 16
77
+/* Error Summary */
78
+#define RX_DESC_RDES0_ERR_SUMM_MASK BIT(15)
79
+/* Descriptor Error */
80
+#define RX_DESC_RDES0_DESC_ERR_MASK BIT(14)
81
+/* Source Address Filter Fail */
82
+#define RX_DESC_RDES0_SRC_ADDR_FILT_FAIL_MASK BIT(13)
83
+/* Length Error */
84
+#define RX_DESC_RDES0_LEN_ERR_MASK BIT(12)
85
+/* Overflow Error */
86
+#define RX_DESC_RDES0_OVRFLW_ERR_MASK BIT(11)
87
+/* VLAN Tag */
88
+#define RX_DESC_RDES0_VLAN_TAG_MASK BIT(10)
89
+/* First Descriptor */
90
+#define RX_DESC_RDES0_FIRST_DESC_MASK BIT(9)
91
+/* Last Descriptor */
92
+#define RX_DESC_RDES0_LAST_DESC_MASK BIT(8)
93
+/* IPC Checksum Error/Giant Frame */
94
+#define RX_DESC_RDES0_IPC_CHKSM_ERR_GNT_FRM_MASK BIT(7)
95
+/* Late Collision */
96
+#define RX_DESC_RDES0_LT_COLL_MASK BIT(6)
97
+/* Frame Type */
98
+#define RX_DESC_RDES0_FRM_TYPE_MASK BIT(5)
99
+/* Receive Watchdog Timeout */
100
+#define RX_DESC_RDES0_REC_WTCHDG_TMT_MASK BIT(4)
101
+/* Receive Error */
102
+#define RX_DESC_RDES0_RCV_ERR_MASK BIT(3)
103
+/* Dribble Bit Error */
104
+#define RX_DESC_RDES0_DRBL_BIT_ERR_MASK BIT(2)
105
+/* Cyclcic Redundancy Check Error */
106
+#define RX_DESC_RDES0_CRC_ERR_MASK BIT(1)
107
+/* Rx MAC Address/Payload Checksum Error */
108
+#define RC_DESC_RDES0_RCE_MASK BIT(0)
109
+
110
+/* Disable Interrupt on Completion */
111
+#define RX_DESC_RDES1_DIS_INTR_COMP_MASK BIT(31)
112
+/* Recieve end of ring */
113
+#define RX_DESC_RDES1_RC_END_RING_MASK BIT(25)
114
+/* Second Address Chained */
115
+#define RX_DESC_RDES1_SEC_ADDR_CHND_MASK BIT(24)
116
+/* Receive Buffer 2 Size */
117
+#define RX_DESC_RDES1_BFFR2_SZ_SHIFT 11
118
+#define RX_DESC_RDES1_BFFR2_SZ_MASK(word) extract32(word, \
119
+ RX_DESC_RDES1_BFFR2_SZ_SHIFT, 11)
120
+/* Receive Buffer 1 Size */
121
+#define RX_DESC_RDES1_BFFR1_SZ_MASK(word) extract32(word, 0, 11)
122
+
123
+
124
+struct NPCMGMACTxDesc {
125
+ uint32_t tdes0;
126
+ uint32_t tdes1;
127
+ uint32_t tdes2;
128
+ uint32_t tdes3;
129
+};
130
+
131
+/* NPCMGMACTxDesc.flags values */
132
+/* TDES2 and TDES3 are buffer addresses */
133
+/* Owner: 0 = software, 1 = gmac */
134
+#define TX_DESC_TDES0_OWN BIT(31)
135
+/* Tx Time Stamp Status */
136
+#define TX_DESC_TDES0_TTSS_MASK BIT(17)
137
+/* IP Header Error */
138
+#define TX_DESC_TDES0_IP_HEAD_ERR_MASK BIT(16)
139
+/* Error Summary */
140
+#define TX_DESC_TDES0_ERR_SUMM_MASK BIT(15)
141
+/* Jabber Timeout */
142
+#define TX_DESC_TDES0_JBBR_TMT_MASK BIT(14)
143
+/* Frame Flushed */
144
+#define TX_DESC_TDES0_FRM_FLSHD_MASK BIT(13)
145
+/* Payload Checksum Error */
146
+#define TX_DESC_TDES0_PYLD_CHKSM_ERR_MASK BIT(12)
147
+/* Loss of Carrier */
148
+#define TX_DESC_TDES0_LSS_CARR_MASK BIT(11)
149
+/* No Carrier */
150
+#define TX_DESC_TDES0_NO_CARR_MASK BIT(10)
151
+/* Late Collision */
152
+#define TX_DESC_TDES0_LATE_COLL_MASK BIT(9)
153
+/* Excessive Collision */
154
+#define TX_DESC_TDES0_EXCS_COLL_MASK BIT(8)
155
+/* VLAN Frame */
156
+#define TX_DESC_TDES0_VLAN_FRM_MASK BIT(7)
157
+/* Collision Count */
158
+#define TX_DESC_TDES0_COLL_CNT_MASK(word) extract32(word, 3, 4)
159
+/* Excessive Deferral */
160
+#define TX_DESC_TDES0_EXCS_DEF_MASK BIT(2)
161
+/* Underflow Error */
162
+#define TX_DESC_TDES0_UNDRFLW_ERR_MASK BIT(1)
163
+/* Deferred Bit */
164
+#define TX_DESC_TDES0_DFRD_BIT_MASK BIT(0)
165
+
166
+/* Interrupt of Completion */
167
+#define TX_DESC_TDES1_INTERR_COMP_MASK BIT(31)
168
+/* Last Segment */
169
+#define TX_DESC_TDES1_LAST_SEG_MASK BIT(30)
170
+/* First Segment */
171
+#define TX_DESC_TDES1_FIRST_SEG_MASK BIT(29)
172
+/* Checksum Insertion Control */
173
+#define TX_DESC_TDES1_CHKSM_INS_CTRL_MASK(word) extract32(word, 27, 2)
174
+/* Disable Cyclic Redundancy Check */
175
+#define TX_DESC_TDES1_DIS_CDC_MASK BIT(26)
176
+/* Transmit End of Ring */
177
+#define TX_DESC_TDES1_TX_END_RING_MASK BIT(25)
178
+/* Secondary Address Chained */
179
+#define TX_DESC_TDES1_SEC_ADDR_CHND_MASK BIT(24)
180
+/* Transmit Buffer 2 Size */
181
+#define TX_DESC_TDES1_BFFR2_SZ_MASK(word) extract32(word, 11, 11)
182
+/* Transmit Buffer 1 Size */
183
+#define TX_DESC_TDES1_BFFR1_SZ_MASK(word) extract32(word, 0, 11)
184
+
185
+typedef struct NPCMGMACState {
186
+ SysBusDevice parent;
187
+
188
+ MemoryRegion iomem;
189
+ qemu_irq irq;
190
+
191
+ NICState *nic;
192
+ NICConf conf;
193
+
194
+ uint32_t regs[NPCM_GMAC_NR_REGS];
195
+ uint16_t phy_regs[NPCM_GMAC_MAX_PHYS][NPCM_GMAC_MAX_PHY_REGS];
196
+} NPCMGMACState;
197
+
198
+#define TYPE_NPCM_GMAC "npcm-gmac"
199
+OBJECT_DECLARE_SIMPLE_TYPE(NPCMGMACState, NPCM_GMAC)
200
+
201
+/* Mask for RO bits in Status */
202
+#define NPCM_DMA_STATUS_RO_MASK(word) (word & 0xfffe0000)
203
+/* Mask for RO bits in Status */
204
+#define NPCM_DMA_STATUS_W1C_MASK(word) (word & 0x1e7ff)
205
+
206
+/* Transmit Process State */
207
+#define NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT 20
208
+/* Transmit States */
209
+#define NPCM_DMA_STATUS_TX_STOPPED_STATE \
210
+ (0b000)
211
+#define NPCM_DMA_STATUS_TX_RUNNING_FETCHING_STATE \
212
+ (0b001)
213
+#define NPCM_DMA_STATUS_TX_RUNNING_WAITING_STATE \
214
+ (0b010)
215
+#define NPCM_DMA_STATUS_TX_RUNNING_READ_STATE \
216
+ (0b011)
217
+#define NPCM_DMA_STATUS_TX_SUSPENDED_STATE \
218
+ (0b110)
219
+#define NPCM_DMA_STATUS_TX_RUNNING_CLOSING_STATE \
220
+ (0b111)
221
+/* Transmit Process State */
222
+#define NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT 17
223
+/* Receive States */
224
+#define NPCM_DMA_STATUS_RX_STOPPED_STATE \
225
+ (0b000)
226
+#define NPCM_DMA_STATUS_RX_RUNNING_FETCHING_STATE \
227
+ (0b001)
228
+#define NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE \
229
+ (0b011)
230
+#define NPCM_DMA_STATUS_RX_SUSPENDED_STATE \
231
+ (0b100)
232
+#define NPCM_DMA_STATUS_RX_RUNNING_CLOSING_STATE \
233
+ (0b101)
234
+#define NPCM_DMA_STATUS_RX_RUNNING_TRANSFERRING_STATE \
235
+ (0b111)
236
+
237
+
238
+/* Early Receive Interrupt */
239
+#define NPCM_DMA_STATUS_ERI BIT(14)
240
+/* Fatal Bus Error Interrupt */
241
+#define NPCM_DMA_STATUS_FBI BIT(13)
242
+/* Early transmit Interrupt */
243
+#define NPCM_DMA_STATUS_ETI BIT(10)
244
+/* Receive Watchdog Timout */
245
+#define NPCM_DMA_STATUS_RWT BIT(9)
246
+/* Receive Process Stopped */
247
+#define NPCM_DMA_STATUS_RPS BIT(8)
248
+/* Receive Buffer Unavailable */
249
+#define NPCM_DMA_STATUS_RU BIT(7)
250
+/* Receive Interrupt */
251
+#define NPCM_DMA_STATUS_RI BIT(6)
252
+/* Transmit Underflow */
253
+#define NPCM_DMA_STATUS_UNF BIT(5)
254
+/* Receive Overflow */
255
+#define NPCM_DMA_STATUS_OVF BIT(4)
256
+/* Transmit Jabber Timeout */
257
+#define NPCM_DMA_STATUS_TJT BIT(3)
258
+/* Transmit Buffer Unavailable */
259
+#define NPCM_DMA_STATUS_TU BIT(2)
260
+/* Transmit Process Stopped */
261
+#define NPCM_DMA_STATUS_TPS BIT(1)
262
+/* Transmit Interrupt */
263
+#define NPCM_DMA_STATUS_TI BIT(0)
264
+
265
+/* Normal Interrupt Summary */
266
+#define NPCM_DMA_STATUS_NIS BIT(16)
267
+/* Interrupts enabled by NIE */
268
+#define NPCM_DMA_STATUS_NIS_BITS (NPCM_DMA_STATUS_TI | \
269
+ NPCM_DMA_STATUS_TU | \
270
+ NPCM_DMA_STATUS_RI | \
271
+ NPCM_DMA_STATUS_ERI)
272
+/* Abnormal Interrupt Summary */
273
+#define NPCM_DMA_STATUS_AIS BIT(15)
274
+/* Interrupts enabled by AIE */
275
+#define NPCM_DMA_STATUS_AIS_BITS (NPCM_DMA_STATUS_TPS | \
276
+ NPCM_DMA_STATUS_TJT | \
277
+ NPCM_DMA_STATUS_OVF | \
278
+ NPCM_DMA_STATUS_UNF | \
279
+ NPCM_DMA_STATUS_RU | \
280
+ NPCM_DMA_STATUS_RPS | \
281
+ NPCM_DMA_STATUS_RWT | \
282
+ NPCM_DMA_STATUS_ETI | \
283
+ NPCM_DMA_STATUS_FBI)
284
+
285
+/* Early Receive Interrupt Enable */
286
+#define NPCM_DMA_INTR_ENAB_ERE BIT(14)
287
+/* Fatal Bus Error Interrupt Enable */
288
+#define NPCM_DMA_INTR_ENAB_FBE BIT(13)
289
+/* Early transmit Interrupt Enable */
290
+#define NPCM_DMA_INTR_ENAB_ETE BIT(10)
291
+/* Receive Watchdog Timout Enable */
292
+#define NPCM_DMA_INTR_ENAB_RWE BIT(9)
293
+/* Receive Process Stopped Enable */
294
+#define NPCM_DMA_INTR_ENAB_RSE BIT(8)
295
+/* Receive Buffer Unavailable Enable */
296
+#define NPCM_DMA_INTR_ENAB_RUE BIT(7)
297
+/* Receive Interrupt Enable */
298
+#define NPCM_DMA_INTR_ENAB_RIE BIT(6)
299
+/* Transmit Underflow Enable */
300
+#define NPCM_DMA_INTR_ENAB_UNE BIT(5)
301
+/* Receive Overflow Enable */
302
+#define NPCM_DMA_INTR_ENAB_OVE BIT(4)
303
+/* Transmit Jabber Timeout Enable */
304
+#define NPCM_DMA_INTR_ENAB_TJE BIT(3)
305
+/* Transmit Buffer Unavailable Enable */
306
+#define NPCM_DMA_INTR_ENAB_TUE BIT(2)
307
+/* Transmit Process Stopped Enable */
308
+#define NPCM_DMA_INTR_ENAB_TSE BIT(1)
309
+/* Transmit Interrupt Enable */
310
+#define NPCM_DMA_INTR_ENAB_TIE BIT(0)
311
+
312
+/* Normal Interrupt Summary Enable */
313
+#define NPCM_DMA_INTR_ENAB_NIE BIT(16)
314
+/* Interrupts enabled by NIE Enable */
315
+#define NPCM_DMA_INTR_ENAB_NIE_BITS (NPCM_DMA_INTR_ENAB_TIE | \
316
+ NPCM_DMA_INTR_ENAB_TUE | \
317
+ NPCM_DMA_INTR_ENAB_RIE | \
318
+ NPCM_DMA_INTR_ENAB_ERE)
319
+/* Abnormal Interrupt Summary Enable */
320
+#define NPCM_DMA_INTR_ENAB_AIE BIT(15)
321
+/* Interrupts enabled by AIE Enable */
322
+#define NPCM_DMA_INTR_ENAB_AIE_BITS (NPCM_DMA_INTR_ENAB_TSE | \
323
+ NPCM_DMA_INTR_ENAB_TJE | \
324
+ NPCM_DMA_INTR_ENAB_OVE | \
325
+ NPCM_DMA_INTR_ENAB_UNE | \
326
+ NPCM_DMA_INTR_ENAB_RUE | \
327
+ NPCM_DMA_INTR_ENAB_RSE | \
328
+ NPCM_DMA_INTR_ENAB_RWE | \
329
+ NPCM_DMA_INTR_ENAB_ETE | \
330
+ NPCM_DMA_INTR_ENAB_FBE)
331
+
332
+/* Flushing Disabled */
333
+#define NPCM_DMA_CONTROL_FLUSH_MASK BIT(24)
334
+/* Start/stop Transmit */
335
+#define NPCM_DMA_CONTROL_START_STOP_TX BIT(13)
336
+/* Start/stop Receive */
337
+#define NPCM_DMA_CONTROL_START_STOP_RX BIT(1)
338
+/* Next receive descriptor start address */
339
+#define NPCM_DMA_HOST_RX_DESC_MASK(word) ((uint32_t) (word) & ~3u)
340
+/* Next transmit descriptor start address */
341
+#define NPCM_DMA_HOST_TX_DESC_MASK(word) ((uint32_t) (word) & ~3u)
342
+
343
+/* Receive enable */
344
+#define NPCM_GMAC_MAC_CONFIG_RX_EN BIT(2)
345
+/* Transmit enable */
346
+#define NPCM_GMAC_MAC_CONFIG_TX_EN BIT(3)
347
+
348
+/* Frame Receive All */
349
+#define NPCM_GMAC_FRAME_FILTER_REC_ALL_MASK BIT(31)
350
+/* Frame HPF Filter*/
351
+#define NPCM_GMAC_FRAME_FILTER_HPF_MASK BIT(10)
352
+/* Frame SAF Filter*/
353
+#define NPCM_GMAC_FRAME_FILTER_SAF_MASK BIT(9)
354
+/* Frame SAIF Filter*/
355
+#define NPCM_GMAC_FRAME_FILTER_SAIF_MASK BIT(8)
356
+/* Frame PCF Filter*/
357
+#define NPCM_GMAC_FRAME_FILTER_PCF_MASK BIT(word) extract32((word), 6, 2)
358
+/* Frame DBF Filter*/
359
+#define NPCM_GMAC_FRAME_FILTER_DBF_MASK BIT(5)
360
+/* Frame PM Filter*/
361
+#define NPCM_GMAC_FRAME_FILTER_PM_MASK BIT(4)
362
+/* Frame DAIF Filter*/
363
+#define NPCM_GMAC_FRAME_FILTER_DAIF_MASK BIT(3)
364
+/* Frame HMC Filter*/
365
+#define NPCM_GMAC_FRAME_FILTER_HMC_MASK BIT(2)
366
+/* Frame HUC Filter*/
367
+#define NPCM_GMAC_FRAME_FILTER_HUC_MASK BIT(1)
368
+/* Frame PR Filter*/
369
+#define NPCM_GMAC_FRAME_FILTER_PR_MASK BIT(0)
370
+
371
+#endif /* NPCM_GMAC_H */
372
diff --git a/hw/net/npcm_gmac.c b/hw/net/npcm_gmac.c
373
new file mode 100644
374
index XXXXXXX..XXXXXXX
375
--- /dev/null
376
+++ b/hw/net/npcm_gmac.c
377
@@ -XXX,XX +XXX,XX @@
279
@@ -XXX,XX +XXX,XX @@
378
+/*
280
#include "hw/resettable.h"
379
+ * Nuvoton NPCM7xx/8xx GMAC Module
281
#include "migration/vmstate.h"
380
+ *
282
#include "qemu/log.h"
381
+ * Copyright 2022 Google LLC
382
+ *
383
+ * This program is free software; you can redistribute it and/or modify it
384
+ * under the terms of the GNU General Public License as published by the
385
+ * Free Software Foundation; either version 2 of the License, or
386
+ * (at your option) any later version.
387
+ *
388
+ * This program is distributed in the hope that it will be useful, but WITHOUT
389
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
390
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
391
+ * for more details.
392
+ *
393
+ * Unsupported/unimplemented features:
394
+ * - MII is not implemented, MII_ADDR.BUSY and MII_DATA always return zero
395
+ * - Precision timestamp (PTP) is not implemented.
396
+ */
397
+
398
+#include "qemu/osdep.h"
399
+
400
+#include "hw/registerfields.h"
401
+#include "hw/net/mii.h"
402
+#include "hw/net/npcm_gmac.h"
403
+#include "migration/vmstate.h"
404
+#include "qemu/log.h"
405
+#include "qemu/units.h"
406
+#include "sysemu/dma.h"
407
+#include "trace.h"
283
+#include "trace.h"
408
+
284
409
+REG32(NPCM_DMA_BUS_MODE, 0x1000)
285
#define PHY_INT_ENERGYON (1 << 7)
410
+REG32(NPCM_DMA_XMT_POLL_DEMAND, 0x1004)
286
#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
411
+REG32(NPCM_DMA_RCV_POLL_DEMAND, 0x1008)
287
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
412
+REG32(NPCM_DMA_RX_BASE_ADDR, 0x100c)
288
413
+REG32(NPCM_DMA_TX_BASE_ADDR, 0x1010)
289
switch (reg) {
414
+REG32(NPCM_DMA_STATUS, 0x1014)
290
case 0: /* Basic Control */
415
+REG32(NPCM_DMA_CONTROL, 0x1018)
291
- return s->control;
416
+REG32(NPCM_DMA_INTR_ENA, 0x101c)
292
+ val = s->control;
417
+REG32(NPCM_DMA_MISSED_FRAME_CTR, 0x1020)
293
+ break;
418
+REG32(NPCM_DMA_HOST_TX_DESC, 0x1048)
294
case 1: /* Basic Status */
419
+REG32(NPCM_DMA_HOST_RX_DESC, 0x104c)
295
- return s->status;
420
+REG32(NPCM_DMA_CUR_TX_BUF_ADDR, 0x1050)
296
+ val = s->status;
421
+REG32(NPCM_DMA_CUR_RX_BUF_ADDR, 0x1054)
297
+ break;
422
+REG32(NPCM_DMA_HW_FEATURE, 0x1058)
298
case 2: /* ID1 */
423
+
299
- return 0x0007;
424
+REG32(NPCM_GMAC_MAC_CONFIG, 0x0)
300
+ val = 0x0007;
425
+REG32(NPCM_GMAC_FRAME_FILTER, 0x4)
301
+ break;
426
+REG32(NPCM_GMAC_HASH_HIGH, 0x8)
302
case 3: /* ID2 */
427
+REG32(NPCM_GMAC_HASH_LOW, 0xc)
303
- return 0xc0d1;
428
+REG32(NPCM_GMAC_MII_ADDR, 0x10)
304
+ val = 0xc0d1;
429
+REG32(NPCM_GMAC_MII_DATA, 0x14)
305
+ break;
430
+REG32(NPCM_GMAC_FLOW_CTRL, 0x18)
306
case 4: /* Auto-neg advertisement */
431
+REG32(NPCM_GMAC_VLAN_FLAG, 0x1c)
307
- return s->advertise;
432
+REG32(NPCM_GMAC_VERSION, 0x20)
308
+ val = s->advertise;
433
+REG32(NPCM_GMAC_WAKEUP_FILTER, 0x28)
309
+ break;
434
+REG32(NPCM_GMAC_PMT, 0x2c)
310
case 5: /* Auto-neg Link Partner Ability */
435
+REG32(NPCM_GMAC_LPI_CTRL, 0x30)
311
- return 0x0f71;
436
+REG32(NPCM_GMAC_TIMER_CTRL, 0x34)
312
+ val = 0x0f71;
437
+REG32(NPCM_GMAC_INT_STATUS, 0x38)
313
+ break;
438
+REG32(NPCM_GMAC_INT_MASK, 0x3c)
314
case 6: /* Auto-neg Expansion */
439
+REG32(NPCM_GMAC_MAC0_ADDR_HI, 0x40)
315
- return 1;
440
+REG32(NPCM_GMAC_MAC0_ADDR_LO, 0x44)
316
- /* TODO 17, 18, 27, 29, 30, 31 */
441
+REG32(NPCM_GMAC_MAC1_ADDR_HI, 0x48)
317
+ val = 1;
442
+REG32(NPCM_GMAC_MAC1_ADDR_LO, 0x4c)
318
+ break;
443
+REG32(NPCM_GMAC_MAC2_ADDR_HI, 0x50)
319
case 29: /* Interrupt source. */
444
+REG32(NPCM_GMAC_MAC2_ADDR_LO, 0x54)
320
val = s->ints;
445
+REG32(NPCM_GMAC_MAC3_ADDR_HI, 0x58)
321
s->ints = 0;
446
+REG32(NPCM_GMAC_MAC3_ADDR_LO, 0x5c)
322
lan9118_phy_update_irq(s);
447
+REG32(NPCM_GMAC_RGMII_STATUS, 0xd8)
323
- return val;
448
+REG32(NPCM_GMAC_WATCHDOG, 0xdc)
324
+ break;
449
+REG32(NPCM_GMAC_PTP_TCR, 0x700)
325
case 30: /* Interrupt mask */
450
+REG32(NPCM_GMAC_PTP_SSIR, 0x704)
326
- return s->int_mask;
451
+REG32(NPCM_GMAC_PTP_STSR, 0x708)
327
+ val = s->int_mask;
452
+REG32(NPCM_GMAC_PTP_STNSR, 0x70c)
328
+ break;
453
+REG32(NPCM_GMAC_PTP_STSUR, 0x710)
329
+ case 17:
454
+REG32(NPCM_GMAC_PTP_STNSUR, 0x714)
330
+ case 18:
455
+REG32(NPCM_GMAC_PTP_TAR, 0x718)
331
+ case 27:
456
+REG32(NPCM_GMAC_PTP_TTSR, 0x71c)
332
+ case 31:
457
+
333
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
458
+/* Register Fields */
334
+ __func__, reg);
459
+#define NPCM_GMAC_MII_ADDR_BUSY BIT(0)
335
+ val = 0;
460
+#define NPCM_GMAC_MII_ADDR_WRITE BIT(1)
336
+ break;
461
+#define NPCM_GMAC_MII_ADDR_GR(rv) extract16((rv), 6, 5)
337
default:
462
+#define NPCM_GMAC_MII_ADDR_PA(rv) extract16((rv), 11, 5)
338
- qemu_log_mask(LOG_GUEST_ERROR,
463
+
339
- "lan9118_phy_read: PHY read reg %d\n", reg);
464
+#define NPCM_GMAC_INT_MASK_LPIIM BIT(10)
340
- return 0;
465
+#define NPCM_GMAC_INT_MASK_PMTM BIT(3)
341
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
466
+#define NPCM_GMAC_INT_MASK_RGIM BIT(0)
342
+ __func__, reg);
467
+
343
+ val = 0;
468
+#define NPCM_DMA_BUS_MODE_SWR BIT(0)
344
+ break;
469
+
345
}
470
+static const uint32_t npcm_gmac_cold_reset_values[NPCM_GMAC_NR_REGS] = {
346
+
471
+ /* Reduce version to 3.2 so that the kernel can enable interrupt. */
347
+ trace_lan9118_phy_read(val, reg);
472
+ [R_NPCM_GMAC_VERSION] = 0x00001032,
348
+
473
+ [R_NPCM_GMAC_TIMER_CTRL] = 0x03e80000,
349
+ return val;
474
+ [R_NPCM_GMAC_MAC0_ADDR_HI] = 0x8000ffff,
350
}
475
+ [R_NPCM_GMAC_MAC0_ADDR_LO] = 0xffffffff,
351
476
+ [R_NPCM_GMAC_MAC1_ADDR_HI] = 0x0000ffff,
352
void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
477
+ [R_NPCM_GMAC_MAC1_ADDR_LO] = 0xffffffff,
353
{
478
+ [R_NPCM_GMAC_MAC2_ADDR_HI] = 0x0000ffff,
354
+ trace_lan9118_phy_write(val, reg);
479
+ [R_NPCM_GMAC_MAC2_ADDR_LO] = 0xffffffff,
355
+
480
+ [R_NPCM_GMAC_MAC3_ADDR_HI] = 0x0000ffff,
356
switch (reg) {
481
+ [R_NPCM_GMAC_MAC3_ADDR_LO] = 0xffffffff,
357
case 0: /* Basic Control */
482
+ [R_NPCM_GMAC_PTP_TCR] = 0x00002000,
358
if (val & 0x8000) {
483
+ [R_NPCM_DMA_BUS_MODE] = 0x00020101,
359
lan9118_phy_reset(s);
484
+ [R_NPCM_DMA_HW_FEATURE] = 0x100d4f37,
360
- break;
485
+};
361
- }
486
+
362
- s->control = val & 0x7980;
487
+static const uint16_t phy_reg_init[] = {
363
- /* Complete autonegotiation immediately. */
488
+ [MII_BMCR] = MII_BMCR_AUTOEN | MII_BMCR_FD | MII_BMCR_SPEED1000,
364
- if (val & 0x1000) {
489
+ [MII_BMSR] = MII_BMSR_100TX_FD | MII_BMSR_100TX_HD | MII_BMSR_10T_FD |
365
- s->status |= 0x0020;
490
+ MII_BMSR_10T_HD | MII_BMSR_EXTSTAT | MII_BMSR_AUTONEG |
366
+ } else {
491
+ MII_BMSR_LINK_ST | MII_BMSR_EXTCAP,
367
+ s->control = val & 0x7980;
492
+ [MII_PHYID1] = 0x0362,
368
+ /* Complete autonegotiation immediately. */
493
+ [MII_PHYID2] = 0x5e6a,
369
+ if (val & 0x1000) {
494
+ [MII_ANAR] = MII_ANAR_TXFD | MII_ANAR_TX | MII_ANAR_10FD |
370
+ s->status |= 0x0020;
495
+ MII_ANAR_10 | MII_ANAR_CSMACD,
496
+ [MII_ANLPAR] = MII_ANLPAR_ACK | MII_ANLPAR_PAUSE |
497
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
498
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD,
499
+ [MII_ANER] = 0x64 | MII_ANER_NWAY,
500
+ [MII_ANNP] = 0x2001,
501
+ [MII_CTRL1000] = MII_CTRL1000_FULL,
502
+ [MII_STAT1000] = MII_STAT1000_FULL,
503
+ [MII_EXTSTAT] = 0x3000, /* 1000BASTE_T full-duplex capable */
504
+};
505
+
506
+static void npcm_gmac_soft_reset(NPCMGMACState *gmac)
507
+{
508
+ memcpy(gmac->regs, npcm_gmac_cold_reset_values,
509
+ NPCM_GMAC_NR_REGS * sizeof(uint32_t));
510
+ /* Clear reset bits */
511
+ gmac->regs[R_NPCM_DMA_BUS_MODE] &= ~NPCM_DMA_BUS_MODE_SWR;
512
+}
513
+
514
+static void gmac_phy_set_link(NPCMGMACState *gmac, bool active)
515
+{
516
+ /* Autonegotiation status mirrors link status. */
517
+ if (active) {
518
+ gmac->phy_regs[0][MII_BMSR] |= (MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
519
+ } else {
520
+ gmac->phy_regs[0][MII_BMSR] &= ~(MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
521
+ }
522
+}
523
+
524
+static bool gmac_can_receive(NetClientState *nc)
525
+{
526
+ return true;
527
+}
528
+
529
+/*
530
+ * Function that updates the GMAC IRQ
531
+ * It find the logical OR of the enabled bits for NIS (if enabled)
532
+ * It find the logical OR of the enabled bits for AIS (if enabled)
533
+ */
534
+static void gmac_update_irq(NPCMGMACState *gmac)
535
+{
536
+ /*
537
+ * Check if the normal interrupts summary is enabled
538
+ * if so, add the bits for the summary that are enabled
539
+ */
540
+ if (gmac->regs[R_NPCM_DMA_INTR_ENA] & gmac->regs[R_NPCM_DMA_STATUS] &
541
+ (NPCM_DMA_INTR_ENAB_NIE_BITS)) {
542
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_NIS;
543
+ }
544
+ /*
545
+ * Check if the abnormal interrupts summary is enabled
546
+ * if so, add the bits for the summary that are enabled
547
+ */
548
+ if (gmac->regs[R_NPCM_DMA_INTR_ENA] & gmac->regs[R_NPCM_DMA_STATUS] &
549
+ (NPCM_DMA_INTR_ENAB_AIE_BITS)) {
550
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_AIS;
551
+ }
552
+
553
+ /* Get the logical OR of both normal and abnormal interrupts */
554
+ int level = !!((gmac->regs[R_NPCM_DMA_STATUS] &
555
+ gmac->regs[R_NPCM_DMA_INTR_ENA] &
556
+ NPCM_DMA_STATUS_NIS) |
557
+ (gmac->regs[R_NPCM_DMA_STATUS] &
558
+ gmac->regs[R_NPCM_DMA_INTR_ENA] &
559
+ NPCM_DMA_STATUS_AIS));
560
+
561
+ /* Set the IRQ */
562
+ trace_npcm_gmac_update_irq(DEVICE(gmac)->canonical_path,
563
+ gmac->regs[R_NPCM_DMA_STATUS],
564
+ gmac->regs[R_NPCM_DMA_INTR_ENA],
565
+ level);
566
+ qemu_set_irq(gmac->irq, level);
567
+}
568
+
569
+static ssize_t gmac_receive(NetClientState *nc, const uint8_t *buf, size_t len)
570
+{
571
+ /* Placeholder. Function will be filled in following patches */
572
+ return 0;
573
+}
574
+
575
+static void gmac_cleanup(NetClientState *nc)
576
+{
577
+ /* Nothing to do yet. */
578
+}
579
+
580
+static void gmac_set_link(NetClientState *nc)
581
+{
582
+ NPCMGMACState *gmac = qemu_get_nic_opaque(nc);
583
+
584
+ trace_npcm_gmac_set_link(!nc->link_down);
585
+ gmac_phy_set_link(gmac, !nc->link_down);
586
+}
587
+
588
+static void npcm_gmac_mdio_access(NPCMGMACState *gmac, uint16_t v)
589
+{
590
+ bool busy = v & NPCM_GMAC_MII_ADDR_BUSY;
591
+ uint8_t is_write;
592
+ uint8_t pa, gr;
593
+ uint16_t data;
594
+
595
+ if (busy) {
596
+ is_write = v & NPCM_GMAC_MII_ADDR_WRITE;
597
+ pa = NPCM_GMAC_MII_ADDR_PA(v);
598
+ gr = NPCM_GMAC_MII_ADDR_GR(v);
599
+ /* Both pa and gr are 5 bits, so they are less than 32. */
600
+ g_assert(pa < NPCM_GMAC_MAX_PHYS);
601
+ g_assert(gr < NPCM_GMAC_MAX_PHY_REGS);
602
+
603
+
604
+ if (v & NPCM_GMAC_MII_ADDR_WRITE) {
605
+ data = gmac->regs[R_NPCM_GMAC_MII_DATA];
606
+ /* Clear reset bit for BMCR register */
607
+ switch (gr) {
608
+ case MII_BMCR:
609
+ data &= ~MII_BMCR_RESET;
610
+ /* Autonegotiation is a W1C bit*/
611
+ if (data & MII_BMCR_ANRESTART) {
612
+ /* Tells autonegotiation to not restart again */
613
+ data &= ~MII_BMCR_ANRESTART;
614
+ }
615
+ if ((data & MII_BMCR_AUTOEN) &&
616
+ !(gmac->phy_regs[pa][MII_BMSR] & MII_BMSR_AN_COMP)) {
617
+ /* sets autonegotiation as complete */
618
+ gmac->phy_regs[pa][MII_BMSR] |= MII_BMSR_AN_COMP;
619
+ /* Resolve AN automatically->need to set this */
620
+ gmac->phy_regs[0][MII_ANLPAR] = 0x0000;
621
+ }
622
+ }
371
+ }
623
+ gmac->phy_regs[pa][gr] = data;
372
}
624
+ } else {
373
break;
625
+ data = gmac->phy_regs[pa][gr];
374
case 4: /* Auto-neg advertisement */
626
+ gmac->regs[R_NPCM_GMAC_MII_DATA] = data;
375
s->advertise = (val & 0x2d7f) | 0x80;
627
+ }
376
break;
628
+ trace_npcm_gmac_mdio_access(DEVICE(gmac)->canonical_path, is_write, pa,
377
- /* TODO 17, 18, 27, 31 */
629
+ gr, data);
378
case 30: /* Interrupt mask */
630
+ }
379
s->int_mask = val & 0xff;
631
+ gmac->regs[R_NPCM_GMAC_MII_ADDR] = v & ~NPCM_GMAC_MII_ADDR_BUSY;
380
lan9118_phy_update_irq(s);
632
+}
381
break;
633
+
382
+ case 17:
634
+static uint64_t npcm_gmac_read(void *opaque, hwaddr offset, unsigned size)
383
+ case 18:
635
+{
384
+ case 27:
636
+ NPCMGMACState *gmac = opaque;
385
+ case 31:
637
+ uint32_t v = 0;
386
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
638
+
387
+ __func__, reg);
639
+ switch (offset) {
388
+ break;
640
+ /* Write only registers */
389
default:
641
+ case A_NPCM_DMA_XMT_POLL_DEMAND:
390
- qemu_log_mask(LOG_GUEST_ERROR,
642
+ case A_NPCM_DMA_RCV_POLL_DEMAND:
391
- "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
643
+ qemu_log_mask(LOG_GUEST_ERROR,
392
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
644
+ "%s: Read of write-only reg: offset: 0x%04" HWADDR_PRIx
393
+ __func__, reg);
645
+ "\n", DEVICE(gmac)->canonical_path, offset);
394
+ break;
646
+ break;
395
}
647
+
396
}
648
+ default:
397
649
+ v = gmac->regs[offset / sizeof(uint32_t)];
398
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
650
+ }
399
651
+
400
/* Autonegotiation status mirrors link status. */
652
+ trace_npcm_gmac_reg_read(DEVICE(gmac)->canonical_path, offset, v);
401
if (link_down) {
653
+ return v;
402
+ trace_lan9118_phy_update_link("down");
654
+}
403
s->status &= ~0x0024;
655
+
404
s->ints |= PHY_INT_DOWN;
656
+static void npcm_gmac_write(void *opaque, hwaddr offset,
405
} else {
657
+ uint64_t v, unsigned size)
406
+ trace_lan9118_phy_update_link("up");
658
+{
407
s->status |= 0x0024;
659
+ NPCMGMACState *gmac = opaque;
408
s->ints |= PHY_INT_ENERGYON;
660
+
409
s->ints |= PHY_INT_AUTONEG_COMPLETE;
661
+ trace_npcm_gmac_reg_write(DEVICE(gmac)->canonical_path, offset, v);
410
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
662
+
411
663
+ switch (offset) {
412
void lan9118_phy_reset(Lan9118PhyState *s)
664
+ /* Read only registers */
413
{
665
+ case A_NPCM_GMAC_VERSION:
414
+ trace_lan9118_phy_reset();
666
+ case A_NPCM_GMAC_INT_STATUS:
415
+
667
+ case A_NPCM_GMAC_RGMII_STATUS:
416
s->control = 0x3000;
668
+ case A_NPCM_GMAC_PTP_STSR:
417
s->status = 0x7809;
669
+ case A_NPCM_GMAC_PTP_STNSR:
418
s->advertise = 0x01e1;
670
+ case A_NPCM_DMA_MISSED_FRAME_CTR:
419
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_phy = {
671
+ case A_NPCM_DMA_HOST_TX_DESC:
420
.version_id = 1,
672
+ case A_NPCM_DMA_HOST_RX_DESC:
421
.minimum_version_id = 1,
673
+ case A_NPCM_DMA_CUR_TX_BUF_ADDR:
422
.fields = (const VMStateField[]) {
674
+ case A_NPCM_DMA_CUR_RX_BUF_ADDR:
423
- VMSTATE_UINT16(control, Lan9118PhyState),
675
+ case A_NPCM_DMA_HW_FEATURE:
424
VMSTATE_UINT16(status, Lan9118PhyState),
676
+ qemu_log_mask(LOG_GUEST_ERROR,
425
+ VMSTATE_UINT16(control, Lan9118PhyState),
677
+ "%s: Write of read-only reg: offset: 0x%04" HWADDR_PRIx
426
VMSTATE_UINT16(advertise, Lan9118PhyState),
678
+ ", value: 0x%04" PRIx64 "\n",
427
VMSTATE_UINT16(ints, Lan9118PhyState),
679
+ DEVICE(gmac)->canonical_path, offset, v);
428
VMSTATE_UINT16(int_mask, Lan9118PhyState),
680
+ break;
429
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
681
+
682
+ case A_NPCM_GMAC_MAC_CONFIG:
683
+ break;
684
+
685
+ case A_NPCM_GMAC_MII_ADDR:
686
+ npcm_gmac_mdio_access(gmac, v);
687
+ break;
688
+
689
+ case A_NPCM_GMAC_MAC0_ADDR_HI:
690
+ gmac->regs[offset / sizeof(uint32_t)] = v;
691
+ gmac->conf.macaddr.a[0] = v >> 8;
692
+ gmac->conf.macaddr.a[1] = v >> 0;
693
+ break;
694
+
695
+ case A_NPCM_GMAC_MAC0_ADDR_LO:
696
+ gmac->regs[offset / sizeof(uint32_t)] = v;
697
+ gmac->conf.macaddr.a[2] = v >> 24;
698
+ gmac->conf.macaddr.a[3] = v >> 16;
699
+ gmac->conf.macaddr.a[4] = v >> 8;
700
+ gmac->conf.macaddr.a[5] = v >> 0;
701
+ break;
702
+
703
+ case A_NPCM_GMAC_MAC1_ADDR_HI:
704
+ case A_NPCM_GMAC_MAC1_ADDR_LO:
705
+ case A_NPCM_GMAC_MAC2_ADDR_HI:
706
+ case A_NPCM_GMAC_MAC2_ADDR_LO:
707
+ case A_NPCM_GMAC_MAC3_ADDR_HI:
708
+ case A_NPCM_GMAC_MAC3_ADDR_LO:
709
+ gmac->regs[offset / sizeof(uint32_t)] = v;
710
+ qemu_log_mask(LOG_UNIMP,
711
+ "%s: Only MAC Address 0 is supported. This request "
712
+ "is ignored.\n", DEVICE(gmac)->canonical_path);
713
+ break;
714
+
715
+ case A_NPCM_DMA_BUS_MODE:
716
+ gmac->regs[offset / sizeof(uint32_t)] = v;
717
+ if (v & NPCM_DMA_BUS_MODE_SWR) {
718
+ npcm_gmac_soft_reset(gmac);
719
+ }
720
+ break;
721
+
722
+ case A_NPCM_DMA_RCV_POLL_DEMAND:
723
+ /* We dont actually care about the value */
724
+ break;
725
+
726
+ case A_NPCM_DMA_STATUS:
727
+ /* Check that RO bits are not written to */
728
+ if (NPCM_DMA_STATUS_RO_MASK(v)) {
729
+ qemu_log_mask(LOG_GUEST_ERROR,
730
+ "%s: Write of read-only bits of reg: offset: 0x%04"
731
+ HWADDR_PRIx ", value: 0x%04" PRIx64 "\n",
732
+ DEVICE(gmac)->canonical_path, offset, v);
733
+ }
734
+ break;
735
+
736
+ default:
737
+ gmac->regs[offset / sizeof(uint32_t)] = v;
738
+ break;
739
+ }
740
+
741
+ gmac_update_irq(gmac);
742
+}
743
+
744
+static void npcm_gmac_reset(DeviceState *dev)
745
+{
746
+ NPCMGMACState *gmac = NPCM_GMAC(dev);
747
+
748
+ npcm_gmac_soft_reset(gmac);
749
+ memcpy(gmac->phy_regs[0], phy_reg_init, sizeof(phy_reg_init));
750
+
751
+ trace_npcm_gmac_reset(DEVICE(gmac)->canonical_path,
752
+ gmac->phy_regs[0][MII_BMSR]);
753
+}
754
+
755
+static NetClientInfo net_npcm_gmac_info = {
756
+ .type = NET_CLIENT_DRIVER_NIC,
757
+ .size = sizeof(NICState),
758
+ .can_receive = gmac_can_receive,
759
+ .receive = gmac_receive,
760
+ .cleanup = gmac_cleanup,
761
+ .link_status_changed = gmac_set_link,
762
+};
763
+
764
+static const struct MemoryRegionOps npcm_gmac_ops = {
765
+ .read = npcm_gmac_read,
766
+ .write = npcm_gmac_write,
767
+ .endianness = DEVICE_LITTLE_ENDIAN,
768
+ .valid = {
769
+ .min_access_size = 4,
770
+ .max_access_size = 4,
771
+ .unaligned = false,
772
+ },
773
+};
774
+
775
+static void npcm_gmac_realize(DeviceState *dev, Error **errp)
776
+{
777
+ NPCMGMACState *gmac = NPCM_GMAC(dev);
778
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
779
+
780
+ memory_region_init_io(&gmac->iomem, OBJECT(gmac), &npcm_gmac_ops, gmac,
781
+ TYPE_NPCM_GMAC, 8 * KiB);
782
+ sysbus_init_mmio(sbd, &gmac->iomem);
783
+ sysbus_init_irq(sbd, &gmac->irq);
784
+
785
+ qemu_macaddr_default_if_unset(&gmac->conf.macaddr);
786
+
787
+ gmac->nic = qemu_new_nic(&net_npcm_gmac_info, &gmac->conf, TYPE_NPCM_GMAC,
788
+ dev->id, &dev->mem_reentrancy_guard, gmac);
789
+ qemu_format_nic_info_str(qemu_get_queue(gmac->nic), gmac->conf.macaddr.a);
790
+ gmac->regs[R_NPCM_GMAC_MAC0_ADDR_HI] = (gmac->conf.macaddr.a[0] << 8) + \
791
+ gmac->conf.macaddr.a[1];
792
+ gmac->regs[R_NPCM_GMAC_MAC0_ADDR_LO] = (gmac->conf.macaddr.a[2] << 24) + \
793
+ (gmac->conf.macaddr.a[3] << 16) + \
794
+ (gmac->conf.macaddr.a[4] << 8) + \
795
+ gmac->conf.macaddr.a[5];
796
+}
797
+
798
+static void npcm_gmac_unrealize(DeviceState *dev)
799
+{
800
+ NPCMGMACState *gmac = NPCM_GMAC(dev);
801
+
802
+ qemu_del_nic(gmac->nic);
803
+}
804
+
805
+static const VMStateDescription vmstate_npcm_gmac = {
806
+ .name = TYPE_NPCM_GMAC,
807
+ .version_id = 0,
808
+ .minimum_version_id = 0,
809
+ .fields = (VMStateField[]) {
810
+ VMSTATE_UINT32_ARRAY(regs, NPCMGMACState, NPCM_GMAC_NR_REGS),
811
+ VMSTATE_END_OF_LIST(),
812
+ },
813
+};
814
+
815
+static Property npcm_gmac_properties[] = {
816
+ DEFINE_NIC_PROPERTIES(NPCMGMACState, conf),
817
+ DEFINE_PROP_END_OF_LIST(),
818
+};
819
+
820
+static void npcm_gmac_class_init(ObjectClass *klass, void *data)
821
+{
822
+ DeviceClass *dc = DEVICE_CLASS(klass);
823
+
824
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
825
+ dc->desc = "NPCM GMAC Controller";
826
+ dc->realize = npcm_gmac_realize;
827
+ dc->unrealize = npcm_gmac_unrealize;
828
+ dc->reset = npcm_gmac_reset;
829
+ dc->vmsd = &vmstate_npcm_gmac;
830
+ device_class_set_props(dc, npcm_gmac_properties);
831
+}
832
+
833
+static const TypeInfo npcm_gmac_types[] = {
834
+ {
835
+ .name = TYPE_NPCM_GMAC,
836
+ .parent = TYPE_SYS_BUS_DEVICE,
837
+ .instance_size = sizeof(NPCMGMACState),
838
+ .class_init = npcm_gmac_class_init,
839
+ },
840
+};
841
+DEFINE_TYPES(npcm_gmac_types)
842
diff --git a/hw/net/meson.build b/hw/net/meson.build
843
index XXXXXXX..XXXXXXX 100644
430
index XXXXXXX..XXXXXXX 100644
844
--- a/hw/net/meson.build
431
--- a/hw/net/Kconfig
845
+++ b/hw/net/meson.build
432
+++ b/hw/net/Kconfig
846
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c'))
433
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_SUN8I_EMAC
847
system_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c'))
434
848
system_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
435
config IMX_FEC
849
system_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c'))
436
bool
850
-system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c'))
437
+ select LAN9118_PHY
851
+system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c', 'npcm_gmac.c'))
438
852
439
config CADENCE
853
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
440
bool
854
system_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
855
diff --git a/hw/net/trace-events b/hw/net/trace-events
441
diff --git a/hw/net/trace-events b/hw/net/trace-events
856
index XXXXXXX..XXXXXXX 100644
442
index XXXXXXX..XXXXXXX 100644
857
--- a/hw/net/trace-events
443
--- a/hw/net/trace-events
858
+++ b/hw/net/trace-events
444
+++ b/hw/net/trace-events
859
@@ -XXX,XX +XXX,XX @@ npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=0x%x"
445
@@ -XXX,XX +XXX,XX @@ allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
860
npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int regno) "emc%d: 0x%x = reg[%s/%d]"
446
allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
861
npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t value) "emc%d: reg[%s/%d] = 0x%x"
447
allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
862
448
863
+# npcm_gmac.c
449
+# lan9118_phy.c
864
+npcm_gmac_reg_read(const char *name, uint64_t offset, uint32_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx32
450
+lan9118_phy_read(uint16_t val, int reg) "[0x%02x] -> 0x%04" PRIx16
865
+npcm_gmac_reg_write(const char *name, uint64_t offset, uint32_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx32
451
+lan9118_phy_write(uint16_t val, int reg) "[0x%02x] <- 0x%04" PRIx16
866
+npcm_gmac_mdio_access(const char *name, uint8_t is_write, uint8_t pa, uint8_t gr, uint16_t val) "%s: is_write: %" PRIu8 " pa: %" PRIu8 " gr: %" PRIu8 " val: 0x%04" PRIx16
452
+lan9118_phy_update_link(const char *s) "%s"
867
+npcm_gmac_reset(const char *name, uint16_t value) "%s: phy_regs[0][1]: 0x%04" PRIx16
453
+lan9118_phy_reset(void) ""
868
+npcm_gmac_set_link(bool active) "Set link: active=%u"
454
+
869
+npcm_gmac_update_irq(const char *name, uint32_t status, uint32_t intr_en, int level) "%s: Status Reg: 0x%04" PRIX32 " Interrupt Enable Reg: 0x%04" PRIX32 " IRQ Set: %d"
455
# lance.c
870
+
456
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=0x%"PRIx64"val=0x%04x"
871
+# npcm_pcs.c
457
lance_mem_writew(uint64_t addr, uint32_t val) "addr=0x%"PRIx64"val=0x%04x"
872
+npcm_pcs_reg_read(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
458
@@ -XXX,XX +XXX,XX @@ i82596_set_multicast(uint16_t count) "Added %d multicast entries"
873
+npcm_pcs_reg_write(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
459
i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
874
+
460
875
# dp8398x.c
461
# imx_fec.c
876
dp8393x_raise_irq(int isr) "raise irq, isr is 0x%04x"
462
-imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
877
dp8393x_lower_irq(void) "lower irq"
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"
878
--
471
--
879
2.34.1
472
2.34.1
diff view generated by jsdifflib
1
From: Anastasia Belova <abelova@astralinux.ru>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
j is used while loading an ELF file to byteswap segments'
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
data. If data is larger than 2GB an overflow may happen.
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
5
So j should be elf_word.
6
5
7
This commit fixes a minor bug: it's unlikely anybody is trying to
6
Fixes: 2a424990170b "LAN9118 emulation"
8
load ELF files with 2GB+ segments for wrong-endianness targets,
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
but if they did, it wouldn't work correctly.
8
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
11
Found by Linux Verification Center (linuxtesting.org) with SVACE.
12
13
Cc: qemu-stable@nongnu.org
14
Fixes: 7ef295ea5b ("loader: Add data swap option to load-elf")
15
Signed-off-by: Anastasia Belova <abelova@astralinux.ru>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20241102125724.532843-4-shentey@gmail.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
12
---
19
include/hw/elf_ops.h | 2 +-
13
hw/net/lan9118_phy.c | 2 +-
20
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
21
15
22
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/elf_ops.h
18
--- a/hw/net/lan9118_phy.c
25
+++ b/include/hw/elf_ops.h
19
+++ b/hw/net/lan9118_phy.c
26
@@ -XXX,XX +XXX,XX @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd,
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
27
}
21
val = s->advertise;
28
22
break;
29
if (data_swab) {
23
case 5: /* Auto-neg Link Partner Ability */
30
- int j;
24
- val = 0x0f71;
31
+ elf_word j;
25
+ val = 0x0fe1;
32
for (j = 0; j < file_size; j += (1 << data_swab)) {
26
break;
33
uint8_t *dp = data + j;
27
case 6: /* Auto-neg Expansion */
34
switch (data_swab) {
28
val = 1;
35
--
29
--
36
2.34.1
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
1
From: Nabih Estefan Diaz <nabihestefan@google.com>
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
- Implementation of Transmit function for packets
3
architectures thus do different things:
4
- Implementation for reading and writing from and to descriptors in
4
* some return the default NaN
5
memory for Tx
5
* some return the input NaN
6
6
* Arm returns the default NaN if the input NaN is quiet,
7
NOTE: This function implements the steps detailed in the datasheet for
7
and the input NaN if it is signalling
8
transmitting messages from the GMAC.
8
9
9
We want to make this logic be runtime selected rather than
10
Added relevant trace-events
10
hardcoded into the binary, because:
11
11
* this will let us have multiple targets in one QEMU binary
12
Change-Id: Icf14f9fcc6cc7808a41acd872bca67c9832087e6
12
* the Arm FEAT_AFP architectural feature includes letting
13
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
13
the guest select a NaN propagation rule at runtime
14
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
14
15
Message-id: 20240110234232.4116804-10-nabihestefan@google.com
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
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-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
18
---
33
---
19
hw/net/npcm_gmac.c | 203 ++++++++++++++++++++++++++++++++++++++++++++
34
include/fpu/softfloat-helpers.h | 11 ++++
20
hw/net/trace-events | 2 +
35
include/fpu/softfloat-types.h | 23 +++++++++
21
2 files changed, 205 insertions(+)
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
22
37
3 files changed, 95 insertions(+), 30 deletions(-)
23
diff --git a/hw/net/npcm_gmac.c b/hw/net/npcm_gmac.c
38
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
24
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/net/npcm_gmac.c
41
--- a/include/fpu/softfloat-helpers.h
26
+++ b/hw/net/npcm_gmac.c
42
+++ b/include/fpu/softfloat-helpers.h
27
@@ -XXX,XX +XXX,XX @@ static int gmac_write_rx_desc(dma_addr_t addr, struct NPCMGMACRxDesc *desc)
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
28
return 0;
44
status->float_2nan_prop_rule = rule;
29
}
45
}
30
46
31
+static int gmac_read_tx_desc(dma_addr_t addr, struct NPCMGMACTxDesc *desc)
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
+ float_status *status)
32
+{
49
+{
33
+ if (dma_memory_read(&address_space_memory, addr, desc,
50
+ status->float_infzeronan_rule = rule;
34
+ sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) {
35
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
36
+ HWADDR_PRIx "\n", __func__, addr);
37
+ return -1;
38
+ }
39
+ desc->tdes0 = le32_to_cpu(desc->tdes0);
40
+ desc->tdes1 = le32_to_cpu(desc->tdes1);
41
+ desc->tdes2 = le32_to_cpu(desc->tdes2);
42
+ desc->tdes3 = le32_to_cpu(desc->tdes3);
43
+ return 0;
44
+}
51
+}
45
+
52
+
46
+static int gmac_write_tx_desc(dma_addr_t addr, struct NPCMGMACTxDesc *desc)
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)
47
+{
61
+{
48
+ struct NPCMGMACTxDesc le_desc;
62
+ return status->float_infzeronan_rule;
49
+ le_desc.tdes0 = cpu_to_le32(desc->tdes0);
50
+ le_desc.tdes1 = cpu_to_le32(desc->tdes1);
51
+ le_desc.tdes2 = cpu_to_le32(desc->tdes2);
52
+ le_desc.tdes3 = cpu_to_le32(desc->tdes3);
53
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
54
+ sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) {
55
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
56
+ HWADDR_PRIx "\n", __func__, addr);
57
+ return -1;
58
+ }
59
+ return 0;
60
+}
63
+}
61
+
64
+
62
static int gmac_rx_transfer_frame_to_buffer(uint32_t rx_buf_len,
65
static inline bool get_flush_to_zero(float_status *status)
63
uint32_t *left_frame,
66
{
64
uint32_t rx_buf_addr,
67
return status->flush_to_zero;
65
@@ -XXX,XX +XXX,XX @@ static ssize_t gmac_receive(NetClientState *nc, const uint8_t *buf, size_t len)
68
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
66
return len;
69
index XXXXXXX..XXXXXXX 100644
67
}
70
--- a/include/fpu/softfloat-types.h
68
71
+++ b/include/fpu/softfloat-types.h
69
+static int gmac_tx_get_csum(uint32_t tdes1)
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
70
+{
73
float_2nan_prop_x87,
71
+ uint32_t mask = TX_DESC_TDES1_CHKSM_INS_CTRL_MASK(tdes1);
74
} Float2NaNPropRule;
72
+ int csum = 0;
75
73
+
76
+/*
74
+ if (likely(mask > 0)) {
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
75
+ csum |= CSUM_IP;
78
+ * This must be a NaN, but implementations differ on whether this
76
+ }
79
+ * is the input NaN or the default NaN.
77
+ if (likely(mask > 1)) {
80
+ *
78
+ csum |= CSUM_TCP | CSUM_UDP;
81
+ * You don't need to set this if default_nan_mode is enabled.
79
+ }
82
+ * When not in default-NaN mode, it is an error for the target
80
+
83
+ * not to set the rule in float_status if it uses muladd, and we
81
+ return csum;
84
+ * will assert if we need to handle an input NaN and no rule was
82
+}
85
+ * selected.
83
+
86
+ */
84
+static void gmac_try_send_next_packet(NPCMGMACState *gmac)
87
+typedef enum __attribute__((__packed__)) {
85
+{
88
+ /* No propagation rule specified */
86
+ /*
89
+ float_infzeronan_none = 0,
87
+ * Comments about steps refer to steps for
90
+ /* Result is never the default NaN (so always the input NaN) */
88
+ * transmitting in page 384 of datasheet
91
+ float_infzeronan_dnan_never,
89
+ */
92
+ /* Result is always the default NaN */
90
+ uint16_t tx_buffer_size = 2048;
93
+ float_infzeronan_dnan_always,
91
+ g_autofree uint8_t *tx_send_buffer = g_malloc(tx_buffer_size);
94
+ /* Result is the default NaN if the input NaN is quiet */
92
+ uint32_t desc_addr;
95
+ float_infzeronan_dnan_if_qnan,
93
+ struct NPCMGMACTxDesc tx_desc;
96
+} FloatInfZeroNaNRule;
94
+ uint32_t tx_buf_addr, tx_buf_len;
97
+
95
+ uint16_t length = 0;
98
/*
96
+ uint8_t *buf = tx_send_buffer;
99
* Floating Point Status. Individual architectures may maintain
97
+ uint32_t prev_buf_size = 0;
100
* several versions of float_status for different functions. The
98
+ int csum = 0;
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
99
+
102
FloatRoundMode float_rounding_mode;
100
+ /* steps 1&2 */
103
FloatX80RoundPrec floatx80_rounding_precision;
101
+ if (!gmac->regs[R_NPCM_DMA_HOST_TX_DESC]) {
104
Float2NaNPropRule float_2nan_prop_rule;
102
+ gmac->regs[R_NPCM_DMA_HOST_TX_DESC] =
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
103
+ NPCM_DMA_HOST_TX_DESC_MASK(gmac->regs[R_NPCM_DMA_TX_BASE_ADDR]);
106
bool tininess_before_rounding;
104
+ }
107
/* should denormalised results go to zero and set the inexact flag? */
105
+ desc_addr = gmac->regs[R_NPCM_DMA_HOST_TX_DESC];
108
bool flush_to_zero;
106
+
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
107
+ while (true) {
110
index XXXXXXX..XXXXXXX 100644
108
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
111
--- a/fpu/softfloat-specialize.c.inc
109
+ NPCM_DMA_STATUS_TX_RUNNING_FETCHING_STATE);
112
+++ b/fpu/softfloat-specialize.c.inc
110
+ if (gmac_read_tx_desc(desc_addr, &tx_desc)) {
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
111
+ qemu_log_mask(LOG_GUEST_ERROR,
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
112
+ "TX Descriptor @ 0x%x can't be read\n",
115
bool infzero, float_status *status)
113
+ desc_addr);
116
{
114
+ return;
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;
115
+ }
155
+ }
116
+ /* step 3 */
156
+#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
117
+
157
+ defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
118
+ trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path,
158
+ defined(TARGET_I386) || defined(TARGET_LOONGARCH)
119
+ desc_addr);
159
+ /*
120
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &tx_desc,
160
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
121
+ tx_desc.tdes0, tx_desc.tdes1, tx_desc.tdes2, tx_desc.tdes3);
161
+ * case sets InvalidOp and returns the input value 'c'
122
+
162
+ */
123
+ /* 1 = DMA Owned, 0 = Software Owned */
163
+ /*
124
+ if (!(tx_desc.tdes0 & TX_DESC_TDES0_OWN)) {
164
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
125
+ qemu_log_mask(LOG_GUEST_ERROR,
165
+ * to return an input NaN if we have one (ie c) rather than generating
126
+ "TX Descriptor @ 0x%x is owned by software\n",
166
+ * a default NaN
127
+ desc_addr);
167
+ */
128
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_TU;
168
+ rule = float_infzeronan_dnan_never;
129
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
169
+#elif defined(TARGET_S390X)
130
+ NPCM_DMA_STATUS_TX_SUSPENDED_STATE);
170
+ rule = float_infzeronan_dnan_always;
131
+ gmac_update_irq(gmac);
171
+#endif
132
+ return;
172
}
133
+ }
173
134
+
174
+ if (infzero) {
135
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
175
+ /*
136
+ NPCM_DMA_STATUS_TX_RUNNING_READ_STATE);
176
+ * Inf * 0 + NaN -- some implementations return the default NaN here,
137
+ /* Give the descriptor back regardless of what happens. */
177
+ * and some return the input NaN.
138
+ tx_desc.tdes0 &= ~TX_DESC_TDES0_OWN;
178
+ */
139
+
179
+ switch (rule) {
140
+ if (tx_desc.tdes1 & TX_DESC_TDES1_FIRST_SEG_MASK) {
180
+ case float_infzeronan_dnan_never:
141
+ csum = gmac_tx_get_csum(tx_desc.tdes1);
181
+ return 2;
142
+ }
182
+ case float_infzeronan_dnan_always:
143
+
183
+ return 3;
144
+ /* step 4 */
184
+ case float_infzeronan_dnan_if_qnan:
145
+ tx_buf_addr = tx_desc.tdes2;
185
+ return is_qnan(c_cls) ? 3 : 2;
146
+ gmac->regs[R_NPCM_DMA_CUR_TX_BUF_ADDR] = tx_buf_addr;
186
+ default:
147
+ tx_buf_len = TX_DESC_TDES1_BFFR1_SZ_MASK(tx_desc.tdes1);
187
+ g_assert_not_reached();
148
+ buf = &tx_send_buffer[prev_buf_size];
149
+
150
+ if ((prev_buf_size + tx_buf_len) > sizeof(buf)) {
151
+ tx_buffer_size = prev_buf_size + tx_buf_len;
152
+ tx_send_buffer = g_realloc(tx_send_buffer, tx_buffer_size);
153
+ buf = &tx_send_buffer[prev_buf_size];
154
+ }
155
+
156
+ /* step 5 */
157
+ if (dma_memory_read(&address_space_memory, tx_buf_addr, buf,
158
+ tx_buf_len, MEMTXATTRS_UNSPECIFIED)) {
159
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n",
160
+ __func__, tx_buf_addr);
161
+ return;
162
+ }
163
+ length += tx_buf_len;
164
+ prev_buf_size += tx_buf_len;
165
+
166
+ /* If not chained we'll have a second buffer. */
167
+ if (!(tx_desc.tdes1 & TX_DESC_TDES1_SEC_ADDR_CHND_MASK)) {
168
+ tx_buf_addr = tx_desc.tdes3;
169
+ gmac->regs[R_NPCM_DMA_CUR_TX_BUF_ADDR] = tx_buf_addr;
170
+ tx_buf_len = TX_DESC_TDES1_BFFR2_SZ_MASK(tx_desc.tdes1);
171
+ buf = &tx_send_buffer[prev_buf_size];
172
+
173
+ if ((prev_buf_size + tx_buf_len) > sizeof(buf)) {
174
+ tx_buffer_size = prev_buf_size + tx_buf_len;
175
+ tx_send_buffer = g_realloc(tx_send_buffer, tx_buffer_size);
176
+ buf = &tx_send_buffer[prev_buf_size];
177
+ }
178
+
179
+ if (dma_memory_read(&address_space_memory, tx_buf_addr, buf,
180
+ tx_buf_len, MEMTXATTRS_UNSPECIFIED)) {
181
+ qemu_log_mask(LOG_GUEST_ERROR,
182
+ "%s: Failed to read packet @ 0x%x\n",
183
+ __func__, tx_buf_addr);
184
+ return;
185
+ }
186
+ length += tx_buf_len;
187
+ prev_buf_size += tx_buf_len;
188
+ }
189
+ if (tx_desc.tdes1 & TX_DESC_TDES1_LAST_SEG_MASK) {
190
+ net_checksum_calculate(tx_send_buffer, length, csum);
191
+ qemu_send_packet(qemu_get_queue(gmac->nic), tx_send_buffer, length);
192
+ trace_npcm_gmac_packet_sent(DEVICE(gmac)->canonical_path, length);
193
+ buf = tx_send_buffer;
194
+ length = 0;
195
+ }
196
+
197
+ /* step 6 */
198
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
199
+ NPCM_DMA_STATUS_TX_RUNNING_CLOSING_STATE);
200
+ gmac_write_tx_desc(desc_addr, &tx_desc);
201
+ if (tx_desc.tdes1 & TX_DESC_TDES1_TX_END_RING_MASK) {
202
+ desc_addr = gmac->regs[R_NPCM_DMA_TX_BASE_ADDR];
203
+ } else if (tx_desc.tdes1 & TX_DESC_TDES1_SEC_ADDR_CHND_MASK) {
204
+ desc_addr = tx_desc.tdes3;
205
+ } else {
206
+ desc_addr += sizeof(tx_desc);
207
+ }
208
+ gmac->regs[R_NPCM_DMA_HOST_TX_DESC] = desc_addr;
209
+
210
+ /* step 7 */
211
+ if (tx_desc.tdes1 & TX_DESC_TDES1_INTERR_COMP_MASK) {
212
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_TI;
213
+ gmac_update_irq(gmac);
214
+ }
188
+ }
215
+ }
189
+ }
216
+}
190
+
217
+
191
+#if defined(TARGET_ARM)
218
static void gmac_cleanup(NetClientState *nc)
192
+
219
{
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
220
/* Nothing to do yet. */
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
221
@@ -XXX,XX +XXX,XX @@ static void npcm_gmac_write(void *opaque, hwaddr offset,
195
*/
222
NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
223
break;
197
}
224
198
#elif defined(TARGET_MIPS)
225
+ case A_NPCM_DMA_XMT_POLL_DEMAND:
199
if (snan_bit_is_one(status)) {
226
+ /* We dont actually care about the value */
200
- /*
227
+ gmac_try_send_next_packet(gmac);
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
228
+ break;
202
- * case sets InvalidOp and returns the default NaN
229
+
203
- */
230
+ case A_NPCM_DMA_CONTROL:
204
- if (infzero) {
231
+ gmac->regs[offset / sizeof(uint32_t)] = v;
205
- return 3;
232
+ if (v & NPCM_DMA_CONTROL_START_STOP_TX) {
206
- }
233
+ gmac_try_send_next_packet(gmac);
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
234
+ } else {
208
if (is_snan(a_cls)) {
235
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
209
return 0;
236
+ NPCM_DMA_STATUS_TX_STOPPED_STATE);
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
237
+ }
211
return 2;
238
+ if (v & NPCM_DMA_CONTROL_START_STOP_RX) {
212
}
239
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
213
} else {
240
+ NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
214
- /*
241
+ qemu_flush_queued_packets(qemu_get_queue(gmac->nic));
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
242
+ } else {
216
- * case sets InvalidOp and returns the input value 'c'
243
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
217
- */
244
+ NPCM_DMA_STATUS_RX_STOPPED_STATE);
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
245
+ }
219
if (is_snan(c_cls)) {
246
+ break;
220
return 2;
247
+
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
248
case A_NPCM_DMA_STATUS:
222
}
249
/* Check that RO bits are not written to */
223
}
250
if (NPCM_DMA_STATUS_RO_MASK(v)) {
224
#elif defined(TARGET_LOONGARCH64)
251
diff --git a/hw/net/trace-events b/hw/net/trace-events
225
- /*
252
index XXXXXXX..XXXXXXX 100644
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
253
--- a/hw/net/trace-events
227
- * case sets InvalidOp and returns the input value 'c'
254
+++ b/hw/net/trace-events
228
- */
255
@@ -XXX,XX +XXX,XX @@ npcm_gmac_packet_desc_read(const char* name, uint32_t desc_addr) "%s: attempting
229
-
256
npcm_gmac_packet_receive(const char* name, uint32_t len) "%s: RX packet length: 0x%04" PRIX32
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
257
npcm_gmac_packet_receiving_buffer(const char* name, uint32_t buf_len, uint32_t rx_buf_addr) "%s: Receiving into Buffer size: 0x%04" PRIX32 " at address 0x%04" PRIX32
231
if (is_snan(c_cls)) {
258
npcm_gmac_packet_received(const char* name, uint32_t len) "%s: Reception finished, packet left: 0x%04" PRIX32
232
return 2;
259
+npcm_gmac_packet_sent(const char* name, uint16_t len) "%s: TX packet sent!, length: 0x%04" PRIX16
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
260
npcm_gmac_debug_desc_data(const char* name, void* addr, uint32_t des0, uint32_t des1, uint32_t des2, uint32_t des3)"%s: Address: %p Descriptor 0: 0x%04" PRIX32 " Descriptor 1: 0x%04" PRIX32 "Descriptor 2: 0x%04" PRIX32 " Descriptor 3: 0x%04" PRIX32
234
return 1;
261
+npcm_gmac_packet_tx_desc_data(const char* name, uint32_t tdes0, uint32_t tdes1) "%s: Tdes0: 0x%04" PRIX32 " Tdes1: 0x%04" PRIX32
235
}
262
236
#elif defined(TARGET_PPC)
263
# npcm_pcs.c
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
264
npcm_pcs_reg_read(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
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)) {
265
--
256
--
266
2.34.1
257
2.34.1
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for the inf-zero-nan
2
muladd special case. In meson.build we put -DTARGET_ARM in fpcflags,
3
and so we should select here the Arm rule of
4
float_infzeronan_dnan_if_qnan.
1
5
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241202131347.498124-5-peter.maydell@linaro.org
9
---
10
tests/fp/fp-bench.c | 5 +++++
11
tests/fp/fp-test.c | 5 +++++
12
2 files changed, 10 insertions(+)
13
14
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/fp/fp-bench.c
17
+++ b/tests/fp/fp-bench.c
18
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
19
{
20
bench_func_t f;
21
22
+ /*
23
+ * These implementation-defined choices for various things IEEE
24
+ * doesn't specify match those used by the Arm architecture.
25
+ */
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
28
29
f = bench_funcs[operation][precision];
30
g_assert(f);
31
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/fp/fp-test.c
34
+++ b/tests/fp/fp-test.c
35
@@ -XXX,XX +XXX,XX @@ void run_test(void)
36
{
37
unsigned int i;
38
39
+ /*
40
+ * These implementation-defined choices for various things IEEE
41
+ * doesn't specify match those used by the Arm architecture.
42
+ */
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
44
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
45
46
genCases_setLevel(test_level);
47
verCases_maxErrorCount = n_max_errors;
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the Arm target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-6-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 3 +++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 4 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
21
+ * and the input NaN if it is signalling
22
*/
23
static void arm_set_default_fp_behaviours(float_status *s)
24
{
25
set_float_detect_tininess(float_tininess_before_rounding, s);
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
28
}
29
30
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
/*
37
* Temporarily fall back to ifdef ladder
38
*/
39
-#if defined(TARGET_ARM)
40
- /*
41
- * For ARM, the (inf,zero,qnan) case returns the default NaN,
42
- * but (inf,zero,snan) returns the input NaN.
43
- */
44
- rule = float_infzeronan_dnan_if_qnan;
45
-#elif defined(TARGET_MIPS)
46
+#if defined(TARGET_MIPS)
47
if (snan_bit_is_one(status)) {
48
/*
49
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
50
--
51
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-7-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
21
+ &env->fpu_status);
22
/* fall through */
23
case RESET_TYPE_S390_CPU_NORMAL:
24
env->psw.mask &= ~PSW_MASK_RI;
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
* a default NaN
31
*/
32
rule = float_infzeronan_dnan_never;
33
-#elif defined(TARGET_S390X)
34
- rule = float_infzeronan_dnan_always;
35
#endif
36
}
37
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the PPC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-8-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 7 +++++++
9
fpu/softfloat-specialize.c.inc | 7 +------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
22
+ * to return an input NaN if we have one (ie c) rather than generating
23
+ * a default NaN
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
27
28
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
29
ppc_spr_t *spr = &env->spr_cb[i];
30
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
32
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
*/
36
rule = float_infzeronan_dnan_never;
37
}
38
-#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
39
+#elif defined(TARGET_SPARC) || \
40
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
41
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
42
/*
43
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
44
* case sets InvalidOp and returns the input value 'c'
45
*/
46
- /*
47
- * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
48
- * to return an input NaN if we have one (ie c) rather than generating
49
- * a default NaN
50
- */
51
rule = float_infzeronan_dnan_never;
52
#endif
53
}
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the MIPS target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-9-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 9 +++++++++
9
target/mips/msa.c | 4 ++++
10
fpu/softfloat-specialize.c.inc | 16 +---------------
11
3 files changed, 14 insertions(+), 15 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_flush_mode(CPUMIPSState *env)
18
static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
{
20
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
21
+ FloatInfZeroNaNRule izn_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
set_snan_bit_is_one(!nan2008, &env->active_fpu.fp_status);
28
set_default_nan_mode(!nan2008, &env->active_fpu.fp_status);
29
+ /*
30
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
31
+ * case sets InvalidOp and returns the default NaN.
32
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
33
+ * case sets InvalidOp and returns the input value 'c'.
34
+ */
35
+ izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
36
+ set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
37
}
38
39
static inline void restore_fp_status(CPUMIPSState *env)
40
diff --git a/target/mips/msa.c b/target/mips/msa.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/mips/msa.c
43
+++ b/target/mips/msa.c
44
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
45
46
/* set proper signanling bit meaning ("1" means "quiet") */
47
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
48
+
49
+ /* Inf * 0 + NaN returns the input NaN */
50
+ set_float_infzeronan_rule(float_infzeronan_dnan_never,
51
+ &env->active_tc.msa_fp_status);
52
}
53
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
54
index XXXXXXX..XXXXXXX 100644
55
--- a/fpu/softfloat-specialize.c.inc
56
+++ b/fpu/softfloat-specialize.c.inc
57
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
58
/*
59
* Temporarily fall back to ifdef ladder
60
*/
61
-#if defined(TARGET_MIPS)
62
- if (snan_bit_is_one(status)) {
63
- /*
64
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
65
- * case sets InvalidOp and returns the default NaN
66
- */
67
- rule = float_infzeronan_dnan_always;
68
- } else {
69
- /*
70
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
71
- * case sets InvalidOp and returns the input value 'c'
72
- */
73
- rule = float_infzeronan_dnan_never;
74
- }
75
-#elif defined(TARGET_SPARC) || \
76
+#if defined(TARGET_SPARC) || \
77
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
78
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
79
/*
80
--
81
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the SPARC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-10-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_SPARC) || \
34
- defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
35
+#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
36
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
37
/*
38
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the xtensa target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-11-peter.maydell@linaro.org
7
---
8
target/xtensa/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 +-
10
2 files changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/xtensa/cpu.c
15
+++ b/target/xtensa/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
17
reset_mmu(env);
18
cs->halted = env->runstall;
19
#endif
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
set_no_signaling_nans(!dfpu, &env->fp_status);
23
xtensa_use_first_nan(env, !dfpu);
24
}
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
34
+#if defined(TARGET_HPPA) || \
35
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
36
/*
37
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the x86 target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-12-peter.maydell@linaro.org
6
---
7
target/i386/tcg/fpu_helper.c | 7 +++++++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 8 insertions(+), 1 deletion(-)
10
11
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/i386/tcg/fpu_helper.c
14
+++ b/target/i386/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
18
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
19
+ /*
20
+ * Only SSE has multiply-add instructions. In the SDM Section 14.5.2
21
+ * "Fused-Multiply-ADD (FMA) Numeric Behavior" the NaN handling is
22
+ * specified -- for 0 * inf + NaN the input NaN is selected, and if
23
+ * there are multiple input NaNs they are selected in the order a, b, c.
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
26
}
27
28
static inline uint8_t save_exception_flags(CPUX86State *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
* Temporarily fall back to ifdef ladder
35
*/
36
#if defined(TARGET_HPPA) || \
37
- defined(TARGET_I386) || defined(TARGET_LOONGARCH)
38
+ defined(TARGET_LOONGARCH)
39
/*
40
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
41
* case sets InvalidOp and returns the input value 'c'
42
--
43
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the loongarch target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-13-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 5 +++++
8
fpu/softfloat-specialize.c.inc | 7 +------
9
2 files changed, 6 insertions(+), 6 deletions(-)
10
11
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/loongarch/tcg/fpu_helper.c
14
+++ b/target/loongarch/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
16
&env->fp_status);
17
set_flush_to_zero(0, &env->fp_status);
18
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
19
+ /*
20
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
21
+ * case sets InvalidOp and returns the input value 'c'
22
+ */
23
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
}
25
26
int ieee_ex_to_loongarch(int xcpt)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
32
/*
33
* Temporarily fall back to ifdef ladder
34
*/
35
-#if defined(TARGET_HPPA) || \
36
- defined(TARGET_LOONGARCH)
37
- /*
38
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
- * case sets InvalidOp and returns the input value 'c'
40
- */
41
+#if defined(TARGET_HPPA)
42
rule = float_infzeronan_dnan_never;
43
#endif
44
}
45
--
46
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
As this is the last target to be converted to explicitly setting
5
the rule, we can remove the fallback code in pickNaNMulAdd()
6
entirely.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
11
---
12
target/hppa/fpu_helper.c | 2 ++
13
fpu/softfloat-specialize.c.inc | 13 +------------
14
2 files changed, 3 insertions(+), 12 deletions(-)
15
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/hppa/fpu_helper.c
19
+++ b/target/hppa/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
21
* HPPA does note implement a CPU reset method at all...
22
*/
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
24
+ /* For inf * 0 + NaN, return the input NaN */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
}
27
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
34
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
bool infzero, float_status *status)
36
{
37
- FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
38
-
39
/*
40
* We guarantee not to require the target to tell us how to
41
* pick a NaN if we're always returning the default NaN.
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
43
*/
44
assert(!status->default_nan_mode);
45
46
- if (rule == float_infzeronan_none) {
47
- /*
48
- * Temporarily fall back to ifdef ladder
49
- */
50
-#if defined(TARGET_HPPA)
51
- rule = float_infzeronan_dnan_never;
52
-#endif
53
- }
54
-
55
if (infzero) {
56
/*
57
* Inf * 0 + NaN -- some implementations return the default NaN here,
58
* and some return the input NaN.
59
*/
60
- switch (rule) {
61
+ switch (status->float_infzeronan_rule) {
62
case float_infzeronan_dnan_never:
63
return 2;
64
case float_infzeronan_dnan_always:
65
--
66
2.34.1
diff view generated by jsdifflib
New patch
1
The new implementation of pickNaNMulAdd() will find it convenient
2
to know whether at least one of the three arguments to the muladd
3
was a signaling NaN. We already calculate that in the caller,
4
so pass it in as a new bool have_snan.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-15-peter.maydell@linaro.org
9
---
10
fpu/softfloat-parts.c.inc | 5 +++--
11
fpu/softfloat-specialize.c.inc | 2 +-
12
2 files changed, 4 insertions(+), 3 deletions(-)
13
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
{
20
int which;
21
bool infzero = (ab_mask == float_cmask_infzero);
22
+ bool have_snan = (abc_mask & float_cmask_snan);
23
24
- if (unlikely(abc_mask & float_cmask_snan)) {
25
+ if (unlikely(have_snan)) {
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
27
}
28
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
if (s->default_nan_mode) {
31
which = 3;
32
} else {
33
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
34
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
35
}
36
37
if (which == 3) {
38
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
39
index XXXXXXX..XXXXXXX 100644
40
--- a/fpu/softfloat-specialize.c.inc
41
+++ b/fpu/softfloat-specialize.c.inc
42
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
43
| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
44
*----------------------------------------------------------------------------*/
45
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
46
- bool infzero, float_status *status)
47
+ bool infzero, bool have_snan, float_status *status)
48
{
49
/*
50
* We guarantee not to require the target to tell us how to
51
--
52
2.34.1
diff view generated by jsdifflib
1
From: Nabih Estefan Diaz <nabihestefan@google.com>
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
2
result if both operands of a 3-operand fused multiply-add operation
3
- Add PCS Register check to npcm_gmac-test
3
are NaNs. As a result different architectures have ended up with
4
4
different rules for propagating NaNs.
5
Change-Id: I34821beb5e0b1e89e2be576ab58eabe41545af12
5
6
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
Message-id: 20240110234232.4116804-11-nabihestefan@google.com
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
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-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
11
---
27
---
12
tests/qtest/npcm_gmac-test.c | 132 +++++++++++++++++++++++++++++++++++
28
include/fpu/softfloat-helpers.h | 11 +++
13
1 file changed, 132 insertions(+)
29
include/fpu/softfloat-types.h | 55 +++++++++++
14
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
15
diff --git a/tests/qtest/npcm_gmac-test.c b/tests/qtest/npcm_gmac-test.c
31
3 files changed, 107 insertions(+), 126 deletions(-)
32
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
16
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qtest/npcm_gmac-test.c
35
--- a/include/fpu/softfloat-helpers.h
18
+++ b/tests/qtest/npcm_gmac-test.c
36
+++ b/include/fpu/softfloat-helpers.h
19
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
20
/* Name of the GMAC Device */
38
status->float_2nan_prop_rule = rule;
21
#define TYPE_NPCM_GMAC "npcm-gmac"
22
23
+/* Address of the PCS Module */
24
+#define PCS_BASE_ADDRESS 0xf0780000
25
+#define NPCM_PCS_IND_AC_BA 0x1fe
26
+
27
typedef struct GMACModule {
28
int irq;
29
uint64_t base_addr;
30
@@ -XXX,XX +XXX,XX @@ typedef enum NPCMRegister {
31
NPCM_GMAC_PTP_STNSUR = 0x714,
32
NPCM_GMAC_PTP_TAR = 0x718,
33
NPCM_GMAC_PTP_TTSR = 0x71c,
34
+
35
+ /* PCS Registers */
36
+ NPCM_PCS_SR_CTL_ID1 = 0x3c0008,
37
+ NPCM_PCS_SR_CTL_ID2 = 0x3c000a,
38
+ NPCM_PCS_SR_CTL_STS = 0x3c0010,
39
+
40
+ NPCM_PCS_SR_MII_CTRL = 0x3e0000,
41
+ NPCM_PCS_SR_MII_STS = 0x3e0002,
42
+ NPCM_PCS_SR_MII_DEV_ID1 = 0x3e0004,
43
+ NPCM_PCS_SR_MII_DEV_ID2 = 0x3e0006,
44
+ NPCM_PCS_SR_MII_AN_ADV = 0x3e0008,
45
+ NPCM_PCS_SR_MII_LP_BABL = 0x3e000a,
46
+ NPCM_PCS_SR_MII_AN_EXPN = 0x3e000c,
47
+ NPCM_PCS_SR_MII_EXT_STS = 0x3e001e,
48
+
49
+ NPCM_PCS_SR_TIM_SYNC_ABL = 0x3e0e10,
50
+ NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_LWR = 0x3e0e12,
51
+ NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_UPR = 0x3e0e14,
52
+ NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_LWR = 0x3e0e16,
53
+ NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_UPR = 0x3e0e18,
54
+ NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_LWR = 0x3e0e1a,
55
+ NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_UPR = 0x3e0e1c,
56
+ NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_LWR = 0x3e0e1e,
57
+ NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_UPR = 0x3e0e20,
58
+
59
+ NPCM_PCS_VR_MII_MMD_DIG_CTRL1 = 0x3f0000,
60
+ NPCM_PCS_VR_MII_AN_CTRL = 0x3f0002,
61
+ NPCM_PCS_VR_MII_AN_INTR_STS = 0x3f0004,
62
+ NPCM_PCS_VR_MII_TC = 0x3f0006,
63
+ NPCM_PCS_VR_MII_DBG_CTRL = 0x3f000a,
64
+ NPCM_PCS_VR_MII_EEE_MCTRL0 = 0x3f000c,
65
+ NPCM_PCS_VR_MII_EEE_TXTIMER = 0x3f0010,
66
+ NPCM_PCS_VR_MII_EEE_RXTIMER = 0x3f0012,
67
+ NPCM_PCS_VR_MII_LINK_TIMER_CTRL = 0x3f0014,
68
+ NPCM_PCS_VR_MII_EEE_MCTRL1 = 0x3f0016,
69
+ NPCM_PCS_VR_MII_DIG_STS = 0x3f0020,
70
+ NPCM_PCS_VR_MII_ICG_ERRCNT1 = 0x3f0022,
71
+ NPCM_PCS_VR_MII_MISC_STS = 0x3f0030,
72
+ NPCM_PCS_VR_MII_RX_LSTS = 0x3f0040,
73
+ NPCM_PCS_VR_MII_MP_TX_BSTCTRL0 = 0x3f0070,
74
+ NPCM_PCS_VR_MII_MP_TX_LVLCTRL0 = 0x3f0074,
75
+ NPCM_PCS_VR_MII_MP_TX_GENCTRL0 = 0x3f007a,
76
+ NPCM_PCS_VR_MII_MP_TX_GENCTRL1 = 0x3f007c,
77
+ NPCM_PCS_VR_MII_MP_TX_STS = 0x3f0090,
78
+ NPCM_PCS_VR_MII_MP_RX_GENCTRL0 = 0x3f00b0,
79
+ NPCM_PCS_VR_MII_MP_RX_GENCTRL1 = 0x3f00b2,
80
+ NPCM_PCS_VR_MII_MP_RX_LOS_CTRL0 = 0x3f00ba,
81
+ NPCM_PCS_VR_MII_MP_MPLL_CTRL0 = 0x3f00f0,
82
+ NPCM_PCS_VR_MII_MP_MPLL_CTRL1 = 0x3f00f2,
83
+ NPCM_PCS_VR_MII_MP_MPLL_STS = 0x3f0110,
84
+ NPCM_PCS_VR_MII_MP_MISC_CTRL2 = 0x3f0126,
85
+ NPCM_PCS_VR_MII_MP_LVL_CTRL = 0x3f0130,
86
+ NPCM_PCS_VR_MII_MP_MISC_CTRL0 = 0x3f0132,
87
+ NPCM_PCS_VR_MII_MP_MISC_CTRL1 = 0x3f0134,
88
+ NPCM_PCS_VR_MII_DIG_CTRL2 = 0x3f01c2,
89
+ NPCM_PCS_VR_MII_DIG_ERRCNT_SEL = 0x3f01c4,
90
} NPCMRegister;
91
92
static uint32_t gmac_read(QTestState *qts, const GMACModule *mod,
93
@@ -XXX,XX +XXX,XX @@ static uint32_t gmac_read(QTestState *qts, const GMACModule *mod,
94
return qtest_readl(qts, mod->base_addr + regno);
95
}
39
}
96
40
97
+static uint16_t pcs_read(QTestState *qts, const GMACModule *mod,
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
98
+ NPCMRegister regno)
42
+ float_status *status)
99
+{
43
+{
100
+ uint32_t write_value = (regno & 0x3ffe00) >> 9;
44
+ status->float_3nan_prop_rule = rule;
101
+ qtest_writel(qts, PCS_BASE_ADDRESS + NPCM_PCS_IND_AC_BA, write_value);
102
+ uint32_t read_offset = regno & 0x1ff;
103
+ return qtest_readl(qts, PCS_BASE_ADDRESS + read_offset);
104
+}
45
+}
105
+
46
+
106
/* Check that GMAC registers are reset to default value */
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
107
static void test_init(gconstpointer test_data)
48
float_status *status)
108
{
49
{
109
@@ -XXX,XX +XXX,XX @@ static void test_init(gconstpointer test_data)
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
110
g_assert_cmphex(gmac_read(qts, mod, (regno)), ==, (value)); \
51
return status->float_2nan_prop_rule;
111
} while (0)
52
}
112
53
113
+#define CHECK_REG_PCS(regno, value) \
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
114
+ do { \
55
+{
115
+ g_assert_cmphex(pcs_read(qts, mod, (regno)), ==, (value)); \
56
+ return status->float_3nan_prop_rule;
116
+ } while (0)
57
+}
117
+
58
+
118
CHECK_REG32(NPCM_DMA_BUS_MODE, 0x00020100);
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
119
CHECK_REG32(NPCM_DMA_XMT_POLL_DEMAND, 0);
60
{
120
CHECK_REG32(NPCM_DMA_RCV_POLL_DEMAND, 0);
61
return status->float_infzeronan_rule;
121
@@ -XXX,XX +XXX,XX @@ static void test_init(gconstpointer test_data)
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
122
CHECK_REG32(NPCM_GMAC_PTP_TAR, 0);
63
index XXXXXXX..XXXXXXX 100644
123
CHECK_REG32(NPCM_GMAC_PTP_TTSR, 0);
64
--- a/include/fpu/softfloat-types.h
124
65
+++ b/include/fpu/softfloat-types.h
125
+ /* TODO Add registers PCS */
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
126
+ if (mod->base_addr == 0xf0802000) {
67
#ifndef SOFTFLOAT_TYPES_H
127
+ CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID1, 0x699e);
68
#define SOFTFLOAT_TYPES_H
128
+ CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID2, 0);
69
129
+ CHECK_REG_PCS(NPCM_PCS_SR_CTL_STS, 0x8000);
70
+#include "hw/registerfields.h"
130
+
71
+
131
+ CHECK_REG_PCS(NPCM_PCS_SR_MII_CTRL, 0x1140);
72
/*
132
+ CHECK_REG_PCS(NPCM_PCS_SR_MII_STS, 0x0109);
73
* Software IEC/IEEE floating-point types.
133
+ CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID1, 0x699e);
74
*/
134
+ CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID2, 0x0ced0);
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
135
+ CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_ADV, 0x0020);
76
float_2nan_prop_x87,
136
+ CHECK_REG_PCS(NPCM_PCS_SR_MII_LP_BABL, 0);
77
} Float2NaNPropRule;
137
+ CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_EXPN, 0);
78
138
+ CHECK_REG_PCS(NPCM_PCS_SR_MII_EXT_STS, 0xc000);
79
+/*
139
+
80
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
140
+ CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_ABL, 0x0003);
81
+ * architectures have different rules for which input NaN is
141
+ CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_LWR, 0x0038);
82
+ * propagated to the output when there is more than one NaN on the
142
+ CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_UPR, 0);
83
+ * input.
143
+ CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_LWR, 0x0038);
84
+ *
144
+ CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_UPR, 0);
85
+ * If default_nan_mode is enabled then it is valid not to set a NaN
145
+ CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_LWR, 0x0058);
86
+ * propagation rule, because the softfloat code guarantees not to try
146
+ CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_UPR, 0);
87
+ * to pick a NaN to propagate in default NaN mode. When not in
147
+ CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_LWR, 0x0048);
88
+ * default-NaN mode, it is an error for the target not to set the rule
148
+ CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_UPR, 0);
89
+ * in float_status if it uses a muladd, and we will assert if we need
149
+
90
+ * to handle an input NaN and no rule was selected.
150
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MMD_DIG_CTRL1, 0x2400);
91
+ *
151
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_CTRL, 0);
92
+ * The naming scheme for Float3NaNPropRule values is:
152
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_INTR_STS, 0x000a);
93
+ * float_3nan_prop_s_abc:
153
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_TC, 0);
94
+ * = "Prefer SNaN over QNaN, then operand A over B over C"
154
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_DBG_CTRL, 0);
95
+ * float_3nan_prop_abc:
155
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL0, 0x899c);
96
+ * = "Prefer A over B over C regardless of SNaN vs QNAN"
156
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_TXTIMER, 0);
97
+ *
157
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_RXTIMER, 0);
98
+ * For QEMU, the multiply-add operation is A * B + C.
158
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_LINK_TIMER_CTRL, 0);
99
+ */
159
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL1, 0);
100
+
160
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_STS, 0x0010);
101
+/*
161
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_ICG_ERRCNT1, 0);
102
+ * We set the Float3NaNPropRule enum values up so we can select the
162
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MISC_STS, 0);
103
+ * right value in pickNaNMulAdd in a data driven way.
163
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_RX_LSTS, 0);
104
+ */
164
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_BSTCTRL0, 0x00a);
105
+FIELD(3NAN, 1ST, 0, 2) /* which operand is most preferred ? */
165
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_LVLCTRL0, 0x007f);
106
+FIELD(3NAN, 2ND, 2, 2) /* which operand is next most preferred ? */
166
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_GENCTRL0, 0x0001);
107
+FIELD(3NAN, 3RD, 4, 2) /* which operand is least preferred ? */
167
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_GENCTRL1, 0);
108
+FIELD(3NAN, SNAN, 6, 1) /* do we prefer SNaN over QNaN ? */
168
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_STS, 0);
109
+
169
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_GENCTRL0, 0x0100);
110
+#define PROPRULE(X, Y, Z) \
170
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_GENCTRL1, 0x1100);
111
+ ((X << R_3NAN_1ST_SHIFT) | (Y << R_3NAN_2ND_SHIFT) | (Z << R_3NAN_3RD_SHIFT))
171
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_LOS_CTRL0, 0x000e);
112
+
172
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_CTRL0, 0x0100);
113
+typedef enum __attribute__((__packed__)) {
173
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_CTRL1, 0x0032);
114
+ float_3nan_prop_none = 0, /* No propagation rule specified */
174
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_STS, 0x0001);
115
+ float_3nan_prop_abc = PROPRULE(0, 1, 2),
175
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL2, 0);
116
+ float_3nan_prop_acb = PROPRULE(0, 2, 1),
176
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_LVL_CTRL, 0x0019);
117
+ float_3nan_prop_bac = PROPRULE(1, 0, 2),
177
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL0, 0);
118
+ float_3nan_prop_bca = PROPRULE(1, 2, 0),
178
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL1, 0);
119
+ float_3nan_prop_cab = PROPRULE(2, 0, 1),
179
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_CTRL2, 0);
120
+ float_3nan_prop_cba = PROPRULE(2, 1, 0),
180
+ CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_ERRCNT_SEL, 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
181
+ }
321
+ }
182
+
322
+
183
qtest_quit(qts);
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;
184
}
337
}
185
338
339
/*----------------------------------------------------------------------------
186
--
340
--
187
2.34.1
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
New patch
1
Set the Float3NaNPropRule explicitly for SPARC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-22-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For fused-multiply add, prefer SNaN over QNaN, then C->B->A */
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
22
/* For inf * 0 + NaN, return the input NaN */
23
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
} else {
31
rule = float_3nan_prop_s_cab;
32
}
33
-#elif defined(TARGET_SPARC)
34
- rule = float_3nan_prop_s_cba;
35
#elif defined(TARGET_XTENSA)
36
if (status->use_first_nan) {
37
rule = float_3nan_prop_abc;
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-23-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 4 ++++
9
target/mips/msa.c | 3 +++
10
fpu/softfloat-specialize.c.inc | 8 +-------
11
3 files changed, 8 insertions(+), 7 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
18
{
19
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
20
FloatInfZeroNaNRule izn_rule;
21
+ Float3NaNPropRule nan3_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
28
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
29
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
30
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
31
+
32
}
33
34
static inline void restore_fp_status(CPUMIPSState *env)
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/mips/msa.c
38
+++ b/target/mips/msa.c
39
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
40
set_float_2nan_prop_rule(float_2nan_prop_s_ab,
41
&env->active_tc.msa_fp_status);
42
43
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
44
+ &env->active_tc.msa_fp_status);
45
+
46
/* clear float_status exception flags */
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
48
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
50
index XXXXXXX..XXXXXXX 100644
51
--- a/fpu/softfloat-specialize.c.inc
52
+++ b/fpu/softfloat-specialize.c.inc
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
54
}
55
56
if (rule == float_3nan_prop_none) {
57
-#if defined(TARGET_MIPS)
58
- if (snan_bit_is_one(status)) {
59
- rule = float_3nan_prop_s_abc;
60
- } else {
61
- rule = float_3nan_prop_s_cab;
62
- }
63
-#elif defined(TARGET_XTENSA)
64
+#if defined(TARGET_XTENSA)
65
if (status->use_first_nan) {
66
rule = float_3nan_prop_abc;
67
} else {
68
--
69
2.34.1
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
Change-Id: Id8a3461fb5042adc4c3fd6f4fbd1ca0d33e22565
4
Signed-off-by: Hao Wu <wuhaotsh@google.com>
5
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
6
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
Message-id: 20240110234232.4116804-6-nabihestefan@google.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
10
---
7
---
11
include/hw/arm/npcm7xx.h | 2 ++
8
target/xtensa/fpu_helper.c | 2 ++
12
hw/arm/npcm7xx.c | 36 ++++++++++++++++++++++++++++++++++--
9
fpu/softfloat-specialize.c.inc | 8 --------
13
2 files changed, 36 insertions(+), 2 deletions(-)
10
2 files changed, 2 insertions(+), 8 deletions(-)
14
11
15
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/npcm7xx.h
14
--- a/target/xtensa/fpu_helper.c
18
+++ b/include/hw/arm/npcm7xx.h
15
+++ b/target/xtensa/fpu_helper.c
19
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
20
#include "hw/misc/npcm7xx_pwm.h"
17
set_use_first_nan(use_first, &env->fp_status);
21
#include "hw/misc/npcm7xx_rng.h"
18
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
22
#include "hw/net/npcm7xx_emc.h"
19
&env->fp_status);
23
+#include "hw/net/npcm_gmac.h"
20
+ set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
24
#include "hw/nvram/npcm7xx_otp.h"
21
+ &env->fp_status);
25
#include "hw/timer/npcm7xx_timer.h"
22
}
26
#include "hw/ssi/npcm7xx_fiu.h"
23
27
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxState {
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
28
OHCISysBusState ohci;
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
29
NPCM7xxFIUState fiu[2];
30
NPCM7xxEMCState emc[2];
31
+ NPCMGMACState gmac[2];
32
NPCM7xxPCIMBoxState pci_mbox;
33
NPCM7xxSDHCIState mmc;
34
NPCMPSPIState pspi[2];
35
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
36
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/npcm7xx.c
27
--- a/fpu/softfloat-specialize.c.inc
38
+++ b/hw/arm/npcm7xx.c
28
+++ b/fpu/softfloat-specialize.c.inc
39
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
40
NPCM7XX_GMAC1_IRQ = 14,
41
NPCM7XX_EMC1RX_IRQ = 15,
42
NPCM7XX_EMC1TX_IRQ,
43
+ NPCM7XX_GMAC2_IRQ,
44
NPCM7XX_MMC_IRQ = 26,
45
NPCM7XX_PSPI2_IRQ = 28,
46
NPCM7XX_PSPI1_IRQ = 31,
47
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_pspi_addr[] = {
48
0xf0201000,
49
};
50
51
+/* Register base address for each GMAC Module */
52
+static const hwaddr npcm7xx_gmac_addr[] = {
53
+ 0xf0802000,
54
+ 0xf0804000,
55
+};
56
+
57
static const struct {
58
hwaddr regs_addr;
59
uint32_t unconnected_pins;
60
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
61
object_initialize_child(obj, "pspi[*]", &s->pspi[i], TYPE_NPCM_PSPI);
62
}
30
}
63
31
64
+ for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
32
if (rule == float_3nan_prop_none) {
65
+ object_initialize_child(obj, "gmac[*]", &s->gmac[i], TYPE_NPCM_GMAC);
33
-#if defined(TARGET_XTENSA)
66
+ }
34
- if (status->use_first_nan) {
67
+
35
- rule = float_3nan_prop_abc;
68
object_initialize_child(obj, "pci-mbox", &s->pci_mbox,
36
- } else {
69
TYPE_NPCM7XX_PCI_MBOX);
37
- rule = float_3nan_prop_cba;
70
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
38
- }
71
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
39
-#else
72
sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
40
rule = float_3nan_prop_abc;
41
-#endif
73
}
42
}
74
43
75
+ /*
44
assert(rule != float_3nan_prop_none);
76
+ * GMAC Modules. Cannot fail.
77
+ */
78
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gmac_addr) != ARRAY_SIZE(s->gmac));
79
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->gmac) != 2);
80
+ for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
81
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->gmac[i]);
82
+
83
+ /*
84
+ * The device exists regardless of whether it's connected to a QEMU
85
+ * netdev backend. So always instantiate it even if there is no
86
+ * backend.
87
+ */
88
+ sysbus_realize(sbd, &error_abort);
89
+ sysbus_mmio_map(sbd, 0, npcm7xx_gmac_addr[i]);
90
+ int irq = i == 0 ? NPCM7XX_GMAC1_IRQ : NPCM7XX_GMAC2_IRQ;
91
+ /*
92
+ * N.B. The values for the second argument sysbus_connect_irq are
93
+ * chosen to match the registration order in npcm7xx_emc_realize.
94
+ */
95
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
96
+ }
97
+
98
/*
99
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
100
* specified, but this is a programming error.
101
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
102
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
103
create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
104
create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
105
- create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
106
- create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
107
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
108
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
109
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
110
--
45
--
111
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
In arm_pamax(), we need to cope with the virt board calling this
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
function on a CPU object which has been inited but not realize.
2
ifdef from pickNaNMulAdd().
3
We used to do propagation of feature-flag implications (such as
4
"V7VE implies LPAE") at realize, so we have some code in arm_pamax()
5
which manually checks for both V7VE and LPAE feature flags.
6
3
7
In commit b8f7959f28c4f36 we moved the feature propagation for
4
HPPA is the only target that was using the default branch of the
8
almost all features from realize to post-init. That means that
5
ifdef ladder (other targets either do not use muladd or set
9
now when the virt board calls arm_pamax(), the feature propagation
6
default_nan_mode), so we can remove the ifdef fallback entirely now
10
has been done. So we can drop the manual propagation handling
7
(allowing the "rule not set" case to fall into the default of the
11
and check only for the feature we actually care about, which
8
switch statement and assert).
12
is ARM_FEATURE_LPAE.
13
9
14
Retain the comment that the virt board is calling this function
10
We add a TODO note that the HPPA rule is probably wrong; this is
15
with a not completely realized CPU object, because that is a
11
not a behavioural change for this refactoring.
16
potential beartrap for later changes which is worth calling out.
17
18
(Note that b8f7959f28c4f36 actually fixed a bug in the arm_pamax()
19
handling: arm_pamax() was missing a check for ARM_FEATURE_V8, so it
20
incorrectly thought that the qemu-system-arm 'max' CPU did not have
21
LPAE and turned off 'highmem' support in the virt board. Following
22
b8f7959f28c4f36 qemu-system-arm 'max' is treated the same as
23
'cortex-a15' and other v7 LPAE CPUs, because the generic feature
24
propagation code does correctly propagate V8 -> V7VE -> LPAE.)
25
12
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Message-id: 20240109143804.1118307-1-peter.maydell@linaro.org
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
29
---
16
---
30
target/arm/ptw.c | 14 ++++++--------
17
target/hppa/fpu_helper.c | 8 ++++++++
31
1 file changed, 6 insertions(+), 8 deletions(-)
18
fpu/softfloat-specialize.c.inc | 4 ----
19
2 files changed, 8 insertions(+), 4 deletions(-)
32
20
33
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
21
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
34
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/ptw.c
23
--- a/target/hppa/fpu_helper.c
36
+++ b/target/arm/ptw.c
24
+++ b/target/hppa/fpu_helper.c
37
@@ -XXX,XX +XXX,XX @@ static const uint8_t pamax_map[] = {
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
38
[6] = 52,
26
* HPPA does note implement a CPU reset method at all...
39
};
27
*/
40
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
41
-/* The cpu-specific constant value of PAMax; also used by hw/arm/virt. */
29
+ /*
42
+/*
30
+ * TODO: The HPPA architecture reference only documents its NaN
43
+ * The cpu-specific constant value of PAMax; also used by hw/arm/virt.
31
+ * propagation rule for 2-operand operations. Testing on real hardware
44
+ * Note that machvirt_init calls this on a CPU that is inited but not realized!
32
+ * might be necessary to confirm whether this order for muladd is correct.
45
+ */
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
46
unsigned int arm_pamax(ARMCPU *cpu)
34
+ * from the documented rules for 2-operand operations.
47
{
35
+ */
48
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
49
@@ -XXX,XX +XXX,XX @@ unsigned int arm_pamax(ARMCPU *cpu)
37
/* For inf * 0 + NaN, return the input NaN */
50
return pamax_map[parange];
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
39
}
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
41
index XXXXXXX..XXXXXXX 100644
42
--- a/fpu/softfloat-specialize.c.inc
43
+++ b/fpu/softfloat-specialize.c.inc
44
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
45
}
51
}
46
}
52
47
53
- /*
48
- if (rule == float_3nan_prop_none) {
54
- * In machvirt_init, we call arm_pamax on a cpu that is not fully
49
- rule = float_3nan_prop_abc;
55
- * initialized, so we can't rely on the propagation done in realize.
50
- }
56
- */
51
-
57
- if (arm_feature(&cpu->env, ARM_FEATURE_LPAE) ||
52
assert(rule != float_3nan_prop_none);
58
- arm_feature(&cpu->env, ARM_FEATURE_V7VE)) {
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
59
- /* v7 with LPAE */
54
/* We have at least one SNaN input and should prefer it */
60
+ if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
61
+ /* v7 or v8 with LPAE */
62
return 40;
63
}
64
/* Anything else */
65
--
55
--
66
2.34.1
56
2.34.1
diff view generated by jsdifflib
New patch
1
The use_first_nan field in float_status was an xtensa-specific way to
2
select at runtime from two different NaN propagation rules. Now that
3
xtensa is using the target-agnostic NaN propagation rule selection
4
that we've just added, we can remove use_first_nan, because there is
5
no longer any code that reads it.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20241202131347.498124-27-peter.maydell@linaro.org
10
---
11
include/fpu/softfloat-helpers.h | 5 -----
12
include/fpu/softfloat-types.h | 1 -
13
target/xtensa/fpu_helper.c | 1 -
14
3 files changed, 7 deletions(-)
15
16
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/fpu/softfloat-helpers.h
19
+++ b/include/fpu/softfloat-helpers.h
20
@@ -XXX,XX +XXX,XX @@ static inline void set_snan_bit_is_one(bool val, float_status *status)
21
status->snan_bit_is_one = val;
22
}
23
24
-static inline void set_use_first_nan(bool val, float_status *status)
25
-{
26
- status->use_first_nan = val;
27
-}
28
-
29
static inline void set_no_signaling_nans(bool val, float_status *status)
30
{
31
status->no_signaling_nans = val;
32
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/fpu/softfloat-types.h
35
+++ b/include/fpu/softfloat-types.h
36
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
37
* softfloat-specialize.inc.c)
38
*/
39
bool snan_bit_is_one;
40
- bool use_first_nan;
41
bool no_signaling_nans;
42
/* should overflowed results subtract re_bias to its exponent? */
43
bool rebias_overflow;
44
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/xtensa/fpu_helper.c
47
+++ b/target/xtensa/fpu_helper.c
48
@@ -XXX,XX +XXX,XX @@ static const struct {
49
50
void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
51
{
52
- set_use_first_nan(use_first, &env->fp_status);
53
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
54
&env->fp_status);
55
set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
56
--
57
2.34.1
diff view generated by jsdifflib
New patch
1
Currently m68k_cpu_reset_hold() calls floatx80_default_nan(NULL)
2
to get the NaN bit pattern to reset the FPU registers. This
3
works because it happens that our implementation of
4
floatx80_default_nan() doesn't actually look at the float_status
5
pointer except for TARGET_MIPS. However, this isn't guaranteed,
6
and to be able to remove the ifdef in floatx80_default_nan()
7
we're going to need a real float_status here.
1
8
9
Rearrange m68k_cpu_reset_hold() so that we initialize env->fp_status
10
earlier, and thus can pass it to floatx80_default_nan().
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20241202131347.498124-28-peter.maydell@linaro.org
15
---
16
target/m68k/cpu.c | 12 +++++++-----
17
1 file changed, 7 insertions(+), 5 deletions(-)
18
19
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/m68k/cpu.c
22
+++ b/target/m68k/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
24
CPUState *cs = CPU(obj);
25
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(obj);
26
CPUM68KState *env = cpu_env(cs);
27
- floatx80 nan = floatx80_default_nan(NULL);
28
+ floatx80 nan;
29
int i;
30
31
if (mcc->parent_phases.hold) {
32
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
33
#else
34
cpu_m68k_set_sr(env, SR_S | SR_I);
35
#endif
36
- for (i = 0; i < 8; i++) {
37
- env->fregs[i].d = nan;
38
- }
39
- cpu_m68k_set_fpcr(env, 0);
40
/*
41
* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
42
* 3.4 FLOATING-POINT INSTRUCTION DETAILS
43
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
44
* preceding paragraph for nonsignaling NaNs.
45
*/
46
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
47
+
48
+ nan = floatx80_default_nan(&env->fp_status);
49
+ for (i = 0; i < 8; i++) {
50
+ env->fregs[i].d = nan;
51
+ }
52
+ cpu_m68k_set_fpcr(env, 0);
53
env->fpsr = 0;
54
55
/* TODO: We should set PC from the interrupt vector. */
56
--
57
2.34.1
diff view generated by jsdifflib
New patch
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.
1
4
5
floatx80 is used only by:
6
i386
7
m68k
8
arm nwfpe old floating-point emulation emulation support
9
(which is essentially dead, especially the parts involving floatx80)
10
PPC (only in the xsrqpxp instruction, which just rounds an input
11
value by converting to floatx80 and back, so will never generate
12
the default NaN)
13
14
The floatx80 default NaN as currently implemented is:
15
m68k: sign = 0, exp = 1...1, int = 1, frac = 1....1
16
i386: sign = 1, exp = 1...1, int = 1, frac = 10...0
17
18
These are the same as the parts64_default_nan for these architectures.
19
20
This is technically a possible behaviour change for arm linux-user
21
nwfpe emulation emulation, because the default NaN will now have the
22
sign bit clear. But we were already generating a different floatx80
23
default NaN from the real kernel emulation we are supposedly
24
following, which appears to use an all-bits-1 value:
25
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L267
26
27
This won't affect the only "real" use of the nwfpe emulation, which
28
is ancient binaries that used it as part of the old floating point
29
calling convention; that only uses loads and stores of 32 and 64 bit
30
floats, not any of the floatx80 behaviour the original hardware had.
31
We also get the nwfpe float64 default NaN value wrong:
32
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L166
33
so if we ever cared about this obscure corner the right fix would be
34
to correct that so nwfpe used its own default-NaN setting rather
35
than the Arm VFP one.
36
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
40
---
41
fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
42
1 file changed, 10 insertions(+), 10 deletions(-)
43
44
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/fpu/softfloat-specialize.c.inc
47
+++ b/fpu/softfloat-specialize.c.inc
48
@@ -XXX,XX +XXX,XX @@ static void parts128_silence_nan(FloatParts128 *p, float_status *status)
49
floatx80 floatx80_default_nan(float_status *status)
50
{
51
floatx80 r;
52
+ /*
53
+ * Extrapolate from the choices made by parts64_default_nan to fill
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;
74
}
75
76
--
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
From: Nabih Estefan Diaz <nabihestefan@google.com>
1
In the helper functions flcmps and flcmpd we use a scratch float_status
2
so that we don't change the CPU state if the comparison raises any
3
floating point exception flags. Instead of zero-initializing this
4
scratch float_status, initialize it as a copy of env->fp_status. This
5
avoids the need to explicitly initialize settings like the NaN
6
propagation rule or others we might add to softfloat in future.
2
7
3
- Implementation of Receive function for packets
8
To do this we need to pass the CPU env pointer in to the helper.
4
- Implementation for reading and writing from and to descriptors in
5
memory for Rx
6
9
7
When RX starts, we need to flush the queued packets so that they
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
can be received by the GMAC device. Without this it won't work
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
with TAP NIC device.
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
13
---
14
target/sparc/helper.h | 4 ++--
15
target/sparc/fop_helper.c | 8 ++++----
16
target/sparc/translate.c | 4 ++--
17
3 files changed, 8 insertions(+), 8 deletions(-)
10
18
11
When RX descriptor list is full, it returns a DMA_STATUS for software
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
12
to handle it. But there's no way to indicate the software has
13
handled all RX descriptors and the whole pipeline stalls.
14
15
We do something similar to NPCM7XX EMC to handle this case.
16
17
1. Return packet size when RX descriptor is full, effectively
18
dropping these packets in such a case.
19
2. When software clears RX descriptor full bit, continue receiving
20
further packets by flushing QEMU packet queue.
21
22
Added relevant trace-events
23
24
Change-Id: I132aa254a94cda1a586aba2ea33bbfc74ecdb831
25
Signed-off-by: Hao Wu <wuhaotsh@google.com>
26
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
27
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
28
Message-id: 20240110234232.4116804-9-nabihestefan@google.com
29
[PMM: moved a couple of functions into the following patch]
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
32
---
33
hw/net/npcm_gmac.c | 276 +++++++++++++++++++++++++++++++++++++++++++-
34
hw/net/trace-events | 5 +
35
2 files changed, 279 insertions(+), 2 deletions(-)
36
37
diff --git a/hw/net/npcm_gmac.c b/hw/net/npcm_gmac.c
38
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/net/npcm_gmac.c
21
--- a/target/sparc/helper.h
40
+++ b/hw/net/npcm_gmac.c
22
+++ b/target/sparc/helper.h
41
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
42
#include "hw/net/mii.h"
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
43
#include "hw/net/npcm_gmac.h"
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
44
#include "migration/vmstate.h"
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
45
+#include "net/checksum.h"
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
46
+#include "net/eth.h"
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
47
+#include "net/net.h"
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
48
+#include "qemu/cutils.h"
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
49
#include "qemu/log.h"
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
50
#include "qemu/units.h"
32
51
#include "sysemu/dma.h"
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
52
@@ -XXX,XX +XXX,XX @@ static void gmac_phy_set_link(NPCMGMACState *gmac, bool active)
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
53
35
index XXXXXXX..XXXXXXX 100644
54
static bool gmac_can_receive(NetClientState *nc)
36
--- a/target/sparc/fop_helper.c
37
+++ b/target/sparc/fop_helper.c
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
39
return finish_fcmp(env, r, GETPC());
40
}
41
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
55
{
44
{
56
+ NPCMGMACState *gmac = NPCM_GMAC(qemu_get_nic_opaque(nc));
45
/*
57
+
46
* FLCMP never raises an exception nor modifies any FSR fields.
58
+ /* If GMAC receive is disabled. */
47
* Perform the comparison with a dummy fp environment.
59
+ if (!(gmac->regs[R_NPCM_GMAC_MAC_CONFIG] & NPCM_GMAC_MAC_CONFIG_RX_EN)) {
48
*/
60
+ return false;
49
- float_status discard = { };
61
+ }
50
+ float_status discard = env->fp_status;
62
+
51
FloatRelation r;
63
+ /* If GMAC DMA RX is stopped. */
52
64
+ if (!(gmac->regs[R_NPCM_DMA_CONTROL] & NPCM_DMA_CONTROL_START_STOP_RX)) {
53
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
65
+ return false;
54
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
66
+ }
55
g_assert_not_reached();
67
return true;
68
}
56
}
69
57
70
@@ -XXX,XX +XXX,XX @@ static void gmac_update_irq(NPCMGMACState *gmac)
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
71
qemu_set_irq(gmac->irq, level);
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);
72
}
77
}
73
78
74
+static int gmac_read_rx_desc(dma_addr_t addr, struct NPCMGMACRxDesc *desc)
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
75
+{
80
76
+ if (dma_memory_read(&address_space_memory, addr, desc,
81
src1 = gen_load_fpr_D(dc, a->rs1);
77
+ sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) {
82
src2 = gen_load_fpr_D(dc, a->rs2);
78
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
79
+ HWADDR_PRIx "\n", __func__, addr);
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
80
+ return -1;
85
return advance_pc(dc);
81
+ }
82
+ desc->rdes0 = le32_to_cpu(desc->rdes0);
83
+ desc->rdes1 = le32_to_cpu(desc->rdes1);
84
+ desc->rdes2 = le32_to_cpu(desc->rdes2);
85
+ desc->rdes3 = le32_to_cpu(desc->rdes3);
86
+ return 0;
87
+}
88
+
89
+static int gmac_write_rx_desc(dma_addr_t addr, struct NPCMGMACRxDesc *desc)
90
+{
91
+ struct NPCMGMACRxDesc le_desc;
92
+ le_desc.rdes0 = cpu_to_le32(desc->rdes0);
93
+ le_desc.rdes1 = cpu_to_le32(desc->rdes1);
94
+ le_desc.rdes2 = cpu_to_le32(desc->rdes2);
95
+ le_desc.rdes3 = cpu_to_le32(desc->rdes3);
96
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
97
+ sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) {
98
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
99
+ HWADDR_PRIx "\n", __func__, addr);
100
+ return -1;
101
+ }
102
+ return 0;
103
+}
104
+
105
+static int gmac_rx_transfer_frame_to_buffer(uint32_t rx_buf_len,
106
+ uint32_t *left_frame,
107
+ uint32_t rx_buf_addr,
108
+ bool *eof_transferred,
109
+ const uint8_t **frame_ptr,
110
+ uint16_t *transferred)
111
+{
112
+ uint32_t to_transfer;
113
+ /*
114
+ * Check that buffer is bigger than the frame being transfered
115
+ * If bigger then transfer only whats left of frame
116
+ * Else, fill frame with all the content possible
117
+ */
118
+ if (rx_buf_len >= *left_frame) {
119
+ to_transfer = *left_frame;
120
+ *eof_transferred = true;
121
+ } else {
122
+ to_transfer = rx_buf_len;
123
+ }
124
+
125
+ /* write frame part to memory */
126
+ if (dma_memory_write(&address_space_memory, (uint64_t) rx_buf_addr,
127
+ *frame_ptr, to_transfer, MEMTXATTRS_UNSPECIFIED)) {
128
+ return -1;
129
+ }
130
+
131
+ /* update frame pointer and size of whats left of frame */
132
+ *frame_ptr += to_transfer;
133
+ *left_frame -= to_transfer;
134
+ *transferred += to_transfer;
135
+
136
+ return 0;
137
+}
138
+
139
+static void gmac_dma_set_state(NPCMGMACState *gmac, int shift, uint32_t state)
140
+{
141
+ gmac->regs[R_NPCM_DMA_STATUS] = deposit32(gmac->regs[R_NPCM_DMA_STATUS],
142
+ shift, 3, state);
143
+}
144
+
145
static ssize_t gmac_receive(NetClientState *nc, const uint8_t *buf, size_t len)
146
{
147
- /* Placeholder. Function will be filled in following patches */
148
- return 0;
149
+ /*
150
+ * Comments have steps that relate to the
151
+ * receiving process steps in pg 386
152
+ */
153
+ NPCMGMACState *gmac = NPCM_GMAC(qemu_get_nic_opaque(nc));
154
+ uint32_t left_frame = len;
155
+ const uint8_t *frame_ptr = buf;
156
+ uint32_t desc_addr;
157
+ uint32_t rx_buf_len, rx_buf_addr;
158
+ struct NPCMGMACRxDesc rx_desc;
159
+ uint16_t transferred = 0;
160
+ bool eof_transferred = false;
161
+
162
+ trace_npcm_gmac_packet_receive(DEVICE(gmac)->canonical_path, len);
163
+ if (!gmac_can_receive(nc)) {
164
+ qemu_log_mask(LOG_GUEST_ERROR, "GMAC Currently is not able for Rx");
165
+ return -1;
166
+ }
167
+ if (!gmac->regs[R_NPCM_DMA_HOST_RX_DESC]) {
168
+ gmac->regs[R_NPCM_DMA_HOST_RX_DESC] =
169
+ NPCM_DMA_HOST_RX_DESC_MASK(gmac->regs[R_NPCM_DMA_RX_BASE_ADDR]);
170
+ }
171
+ desc_addr = NPCM_DMA_HOST_RX_DESC_MASK(gmac->regs[R_NPCM_DMA_HOST_RX_DESC]);
172
+
173
+ /* step 1 */
174
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
175
+ NPCM_DMA_STATUS_RX_RUNNING_FETCHING_STATE);
176
+ trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path, desc_addr);
177
+ if (gmac_read_rx_desc(desc_addr, &rx_desc)) {
178
+ qemu_log_mask(LOG_GUEST_ERROR, "RX Descriptor @ 0x%x cant be read\n",
179
+ desc_addr);
180
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
181
+ NPCM_DMA_STATUS_RX_SUSPENDED_STATE);
182
+ return -1;
183
+ }
184
+
185
+ /* step 2 */
186
+ if (!(rx_desc.rdes0 & RX_DESC_RDES0_OWN)) {
187
+ qemu_log_mask(LOG_GUEST_ERROR,
188
+ "RX Descriptor @ 0x%x is owned by software\n",
189
+ desc_addr);
190
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RU;
191
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RI;
192
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
193
+ NPCM_DMA_STATUS_RX_SUSPENDED_STATE);
194
+ gmac_update_irq(gmac);
195
+ return len;
196
+ }
197
+ /* step 3 */
198
+ /*
199
+ * TODO --
200
+ * Implement all frame filtering and processing (with its own interrupts)
201
+ */
202
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &rx_desc,
203
+ rx_desc.rdes0, rx_desc.rdes1, rx_desc.rdes2,
204
+ rx_desc.rdes3);
205
+ /* Clear rdes0 for the incoming descriptor and set FS in first descriptor.*/
206
+ rx_desc.rdes0 = RX_DESC_RDES0_FIRST_DESC_MASK;
207
+
208
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
209
+ NPCM_DMA_STATUS_RX_RUNNING_TRANSFERRING_STATE);
210
+
211
+ /* Pad the frame with FCS as the kernel driver will strip it away. */
212
+ left_frame += ETH_FCS_LEN;
213
+
214
+ /* repeat while we still have frame to transfer to memory */
215
+ while (!eof_transferred) {
216
+ /* Return descriptor no matter what happens */
217
+ rx_desc.rdes0 &= ~RX_DESC_RDES0_OWN;
218
+ /* Set the frame to be an IPv4/IPv6 frame. */
219
+ rx_desc.rdes0 |= RX_DESC_RDES0_FRM_TYPE_MASK;
220
+
221
+ /* step 4 */
222
+ rx_buf_len = RX_DESC_RDES1_BFFR1_SZ_MASK(rx_desc.rdes1);
223
+ rx_buf_addr = rx_desc.rdes2;
224
+ gmac->regs[R_NPCM_DMA_CUR_RX_BUF_ADDR] = rx_buf_addr;
225
+ gmac_rx_transfer_frame_to_buffer(rx_buf_len, &left_frame, rx_buf_addr,
226
+ &eof_transferred, &frame_ptr,
227
+ &transferred);
228
+
229
+ trace_npcm_gmac_packet_receiving_buffer(DEVICE(gmac)->canonical_path,
230
+ rx_buf_len, rx_buf_addr);
231
+ /* if we still have frame left and the second buffer is not chained */
232
+ if (!(rx_desc.rdes1 & RX_DESC_RDES1_SEC_ADDR_CHND_MASK) && \
233
+ !eof_transferred) {
234
+ /* repeat process from above on buffer 2 */
235
+ rx_buf_len = RX_DESC_RDES1_BFFR2_SZ_MASK(rx_desc.rdes1);
236
+ rx_buf_addr = rx_desc.rdes3;
237
+ gmac->regs[R_NPCM_DMA_CUR_RX_BUF_ADDR] = rx_buf_addr;
238
+ gmac_rx_transfer_frame_to_buffer(rx_buf_len, &left_frame,
239
+ rx_buf_addr, &eof_transferred,
240
+ &frame_ptr, &transferred);
241
+ trace_npcm_gmac_packet_receiving_buffer( \
242
+ DEVICE(gmac)->canonical_path,
243
+ rx_buf_len, rx_buf_addr);
244
+ }
245
+ /* update address for descriptor */
246
+ gmac->regs[R_NPCM_DMA_HOST_RX_DESC] = rx_buf_addr;
247
+ /* Return descriptor */
248
+ rx_desc.rdes0 &= ~RX_DESC_RDES0_OWN;
249
+ /* Update frame length transferred */
250
+ rx_desc.rdes0 |= ((uint32_t)transferred)
251
+ << RX_DESC_RDES0_FRAME_LEN_SHIFT;
252
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &rx_desc,
253
+ rx_desc.rdes0, rx_desc.rdes1,
254
+ rx_desc.rdes2, rx_desc.rdes3);
255
+
256
+ /* step 5 */
257
+ gmac_write_rx_desc(desc_addr, &rx_desc);
258
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path,
259
+ &rx_desc, rx_desc.rdes0,
260
+ rx_desc.rdes1, rx_desc.rdes2,
261
+ rx_desc.rdes3);
262
+ /* read new descriptor into rx_desc if needed*/
263
+ if (!eof_transferred) {
264
+ /* Get next descriptor address (chained or sequential) */
265
+ if (rx_desc.rdes1 & RX_DESC_RDES1_RC_END_RING_MASK) {
266
+ desc_addr = gmac->regs[R_NPCM_DMA_RX_BASE_ADDR];
267
+ } else if (rx_desc.rdes1 & RX_DESC_RDES1_SEC_ADDR_CHND_MASK) {
268
+ desc_addr = rx_desc.rdes3;
269
+ } else {
270
+ desc_addr += sizeof(rx_desc);
271
+ }
272
+ trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path,
273
+ desc_addr);
274
+ if (gmac_read_rx_desc(desc_addr, &rx_desc)) {
275
+ qemu_log_mask(LOG_GUEST_ERROR,
276
+ "RX Descriptor @ 0x%x cant be read\n",
277
+ desc_addr);
278
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RU;
279
+ gmac_update_irq(gmac);
280
+ return len;
281
+ }
282
+
283
+ /* step 6 */
284
+ if (!(rx_desc.rdes0 & RX_DESC_RDES0_OWN)) {
285
+ if (!(gmac->regs[R_NPCM_DMA_CONTROL] & \
286
+ NPCM_DMA_CONTROL_FLUSH_MASK)) {
287
+ rx_desc.rdes0 |= RX_DESC_RDES0_DESC_ERR_MASK;
288
+ }
289
+ eof_transferred = true;
290
+ }
291
+ /* Clear rdes0 for the incoming descriptor */
292
+ rx_desc.rdes0 = 0;
293
+ }
294
+ }
295
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
296
+ NPCM_DMA_STATUS_RX_RUNNING_CLOSING_STATE);
297
+
298
+ rx_desc.rdes0 |= RX_DESC_RDES0_LAST_DESC_MASK;
299
+ if (!(rx_desc.rdes1 & RX_DESC_RDES1_DIS_INTR_COMP_MASK)) {
300
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RI;
301
+ gmac_update_irq(gmac);
302
+ }
303
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &rx_desc,
304
+ rx_desc.rdes0, rx_desc.rdes1, rx_desc.rdes2,
305
+ rx_desc.rdes3);
306
+
307
+ /* step 8 */
308
+ gmac->regs[R_NPCM_DMA_CONTROL] |= NPCM_DMA_CONTROL_FLUSH_MASK;
309
+
310
+ /* step 9 */
311
+ trace_npcm_gmac_packet_received(DEVICE(gmac)->canonical_path, left_frame);
312
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
313
+ NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
314
+ gmac_write_rx_desc(desc_addr, &rx_desc);
315
+
316
+ /* Get next descriptor address (chained or sequential) */
317
+ if (rx_desc.rdes1 & RX_DESC_RDES1_RC_END_RING_MASK) {
318
+ desc_addr = gmac->regs[R_NPCM_DMA_RX_BASE_ADDR];
319
+ } else if (rx_desc.rdes1 & RX_DESC_RDES1_SEC_ADDR_CHND_MASK) {
320
+ desc_addr = rx_desc.rdes3;
321
+ } else {
322
+ desc_addr += sizeof(rx_desc);
323
+ }
324
+ gmac->regs[R_NPCM_DMA_HOST_RX_DESC] = desc_addr;
325
+ return len;
326
}
86
}
327
87
328
static void gmac_cleanup(NetClientState *nc)
329
@@ -XXX,XX +XXX,XX @@ static void npcm_gmac_write(void *opaque, hwaddr offset,
330
break;
331
332
case A_NPCM_GMAC_MAC_CONFIG:
333
+ gmac->regs[offset / sizeof(uint32_t)] = v;
334
break;
335
336
case A_NPCM_GMAC_MII_ADDR:
337
@@ -XXX,XX +XXX,XX @@ static void npcm_gmac_write(void *opaque, hwaddr offset,
338
339
case A_NPCM_DMA_RCV_POLL_DEMAND:
340
/* We dont actually care about the value */
341
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
342
+ NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
343
break;
344
345
case A_NPCM_DMA_STATUS:
346
@@ -XXX,XX +XXX,XX @@ static void npcm_gmac_write(void *opaque, hwaddr offset,
347
HWADDR_PRIx ", value: 0x%04" PRIx64 "\n",
348
DEVICE(gmac)->canonical_path, offset, v);
349
}
350
+ /* for W1C bits, implement W1C */
351
+ gmac->regs[offset / sizeof(uint32_t)] &= ~NPCM_DMA_STATUS_W1C_MASK(v);
352
+ if (v & NPCM_DMA_STATUS_RU) {
353
+ /* Clearing RU bit indicates descriptor is owned by DMA again. */
354
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
355
+ NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
356
+ qemu_flush_queued_packets(qemu_get_queue(gmac->nic));
357
+ }
358
break;
359
360
default:
361
diff --git a/hw/net/trace-events b/hw/net/trace-events
362
index XXXXXXX..XXXXXXX 100644
363
--- a/hw/net/trace-events
364
+++ b/hw/net/trace-events
365
@@ -XXX,XX +XXX,XX @@ npcm_gmac_mdio_access(const char *name, uint8_t is_write, uint8_t pa, uint8_t gr
366
npcm_gmac_reset(const char *name, uint16_t value) "%s: phy_regs[0][1]: 0x%04" PRIx16
367
npcm_gmac_set_link(bool active) "Set link: active=%u"
368
npcm_gmac_update_irq(const char *name, uint32_t status, uint32_t intr_en, int level) "%s: Status Reg: 0x%04" PRIX32 " Interrupt Enable Reg: 0x%04" PRIX32 " IRQ Set: %d"
369
+npcm_gmac_packet_desc_read(const char* name, uint32_t desc_addr) "%s: attempting to read descriptor @0x%04" PRIX32
370
+npcm_gmac_packet_receive(const char* name, uint32_t len) "%s: RX packet length: 0x%04" PRIX32
371
+npcm_gmac_packet_receiving_buffer(const char* name, uint32_t buf_len, uint32_t rx_buf_addr) "%s: Receiving into Buffer size: 0x%04" PRIX32 " at address 0x%04" PRIX32
372
+npcm_gmac_packet_received(const char* name, uint32_t len) "%s: Reception finished, packet left: 0x%04" PRIX32
373
+npcm_gmac_debug_desc_data(const char* name, void* addr, uint32_t des0, uint32_t des1, uint32_t des2, uint32_t des3)"%s: Address: %p Descriptor 0: 0x%04" PRIX32 " Descriptor 1: 0x%04" PRIX32 "Descriptor 2: 0x%04" PRIX32 " Descriptor 3: 0x%04" PRIX32
374
375
# npcm_pcs.c
376
npcm_pcs_reg_read(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
377
--
88
--
378
2.34.1
89
2.34.1
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
Now that float_status has a bunch of fp parameters,
4
it is easier to copy an existing structure than create
5
one from scratch. Begin by copying the structure that
6
corresponds to the FPSR and make only the adjustments
7
required for BFloat16 semantics.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Acked-by: Alistair Francis <alistair.francis@wdc.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
6
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
7
Message-id: 20240109160658.311932-4-ines.varhol@telecom-paris.fr
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
14
---
10
tests/qtest/stm32l4x5_exti-test.c | 524 ++++++++++++++++++++++++++++++
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
11
tests/qtest/meson.build | 5 +
16
1 file changed, 7 insertions(+), 13 deletions(-)
12
2 files changed, 529 insertions(+)
13
create mode 100644 tests/qtest/stm32l4x5_exti-test.c
14
17
15
diff --git a/tests/qtest/stm32l4x5_exti-test.c b/tests/qtest/stm32l4x5_exti-test.c
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
16
new file mode 100644
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX
20
--- a/target/arm/tcg/vec_helper.c
18
--- /dev/null
21
+++ b/target/arm/tcg/vec_helper.c
19
+++ b/tests/qtest/stm32l4x5_exti-test.c
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
20
@@ -XXX,XX +XXX,XX @@
23
* no effect on AArch32 instructions.
21
+/*
24
*/
22
+ * QTest testcase for STM32L4x5_EXTI
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
23
+ *
26
- *statusp = (float_status){
24
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
27
- .tininess_before_rounding = float_tininess_before_rounding,
25
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
28
- .float_rounding_mode = float_round_to_odd_inf,
26
+ *
29
- .flush_to_zero = true,
27
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
30
- .flush_inputs_to_zero = true,
28
+ * See the COPYING file in the top-level directory.
31
- .default_nan_mode = true,
29
+ */
32
- };
30
+
33
+
31
+#include "qemu/osdep.h"
34
+ *statusp = env->vfp.fp_status;
32
+#include "libqtest-single.h"
35
+ set_default_nan_mode(true, statusp);
33
+
36
34
+#define EXTI_BASE_ADDR 0x40010400
37
if (ebf) {
35
+#define EXTI_IMR1 0x00
38
- float_status *fpst = &env->vfp.fp_status;
36
+#define EXTI_EMR1 0x04
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
37
+#define EXTI_RTSR1 0x08
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
38
+#define EXTI_FTSR1 0x0C
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
39
+#define EXTI_SWIER1 0x10
42
-
40
+#define EXTI_PR1 0x14
43
/* EBF=1 needs to do a step with round-to-odd semantics */
41
+#define EXTI_IMR2 0x20
44
*oddstatusp = *statusp;
42
+#define EXTI_EMR2 0x24
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
43
+#define EXTI_RTSR2 0x28
46
+ } else {
44
+#define EXTI_FTSR2 0x2C
47
+ set_flush_to_zero(true, statusp);
45
+#define EXTI_SWIER2 0x30
48
+ set_flush_inputs_to_zero(true, statusp);
46
+#define EXTI_PR2 0x34
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
47
+
50
}
48
+#define NVIC_ISER 0xE000E100
51
-
49
+#define NVIC_ISPR 0xE000E200
52
return ebf;
50
+#define NVIC_ICPR 0xE000E280
53
}
51
+
52
+#define EXTI0_IRQ 6
53
+#define EXTI1_IRQ 7
54
+#define EXTI35_IRQ 1
55
+
56
+static void enable_nvic_irq(unsigned int n)
57
+{
58
+ writel(NVIC_ISER, 1 << n);
59
+}
60
+
61
+static void unpend_nvic_irq(unsigned int n)
62
+{
63
+ writel(NVIC_ICPR, 1 << n);
64
+}
65
+
66
+static bool check_nvic_pending(unsigned int n)
67
+{
68
+ return readl(NVIC_ISPR) & (1 << n);
69
+}
70
+
71
+static void exti_writel(unsigned int offset, uint32_t value)
72
+{
73
+ writel(EXTI_BASE_ADDR + offset, value);
74
+}
75
+
76
+static uint32_t exti_readl(unsigned int offset)
77
+{
78
+ return readl(EXTI_BASE_ADDR + offset);
79
+}
80
+
81
+static void exti_set_irq(int num, int level)
82
+{
83
+ qtest_set_irq_in(global_qtest, "/machine/soc/exti", NULL,
84
+ num, level);
85
+}
86
+
87
+static void test_reg_write_read(void)
88
+{
89
+ /* Test that non-reserved bits in xMR and xTSR can be set and cleared */
90
+
91
+ exti_writel(EXTI_IMR1, 0xFFFFFFFF);
92
+ g_assert_cmpuint(exti_readl(EXTI_IMR1), ==, 0xFFFFFFFF);
93
+ exti_writel(EXTI_IMR1, 0x00000000);
94
+ g_assert_cmpuint(exti_readl(EXTI_IMR1), ==, 0x00000000);
95
+
96
+ exti_writel(EXTI_EMR1, 0xFFFFFFFF);
97
+ g_assert_cmpuint(exti_readl(EXTI_EMR1), ==, 0xFFFFFFFF);
98
+ exti_writel(EXTI_EMR1, 0x00000000);
99
+ g_assert_cmpuint(exti_readl(EXTI_EMR1), ==, 0x00000000);
100
+
101
+ exti_writel(EXTI_RTSR1, 0xFFFFFFFF);
102
+ g_assert_cmpuint(exti_readl(EXTI_RTSR1), ==, 0x007DFFFF);
103
+ exti_writel(EXTI_RTSR1, 0x00000000);
104
+ g_assert_cmpuint(exti_readl(EXTI_RTSR1), ==, 0x00000000);
105
+
106
+ exti_writel(EXTI_FTSR1, 0xFFFFFFFF);
107
+ g_assert_cmpuint(exti_readl(EXTI_FTSR1), ==, 0x007DFFFF);
108
+ exti_writel(EXTI_FTSR1, 0x00000000);
109
+ g_assert_cmpuint(exti_readl(EXTI_FTSR1), ==, 0x00000000);
110
+
111
+ exti_writel(EXTI_IMR2, 0xFFFFFFFF);
112
+ g_assert_cmpuint(exti_readl(EXTI_IMR2), ==, 0x000000FF);
113
+ exti_writel(EXTI_IMR2, 0x00000000);
114
+ g_assert_cmpuint(exti_readl(EXTI_IMR2), ==, 0x00000000);
115
+
116
+ exti_writel(EXTI_EMR2, 0xFFFFFFFF);
117
+ g_assert_cmpuint(exti_readl(EXTI_EMR2), ==, 0x000000FF);
118
+ exti_writel(EXTI_EMR2, 0x00000000);
119
+ g_assert_cmpuint(exti_readl(EXTI_EMR2), ==, 0x00000000);
120
+
121
+ exti_writel(EXTI_RTSR2, 0xFFFFFFFF);
122
+ g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000078);
123
+ exti_writel(EXTI_RTSR2, 0x00000000);
124
+ g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000000);
125
+
126
+ exti_writel(EXTI_FTSR2, 0xFFFFFFFF);
127
+ g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000078);
128
+ exti_writel(EXTI_FTSR2, 0x00000000);
129
+ g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000000);
130
+}
131
+
132
+static void test_direct_lines_write(void)
133
+{
134
+ /* Test that direct lines reserved bits are not written to */
135
+
136
+ exti_writel(EXTI_RTSR1, 0xFF820000);
137
+ g_assert_cmpuint(exti_readl(EXTI_RTSR1), ==, 0x00000000);
138
+
139
+ exti_writel(EXTI_FTSR1, 0xFF820000);
140
+ g_assert_cmpuint(exti_readl(EXTI_FTSR1), ==, 0x00000000);
141
+
142
+ exti_writel(EXTI_SWIER1, 0xFF820000);
143
+ g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000000);
144
+
145
+ exti_writel(EXTI_PR1, 0xFF820000);
146
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
147
+
148
+ exti_writel(EXTI_RTSR2, 0x00000087);
149
+ g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000000);
150
+
151
+ exti_writel(EXTI_FTSR2, 0x00000087);
152
+ g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000000);
153
+
154
+ exti_writel(EXTI_SWIER2, 0x00000087);
155
+ g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000000);
156
+
157
+ exti_writel(EXTI_PR2, 0x00000087);
158
+ g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
159
+}
160
+
161
+static void test_reserved_bits_write(void)
162
+{
163
+ /* Test that reserved bits stay are not written to */
164
+
165
+ exti_writel(EXTI_IMR2, 0xFFFFFF00);
166
+ g_assert_cmpuint(exti_readl(EXTI_IMR2), ==, 0x00000000);
167
+
168
+ exti_writel(EXTI_EMR2, 0xFFFFFF00);
169
+ g_assert_cmpuint(exti_readl(EXTI_EMR2), ==, 0x00000000);
170
+
171
+ exti_writel(EXTI_RTSR2, 0xFFFFFF00);
172
+ g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000000);
173
+
174
+ exti_writel(EXTI_FTSR2, 0xFFFFFF00);
175
+ g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000000);
176
+
177
+ exti_writel(EXTI_SWIER2, 0xFFFFFF00);
178
+ g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000000);
179
+
180
+ exti_writel(EXTI_PR2, 0xFFFFFF00);
181
+ g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
182
+}
183
+
184
+static void test_software_interrupt(void)
185
+{
186
+ /*
187
+ * Test that we can launch a software irq by :
188
+ * - enabling its line in IMR
189
+ * - and then setting a bit from '0' to '1' in SWIER
190
+ *
191
+ * And that the interruption stays pending in NVIC
192
+ * even after clearing the pending bit in PR.
193
+ */
194
+
195
+ /*
196
+ * Testing interrupt line EXTI0
197
+ * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
198
+ */
199
+
200
+ enable_nvic_irq(EXTI0_IRQ);
201
+ /* Check that there are no interrupts already pending in PR */
202
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
203
+ /* Check that this specific interrupt isn't pending in NVIC */
204
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
205
+
206
+ /* Enable interrupt line EXTI0 */
207
+ exti_writel(EXTI_IMR1, 0x00000001);
208
+ /* Set the right SWIER bit from '0' to '1' */
209
+ exti_writel(EXTI_SWIER1, 0x00000000);
210
+ exti_writel(EXTI_SWIER1, 0x00000001);
211
+
212
+ /* Check that the write in SWIER was effective */
213
+ g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000001);
214
+ /* Check that the corresponding pending bit in PR is set */
215
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
216
+ /* Check that the corresponding interrupt is pending in the NVIC */
217
+ g_assert_true(check_nvic_pending(EXTI0_IRQ));
218
+
219
+ /* Clear the pending bit in PR */
220
+ exti_writel(EXTI_PR1, 0x00000001);
221
+
222
+ /* Check that the write in PR was effective */
223
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
224
+ /* Check that the corresponding bit in SWIER was cleared */
225
+ g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000000);
226
+ /* Check that the interrupt is still pending in the NVIC */
227
+ g_assert_true(check_nvic_pending(EXTI0_IRQ));
228
+
229
+ /*
230
+ * Testing interrupt line EXTI35
231
+ * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
232
+ */
233
+
234
+ enable_nvic_irq(EXTI35_IRQ);
235
+ /* Check that there are no interrupts already pending */
236
+ g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
237
+ g_assert_false(check_nvic_pending(EXTI35_IRQ));
238
+
239
+ /* Enable interrupt line EXTI0 */
240
+ exti_writel(EXTI_IMR2, 0x00000008);
241
+ /* Set the right SWIER bit from '0' to '1' */
242
+ exti_writel(EXTI_SWIER2, 0x00000000);
243
+ exti_writel(EXTI_SWIER2, 0x00000008);
244
+
245
+ /* Check that the write in SWIER was effective */
246
+ g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000008);
247
+ /* Check that the corresponding pending bit in PR is set */
248
+ g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000008);
249
+ /* Check that the corresponding interrupt is pending in the NVIC */
250
+ g_assert_true(check_nvic_pending(EXTI35_IRQ));
251
+
252
+ /* Clear the pending bit in PR */
253
+ exti_writel(EXTI_PR2, 0x00000008);
254
+
255
+ /* Check that the write in PR was effective */
256
+ g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
257
+ /* Check that the corresponding bit in SWIER was cleared */
258
+ g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000000);
259
+ /* Check that the interrupt is still pending in the NVIC */
260
+ g_assert_true(check_nvic_pending(EXTI35_IRQ));
261
+
262
+ /* Clean NVIC */
263
+ unpend_nvic_irq(EXTI0_IRQ);
264
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
265
+ unpend_nvic_irq(EXTI35_IRQ);
266
+ g_assert_false(check_nvic_pending(EXTI35_IRQ));
267
+}
268
+
269
+static void test_edge_selector(void)
270
+{
271
+ enable_nvic_irq(EXTI0_IRQ);
272
+
273
+ /* Configure EXTI line 0 irq on rising edge */
274
+ exti_set_irq(0, 1);
275
+ exti_writel(EXTI_IMR1, 0x00000001);
276
+ exti_writel(EXTI_RTSR1, 0x00000001);
277
+ exti_writel(EXTI_FTSR1, 0x00000000);
278
+
279
+ /* Test that an irq is raised on rising edge only */
280
+ exti_set_irq(0, 0);
281
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
282
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
283
+
284
+ exti_set_irq(0, 1);
285
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
286
+ g_assert_true(check_nvic_pending(EXTI0_IRQ));
287
+
288
+ /* Clean the test */
289
+ exti_writel(EXTI_PR1, 0x00000001);
290
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
291
+ unpend_nvic_irq(EXTI0_IRQ);
292
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
293
+
294
+ /* Configure EXTI line 0 irq on falling edge */
295
+ exti_set_irq(0, 0);
296
+ exti_writel(EXTI_IMR1, 0x00000001);
297
+ exti_writel(EXTI_RTSR1, 0x00000000);
298
+ exti_writel(EXTI_FTSR1, 0x00000001);
299
+
300
+ /* Test that an irq is raised on falling edge only */
301
+ exti_set_irq(0, 1);
302
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
303
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
304
+
305
+ exti_set_irq(0, 0);
306
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
307
+ g_assert_true(check_nvic_pending(EXTI0_IRQ));
308
+
309
+ /* Clean the test */
310
+ exti_writel(EXTI_PR1, 0x00000001);
311
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
312
+ unpend_nvic_irq(EXTI0_IRQ);
313
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
314
+
315
+ /* Configure EXTI line 0 irq on falling and rising edge */
316
+ exti_writel(EXTI_IMR1, 0x00000001);
317
+ exti_writel(EXTI_RTSR1, 0x00000001);
318
+ exti_writel(EXTI_FTSR1, 0x00000001);
319
+
320
+ /* Test that an irq is raised on rising edge */
321
+ exti_set_irq(0, 1);
322
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
323
+ g_assert_true(check_nvic_pending(EXTI0_IRQ));
324
+
325
+ /* Clean the test */
326
+ exti_writel(EXTI_PR1, 0x00000001);
327
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
328
+ unpend_nvic_irq(EXTI0_IRQ);
329
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
330
+
331
+ /* Test that an irq is raised on falling edge */
332
+ exti_set_irq(0, 0);
333
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
334
+ g_assert_true(check_nvic_pending(EXTI0_IRQ));
335
+
336
+ /* Clean the test */
337
+ exti_writel(EXTI_PR1, 0x00000001);
338
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
339
+ unpend_nvic_irq(EXTI0_IRQ);
340
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
341
+
342
+ /* Configure EXTI line 0 irq without selecting an edge trigger */
343
+ exti_writel(EXTI_IMR1, 0x00000001);
344
+ exti_writel(EXTI_RTSR1, 0x00000000);
345
+ exti_writel(EXTI_FTSR1, 0x00000000);
346
+
347
+ /* Test that no irq is raised */
348
+ exti_set_irq(0, 1);
349
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
350
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
351
+
352
+ exti_set_irq(0, 0);
353
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
354
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
355
+}
356
+
357
+static void test_no_software_interrupt(void)
358
+{
359
+ /*
360
+ * Test that software irq doesn't happen when :
361
+ * - corresponding bit in IMR isn't set
362
+ * - SWIER is set to 1 before IMR is set to 1
363
+ */
364
+
365
+ /*
366
+ * Testing interrupt line EXTI0
367
+ * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
368
+ */
369
+
370
+ enable_nvic_irq(EXTI0_IRQ);
371
+ /* Check that there are no interrupts already pending in PR */
372
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
373
+ /* Check that this specific interrupt isn't pending in NVIC */
374
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
375
+
376
+ /* Mask interrupt line EXTI0 */
377
+ exti_writel(EXTI_IMR1, 0x00000000);
378
+ /* Set the corresponding SWIER bit from '0' to '1' */
379
+ exti_writel(EXTI_SWIER1, 0x00000000);
380
+ exti_writel(EXTI_SWIER1, 0x00000001);
381
+
382
+ /* Check that the write in SWIER was effective */
383
+ g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000001);
384
+ /* Check that the pending bit in PR wasn't set */
385
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
386
+ /* Check that the interrupt isn't pending in NVIC */
387
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
388
+
389
+ /* Enable interrupt line EXTI0 */
390
+ exti_writel(EXTI_IMR1, 0x00000001);
391
+
392
+ /* Check that the pending bit in PR wasn't set */
393
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
394
+ /* Check that the interrupt isn't pending in NVIC */
395
+ g_assert_false(check_nvic_pending(EXTI0_IRQ));
396
+
397
+ /*
398
+ * Testing interrupt line EXTI35
399
+ * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
400
+ */
401
+
402
+ enable_nvic_irq(EXTI35_IRQ);
403
+ /* Check that there are no interrupts already pending in PR */
404
+ g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
405
+ /* Check that this specific interrupt isn't pending in NVIC */
406
+ g_assert_false(check_nvic_pending(EXTI35_IRQ));
407
+
408
+ /* Mask interrupt line EXTI35 */
409
+ exti_writel(EXTI_IMR2, 0x00000000);
410
+ /* Set the corresponding SWIER bit from '0' to '1' */
411
+ exti_writel(EXTI_SWIER2, 0x00000000);
412
+ exti_writel(EXTI_SWIER2, 0x00000008);
413
+
414
+ /* Check that the write in SWIER was effective */
415
+ g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000008);
416
+ /* Check that the pending bit in PR wasn't set */
417
+ g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
418
+ /* Check that the interrupt isn't pending in NVIC */
419
+ g_assert_false(check_nvic_pending(EXTI35_IRQ));
420
+
421
+ /* Enable interrupt line EXTI35 */
422
+ exti_writel(EXTI_IMR2, 0x00000008);
423
+
424
+ /* Check that the pending bit in PR wasn't set */
425
+ g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
426
+ /* Check that the interrupt isn't pending in NVIC */
427
+ g_assert_false(check_nvic_pending(EXTI35_IRQ));
428
+}
429
+
430
+static void test_masked_interrupt(void)
431
+{
432
+ /*
433
+ * Test that irq doesn't happen when :
434
+ * - corresponding bit in IMR isn't set
435
+ * - SWIER is set to 1 before IMR is set to 1
436
+ */
437
+
438
+ /*
439
+ * Testing interrupt line EXTI1
440
+ * with rising edge from GPIOx pin 1
441
+ */
442
+
443
+ enable_nvic_irq(EXTI1_IRQ);
444
+ /* Check that there are no interrupts already pending in PR */
445
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
446
+ /* Check that this specific interrupt isn't pending in NVIC */
447
+ g_assert_false(check_nvic_pending(EXTI1_IRQ));
448
+
449
+ /* Mask interrupt line EXTI1 */
450
+ exti_writel(EXTI_IMR1, 0x00000000);
451
+
452
+ /* Configure interrupt on rising edge */
453
+ exti_writel(EXTI_RTSR1, 0x00000002);
454
+
455
+ /* Simulate rising edge from GPIO line 1 */
456
+ exti_set_irq(1, 1);
457
+
458
+ /* Check that the pending bit in PR wasn't set */
459
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
460
+ /* Check that the interrupt isn't pending in NVIC */
461
+ g_assert_false(check_nvic_pending(EXTI1_IRQ));
462
+
463
+ /* Enable interrupt line EXTI1 */
464
+ exti_writel(EXTI_IMR1, 0x00000002);
465
+
466
+ /* Check that the pending bit in PR wasn't set */
467
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
468
+ /* Check that the interrupt isn't pending in NVIC */
469
+ g_assert_false(check_nvic_pending(EXTI1_IRQ));
470
+}
471
+
472
+static void test_interrupt(void)
473
+{
474
+ /*
475
+ * Test that we can launch an irq by :
476
+ * - enabling its line in IMR
477
+ * - configuring interrupt on rising edge
478
+ * - and then setting the input line from '0' to '1'
479
+ *
480
+ * And that the interruption stays pending in NVIC
481
+ * even after clearing the pending bit in PR.
482
+ */
483
+
484
+ /*
485
+ * Testing interrupt line EXTI1
486
+ * with rising edge from GPIOx pin 1
487
+ */
488
+
489
+ enable_nvic_irq(EXTI1_IRQ);
490
+ /* Check that there are no interrupts already pending in PR */
491
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
492
+ /* Check that this specific interrupt isn't pending in NVIC */
493
+ g_assert_false(check_nvic_pending(EXTI1_IRQ));
494
+
495
+ /* Enable interrupt line EXTI1 */
496
+ exti_writel(EXTI_IMR1, 0x00000002);
497
+
498
+ /* Configure interrupt on rising edge */
499
+ exti_writel(EXTI_RTSR1, 0x00000002);
500
+
501
+ /* Simulate rising edge from GPIO line 1 */
502
+ exti_set_irq(1, 1);
503
+
504
+ /* Check that the pending bit in PR was set */
505
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000002);
506
+ /* Check that the interrupt is pending in NVIC */
507
+ g_assert_true(check_nvic_pending(EXTI1_IRQ));
508
+
509
+ /* Clear the pending bit in PR */
510
+ exti_writel(EXTI_PR1, 0x00000002);
511
+
512
+ /* Check that the write in PR was effective */
513
+ g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
514
+ /* Check that the interrupt is still pending in the NVIC */
515
+ g_assert_true(check_nvic_pending(EXTI1_IRQ));
516
+
517
+ /* Clean NVIC */
518
+ unpend_nvic_irq(EXTI1_IRQ);
519
+ g_assert_false(check_nvic_pending(EXTI1_IRQ));
520
+}
521
+
522
+int main(int argc, char **argv)
523
+{
524
+ int ret;
525
+
526
+ g_test_init(&argc, &argv, NULL);
527
+ g_test_set_nonfatal_assertions();
528
+ qtest_add_func("stm32l4x5/exti/direct_lines", test_direct_lines_write);
529
+ qtest_add_func("stm32l4x5/exti/reserved_bits", test_reserved_bits_write);
530
+ qtest_add_func("stm32l4x5/exti/reg_write_read", test_reg_write_read);
531
+ qtest_add_func("stm32l4x5/exti/no_software_interrupt",
532
+ test_no_software_interrupt);
533
+ qtest_add_func("stm32l4x5/exti/software_interrupt",
534
+ test_software_interrupt);
535
+ qtest_add_func("stm32l4x5/exti/masked_interrupt", test_masked_interrupt);
536
+ qtest_add_func("stm32l4x5/exti/interrupt", test_interrupt);
537
+ qtest_add_func("stm32l4x5/exti/test_edge_selector", test_edge_selector);
538
+
539
+ qtest_start("-machine b-l475e-iot01a");
540
+ ret = g_test_run();
541
+ qtest_end();
542
+
543
+ return ret;
544
+}
545
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
546
index XXXXXXX..XXXXXXX 100644
547
--- a/tests/qtest/meson.build
548
+++ b/tests/qtest/meson.build
549
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
550
['aspeed_hace-test',
551
'aspeed_smc-test',
552
'aspeed_gpio-test']
553
+
554
+qtests_stm32l4x5 = \
555
+ ['stm32l4x5_exti-test']
556
+
557
qtests_arm = \
558
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
559
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
560
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
561
(config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
562
(config_all_devices.has_key('CONFIG_VEXPRESS') ? ['test-arm-mptimer'] : []) + \
563
(config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \
564
+ (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 : []) + \
565
['arm-cpu-features',
566
'boot-serial-test']
567
54
568
--
55
--
569
2.34.1
56
2.34.1
570
57
571
58
diff view generated by jsdifflib
1
From: Nabih Estefan Diaz <nabihestefan@google.com>
1
Currently we hardcode the default NaN value in parts64_default_nan()
2
using a compile-time ifdef ladder. This is awkward for two cases:
3
* for single-QEMU-binary we can't hard-code target-specifics like this
4
* for Arm FEAT_AFP the default NaN value depends on FPCR.AH
5
(specifically the sign bit is different)
2
6
3
- Created qtest to check initialization of registers in GMAC Module.
7
Add a field to float_status to specify the default NaN value; fall
4
- Implemented test into Build File.
8
back to the old ifdef behaviour if these are not set.
5
9
6
Change-Id: I8b2fe152d3987a7eec4cf6a1d25ba92e75a5391d
10
The default NaN value is specified by setting a uint8_t to a
7
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
11
pattern corresponding to the sign and upper fraction parts of
8
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
the NaN; the lower bits of the fraction are set from bit 0 of
9
Message-id: 20240110234232.4116804-7-nabihestefan@google.com
13
the pattern.
14
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-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/npcm_gmac-test.c | 209 +++++++++++++++++++++++++++++++++++
19
include/fpu/softfloat-helpers.h | 11 +++++++
14
tests/qtest/meson.build | 1 +
20
include/fpu/softfloat-types.h | 10 ++++++
15
2 files changed, 210 insertions(+)
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
16
create mode 100644 tests/qtest/npcm_gmac-test.c
22
3 files changed, 54 insertions(+), 22 deletions(-)
17
23
18
diff --git a/tests/qtest/npcm_gmac-test.c b/tests/qtest/npcm_gmac-test.c
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
19
new file mode 100644
25
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX
26
--- a/include/fpu/softfloat-helpers.h
21
--- /dev/null
27
+++ b/include/fpu/softfloat-helpers.h
22
+++ b/tests/qtest/npcm_gmac-test.c
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
23
@@ -XXX,XX +XXX,XX @@
29
status->float_infzeronan_rule = rule;
24
+/*
30
}
25
+ * QTests for Nuvoton NPCM7xx/8xx GMAC Modules.
31
26
+ *
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
27
+ * Copyright 2023 Google LLC
33
+ float_status *status)
28
+ *
29
+ * This program is free software; you can redistribute it and/or modify it
30
+ * under the terms of the GNU General Public License as published by the
31
+ * Free Software Foundation; either version 2 of the License, or
32
+ * (at your option) any later version.
33
+ *
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+ * for more details.
38
+ */
39
+
40
+#include "qemu/osdep.h"
41
+#include "libqos/libqos.h"
42
+
43
+/* Name of the GMAC Device */
44
+#define TYPE_NPCM_GMAC "npcm-gmac"
45
+
46
+typedef struct GMACModule {
47
+ int irq;
48
+ uint64_t base_addr;
49
+} GMACModule;
50
+
51
+typedef struct TestData {
52
+ const GMACModule *module;
53
+} TestData;
54
+
55
+/* Values extracted from hw/arm/npcm8xx.c */
56
+static const GMACModule gmac_module_list[] = {
57
+ {
58
+ .irq = 14,
59
+ .base_addr = 0xf0802000
60
+ },
61
+ {
62
+ .irq = 15,
63
+ .base_addr = 0xf0804000
64
+ },
65
+ {
66
+ .irq = 16,
67
+ .base_addr = 0xf0806000
68
+ },
69
+ {
70
+ .irq = 17,
71
+ .base_addr = 0xf0808000
72
+ }
73
+};
74
+
75
+/* Returns the index of the GMAC module. */
76
+static int gmac_module_index(const GMACModule *mod)
77
+{
34
+{
78
+ ptrdiff_t diff = mod - gmac_module_list;
35
+ status->default_nan_pattern = dnan_pattern;
79
+
80
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(gmac_module_list));
81
+
82
+ return diff;
83
+}
36
+}
84
+
37
+
85
+/* 32-bit register indices. Taken from npcm_gmac.c */
38
static inline void set_flush_to_zero(bool val, float_status *status)
86
+typedef enum NPCMRegister {
39
{
87
+ /* DMA Registers */
40
status->flush_to_zero = val;
88
+ NPCM_DMA_BUS_MODE = 0x1000,
41
@@ -XXX,XX +XXX,XX @@ static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status
89
+ NPCM_DMA_XMT_POLL_DEMAND = 0x1004,
42
return status->float_infzeronan_rule;
90
+ NPCM_DMA_RCV_POLL_DEMAND = 0x1008,
43
}
91
+ NPCM_DMA_RCV_BASE_ADDR = 0x100c,
44
92
+ NPCM_DMA_TX_BASE_ADDR = 0x1010,
45
+static inline uint8_t get_float_default_nan_pattern(float_status *status)
93
+ NPCM_DMA_STATUS = 0x1014,
94
+ NPCM_DMA_CONTROL = 0x1018,
95
+ NPCM_DMA_INTR_ENA = 0x101c,
96
+ NPCM_DMA_MISSED_FRAME_CTR = 0x1020,
97
+ NPCM_DMA_HOST_TX_DESC = 0x1048,
98
+ NPCM_DMA_HOST_RX_DESC = 0x104c,
99
+ NPCM_DMA_CUR_TX_BUF_ADDR = 0x1050,
100
+ NPCM_DMA_CUR_RX_BUF_ADDR = 0x1054,
101
+ NPCM_DMA_HW_FEATURE = 0x1058,
102
+
103
+ /* GMAC Registers */
104
+ NPCM_GMAC_MAC_CONFIG = 0x0,
105
+ NPCM_GMAC_FRAME_FILTER = 0x4,
106
+ NPCM_GMAC_HASH_HIGH = 0x8,
107
+ NPCM_GMAC_HASH_LOW = 0xc,
108
+ NPCM_GMAC_MII_ADDR = 0x10,
109
+ NPCM_GMAC_MII_DATA = 0x14,
110
+ NPCM_GMAC_FLOW_CTRL = 0x18,
111
+ NPCM_GMAC_VLAN_FLAG = 0x1c,
112
+ NPCM_GMAC_VERSION = 0x20,
113
+ NPCM_GMAC_WAKEUP_FILTER = 0x28,
114
+ NPCM_GMAC_PMT = 0x2c,
115
+ NPCM_GMAC_LPI_CTRL = 0x30,
116
+ NPCM_GMAC_TIMER_CTRL = 0x34,
117
+ NPCM_GMAC_INT_STATUS = 0x38,
118
+ NPCM_GMAC_INT_MASK = 0x3c,
119
+ NPCM_GMAC_MAC0_ADDR_HI = 0x40,
120
+ NPCM_GMAC_MAC0_ADDR_LO = 0x44,
121
+ NPCM_GMAC_MAC1_ADDR_HI = 0x48,
122
+ NPCM_GMAC_MAC1_ADDR_LO = 0x4c,
123
+ NPCM_GMAC_MAC2_ADDR_HI = 0x50,
124
+ NPCM_GMAC_MAC2_ADDR_LO = 0x54,
125
+ NPCM_GMAC_MAC3_ADDR_HI = 0x58,
126
+ NPCM_GMAC_MAC3_ADDR_LO = 0x5c,
127
+ NPCM_GMAC_RGMII_STATUS = 0xd8,
128
+ NPCM_GMAC_WATCHDOG = 0xdc,
129
+ NPCM_GMAC_PTP_TCR = 0x700,
130
+ NPCM_GMAC_PTP_SSIR = 0x704,
131
+ NPCM_GMAC_PTP_STSR = 0x708,
132
+ NPCM_GMAC_PTP_STNSR = 0x70c,
133
+ NPCM_GMAC_PTP_STSUR = 0x710,
134
+ NPCM_GMAC_PTP_STNSUR = 0x714,
135
+ NPCM_GMAC_PTP_TAR = 0x718,
136
+ NPCM_GMAC_PTP_TTSR = 0x71c,
137
+} NPCMRegister;
138
+
139
+static uint32_t gmac_read(QTestState *qts, const GMACModule *mod,
140
+ NPCMRegister regno)
141
+{
46
+{
142
+ return qtest_readl(qts, mod->base_addr + regno);
47
+ return status->default_nan_pattern;
143
+}
48
+}
144
+
49
+
145
+/* Check that GMAC registers are reset to default value */
50
static inline bool get_flush_to_zero(float_status *status)
146
+static void test_init(gconstpointer test_data)
51
{
147
+{
52
return status->flush_to_zero;
148
+ const TestData *td = test_data;
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
149
+ const GMACModule *mod = td->module;
54
index XXXXXXX..XXXXXXX 100644
150
+ QTestState *qts = qtest_init("-machine npcm845-evb");
55
--- a/include/fpu/softfloat-types.h
56
+++ b/include/fpu/softfloat-types.h
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
58
/* should denormalised inputs go to zero and set the input_denormal flag? */
59
bool flush_inputs_to_zero;
60
bool default_nan_mode;
61
+ /*
62
+ * The pattern to use for the default NaN. Here the high bit specifies
63
+ * the default NaN's sign bit, and bits 6..0 specify the high bits of the
64
+ * fractional part. The low bits of the fractional part are copies of bit 0.
65
+ * The exponent of the default NaN is (as for any NaN) always all 1s.
66
+ * Note that a value of 0 here is not a valid NaN. The target must set
67
+ * this to the correct non-zero value, or we will assert when trying to
68
+ * create a default NaN.
69
+ */
70
+ uint8_t default_nan_pattern;
71
/*
72
* The flags below are not used on all specializations and may
73
* constant fold away (see snan_bit_is_one()/no_signalling_nans() in
74
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
75
index XXXXXXX..XXXXXXX 100644
76
--- a/fpu/softfloat-specialize.c.inc
77
+++ b/fpu/softfloat-specialize.c.inc
78
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
79
{
80
bool sign = 0;
81
uint64_t frac;
82
+ uint8_t dnan_pattern = status->default_nan_pattern;
83
84
+ if (dnan_pattern == 0) {
85
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
86
- /* !snan_bit_is_one, set all bits */
87
- frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
88
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
89
+ /* Sign bit clear, all frac bits set */
90
+ dnan_pattern = 0b01111111;
91
+#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
92
|| defined(TARGET_MICROBLAZE)
93
- /* !snan_bit_is_one, set sign and msb */
94
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
95
- sign = 1;
96
+ /* Sign bit set, most significant frac bit set */
97
+ dnan_pattern = 0b11000000;
98
#elif defined(TARGET_HPPA)
99
- /* snan_bit_is_one, set msb-1. */
100
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
101
+ /* Sign bit clear, msb-1 frac bit set */
102
+ dnan_pattern = 0b00100000;
103
#elif defined(TARGET_HEXAGON)
104
- sign = 1;
105
- frac = ~0ULL;
106
+ /* Sign bit set, all frac bits set. */
107
+ dnan_pattern = 0b11111111;
108
#else
109
- /*
110
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
111
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
112
- * do not have floating-point.
113
- */
114
- if (snan_bit_is_one(status)) {
115
- /* set all bits other than msb */
116
- frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
117
- } else {
118
- /* set msb */
119
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
120
- }
121
+ /*
122
+ * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
123
+ * S390, SH4, TriCore, and Xtensa. Our other supported targets
124
+ * do not have floating-point.
125
+ */
126
+ if (snan_bit_is_one(status)) {
127
+ /* sign bit clear, set all frac bits other than msb */
128
+ dnan_pattern = 0b00111111;
129
+ } else {
130
+ /* sign bit clear, set frac msb */
131
+ dnan_pattern = 0b01000000;
132
+ }
133
#endif
134
+ }
135
+ assert(dnan_pattern != 0);
151
+
136
+
152
+#define CHECK_REG32(regno, value) \
137
+ sign = dnan_pattern >> 7;
153
+ do { \
138
+ /*
154
+ g_assert_cmphex(gmac_read(qts, mod, (regno)), ==, (value)); \
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
155
+ } while (0)
140
+ * and replecate bit [0] down into [55:0]
156
+
141
+ */
157
+ CHECK_REG32(NPCM_DMA_BUS_MODE, 0x00020100);
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
158
+ CHECK_REG32(NPCM_DMA_XMT_POLL_DEMAND, 0);
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
159
+ CHECK_REG32(NPCM_DMA_RCV_POLL_DEMAND, 0);
144
160
+ CHECK_REG32(NPCM_DMA_RCV_BASE_ADDR, 0);
145
*p = (FloatParts64) {
161
+ CHECK_REG32(NPCM_DMA_TX_BASE_ADDR, 0);
146
.cls = float_class_qnan,
162
+ CHECK_REG32(NPCM_DMA_STATUS, 0);
163
+ CHECK_REG32(NPCM_DMA_CONTROL, 0);
164
+ CHECK_REG32(NPCM_DMA_INTR_ENA, 0);
165
+ CHECK_REG32(NPCM_DMA_MISSED_FRAME_CTR, 0);
166
+ CHECK_REG32(NPCM_DMA_HOST_TX_DESC, 0);
167
+ CHECK_REG32(NPCM_DMA_HOST_RX_DESC, 0);
168
+ CHECK_REG32(NPCM_DMA_CUR_TX_BUF_ADDR, 0);
169
+ CHECK_REG32(NPCM_DMA_CUR_RX_BUF_ADDR, 0);
170
+ CHECK_REG32(NPCM_DMA_HW_FEATURE, 0x100d4f37);
171
+
172
+ CHECK_REG32(NPCM_GMAC_MAC_CONFIG, 0);
173
+ CHECK_REG32(NPCM_GMAC_FRAME_FILTER, 0);
174
+ CHECK_REG32(NPCM_GMAC_HASH_HIGH, 0);
175
+ CHECK_REG32(NPCM_GMAC_HASH_LOW, 0);
176
+ CHECK_REG32(NPCM_GMAC_MII_ADDR, 0);
177
+ CHECK_REG32(NPCM_GMAC_MII_DATA, 0);
178
+ CHECK_REG32(NPCM_GMAC_FLOW_CTRL, 0);
179
+ CHECK_REG32(NPCM_GMAC_VLAN_FLAG, 0);
180
+ CHECK_REG32(NPCM_GMAC_VERSION, 0x00001032);
181
+ CHECK_REG32(NPCM_GMAC_WAKEUP_FILTER, 0);
182
+ CHECK_REG32(NPCM_GMAC_PMT, 0);
183
+ CHECK_REG32(NPCM_GMAC_LPI_CTRL, 0);
184
+ CHECK_REG32(NPCM_GMAC_TIMER_CTRL, 0x03e80000);
185
+ CHECK_REG32(NPCM_GMAC_INT_STATUS, 0);
186
+ CHECK_REG32(NPCM_GMAC_INT_MASK, 0);
187
+ CHECK_REG32(NPCM_GMAC_MAC0_ADDR_HI, 0x8000ffff);
188
+ CHECK_REG32(NPCM_GMAC_MAC0_ADDR_LO, 0xffffffff);
189
+ CHECK_REG32(NPCM_GMAC_MAC1_ADDR_HI, 0x0000ffff);
190
+ CHECK_REG32(NPCM_GMAC_MAC1_ADDR_LO, 0xffffffff);
191
+ CHECK_REG32(NPCM_GMAC_MAC2_ADDR_HI, 0x0000ffff);
192
+ CHECK_REG32(NPCM_GMAC_MAC2_ADDR_LO, 0xffffffff);
193
+ CHECK_REG32(NPCM_GMAC_MAC3_ADDR_HI, 0x0000ffff);
194
+ CHECK_REG32(NPCM_GMAC_MAC3_ADDR_LO, 0xffffffff);
195
+ CHECK_REG32(NPCM_GMAC_RGMII_STATUS, 0);
196
+ CHECK_REG32(NPCM_GMAC_WATCHDOG, 0);
197
+ CHECK_REG32(NPCM_GMAC_PTP_TCR, 0x00002000);
198
+ CHECK_REG32(NPCM_GMAC_PTP_SSIR, 0);
199
+ CHECK_REG32(NPCM_GMAC_PTP_STSR, 0);
200
+ CHECK_REG32(NPCM_GMAC_PTP_STNSR, 0);
201
+ CHECK_REG32(NPCM_GMAC_PTP_STSUR, 0);
202
+ CHECK_REG32(NPCM_GMAC_PTP_STNSUR, 0);
203
+ CHECK_REG32(NPCM_GMAC_PTP_TAR, 0);
204
+ CHECK_REG32(NPCM_GMAC_PTP_TTSR, 0);
205
+
206
+ qtest_quit(qts);
207
+}
208
+
209
+static void gmac_add_test(const char *name, const TestData* td,
210
+ GTestDataFunc fn)
211
+{
212
+ g_autofree char *full_name = g_strdup_printf(
213
+ "npcm7xx_gmac/gmac[%d]/%s", gmac_module_index(td->module), name);
214
+ qtest_add_data_func(full_name, td, fn);
215
+}
216
+
217
+int main(int argc, char **argv)
218
+{
219
+ TestData test_data_list[ARRAY_SIZE(gmac_module_list)];
220
+
221
+ g_test_init(&argc, &argv, NULL);
222
+
223
+ for (int i = 0; i < ARRAY_SIZE(gmac_module_list); ++i) {
224
+ TestData *td = &test_data_list[i];
225
+
226
+ td->module = &gmac_module_list[i];
227
+
228
+ gmac_add_test("init", td, test_init);
229
+ }
230
+
231
+ return g_test_run();
232
+}
233
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
234
index XXXXXXX..XXXXXXX 100644
235
--- a/tests/qtest/meson.build
236
+++ b/tests/qtest/meson.build
237
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
238
(config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \
239
(config_all_accel.has_key('CONFIG_TCG') and \
240
config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
241
+ (config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
242
['arm-cpu-features',
243
'numa-test',
244
'boot-serial-test',
245
--
147
--
246
2.34.1
148
2.34.1
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
New patch
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.
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-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(+)
13
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/arm/nwfpe/fpa11.c
17
+++ b/linux-user/arm/nwfpe/fpa11.c
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);
27
}
28
29
void SetRoundingMode(const unsigned int opcode)
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
35
* the pseudocode function the arguments are in the order c, a, b.
36
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
37
* and the input NaN if it is signalling
38
+ * * Default NaN has sign bit clear, msb frac bit set
39
*/
40
static void arm_set_default_fp_behaviours(float_status *s)
41
{
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
46
+ set_float_default_nan_pattern(0b01000000, s);
47
}
48
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
50
--
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
New patch
1
Set the default NaN pattern explicitly for xtensa.
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-51-peter.maydell@linaro.org
6
---
7
target/xtensa/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/xtensa/cpu.c
13
+++ b/target/xtensa/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
15
/* For inf * 0 + NaN, return the input NaN */
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
17
set_no_signaling_nans(!dfpu, &env->fp_status);
18
+ /* Default NaN value: sign bit clear, set frac msb */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
xtensa_use_first_nan(env, !dfpu);
21
}
22
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
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.
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-52-peter.maydell@linaro.org
8
---
9
target/hexagon/cpu.c | 2 ++
10
fpu/softfloat-specialize.c.inc | 5 -----
11
2 files changed, 2 insertions(+), 5 deletions(-)
12
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/hexagon/cpu.c
16
+++ b/target/hexagon/cpu.c
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
18
19
set_default_nan_mode(1, &env->fp_status);
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
21
+ /* Default NaN value: sign bit set, all frac bits set */
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
23
}
24
25
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
26
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
27
index XXXXXXX..XXXXXXX 100644
28
--- a/fpu/softfloat-specialize.c.inc
29
+++ b/fpu/softfloat-specialize.c.inc
30
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
31
uint8_t dnan_pattern = status->default_nan_pattern;
32
33
if (dnan_pattern == 0) {
34
-#if defined(TARGET_HEXAGON)
35
- /* Sign bit set, all frac bits set. */
36
- dnan_pattern = 0b11111111;
37
-#else
38
/*
39
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
40
* S390, SH4, TriCore, and Xtensa. Our other supported targets
41
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
42
/* sign bit clear, set frac msb */
43
dnan_pattern = 0b01000000;
44
}
45
-#endif
46
}
47
assert(dnan_pattern != 0);
48
49
--
50
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for riscv.
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-53-peter.maydell@linaro.org
6
---
7
target/riscv/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/riscv/cpu.c
13
+++ b/target/riscv/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
15
cs->exception_index = RISCV_EXCP_NONE;
16
env->load_res = -1;
17
set_default_nan_mode(1, &env->fp_status);
18
+ /* Default NaN value: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
env->vill = true;
21
22
#ifndef CONFIG_USER_ONLY
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for tricore.
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-54-peter.maydell@linaro.org
6
---
7
target/tricore/helper.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/tricore/helper.c
13
+++ b/target/tricore/helper.c
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
15
set_flush_to_zero(1, &env->fp_status);
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
17
set_default_nan_mode(1, &env->fp_status);
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
}
21
22
uint32_t psw_read(CPUTriCoreState *env)
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
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().
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-55-peter.maydell@linaro.org
8
---
9
fpu/softfloat-specialize.c.inc | 14 --------------
10
1 file changed, 14 deletions(-)
11
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
13
index XXXXXXX..XXXXXXX 100644
14
--- a/fpu/softfloat-specialize.c.inc
15
+++ b/fpu/softfloat-specialize.c.inc
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
17
uint64_t frac;
18
uint8_t dnan_pattern = status->default_nan_pattern;
19
20
- if (dnan_pattern == 0) {
21
- /*
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
24
- * do not have floating-point.
25
- */
26
- if (snan_bit_is_one(status)) {
27
- /* sign bit clear, set all frac bits other than msb */
28
- dnan_pattern = 0b00111111;
29
- } else {
30
- /* sign bit clear, set frac msb */
31
- dnan_pattern = 0b01000000;
32
- }
33
- }
34
assert(dnan_pattern != 0);
35
36
sign = dnan_pattern >> 7;
37
--
38
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
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
3
Inline pickNaNMulAdd into its only caller. This makes
4
one assert redundant with the immediately preceding IF.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Acked-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
6
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
9
[PMM: keep comment from old code in new location]
7
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
8
Message-id: 20240109194438.70934-4-ines.varhol@telecom-paris.fr
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
tests/qtest/stm32l4x5_syscfg-test.c | 331 ++++++++++++++++++++++++++++
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
12
tests/qtest/meson.build | 3 +-
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
13
2 files changed, 333 insertions(+), 1 deletion(-)
14
2 files changed, 40 insertions(+), 55 deletions(-)
14
create mode 100644 tests/qtest/stm32l4x5_syscfg-test.c
15
15
16
diff --git a/tests/qtest/stm32l4x5_syscfg-test.c b/tests/qtest/stm32l4x5_syscfg-test.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
17
new file mode 100644
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX
18
--- a/fpu/softfloat-parts.c.inc
19
--- /dev/null
19
+++ b/fpu/softfloat-parts.c.inc
20
+++ b/tests/qtest/stm32l4x5_syscfg-test.c
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
@@ -XXX,XX +XXX,XX @@
21
}
22
+/*
22
23
+ * QTest testcase for STM32L4x5_SYSCFG
23
if (s->default_nan_mode) {
24
+ *
24
+ /*
25
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
25
+ * We guarantee not to require the target to tell us how to
26
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
26
+ * pick a NaN if we're always returning the default NaN.
27
+ *
27
+ * But if we're not in default-NaN mode then the target must
28
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
28
+ * specify.
29
+ * See the COPYING file in the top-level directory.
29
+ */
30
+ */
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;
31
+
53
+
32
+#include "qemu/osdep.h"
54
+ assert(rule != float_3nan_prop_none);
33
+#include "libqtest-single.h"
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
34
+
56
+ /* We have at least one SNaN input and should prefer it */
35
+#define SYSCFG_BASE_ADDR 0x40010000
57
+ do {
36
+#define SYSCFG_MEMRMP 0x00
58
+ which = rule & R_3NAN_1ST_MASK;
37
+#define SYSCFG_CFGR1 0x04
59
+ rule >>= R_3NAN_1ST_LENGTH;
38
+#define SYSCFG_EXTICR1 0x08
60
+ } while (!is_snan(cls[which]));
39
+#define SYSCFG_EXTICR2 0x0C
61
+ } else {
40
+#define SYSCFG_EXTICR3 0x10
62
+ do {
41
+#define SYSCFG_EXTICR4 0x14
63
+ which = rule & R_3NAN_1ST_MASK;
42
+#define SYSCFG_SCSR 0x18
64
+ rule >>= R_3NAN_1ST_LENGTH;
43
+#define SYSCFG_CFGR2 0x1C
65
+ } while (!is_nan(cls[which]));
44
+#define SYSCFG_SWPR 0x20
66
+ }
45
+#define SYSCFG_SKR 0x24
67
}
46
+#define SYSCFG_SWPR2 0x28
68
47
+#define INVALID_ADDR 0x2C
69
if (which == 3) {
48
+
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
49
+static void syscfg_writel(unsigned int offset, uint32_t value)
50
+{
51
+ writel(SYSCFG_BASE_ADDR + offset, value);
52
+}
53
+
54
+static uint32_t syscfg_readl(unsigned int offset)
55
+{
56
+ return readl(SYSCFG_BASE_ADDR + offset);
57
+}
58
+
59
+static void syscfg_set_irq(int num, int level)
60
+{
61
+ qtest_set_irq_in(global_qtest, "/machine/soc/syscfg",
62
+ NULL, num, level);
63
+}
64
+
65
+static void system_reset(void)
66
+{
67
+ QDict *response;
68
+ response = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
69
+ g_assert(qdict_haskey(response, "return"));
70
+ qobject_unref(response);
71
+}
72
+
73
+static void test_reset(void)
74
+{
75
+ /*
76
+ * Test that registers are initialized at the correct values
77
+ */
78
+ g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
79
+
80
+ g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
81
+
82
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
83
+
84
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
85
+
86
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
87
+
88
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
89
+
90
+ g_assert_cmpuint(syscfg_readl(SYSCFG_SCSR), ==, 0x00000000);
91
+
92
+ g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
93
+
94
+ g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR), ==, 0x00000000);
95
+
96
+ g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
97
+
98
+ g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR2), ==, 0x00000000);
99
+}
100
+
101
+static void test_reserved_bits(void)
102
+{
103
+ /*
104
+ * Test that reserved bits stay at reset value
105
+ * (which is 0 for all of them) by writing '1'
106
+ * in all reserved bits (keeping reset value for
107
+ * other bits) and checking that the
108
+ * register is still at reset value
109
+ */
110
+ syscfg_writel(SYSCFG_MEMRMP, 0xFFFFFEF8);
111
+ g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
112
+
113
+ syscfg_writel(SYSCFG_CFGR1, 0x7F00FEFF);
114
+ g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
115
+
116
+ syscfg_writel(SYSCFG_EXTICR1, 0xFFFF0000);
117
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
118
+
119
+ syscfg_writel(SYSCFG_EXTICR2, 0xFFFF0000);
120
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
121
+
122
+ syscfg_writel(SYSCFG_EXTICR3, 0xFFFF0000);
123
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
124
+
125
+ syscfg_writel(SYSCFG_EXTICR4, 0xFFFF0000);
126
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
127
+
128
+ syscfg_writel(SYSCFG_SKR, 0xFFFFFF00);
129
+ g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
130
+}
131
+
132
+static void test_set_and_clear(void)
133
+{
134
+ /*
135
+ * Test that regular bits can be set and cleared
136
+ */
137
+ syscfg_writel(SYSCFG_MEMRMP, 0x00000107);
138
+ g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000107);
139
+ syscfg_writel(SYSCFG_MEMRMP, 0x00000000);
140
+ g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
141
+
142
+ /* cfgr1 bit 0 is clear only so we keep it set */
143
+ syscfg_writel(SYSCFG_CFGR1, 0xFCFF0101);
144
+ g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0xFCFF0101);
145
+ syscfg_writel(SYSCFG_CFGR1, 0x00000001);
146
+ g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000001);
147
+
148
+ syscfg_writel(SYSCFG_EXTICR1, 0x0000FFFF);
149
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x0000FFFF);
150
+ syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
151
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
152
+
153
+ syscfg_writel(SYSCFG_EXTICR2, 0x0000FFFF);
154
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x0000FFFF);
155
+ syscfg_writel(SYSCFG_EXTICR2, 0x00000000);
156
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
157
+
158
+ syscfg_writel(SYSCFG_EXTICR3, 0x0000FFFF);
159
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x0000FFFF);
160
+ syscfg_writel(SYSCFG_EXTICR3, 0x00000000);
161
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
162
+
163
+ syscfg_writel(SYSCFG_EXTICR4, 0x0000FFFF);
164
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x0000FFFF);
165
+ syscfg_writel(SYSCFG_EXTICR4, 0x00000000);
166
+ g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
167
+
168
+ syscfg_writel(SYSCFG_SKR, 0x000000FF);
169
+ g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x000000FF);
170
+ syscfg_writel(SYSCFG_SKR, 0x00000000);
171
+ g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
172
+}
173
+
174
+static void test_clear_by_writing_1(void)
175
+{
176
+ /*
177
+ * Test that writing '1' doesn't set the bit
178
+ */
179
+ syscfg_writel(SYSCFG_CFGR2, 0x00000100);
180
+ g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
181
+}
182
+
183
+static void test_set_only_bits(void)
184
+{
185
+ /*
186
+ * Test that set only bits stay can't be cleared
187
+ */
188
+ syscfg_writel(SYSCFG_CFGR2, 0x0000000F);
189
+ syscfg_writel(SYSCFG_CFGR2, 0x00000000);
190
+ g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x0000000F);
191
+
192
+ syscfg_writel(SYSCFG_SWPR, 0xFFFFFFFF);
193
+ syscfg_writel(SYSCFG_SWPR, 0x00000000);
194
+ g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR), ==, 0xFFFFFFFF);
195
+
196
+ syscfg_writel(SYSCFG_SWPR2, 0xFFFFFFFF);
197
+ syscfg_writel(SYSCFG_SWPR2, 0x00000000);
198
+ g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR2), ==, 0xFFFFFFFF);
199
+
200
+ system_reset();
201
+}
202
+
203
+static void test_clear_only_bits(void)
204
+{
205
+ /*
206
+ * Test that clear only bits stay can't be set
207
+ */
208
+ syscfg_writel(SYSCFG_CFGR1, 0x00000000);
209
+ syscfg_writel(SYSCFG_CFGR1, 0x00000001);
210
+ g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000000);
211
+
212
+ system_reset();
213
+}
214
+
215
+static void test_interrupt(void)
216
+{
217
+ /*
218
+ * Test that GPIO rising lines result in an irq
219
+ * with the right configuration
220
+ */
221
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
222
+
223
+ /* GPIOA is the default source for EXTI lines 0 to 15 */
224
+
225
+ syscfg_set_irq(0, 1);
226
+
227
+ g_assert_true(get_irq(0));
228
+
229
+
230
+ syscfg_set_irq(15, 1);
231
+
232
+ g_assert_true(get_irq(15));
233
+
234
+ /* Configure GPIOB[1] as the source input for EXTI1 */
235
+ syscfg_writel(SYSCFG_EXTICR1, 0x00000010);
236
+
237
+ syscfg_set_irq(17, 1);
238
+
239
+ g_assert_true(get_irq(1));
240
+
241
+ /* Clean the test */
242
+ syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
243
+ syscfg_set_irq(0, 0);
244
+ syscfg_set_irq(15, 0);
245
+ syscfg_set_irq(17, 0);
246
+}
247
+
248
+static void test_irq_pin_multiplexer(void)
249
+{
250
+ /*
251
+ * Test that syscfg irq sets the right exti irq
252
+ */
253
+
254
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
255
+
256
+ syscfg_set_irq(0, 1);
257
+
258
+ /* Check that irq 0 was set and irq 15 wasn't */
259
+ g_assert_true(get_irq(0));
260
+ g_assert_false(get_irq(15));
261
+
262
+ /* Clean the test */
263
+ syscfg_set_irq(0, 0);
264
+
265
+ syscfg_set_irq(15, 1);
266
+
267
+ /* Check that irq 15 was set and irq 0 wasn't */
268
+ g_assert_true(get_irq(15));
269
+ g_assert_false(get_irq(0));
270
+
271
+ /* Clean the test */
272
+ syscfg_set_irq(15, 0);
273
+}
274
+
275
+static void test_irq_gpio_multiplexer(void)
276
+{
277
+ /*
278
+ * Test that an irq is generated only by the right GPIO
279
+ */
280
+
281
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
282
+
283
+ /* GPIOA is the default source for EXTI lines 0 to 15 */
284
+
285
+ /* Check that setting rising pin GPIOA[0] generates an irq */
286
+ syscfg_set_irq(0, 1);
287
+
288
+ g_assert_true(get_irq(0));
289
+
290
+ /* Clean the test */
291
+ syscfg_set_irq(0, 0);
292
+
293
+ /* Check that setting rising pin GPIOB[0] doesn't generate an irq */
294
+ syscfg_set_irq(16, 1);
295
+
296
+ g_assert_false(get_irq(0));
297
+
298
+ /* Clean the test */
299
+ syscfg_set_irq(16, 0);
300
+
301
+ /* Configure GPIOB[0] as the source input for EXTI0 */
302
+ syscfg_writel(SYSCFG_EXTICR1, 0x00000001);
303
+
304
+ /* Check that setting rising pin GPIOA[0] doesn't generate an irq */
305
+ syscfg_set_irq(0, 1);
306
+
307
+ g_assert_false(get_irq(0));
308
+
309
+ /* Clean the test */
310
+ syscfg_set_irq(0, 0);
311
+
312
+ /* Check that setting rising pin GPIOB[0] generates an irq */
313
+ syscfg_set_irq(16, 1);
314
+
315
+ g_assert_true(get_irq(0));
316
+
317
+ /* Clean the test */
318
+ syscfg_set_irq(16, 0);
319
+ syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
320
+}
321
+
322
+int main(int argc, char **argv)
323
+{
324
+ int ret;
325
+
326
+ g_test_init(&argc, &argv, NULL);
327
+ g_test_set_nonfatal_assertions();
328
+
329
+ qtest_add_func("stm32l4x5/syscfg/test_reset", test_reset);
330
+ qtest_add_func("stm32l4x5/syscfg/test_reserved_bits",
331
+ test_reserved_bits);
332
+ qtest_add_func("stm32l4x5/syscfg/test_set_and_clear",
333
+ test_set_and_clear);
334
+ qtest_add_func("stm32l4x5/syscfg/test_clear_by_writing_1",
335
+ test_clear_by_writing_1);
336
+ qtest_add_func("stm32l4x5/syscfg/test_set_only_bits",
337
+ test_set_only_bits);
338
+ qtest_add_func("stm32l4x5/syscfg/test_clear_only_bits",
339
+ test_clear_only_bits);
340
+ qtest_add_func("stm32l4x5/syscfg/test_interrupt",
341
+ test_interrupt);
342
+ qtest_add_func("stm32l4x5/syscfg/test_irq_pin_multiplexer",
343
+ test_irq_pin_multiplexer);
344
+ qtest_add_func("stm32l4x5/syscfg/test_irq_gpio_multiplexer",
345
+ test_irq_gpio_multiplexer);
346
+
347
+ qtest_start("-machine b-l475e-iot01a");
348
+ ret = g_test_run();
349
+ qtest_end();
350
+
351
+ return ret;
352
+}
353
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
354
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
355
--- a/tests/qtest/meson.build
72
--- a/fpu/softfloat-specialize.c.inc
356
+++ b/tests/qtest/meson.build
73
+++ b/fpu/softfloat-specialize.c.inc
357
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
358
'aspeed_gpio-test']
75
}
359
76
}
360
qtests_stm32l4x5 = \
77
361
- ['stm32l4x5_exti-test']
78
-/*----------------------------------------------------------------------------
362
+ ['stm32l4x5_exti-test',
79
-| Select which NaN to propagate for a three-input operation.
363
+ 'stm32l4x5_syscfg-test']
80
-| For the moment we assume that no CPU needs the 'larger significand'
364
81
-| information.
365
qtests_arm = \
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
366
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
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;
90
-
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);
98
-
99
- if (infzero) {
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
- }
115
-
116
- assert(rule != float_3nan_prop_none);
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
118
- /* We have at least one SNaN input and should prefer it */
119
- do {
120
- which = rule & R_3NAN_1ST_MASK;
121
- rule >>= R_3NAN_1ST_LENGTH;
122
- } while (!is_snan(cls[which]));
123
- } else {
124
- do {
125
- which = rule & R_3NAN_1ST_MASK;
126
- rule >>= R_3NAN_1ST_LENGTH;
127
- } while (!is_nan(cls[which]));
128
- }
129
- return which;
130
-}
131
-
132
/*----------------------------------------------------------------------------
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
134
| NaN; otherwise returns 0.
367
--
135
--
368
2.34.1
136
2.34.1
369
137
370
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
The SYSCFG input GPIOs aren't connected yet. When the STM32L4x5 GPIO
3
Remove "3" as a special case for which and simply
4
device will be implemented, its output GPIOs will be connected to the
4
branch to return the desired value.
5
SYSCFG input GPIOs.
6
5
7
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
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
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
10
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
11
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Message-id: 20240109194438.70934-3-ines.varhol@telecom-paris.fr
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
include/hw/arm/stm32l4x5_soc.h | 2 ++
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
16
hw/arm/stm32l4x5_soc.c | 21 ++++++++++++++++++++-
12
1 file changed, 10 insertions(+), 10 deletions(-)
17
hw/arm/Kconfig | 1 +
18
3 files changed, 23 insertions(+), 1 deletion(-)
19
13
20
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/stm32l4x5_soc.h
16
--- a/fpu/softfloat-parts.c.inc
23
+++ b/include/hw/arm/stm32l4x5_soc.h
17
+++ b/fpu/softfloat-parts.c.inc
24
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
25
19
* But if we're not in default-NaN mode then the target must
26
#include "exec/memory.h"
20
* specify.
27
#include "hw/arm/armv7m.h"
21
*/
28
+#include "hw/misc/stm32l4x5_syscfg.h"
22
- which = 3;
29
#include "hw/misc/stm32l4x5_exti.h"
23
+ goto default_nan;
30
#include "qom/object.h"
24
} else if (infzero) {
31
25
/*
32
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
26
* Inf * 0 + NaN -- some implementations return the
33
ARMv7MState armv7m;
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
34
28
*/
35
Stm32l4x5ExtiState exti;
29
switch (s->float_infzeronan_rule) {
36
+ Stm32l4x5SyscfgState syscfg;
30
case float_infzeronan_dnan_never:
37
31
- which = 2;
38
MemoryRegion sram1;
32
break;
39
MemoryRegion sram2;
33
case float_infzeronan_dnan_always:
40
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
34
- which = 3;
41
index XXXXXXX..XXXXXXX 100644
35
- break;
42
--- a/hw/arm/stm32l4x5_soc.c
36
+ goto default_nan;
43
+++ b/hw/arm/stm32l4x5_soc.c
37
case float_infzeronan_dnan_if_qnan:
44
@@ -XXX,XX +XXX,XX @@
38
- which = is_qnan(c->cls) ? 3 : 2;
45
#define SRAM2_SIZE (32 * KiB)
39
+ if (is_qnan(c->cls)) {
46
40
+ goto default_nan;
47
#define EXTI_ADDR 0x40010400
41
+ }
48
+#define SYSCFG_ADDR 0x40010000
42
break;
49
43
default:
50
#define NUM_EXTI_IRQ 40
44
g_assert_not_reached();
51
/* Match exti line connections with their CPU IRQ number */
45
}
52
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
46
+ which = 2;
53
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
47
} else {
54
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
55
object_initialize_child(obj, "exti", &s->exti, TYPE_STM32L4X5_EXTI);
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
56
+ object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
57
51
}
58
s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
59
s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
60
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
61
return;
62
}
52
}
63
53
64
+ /* System configuration controller */
54
- if (which == 3) {
65
+ busdev = SYS_BUS_DEVICE(&s->syscfg);
55
- parts_default_nan(a, s);
66
+ if (!sysbus_realize(busdev, errp)) {
56
- return a;
67
+ return;
57
- }
68
+ }
58
-
69
+ sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
59
switch (which) {
70
+ /*
60
case 0:
71
+ * TODO: when the GPIO device is implemented, connect it
61
break;
72
+ * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
62
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
73
+ * GPIO_NUM_PINS.
63
parts_silence_nan(a, s);
74
+ */
64
}
65
return a;
75
+
66
+
76
+ /* EXTI device */
67
+ default_nan:
77
busdev = SYS_BUS_DEVICE(&s->exti);
68
+ parts_default_nan(a, s);
78
if (!sysbus_realize(busdev, errp)) {
69
+ return a;
79
return;
70
}
80
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
71
81
sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
72
/*
82
}
83
84
+ for (unsigned i = 0; i < 16; i++) {
85
+ qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
86
+ qdev_get_gpio_in(DEVICE(&s->exti), i));
87
+ }
88
+
89
/* APB1 BUS */
90
create_unimplemented_device("TIM2", 0x40000000, 0x400);
91
create_unimplemented_device("TIM3", 0x40000400, 0x400);
92
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
93
/* RESERVED: 0x40009800, 0x6800 */
94
95
/* APB2 BUS */
96
- create_unimplemented_device("SYSCFG", 0x40010000, 0x30);
97
create_unimplemented_device("VREFBUF", 0x40010030, 0x1D0);
98
create_unimplemented_device("COMP", 0x40010200, 0x200);
99
/* RESERVED: 0x40010800, 0x1400 */
100
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
101
index XXXXXXX..XXXXXXX 100644
102
--- a/hw/arm/Kconfig
103
+++ b/hw/arm/Kconfig
104
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
105
bool
106
select ARM_V7M
107
select OR_IRQ
108
+ select STM32L4X5_SYSCFG
109
select STM32L4X5_EXTI
110
111
config XLNX_ZYNQMP_ARM
112
--
73
--
113
2.34.1
74
2.34.1
114
75
115
76
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
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
3
Assign the pointer return value to 'a' directly,
4
rather than going through an intermediary index.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
6
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
7
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
8
Message-id: 20240109160658.311932-3-ines.varhol@telecom-paris.fr
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
include/hw/arm/stm32l4x5_soc.h | 3 ++
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
12
hw/arm/stm32l4x5_soc.c | 52 +++++++++++++++++++++++++++++++++-
12
1 file changed, 10 insertions(+), 22 deletions(-)
13
hw/arm/Kconfig | 1 +
14
3 files changed, 55 insertions(+), 1 deletion(-)
15
13
16
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.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/stm32l4x5_soc.h
16
--- a/fpu/softfloat-parts.c.inc
19
+++ b/include/hw/arm/stm32l4x5_soc.h
17
+++ b/fpu/softfloat-parts.c.inc
20
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
19
FloatPartsN *c, float_status *s,
22
#include "exec/memory.h"
20
int ab_mask, int abc_mask)
23
#include "hw/arm/armv7m.h"
24
+#include "hw/misc/stm32l4x5_exti.h"
25
#include "qom/object.h"
26
27
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
28
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
29
30
ARMv7MState armv7m;
31
32
+ Stm32l4x5ExtiState exti;
33
+
34
MemoryRegion sram1;
35
MemoryRegion sram2;
36
MemoryRegion flash;
37
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/stm32l4x5_soc.c
40
+++ b/hw/arm/stm32l4x5_soc.c
41
@@ -XXX,XX +XXX,XX @@
42
#define SRAM2_BASE_ADDRESS 0x10000000
43
#define SRAM2_SIZE (32 * KiB)
44
45
+#define EXTI_ADDR 0x40010400
46
+
47
+#define NUM_EXTI_IRQ 40
48
+/* Match exti line connections with their CPU IRQ number */
49
+/* See Vector Table (Reference Manual p.396) */
50
+static const int exti_irq[NUM_EXTI_IRQ] = {
51
+ 6, /* GPIO[0] */
52
+ 7, /* GPIO[1] */
53
+ 8, /* GPIO[2] */
54
+ 9, /* GPIO[3] */
55
+ 10, /* GPIO[4] */
56
+ 23, 23, 23, 23, 23, /* GPIO[5..9] */
57
+ 40, 40, 40, 40, 40, 40, /* GPIO[10..15] */
58
+ 1, /* PVD */
59
+ 67, /* OTG_FS_WKUP, Direct */
60
+ 41, /* RTC_ALARM */
61
+ 2, /* RTC_TAMP_STAMP2/CSS_LSE */
62
+ 3, /* RTC wakeup timer */
63
+ 63, /* COMP1 */
64
+ 63, /* COMP2 */
65
+ 31, /* I2C1 wakeup, Direct */
66
+ 33, /* I2C2 wakeup, Direct */
67
+ 72, /* I2C3 wakeup, Direct */
68
+ 37, /* USART1 wakeup, Direct */
69
+ 38, /* USART2 wakeup, Direct */
70
+ 39, /* USART3 wakeup, Direct */
71
+ 52, /* UART4 wakeup, Direct */
72
+ 53, /* UART4 wakeup, Direct */
73
+ 70, /* LPUART1 wakeup, Direct */
74
+ 65, /* LPTIM1, Direct */
75
+ 66, /* LPTIM2, Direct */
76
+ 76, /* SWPMI1 wakeup, Direct */
77
+ 1, /* PVM1 wakeup */
78
+ 1, /* PVM2 wakeup */
79
+ 1, /* PVM3 wakeup */
80
+ 1, /* PVM4 wakeup */
81
+ 78 /* LCD wakeup, Direct */
82
+};
83
+
84
static void stm32l4x5_soc_initfn(Object *obj)
85
{
21
{
86
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
22
- int which;
87
23
bool infzero = (ab_mask == float_cmask_infzero);
88
+ object_initialize_child(obj, "exti", &s->exti, TYPE_STM32L4X5_EXTI);
24
bool have_snan = (abc_mask & float_cmask_snan);
89
+
25
+ FloatPartsN *ret;
90
s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
26
91
s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
27
if (unlikely(have_snan)) {
92
}
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
93
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
94
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
30
default:
95
MemoryRegion *system_memory = get_system_memory();
31
g_assert_not_reached();
96
DeviceState *armv7m;
32
}
97
+ SysBusDevice *busdev;
33
- which = 2;
98
34
+ ret = c;
99
/*
35
} else {
100
* We use s->refclk internally and only define it with qdev_init_clock_in()
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
101
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
37
+ FloatPartsN *val[3] = { a, b, c };
102
return;
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
40
assert(rule != float_3nan_prop_none);
41
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
42
/* We have at least one SNaN input and should prefer it */
43
do {
44
- which = rule & R_3NAN_1ST_MASK;
45
+ ret = val[rule & R_3NAN_1ST_MASK];
46
rule >>= R_3NAN_1ST_LENGTH;
47
- } while (!is_snan(cls[which]));
48
+ } while (!is_snan(ret->cls));
49
} else {
50
do {
51
- which = rule & R_3NAN_1ST_MASK;
52
+ ret = val[rule & R_3NAN_1ST_MASK];
53
rule >>= R_3NAN_1ST_LENGTH;
54
- } while (!is_nan(cls[which]));
55
+ } while (!is_nan(ret->cls));
56
}
103
}
57
}
104
58
105
+ busdev = SYS_BUS_DEVICE(&s->exti);
59
- switch (which) {
106
+ if (!sysbus_realize(busdev, errp)) {
60
- case 0:
107
+ return;
61
- break;
108
+ }
62
- case 1:
109
+ sysbus_mmio_map(busdev, 0, EXTI_ADDR);
63
- a = b;
110
+ for (unsigned i = 0; i < NUM_EXTI_IRQ; i++) {
64
- break;
111
+ sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
65
- case 2:
112
+ }
66
- a = c;
113
+
67
- break;
114
/* APB1 BUS */
68
- default:
115
create_unimplemented_device("TIM2", 0x40000000, 0x400);
69
- g_assert_not_reached();
116
create_unimplemented_device("TIM3", 0x40000400, 0x400);
70
+ if (is_snan(ret->cls)) {
117
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
71
+ parts_silence_nan(ret, s);
118
create_unimplemented_device("SYSCFG", 0x40010000, 0x30);
72
}
119
create_unimplemented_device("VREFBUF", 0x40010030, 0x1D0);
73
- if (is_snan(a->cls)) {
120
create_unimplemented_device("COMP", 0x40010200, 0x200);
74
- parts_silence_nan(a, s);
121
- create_unimplemented_device("EXTI", 0x40010400, 0x400);
75
- }
122
/* RESERVED: 0x40010800, 0x1400 */
76
- return a;
123
create_unimplemented_device("FIREWALL", 0x40011C00, 0x400);
77
+ return ret;
124
/* RESERVED: 0x40012000, 0x800 */
78
125
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
79
default_nan:
126
index XXXXXXX..XXXXXXX 100644
80
parts_default_nan(a, s);
127
--- a/hw/arm/Kconfig
128
+++ b/hw/arm/Kconfig
129
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
130
bool
131
select ARM_V7M
132
select OR_IRQ
133
+ select STM32L4X5_EXTI
134
135
config XLNX_ZYNQMP_ARM
136
bool
137
--
81
--
138
2.34.1
82
2.34.1
139
83
140
84
diff view generated by jsdifflib
1
From: Samuel Tardieu <sam@rfc1149.net>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Samuel Tardieu <sam@rfc1149.net>
3
While all indices into val[] should be in [0-2], the mask
4
applied is two bits. To help static analysis see there is
5
no possibility of read beyond the end of the array, pad the
6
array to 4 entries, with the final being (implicitly) NULL.
7
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
6
Message-id: 20240109184508.3189599-1-sam@rfc1149.net
7
Fixes: ff68dacbc786 ("armv7m: Split systick out from NVIC")
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
hw/timer/trace-events | 2 +-
13
fpu/softfloat-parts.c.inc | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
12
15
13
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/timer/trace-events
18
--- a/fpu/softfloat-parts.c.inc
16
+++ b/hw/timer/trace-events
19
+++ b/fpu/softfloat-parts.c.inc
17
@@ -XXX,XX +XXX,XX @@ aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) "From 0x%" PRI
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
18
21
}
19
# armv7m_systick.c
22
ret = c;
20
systick_reload(void) "systick reload"
23
} else {
21
-systick_timer_tick(void) "systick reload"
24
- FloatPartsN *val[3] = { a, b, c };
22
+systick_timer_tick(void) "systick tick"
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
23
systick_read(uint64_t addr, uint32_t value, unsigned size) "systick read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
24
systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
27
25
28
assert(rule != float_3nan_prop_none);
26
--
29
--
27
2.34.1
30
2.34.1
28
31
29
32
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This patches adds a qtest for NPCM7XX PCI Mailbox module.
3
This function is part of the public interface and
4
It sends read and write requests to the module, and verifies that
4
is not "specialized" to any target in any way.
5
the module contains the correct data after the requests.
6
5
7
Change-Id: I2e1dbaecf8be9ec7eab55cb54f7fdeb0715b8275
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Message-id: 20240110234232.4116804-4-nabihestefan@google.com
12
[PMM: avoid in_port_t type as it is not present on Windows]
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-7-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
10
---
16
tests/qtest/npcm7xx_pci_mbox-test.c | 238 ++++++++++++++++++++++++++++
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
17
tests/qtest/meson.build | 1 +
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
18
2 files changed, 239 insertions(+)
13
2 files changed, 52 insertions(+), 52 deletions(-)
19
create mode 100644 tests/qtest/npcm7xx_pci_mbox-test.c
20
14
21
diff --git a/tests/qtest/npcm7xx_pci_mbox-test.c b/tests/qtest/npcm7xx_pci_mbox-test.c
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
22
new file mode 100644
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX
17
--- a/fpu/softfloat.c
24
--- /dev/null
18
+++ b/fpu/softfloat.c
25
+++ b/tests/qtest/npcm7xx_pci_mbox-test.c
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
26
@@ -XXX,XX +XXX,XX @@
20
*zExpPtr = 1 - shiftCount;
27
+/*
21
}
28
+ * QTests for Nuvoton NPCM7xx PCI Mailbox Modules.
22
29
+ *
23
+/*----------------------------------------------------------------------------
30
+ * Copyright 2021 Google LLC
24
+| Takes two extended double-precision floating-point values `a' and `b', one
31
+ *
25
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
32
+ * This program is free software; you can redistribute it and/or modify it
26
+| `b' is a signaling NaN, the invalid exception is raised.
33
+ * under the terms of the GNU General Public License as published by the
27
+*----------------------------------------------------------------------------*/
34
+ * Free Software Foundation; either version 2 of the License, or
35
+ * (at your option) any later version.
36
+ *
37
+ * This program is distributed in the hope that it will be useful, but WITHOUT
38
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
39
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40
+ * for more details.
41
+ */
42
+
28
+
43
+#include "qemu/osdep.h"
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
44
+#include "qemu/bitops.h"
30
+{
45
+#include "qapi/qmp/qdict.h"
31
+ bool aIsLargerSignificand;
46
+#include "qapi/qmp/qnum.h"
32
+ FloatClass a_cls, b_cls;
47
+#include "libqtest-single.h"
48
+
33
+
49
+#define PCI_MBOX_BA 0xf0848000
34
+ /* This is not complete, but is good enough for pickNaN. */
50
+#define PCI_MBOX_IRQ 8
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);
51
+
45
+
52
+/* register offset */
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
53
+#define PCI_MBOX_STAT 0x00
47
+ float_raise(float_flag_invalid, status);
54
+#define PCI_MBOX_CTL 0x04
48
+ }
55
+#define PCI_MBOX_CMD 0x08
56
+
49
+
57
+#define CODE_OK 0x00
50
+ if (status->default_nan_mode) {
58
+#define CODE_INVALID_OP 0xa0
51
+ return floatx80_default_nan(status);
59
+#define CODE_INVALID_SIZE 0xa1
52
+ }
60
+#define CODE_ERROR 0xff
61
+
53
+
62
+#define OP_READ 0x01
54
+ if (a.low < b.low) {
63
+#define OP_WRITE 0x02
55
+ aIsLargerSignificand = 0;
64
+#define OP_INVALID 0x41
56
+ } else if (b.low < a.low) {
57
+ aIsLargerSignificand = 1;
58
+ } else {
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
60
+ }
65
+
61
+
66
+
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
67
+static int sock;
63
+ if (is_snan(b_cls)) {
68
+static int fd;
64
+ return floatx80_silence_nan(b, status);
69
+
70
+/*
71
+ * Create a local TCP socket with any port, then save off the port we got.
72
+ */
73
+static int open_socket(void)
74
+{
75
+ struct sockaddr_in myaddr;
76
+ socklen_t addrlen;
77
+
78
+ myaddr.sin_family = AF_INET;
79
+ myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
80
+ myaddr.sin_port = 0;
81
+ sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
82
+ g_assert(sock != -1);
83
+ g_assert(bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) != -1);
84
+ addrlen = sizeof(myaddr);
85
+ g_assert(getsockname(sock, (struct sockaddr *) &myaddr , &addrlen) != -1);
86
+ g_assert(listen(sock, 1) != -1);
87
+ return ntohs(myaddr.sin_port);
88
+}
89
+
90
+static void setup_fd(void)
91
+{
92
+ fd_set readfds;
93
+
94
+ FD_ZERO(&readfds);
95
+ FD_SET(sock, &readfds);
96
+ g_assert(select(sock + 1, &readfds, NULL, NULL, NULL) == 1);
97
+
98
+ fd = accept(sock, NULL, 0);
99
+ g_assert(fd >= 0);
100
+}
101
+
102
+static uint8_t read_response(uint8_t *buf, size_t len)
103
+{
104
+ uint8_t code;
105
+ ssize_t ret = read(fd, &code, 1);
106
+
107
+ if (ret == -1) {
108
+ return CODE_ERROR;
109
+ }
110
+ if (code != CODE_OK) {
111
+ return code;
112
+ }
113
+ g_test_message("response code: %x", code);
114
+ if (len > 0) {
115
+ ret = read(fd, buf, len);
116
+ if (ret < len) {
117
+ return CODE_ERROR;
118
+ }
65
+ }
119
+ }
66
+ return b;
120
+ return CODE_OK;
67
+ } else {
121
+}
68
+ if (is_snan(a_cls)) {
122
+
69
+ return floatx80_silence_nan(a, status);
123
+static void receive_data(uint64_t offset, uint8_t *buf, size_t len)
124
+{
125
+ uint8_t op = OP_READ;
126
+ uint8_t code;
127
+ ssize_t rv;
128
+
129
+ while (len > 0) {
130
+ uint8_t size;
131
+
132
+ if (len >= 8) {
133
+ size = 8;
134
+ } else if (len >= 4) {
135
+ size = 4;
136
+ } else if (len >= 2) {
137
+ size = 2;
138
+ } else {
139
+ size = 1;
140
+ }
70
+ }
141
+
71
+ return a;
142
+ g_test_message("receiving %u bytes", size);
143
+ /* Write op */
144
+ rv = write(fd, &op, 1);
145
+ g_assert_cmpint(rv, ==, 1);
146
+ /* Write offset */
147
+ rv = write(fd, (uint8_t *)&offset, sizeof(uint64_t));
148
+ g_assert_cmpint(rv, ==, sizeof(uint64_t));
149
+ /* Write size */
150
+ g_assert_cmpint(write(fd, &size, 1), ==, 1);
151
+
152
+ /* Read data and Expect response */
153
+ code = read_response(buf, size);
154
+ g_assert_cmphex(code, ==, CODE_OK);
155
+
156
+ buf += size;
157
+ offset += size;
158
+ len -= size;
159
+ }
72
+ }
160
+}
73
+}
161
+
74
+
162
+static void send_data(uint64_t offset, const uint8_t *buf, size_t len)
75
/*----------------------------------------------------------------------------
163
+{
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
164
+ uint8_t op = OP_WRITE;
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
165
+ uint8_t code;
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
166
+ ssize_t rv;
167
+
168
+ while (len > 0) {
169
+ uint8_t size;
170
+
171
+ if (len >= 8) {
172
+ size = 8;
173
+ } else if (len >= 4) {
174
+ size = 4;
175
+ } else if (len >= 2) {
176
+ size = 2;
177
+ } else {
178
+ size = 1;
179
+ }
180
+
181
+ g_test_message("sending %u bytes", size);
182
+ /* Write op */
183
+ rv = write(fd, &op, 1);
184
+ g_assert_cmpint(rv, ==, 1);
185
+ /* Write offset */
186
+ rv = write(fd, (uint8_t *)&offset, sizeof(uint64_t));
187
+ g_assert_cmpint(rv, ==, sizeof(uint64_t));
188
+ /* Write size */
189
+ g_assert_cmpint(write(fd, &size, 1), ==, 1);
190
+ /* Write data */
191
+ g_assert_cmpint(write(fd, buf, size), ==, size);
192
+
193
+ /* Expect response */
194
+ code = read_response(NULL, 0);
195
+ g_assert_cmphex(code, ==, CODE_OK);
196
+
197
+ buf += size;
198
+ offset += size;
199
+ len -= size;
200
+ }
201
+}
202
+
203
+static void test_invalid_op(void)
204
+{
205
+ uint8_t op = OP_INVALID;
206
+ uint8_t code;
207
+ uint8_t buf[1];
208
+
209
+ g_assert_cmpint(write(fd, &op, 1), ==, 1);
210
+ code = read_response(buf, 1);
211
+ g_assert_cmphex(code, ==, CODE_INVALID_OP);
212
+}
213
+
214
+/* Send data via chardev and read them in guest. */
215
+static void test_guest_read(void)
216
+{
217
+ const char *data = "Hello World!";
218
+ uint64_t offset = 0xa0;
219
+ char buf[100];
220
+ size_t len = strlen(data);
221
+
222
+ send_data(offset, (uint8_t *)data, len);
223
+ memread(PCI_MBOX_BA + offset, buf, len);
224
+ g_assert_cmpint(strncmp(data, buf, len), ==, 0);
225
+}
226
+
227
+/* Write data in guest and read out via chardev. */
228
+static void test_guest_write(void)
229
+{
230
+ const char *data = "Hello World!";
231
+ uint64_t offset = 0xa0;
232
+ char buf[100];
233
+ size_t len = strlen(data);
234
+
235
+ memwrite(PCI_MBOX_BA + offset, data, len);
236
+ receive_data(offset, (uint8_t *)buf, len);
237
+ g_assert_cmpint(strncmp(data, buf, len), ==, 0);
238
+}
239
+
240
+int main(int argc, char **argv)
241
+{
242
+ int ret;
243
+ int port;
244
+
245
+ g_test_init(&argc, &argv, NULL);
246
+ port = open_socket();
247
+ g_test_message("port=%d", port);
248
+ global_qtest = qtest_initf("-machine npcm750-evb "
249
+ "-chardev socket,id=npcm7xx-pcimbox-chr,host=localhost,"
250
+ "port=%d,reconnect=10 "
251
+ "-global driver=npcm7xx-pci-mbox,property=chardev,"
252
+ "value=npcm7xx-pcimbox-chr",
253
+ port);
254
+ setup_fd();
255
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
256
+
257
+ qtest_add_func("/npcm7xx_pci_mbox/invalid_op", test_invalid_op);
258
+ qtest_add_func("/npcm7xx_pci_mbox/read", test_guest_read);
259
+ qtest_add_func("/npcm7xx_pci_mbox/write", test_guest_write);
260
+ ret = g_test_run();
261
+ qtest_quit(global_qtest);
262
+
263
+ return ret;
264
+}
265
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
266
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
267
--- a/tests/qtest/meson.build
80
--- a/fpu/softfloat-specialize.c.inc
268
+++ b/tests/qtest/meson.build
81
+++ b/fpu/softfloat-specialize.c.inc
269
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
270
qtests_npcm7xx = \
83
return a;
271
['npcm7xx_adc-test',
84
}
272
'npcm7xx_gpio-test',
85
273
+ 'npcm7xx_pci_mbox-test',
86
-/*----------------------------------------------------------------------------
274
'npcm7xx_pwm-test',
87
-| Takes two extended double-precision floating-point values `a' and `b', one
275
'npcm7xx_rng-test',
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
276
'npcm7xx_sdhci-test',
89
-| `b' is a signaling NaN, the invalid exception is raised.
90
-*----------------------------------------------------------------------------*/
91
-
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
93
-{
94
- bool aIsLargerSignificand;
95
- FloatClass a_cls, b_cls;
96
-
97
- /* This is not complete, but is good enough for pickNaN. */
98
- a_cls = (!floatx80_is_any_nan(a)
99
- ? float_class_normal
100
- : floatx80_is_signaling_nan(a, status)
101
- ? float_class_snan
102
- : float_class_qnan);
103
- b_cls = (!floatx80_is_any_nan(b)
104
- ? float_class_normal
105
- : floatx80_is_signaling_nan(b, status)
106
- ? float_class_snan
107
- : float_class_qnan);
108
-
109
- if (is_snan(a_cls) || is_snan(b_cls)) {
110
- float_raise(float_flag_invalid, status);
111
- }
112
-
113
- if (status->default_nan_mode) {
114
- return floatx80_default_nan(status);
115
- }
116
-
117
- if (a.low < b.low) {
118
- aIsLargerSignificand = 0;
119
- } else if (b.low < a.low) {
120
- aIsLargerSignificand = 1;
121
- } else {
122
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
123
- }
124
-
125
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
126
- if (is_snan(b_cls)) {
127
- return floatx80_silence_nan(b, status);
128
- }
129
- return b;
130
- } else {
131
- if (is_snan(a_cls)) {
132
- return floatx80_silence_nan(a, status);
133
- }
134
- return a;
135
- }
136
-}
137
-
138
/*----------------------------------------------------------------------------
139
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
140
| NaN; otherwise returns 0.
277
--
141
--
278
2.34.1
142
2.34.1
diff view generated by jsdifflib
1
This patch wires the PCI mailbox module to Nuvoton SoC.
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Change-Id: I14c42c628258804030f0583889882842bde0d972
3
Unpacking and repacking the parts may be slightly more work
4
Signed-off-by: Hao Wu <wuhaotsh@google.com>
4
than we did before, but we get to reuse more code. For a
5
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
5
code path handling exceptional values, this is an improvement.
6
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
6
7
Message-id: 20240110234232.4116804-3-nabihestefan@google.com
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
[PMM: moved some changes incorrectly in previous patch into this one]
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
docs/system/arm/nuvoton.rst | 2 ++
12
fpu/softfloat.c | 43 +++++--------------------------------------
13
include/hw/arm/npcm7xx.h | 2 ++
13
1 file changed, 5 insertions(+), 38 deletions(-)
14
hw/arm/npcm7xx.c | 17 ++++++++++++++++-
15
3 files changed, 20 insertions(+), 1 deletion(-)
16
14
17
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/system/arm/nuvoton.rst
17
--- a/fpu/softfloat.c
20
+++ b/docs/system/arm/nuvoton.rst
18
+++ b/fpu/softfloat.c
21
@@ -XXX,XX +XXX,XX @@ Supported devices
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
22
* Ethernet controller (EMC)
20
23
* Tachometer
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
24
* Peripheral SPI controller (PSPI)
22
{
25
+ * BIOS POST code FIFO
23
- bool aIsLargerSignificand;
26
+ * PCI Mailbox
24
- FloatClass a_cls, b_cls;
27
25
+ FloatParts128 pa, pb, *pr;
28
Missing devices
26
29
---------------
27
- /* This is not complete, but is good enough for pickNaN. */
30
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
28
- a_cls = (!floatx80_is_any_nan(a)
31
index XXXXXXX..XXXXXXX 100644
29
- ? float_class_normal
32
--- a/include/hw/arm/npcm7xx.h
30
- : floatx80_is_signaling_nan(a, status)
33
+++ b/include/hw/arm/npcm7xx.h
31
- ? float_class_snan
34
@@ -XXX,XX +XXX,XX @@
32
- : float_class_qnan);
35
#include "hw/misc/npcm7xx_clk.h"
33
- b_cls = (!floatx80_is_any_nan(b)
36
#include "hw/misc/npcm7xx_gcr.h"
34
- ? float_class_normal
37
#include "hw/misc/npcm7xx_mft.h"
35
- : floatx80_is_signaling_nan(b, status)
38
+#include "hw/misc/npcm7xx_pci_mbox.h"
36
- ? float_class_snan
39
#include "hw/misc/npcm7xx_pwm.h"
37
- : float_class_qnan);
40
#include "hw/misc/npcm7xx_rng.h"
38
-
41
#include "hw/net/npcm7xx_emc.h"
39
- if (is_snan(a_cls) || is_snan(b_cls)) {
42
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxState {
40
- float_raise(float_flag_invalid, status);
43
OHCISysBusState ohci;
41
- }
44
NPCM7xxFIUState fiu[2];
42
-
45
NPCM7xxEMCState emc[2];
43
- if (status->default_nan_mode) {
46
+ NPCM7xxPCIMBoxState pci_mbox;
44
+ if (!floatx80_unpack_canonical(&pa, a, status) ||
47
NPCM7xxSDHCIState mmc;
45
+ !floatx80_unpack_canonical(&pb, b, status)) {
48
NPCMPSPIState pspi[2];
46
return floatx80_default_nan(status);
49
};
50
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/arm/npcm7xx.c
53
+++ b/hw/arm/npcm7xx.c
54
@@ -XXX,XX +XXX,XX @@
55
/* ADC Module */
56
#define NPCM7XX_ADC_BA (0xf000c000)
57
58
+/* PCI Mailbox Module */
59
+#define NPCM7XX_PCI_MBOX_BA (0xf0848000)
60
+
61
/* Internal AHB SRAM */
62
#define NPCM7XX_RAM3_BA (0xc0008000)
63
#define NPCM7XX_RAM3_SZ (4 * KiB)
64
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
65
NPCM7XX_UART1_IRQ,
66
NPCM7XX_UART2_IRQ,
67
NPCM7XX_UART3_IRQ,
68
+ NPCM7XX_PCI_MBOX_IRQ = 8,
69
+ NPCM7XX_KCS_HIB_IRQ = 9,
70
+ NPCM7XX_GMAC1_IRQ = 14,
71
NPCM7XX_EMC1RX_IRQ = 15,
72
NPCM7XX_EMC1TX_IRQ,
73
NPCM7XX_MMC_IRQ = 26,
74
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
75
object_initialize_child(obj, "pspi[*]", &s->pspi[i], TYPE_NPCM_PSPI);
76
}
47
}
77
48
78
+ object_initialize_child(obj, "pci-mbox", &s->pci_mbox,
49
- if (a.low < b.low) {
79
+ TYPE_NPCM7XX_PCI_MBOX);
50
- aIsLargerSignificand = 0;
80
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
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);
81
}
70
}
82
71
83
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
72
/*----------------------------------------------------------------------------
84
}
85
}
86
87
+ /* PCI Mailbox. Cannot fail */
88
+ sysbus_realize(SYS_BUS_DEVICE(&s->pci_mbox), &error_abort);
89
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pci_mbox), 0, NPCM7XX_PCI_MBOX_BA);
90
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pci_mbox), 1,
91
+ NPCM7XX_PCI_MBOX_BA + NPCM7XX_PCI_MBOX_RAM_SIZE);
92
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pci_mbox), 0,
93
+ npcm7xx_irq(s, NPCM7XX_PCI_MBOX_IRQ));
94
+
95
/* RAM2 (SRAM) */
96
memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
97
NPCM7XX_RAM2_SZ, &error_abort);
98
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
99
create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
100
create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
101
create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
102
- create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
103
create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
104
create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);
105
create_unimplemented_device("npcm7xx.sha", 0xf085a000, 4 * KiB);
106
--
73
--
107
2.34.1
74
2.34.1
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The PCI Mailbox Module is a high-bandwidth communcation module
3
Inline pickNaN into its only caller. This makes one assert
4
between a Nuvoton BMC and CPU. It features 16KB RAM that are both
4
redundant with the immediately preceding IF.
5
accessible by the BMC and core CPU. and supports interrupt for
5
6
both sides.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
This patch implements the BMC side of the PCI mailbox module.
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
9
Communication with the core CPU is emulated via a chardev and
10
will be in a follow-up patch.
11
12
Change-Id: Iaca22f81c4526927d437aa367079ed038faf43f2
13
Signed-off-by: Hao Wu <wuhaotsh@google.com>
14
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
15
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
16
Message-id: 20240110234232.4116804-2-nabihestefan@google.com
17
[PMM: Moved some changes that should have been in the following commit]
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
---
10
---
21
include/hw/misc/npcm7xx_pci_mbox.h | 81 ++++++++
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
22
hw/misc/npcm7xx_pci_mbox.c | 324 +++++++++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
23
hw/misc/meson.build | 1 +
13
2 files changed, 73 insertions(+), 105 deletions(-)
24
hw/misc/trace-events | 5 +
14
25
4 files changed, 411 insertions(+)
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
26
create mode 100644 include/hw/misc/npcm7xx_pci_mbox.h
16
index XXXXXXX..XXXXXXX 100644
27
create mode 100644 hw/misc/npcm7xx_pci_mbox.c
17
--- a/fpu/softfloat-parts.c.inc
28
18
+++ b/fpu/softfloat-parts.c.inc
29
diff --git a/include/hw/misc/npcm7xx_pci_mbox.h b/include/hw/misc/npcm7xx_pci_mbox.h
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
30
new file mode 100644
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
31
index XXXXXXX..XXXXXXX
21
float_status *s)
32
--- /dev/null
22
{
33
+++ b/include/hw/misc/npcm7xx_pci_mbox.h
23
+ int cmp, which;
34
@@ -XXX,XX +XXX,XX @@
35
+/*
36
+ * Nuvoton NPCM7xx PCI Mailbox Module
37
+ *
38
+ * Copyright 2021 Google LLC
39
+ *
40
+ * This program is free software; you can redistribute it and/or modify it
41
+ * under the terms of the GNU General Public License as published by the
42
+ * Free Software Foundation; either version 2 of the License, or
43
+ * (at your option) any later version.
44
+ *
45
+ * This program is distributed in the hope that it will be useful, but WITHOUT
46
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
47
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
48
+ * for more details.
49
+ */
50
+#ifndef NPCM7XX_PCI_MBOX_H
51
+#define NPCM7XX_PCI_MBOX_H
52
+
24
+
53
+#include "chardev/char-fe.h"
25
if (is_snan(a->cls) || is_snan(b->cls)) {
54
+#include "exec/memory.h"
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
55
+#include "hw/clock.h"
27
}
56
+#include "hw/irq.h"
28
57
+#include "hw/pci/pci.h"
29
if (s->default_nan_mode) {
58
+#include "hw/sysbus.h"
30
parts_default_nan(a, s);
59
+#include "qom/object.h"
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
+ }
60
+
46
+
61
+#define NPCM7XX_PCI_MBOX_RAM_SIZE 0x4000
47
+ switch (s->float_2nan_prop_rule) {
62
+
48
+ case float_2nan_prop_s_ab:
63
+#define NPCM7XX_PCI_VENDOR_ID 0x1050
49
if (is_snan(a->cls)) {
64
+#define NPCM7XX_PCI_DEVICE_ID 0x0750
50
- parts_silence_nan(a, s);
65
+#define NPCM7XX_PCI_REVISION 0
51
+ which = 0;
66
+#define NPCM7XX_PCI_CLASS_CODE 0xff
52
+ } else if (is_snan(b->cls)) {
67
+
53
+ which = 1;
68
+typedef enum NPCM7xxPCIMBoxHostState {
54
+ } else if (is_qnan(a->cls)) {
69
+ NPCM7XX_PCI_MBOX_STATE_IDLE,
55
+ which = 0;
70
+ NPCM7XX_PCI_MBOX_STATE_OFFSET,
56
+ } else {
71
+ NPCM7XX_PCI_MBOX_STATE_SIZE,
57
+ which = 1;
72
+ NPCM7XX_PCI_MBOX_STATE_DATA,
58
}
73
+} NPCM7xxPCIMBoxHostState ;
59
+ break;
74
+
60
+ case float_2nan_prop_s_ba:
75
+/*
61
+ if (is_snan(b->cls)) {
76
+ * Maximum amount of control registers in PCI Mailbox module. Do not increase
62
+ which = 1;
77
+ * this value without bumping vm version.
63
+ } else if (is_snan(a->cls)) {
78
+ */
64
+ which = 0;
79
+#define NPCM7XX_PCI_MBOX_NR_REGS 3
65
+ } else if (is_qnan(b->cls)) {
80
+
66
+ which = 1;
81
+/**
67
+ } else {
82
+ * struct NPCM7xxPciMboxState - PCI Mailbox Device
68
+ which = 0;
83
+ * @parent: System bus device.
84
+ * @ram: the mailbox RAM memory space
85
+ * @iomem: Memory region through which registers are accessed.
86
+ * @content: The content of the PCI mailbox, initialized to 0.
87
+ * @regs: The MMIO registers.
88
+ * @chr: The chardev backend used to communicate with core CPU.
89
+ * @offset: The offset to start transfer.
90
+ */
91
+typedef struct NPCM7xxPCIMBoxState {
92
+ SysBusDevice parent;
93
+
94
+ MemoryRegion ram;
95
+ MemoryRegion iomem;
96
+
97
+ qemu_irq irq;
98
+ uint8_t content[NPCM7XX_PCI_MBOX_RAM_SIZE];
99
+ uint32_t regs[NPCM7XX_PCI_MBOX_NR_REGS];
100
+ CharBackend chr;
101
+
102
+ /* aux data for receiving host commands. */
103
+ NPCM7xxPCIMBoxHostState state;
104
+ uint8_t op;
105
+ hwaddr offset;
106
+ uint8_t size;
107
+ uint64_t data;
108
+ int receive_count;
109
+} NPCM7xxPCIMBoxState;
110
+
111
+#define TYPE_NPCM7XX_PCI_MBOX "npcm7xx-pci-mbox"
112
+#define NPCM7XX_PCI_MBOX(obj) \
113
+ OBJECT_CHECK(NPCM7xxPCIMBoxState, (obj), TYPE_NPCM7XX_PCI_MBOX)
114
+
115
+#endif /* NPCM7XX_PCI_MBOX_H */
116
diff --git a/hw/misc/npcm7xx_pci_mbox.c b/hw/misc/npcm7xx_pci_mbox.c
117
new file mode 100644
118
index XXXXXXX..XXXXXXX
119
--- /dev/null
120
+++ b/hw/misc/npcm7xx_pci_mbox.c
121
@@ -XXX,XX +XXX,XX @@
122
+/*
123
+ * Nuvoton NPCM7xx PCI Mailbox Module
124
+ *
125
+ * Copyright 2021 Google LLC
126
+ *
127
+ * This program is free software; you can redistribute it and/or modify it
128
+ * under the terms of the GNU General Public License as published by the
129
+ * Free Software Foundation; either version 2 of the License, or
130
+ * (at your option) any later version.
131
+ *
132
+ * This program is distributed in the hope that it will be useful, but WITHOUT
133
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
134
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
135
+ * for more details.
136
+ */
137
+
138
+#include "qemu/osdep.h"
139
+#include "chardev/char-fe.h"
140
+#include "hw/irq.h"
141
+#include "hw/qdev-clock.h"
142
+#include "hw/qdev-properties-system.h"
143
+#include "hw/misc/npcm7xx_pci_mbox.h"
144
+#include "hw/registerfields.h"
145
+#include "migration/vmstate.h"
146
+#include "qapi/error.h"
147
+#include "qapi/visitor.h"
148
+#include "qemu/bitops.h"
149
+#include "qemu/error-report.h"
150
+#include "qemu/log.h"
151
+#include "qemu/module.h"
152
+#include "qemu/timer.h"
153
+#include "qemu/units.h"
154
+#include "trace.h"
155
+
156
+REG32(NPCM7XX_PCI_MBOX_BMBXSTAT, 0x00);
157
+REG32(NPCM7XX_PCI_MBOX_BMBXCTL, 0x04);
158
+REG32(NPCM7XX_PCI_MBOX_BMBXCMD, 0x08);
159
+
160
+enum NPCM7xxPCIMBoxOperation {
161
+ NPCM7XX_PCI_MBOX_OP_READ = 1,
162
+ NPCM7XX_PCI_MBOX_OP_WRITE,
163
+};
164
+
165
+#define NPCM7XX_PCI_MBOX_OFFSET_BYTES 8
166
+
167
+/* Response code */
168
+#define NPCM7XX_PCI_MBOX_OK 0
169
+#define NPCM7XX_PCI_MBOX_INVALID_OP 0xa0
170
+#define NPCM7XX_PCI_MBOX_INVALID_SIZE 0xa1
171
+#define NPCM7XX_PCI_MBOX_UNSPECIFIED_ERROR 0xff
172
+
173
+#define NPCM7XX_PCI_MBOX_NR_CI 8
174
+#define NPCM7XX_PCI_MBOX_CI_MASK MAKE_64BIT_MASK(0, NPCM7XX_PCI_MBOX_NR_CI)
175
+
176
+static void npcm7xx_pci_mbox_update_irq(NPCM7xxPCIMBoxState *s)
177
+{
178
+ /* We should send an interrupt when one of the CIE and CIF are both 1. */
179
+ if (s->regs[R_NPCM7XX_PCI_MBOX_BMBXSTAT] &
180
+ s->regs[R_NPCM7XX_PCI_MBOX_BMBXCTL] &
181
+ NPCM7XX_PCI_MBOX_CI_MASK) {
182
+ qemu_irq_raise(s->irq);
183
+ trace_npcm7xx_pci_mbox_irq(1);
184
+ } else {
185
+ qemu_irq_lower(s->irq);
186
+ trace_npcm7xx_pci_mbox_irq(0);
187
+ }
188
+}
189
+
190
+static void npcm7xx_pci_mbox_send_response(NPCM7xxPCIMBoxState *s, uint8_t code)
191
+{
192
+ qemu_chr_fe_write(&s->chr, &code, 1);
193
+ if (code == NPCM7XX_PCI_MBOX_OK && s->op == NPCM7XX_PCI_MBOX_OP_READ) {
194
+ qemu_chr_fe_write(&s->chr, (uint8_t *)(&s->data), s->size);
195
+ }
196
+}
197
+
198
+static void npcm7xx_pci_mbox_handle_read(NPCM7xxPCIMBoxState *s)
199
+{
200
+ MemTxResult r = memory_region_dispatch_read(
201
+ &s->ram, s->offset, &s->data, MO_LE | size_memop(s->size),
202
+ MEMTXATTRS_UNSPECIFIED);
203
+
204
+ npcm7xx_pci_mbox_send_response(s, (uint8_t)r);
205
+}
206
+
207
+static void npcm7xx_pci_mbox_handle_write(NPCM7xxPCIMBoxState *s)
208
+{
209
+ MemTxResult r = memory_region_dispatch_write(
210
+ &s->ram, s->offset, s->data, MO_LE | size_memop(s->size),
211
+ MEMTXATTRS_UNSPECIFIED);
212
+
213
+ npcm7xx_pci_mbox_send_response(s, (uint8_t)r);
214
+}
215
+
216
+static void npcm7xx_pci_mbox_receive_char(NPCM7xxPCIMBoxState *s, uint8_t byte)
217
+{
218
+ switch (s->state) {
219
+ case NPCM7XX_PCI_MBOX_STATE_IDLE:
220
+ switch (byte) {
221
+ case NPCM7XX_PCI_MBOX_OP_READ:
222
+ case NPCM7XX_PCI_MBOX_OP_WRITE:
223
+ s->op = byte;
224
+ s->state = NPCM7XX_PCI_MBOX_STATE_OFFSET;
225
+ s->offset = 0;
226
+ s->receive_count = 0;
227
+ break;
228
+
229
+ default:
230
+ qemu_log_mask(LOG_GUEST_ERROR,
231
+ "received invalid op type: 0x%" PRIx8, byte);
232
+ npcm7xx_pci_mbox_send_response(s, NPCM7XX_PCI_MBOX_INVALID_OP);
233
+ break;
234
+ }
69
+ }
235
+ break;
70
+ break;
236
+
71
+ case float_2nan_prop_ab:
237
+ case NPCM7XX_PCI_MBOX_STATE_OFFSET:
72
+ which = is_nan(a->cls) ? 0 : 1;
238
+ s->offset += (uint64_t)byte << (s->receive_count * BITS_PER_BYTE);
73
+ break;
239
+ if (++s->receive_count >= NPCM7XX_PCI_MBOX_OFFSET_BYTES) {
74
+ case float_2nan_prop_ba:
240
+ s->state = NPCM7XX_PCI_MBOX_STATE_SIZE;
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;
241
+ }
103
+ }
242
+ break;
104
+ break;
243
+
244
+ case NPCM7XX_PCI_MBOX_STATE_SIZE:
245
+ s->size = byte;
246
+ if (s->size < 1 || s->size > sizeof(uint64_t)) {
247
+ qemu_log_mask(LOG_GUEST_ERROR, "received invalid size: %u", byte);
248
+ npcm7xx_pci_mbox_send_response(s, NPCM7XX_PCI_MBOX_INVALID_SIZE);
249
+ s->state = NPCM7XX_PCI_MBOX_STATE_IDLE;
250
+ break;
251
+ }
252
+ if (s->op == NPCM7XX_PCI_MBOX_OP_READ) {
253
+ npcm7xx_pci_mbox_handle_read(s);
254
+ s->state = NPCM7XX_PCI_MBOX_STATE_IDLE;
255
+ } else {
256
+ s->receive_count = 0;
257
+ s->data = 0;
258
+ s->state = NPCM7XX_PCI_MBOX_STATE_DATA;
259
+ }
260
+ break;
261
+
262
+ case NPCM7XX_PCI_MBOX_STATE_DATA:
263
+ g_assert(s->op == NPCM7XX_PCI_MBOX_OP_WRITE);
264
+ s->data += (uint64_t)byte << (s->receive_count * BITS_PER_BYTE);
265
+ if (++s->receive_count >= s->size) {
266
+ npcm7xx_pci_mbox_handle_write(s);
267
+ s->state = NPCM7XX_PCI_MBOX_STATE_IDLE;
268
+ }
269
+ break;
270
+
271
+ default:
105
+ default:
272
+ g_assert_not_reached();
106
+ g_assert_not_reached();
273
+ }
107
+ }
274
+}
275
+
108
+
276
+static uint64_t npcm7xx_pci_mbox_read(void *opaque, hwaddr offset,
109
+ if (which) {
277
+ unsigned size)
110
+ a = b;
278
+{
111
+ }
279
+ NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(opaque);
112
+ if (is_snan(a->cls)) {
280
+ uint16_t value = 0;
113
+ parts_silence_nan(a, s);
281
+
114
}
282
+ if (offset / sizeof(uint32_t) >= NPCM7XX_PCI_MBOX_NR_REGS) {
115
return a;
283
+ qemu_log_mask(LOG_GUEST_ERROR,
116
}
284
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
117
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
285
+ __func__, offset);
286
+ return 0;
287
+ }
288
+
289
+ value = s->regs[offset / sizeof(uint32_t)];
290
+ trace_npcm7xx_pci_mbox_read(DEVICE(s)->canonical_path, offset, value, size);
291
+ return value;
292
+}
293
+
294
+static void npcm7xx_pci_mbox_write(void *opaque, hwaddr offset,
295
+ uint64_t v, unsigned size)
296
+{
297
+ NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(opaque);
298
+
299
+ trace_npcm7xx_pci_mbox_write(DEVICE(s)->canonical_path, offset, v, size);
300
+ switch (offset) {
301
+ case A_NPCM7XX_PCI_MBOX_BMBXSTAT:
302
+ /* Clear bits that are 1. */
303
+ s->regs[R_NPCM7XX_PCI_MBOX_BMBXSTAT] &= ~v;
304
+ break;
305
+
306
+ case A_NPCM7XX_PCI_MBOX_BMBXCTL:
307
+ s->regs[R_NPCM7XX_PCI_MBOX_BMBXCTL] = v;
308
+ break;
309
+
310
+ case A_NPCM7XX_PCI_MBOX_BMBXCMD:
311
+ /* Set the bits that are 1. */
312
+ s->regs[R_NPCM7XX_PCI_MBOX_BMBXCMD] |= v;
313
+ /* TODO: Set interrupt to host. */
314
+ break;
315
+
316
+ default:
317
+ qemu_log_mask(LOG_GUEST_ERROR,
318
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
319
+ __func__, offset);
320
+ }
321
+ npcm7xx_pci_mbox_update_irq(s);
322
+}
323
+
324
+static const struct MemoryRegionOps npcm7xx_pci_mbox_ops = {
325
+ .read = npcm7xx_pci_mbox_read,
326
+ .write = npcm7xx_pci_mbox_write,
327
+ .endianness = DEVICE_LITTLE_ENDIAN,
328
+ .valid = {
329
+ .min_access_size = 4,
330
+ .max_access_size = 4,
331
+ .unaligned = false,
332
+ },
333
+};
334
+
335
+static void npcm7xx_pci_mbox_enter_reset(Object *obj, ResetType type)
336
+{
337
+ NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(obj);
338
+
339
+ memset(s->regs, 0, 4 * NPCM7XX_PCI_MBOX_NR_REGS);
340
+ s->state = NPCM7XX_PCI_MBOX_STATE_IDLE;
341
+ s->receive_count = 0;
342
+}
343
+
344
+static void npcm7xx_pci_mbox_hold_reset(Object *obj)
345
+{
346
+ NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(obj);
347
+
348
+ qemu_irq_lower(s->irq);
349
+}
350
+
351
+static int can_receive(void *opaque)
352
+{
353
+ return 1;
354
+}
355
+
356
+static void receive(void *opaque, const uint8_t *buf, int size)
357
+{
358
+ NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(opaque);
359
+ int i;
360
+
361
+ for (i = 0; i < size; ++i) {
362
+ npcm7xx_pci_mbox_receive_char(s, buf[i]);
363
+ }
364
+}
365
+
366
+static void chr_event(void *opaque, QEMUChrEvent event)
367
+{
368
+ switch (event) {
369
+ case CHR_EVENT_OPENED:
370
+ case CHR_EVENT_CLOSED:
371
+ case CHR_EVENT_BREAK:
372
+ case CHR_EVENT_MUX_IN:
373
+ case CHR_EVENT_MUX_OUT:
374
+ /* Ignore */
375
+ break;
376
+
377
+ default:
378
+ g_assert_not_reached();
379
+ }
380
+}
381
+
382
+static void npcm7xx_pci_mbox_init(Object *obj)
383
+{
384
+ NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(obj);
385
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
386
+
387
+ memory_region_init_ram_device_ptr(&s->ram, obj, "pci-mbox-ram",
388
+ NPCM7XX_PCI_MBOX_RAM_SIZE, s->content);
389
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_pci_mbox_ops, s,
390
+ "pci-mbox-iomem", 4 * KiB);
391
+ sysbus_init_mmio(sbd, &s->ram);
392
+ sysbus_init_mmio(sbd, &s->iomem);
393
+ sysbus_init_irq(sbd, &s->irq);
394
+}
395
+
396
+static void npcm7xx_pci_mbox_realize(DeviceState *dev, Error **errp)
397
+{
398
+ NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(dev);
399
+
400
+ qemu_chr_fe_set_handlers(&s->chr, can_receive, receive,
401
+ chr_event, NULL, OBJECT(dev), NULL, true);
402
+}
403
+
404
+static const VMStateDescription vmstate_npcm7xx_pci_mbox = {
405
+ .name = "npcm7xx-pci-mbox-module",
406
+ .version_id = 0,
407
+ .minimum_version_id = 0,
408
+ .fields = (VMStateField[]) {
409
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxPCIMBoxState,
410
+ NPCM7XX_PCI_MBOX_NR_REGS),
411
+ VMSTATE_END_OF_LIST(),
412
+ },
413
+};
414
+
415
+static Property npcm7xx_pci_mbox_properties[] = {
416
+ DEFINE_PROP_CHR("chardev", NPCM7xxPCIMBoxState, chr),
417
+ DEFINE_PROP_END_OF_LIST(),
418
+};
419
+
420
+static void npcm7xx_pci_mbox_class_init(ObjectClass *klass, void *data)
421
+{
422
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
423
+ DeviceClass *dc = DEVICE_CLASS(klass);
424
+
425
+ dc->desc = "NPCM7xx PCI Mailbox Controller";
426
+ dc->vmsd = &vmstate_npcm7xx_pci_mbox;
427
+ dc->realize = npcm7xx_pci_mbox_realize;
428
+ rc->phases.enter = npcm7xx_pci_mbox_enter_reset;
429
+ rc->phases.hold = npcm7xx_pci_mbox_hold_reset;
430
+ device_class_set_props(dc, npcm7xx_pci_mbox_properties);
431
+}
432
+
433
+static const TypeInfo npcm7xx_pci_mbox_info = {
434
+ .name = TYPE_NPCM7XX_PCI_MBOX,
435
+ .parent = TYPE_SYS_BUS_DEVICE,
436
+ .instance_size = sizeof(NPCM7xxPCIMBoxState),
437
+ .class_init = npcm7xx_pci_mbox_class_init,
438
+ .instance_init = npcm7xx_pci_mbox_init,
439
+};
440
+
441
+static void npcm7xx_pci_mbox_register_type(void)
442
+{
443
+ type_register_static(&npcm7xx_pci_mbox_info);
444
+}
445
+type_init(npcm7xx_pci_mbox_register_type);
446
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
447
index XXXXXXX..XXXXXXX 100644
118
index XXXXXXX..XXXXXXX 100644
448
--- a/hw/misc/meson.build
119
--- a/fpu/softfloat-specialize.c.inc
449
+++ b/hw/misc/meson.build
120
+++ b/fpu/softfloat-specialize.c.inc
450
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
451
'npcm7xx_clk.c',
122
}
452
'npcm7xx_gcr.c',
123
}
453
'npcm7xx_mft.c',
124
454
+ 'npcm7xx_pci_mbox.c',
125
-/*----------------------------------------------------------------------------
455
'npcm7xx_pwm.c',
126
-| Select which NaN to propagate for a two-input operation.
456
'npcm7xx_rng.c',
127
-| IEEE754 doesn't specify all the details of this, so the
457
))
128
-| algorithm is target-specific.
458
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
129
-| The routine is passed various bits of information about the
459
index XXXXXXX..XXXXXXX 100644
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
460
--- a/hw/misc/trace-events
131
-| Note that signalling NaNs are always squashed to quiet NaNs
461
+++ b/hw/misc/trace-events
132
-| by the caller, by calling floatXX_silence_nan() before
462
@@ -XXX,XX +XXX,XX @@ npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0
133
-| returning them.
463
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"
134
-|
464
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"
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
465
136
-| of some kind, and is true if a has the larger significand,
466
+# npcm7xx_pci_mbox.c
137
-| or if both a and b have the same significand but a is
467
+npcm7xx_pci_mbox_read(const char *id, uint64_t offset, uint64_t value, unsigned size) "%s offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
138
-| positive but b is negative. It is only needed for the x87
468
+npcm7xx_pci_mbox_write(const char *id, uint64_t offset, uint64_t value, unsigned size) "%s offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
139
-| tie-break rule.
469
+npcm7xx_pci_mbox_irq(int irq_level) "irq level: %d"
140
-*----------------------------------------------------------------------------*/
470
+
141
-
471
# stm32f4xx_syscfg.c
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
472
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interrupt: GPIO: %d, Line: %d; Level: %d"
143
- bool aIsLargerSignificand, float_status *status)
473
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
144
-{
145
- /*
146
- * We guarantee not to require the target to tell us how to
147
- * pick a NaN if we're always returning the default NaN.
148
- * But if we're not in default-NaN mode then the target must
149
- * specify via set_float_2nan_prop_rule().
150
- */
151
- assert(!status->default_nan_mode);
152
-
153
- switch (status->float_2nan_prop_rule) {
154
- case float_2nan_prop_s_ab:
155
- if (is_snan(a_cls)) {
156
- return 0;
157
- } else if (is_snan(b_cls)) {
158
- return 1;
159
- } else if (is_qnan(a_cls)) {
160
- return 0;
161
- } else {
162
- return 1;
163
- }
164
- break;
165
- case float_2nan_prop_s_ba:
166
- if (is_snan(b_cls)) {
167
- return 1;
168
- } else if (is_snan(a_cls)) {
169
- return 0;
170
- } else if (is_qnan(b_cls)) {
171
- return 1;
172
- } else {
173
- return 0;
174
- }
175
- break;
176
- case float_2nan_prop_ab:
177
- if (is_nan(a_cls)) {
178
- return 0;
179
- } else {
180
- return 1;
181
- }
182
- break;
183
- case float_2nan_prop_ba:
184
- if (is_nan(b_cls)) {
185
- return 1;
186
- } else {
187
- return 0;
188
- }
189
- break;
190
- case float_2nan_prop_x87:
191
- /*
192
- * This implements x87 NaN propagation rules:
193
- * SNaN + QNaN => return the QNaN
194
- * two SNaNs => return the one with the larger significand, silenced
195
- * two QNaNs => return the one with the larger significand
196
- * SNaN and a non-NaN => return the SNaN, silenced
197
- * QNaN and a non-NaN => return the QNaN
198
- *
199
- * If we get down to comparing significands and they are the same,
200
- * return the NaN with the positive sign bit (if any).
201
- */
202
- if (is_snan(a_cls)) {
203
- if (is_snan(b_cls)) {
204
- return aIsLargerSignificand ? 0 : 1;
205
- }
206
- return is_qnan(b_cls) ? 1 : 0;
207
- } else if (is_qnan(a_cls)) {
208
- if (is_snan(b_cls) || !is_qnan(b_cls)) {
209
- return 0;
210
- } else {
211
- return aIsLargerSignificand ? 0 : 1;
212
- }
213
- } else {
214
- return 1;
215
- }
216
- default:
217
- g_assert_not_reached();
218
- }
219
-}
220
-
221
/*----------------------------------------------------------------------------
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
223
| NaN; otherwise returns 0.
474
--
224
--
475
2.34.1
225
2.34.1
226
227
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Remember if there was an SNaN, and use that to simplify
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.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
15
1 file changed, 12 insertions(+), 20 deletions(-)
16
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
index XXXXXXX..XXXXXXX 100644
19
--- a/fpu/softfloat-parts.c.inc
20
+++ b/fpu/softfloat-parts.c.inc
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
23
float_status *s)
24
{
25
+ bool have_snan = false;
26
int cmp, which;
27
28
if (is_snan(a->cls) || is_snan(b->cls)) {
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
30
+ have_snan = true;
31
}
32
33
if (s->default_nan_mode) {
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
35
36
switch (s->float_2nan_prop_rule) {
37
case float_2nan_prop_s_ab:
38
- if (is_snan(a->cls)) {
39
- which = 0;
40
- } else if (is_snan(b->cls)) {
41
- which = 1;
42
- } else if (is_qnan(a->cls)) {
43
- which = 0;
44
- } else {
45
- which = 1;
46
+ if (have_snan) {
47
+ which = is_snan(a->cls) ? 0 : 1;
48
+ break;
49
}
50
- break;
51
- case float_2nan_prop_s_ba:
52
- if (is_snan(b->cls)) {
53
- which = 1;
54
- } else if (is_snan(a->cls)) {
55
- which = 0;
56
- } else if (is_qnan(b->cls)) {
57
- which = 1;
58
- } else {
59
- which = 0;
60
- }
61
- break;
62
+ /* fall through */
63
case float_2nan_prop_ab:
64
which = is_nan(a->cls) ? 0 : 1;
65
break;
66
+ case float_2nan_prop_s_ba:
67
+ if (have_snan) {
68
+ which = is_snan(b->cls) ? 1 : 0;
69
+ break;
70
+ }
71
+ /* fall through */
72
case float_2nan_prop_ba:
73
which = is_nan(b->cls) ? 1 : 0;
74
break;
75
--
76
2.34.1
diff view generated by jsdifflib
1
From: Gavin Shan <gshan@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
It's found that some of the CPU type names in the array of valid
3
Move the fractional comparison to the end of the
4
CPU types are invalid because their corresponding classes aren't
4
float_2nan_prop_x87 case. This is not required for
5
registered, as reported by Peter Maydell.
5
any other 2nan propagation rule. Reorganize the
6
x87 case itself to break out of the switch when the
7
fractional comparison is not required.
6
8
7
[gshan@gshan build]$ ./qemu-system-arm -machine virt -cpu cortex-a9
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
qemu-system-arm: Invalid CPU model: cortex-a9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
The valid models are: cortex-a7, cortex-a15, (null), (null), (null),
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
10
(null), (null), (null), (null), (null), (null), (null), (null), max
11
12
Fix it by consolidating the array of valid CPU types. After it's
13
applied, we have the following output when TCG is enabled.
14
15
[gshan@gshan build]$ ./qemu-system-arm -machine virt -cpu cortex-a9
16
qemu-system-arm: Invalid CPU model: cortex-a9
17
The valid models are: cortex-a7, cortex-a15, max
18
19
[gshan@gshan build]$ ./qemu-system-aarch64 -machine virt -cpu cortex-a9
20
qemu-system-aarch64: Invalid CPU model: cortex-a9
21
The valid models are: cortex-a7, cortex-a15, cortex-a35, cortex-a55,
22
cortex-a72, cortex-a76, cortex-a710, a64fx, neoverse-n1, neoverse-v1,
23
neoverse-n2, cortex-a53, cortex-a57, max
24
25
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2084
26
Reported-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Gavin Shan <gshan@redhat.com>
28
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
29
Message-id: 20240111051054.83304-1-gshan@redhat.com
30
Fixes: fa8c617791 ("hw/arm/virt: Check CPU type in machine_run_board_init()")
31
Signed-off-by: Gavin Shan <gshan@redhat.com>
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
---
13
---
34
hw/arm/virt.c | 8 ++++++--
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
35
1 file changed, 6 insertions(+), 2 deletions(-)
15
1 file changed, 9 insertions(+), 10 deletions(-)
36
16
37
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
38
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/virt.c
19
--- a/fpu/softfloat-parts.c.inc
40
+++ b/hw/arm/virt.c
20
+++ b/fpu/softfloat-parts.c.inc
41
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
42
#ifdef CONFIG_TCG
22
return a;
43
ARM_CPU_TYPE_NAME("cortex-a7"),
23
}
44
ARM_CPU_TYPE_NAME("cortex-a15"),
24
45
+#ifdef TARGET_AARCH64
25
- cmp = frac_cmp(a, b);
46
ARM_CPU_TYPE_NAME("cortex-a35"),
26
- if (cmp == 0) {
47
ARM_CPU_TYPE_NAME("cortex-a55"),
27
- cmp = a->sign < b->sign;
48
ARM_CPU_TYPE_NAME("cortex-a72"),
28
- }
49
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
29
-
50
ARM_CPU_TYPE_NAME("neoverse-n1"),
30
switch (s->float_2nan_prop_rule) {
51
ARM_CPU_TYPE_NAME("neoverse-v1"),
31
case float_2nan_prop_s_ab:
52
ARM_CPU_TYPE_NAME("neoverse-n2"),
32
if (have_snan) {
53
-#endif
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
54
+#endif /* TARGET_AARCH64 */
34
* return the NaN with the positive sign bit (if any).
55
+#endif /* CONFIG_TCG */
35
*/
56
+#ifdef TARGET_AARCH64
36
if (is_snan(a->cls)) {
57
ARM_CPU_TYPE_NAME("cortex-a53"),
37
- if (is_snan(b->cls)) {
58
ARM_CPU_TYPE_NAME("cortex-a57"),
38
- which = cmp > 0 ? 0 : 1;
59
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
39
- } else {
60
ARM_CPU_TYPE_NAME("host"),
40
+ if (!is_snan(b->cls)) {
61
-#endif
41
which = is_qnan(b->cls) ? 1 : 0;
62
+#endif /* CONFIG_KVM || CONFIG_HVF */
42
+ break;
63
+#endif /* TARGET_AARCH64 */
43
}
64
ARM_CPU_TYPE_NAME("max"),
44
} else if (is_qnan(a->cls)) {
65
NULL
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
66
};
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();
67
--
63
--
68
2.34.1
64
2.34.1
diff view generated by jsdifflib
1
Improve the 'highmem' option docs to note that by default we assume
1
From: Richard Henderson <richard.henderson@linaro.org>
2
that a 32-bit kernel on an LPAE-capable CPU has LPAE enabled, and
3
what the consequences are.
4
2
3
Replace the "index" selecting between A and B with a result variable
4
of the proper type. This improves clarity within the function.
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-12-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: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Eric Auger <eric.auger@redhat.com>
8
Message-id: 20240109170834.1387457-1-peter.maydell@linaro.org
9
---
10
---
10
docs/system/arm/virt.rst | 8 +++++++-
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
11
1 file changed, 7 insertions(+), 1 deletion(-)
12
1 file changed, 13 insertions(+), 15 deletions(-)
12
13
13
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/docs/system/arm/virt.rst
16
--- a/fpu/softfloat-parts.c.inc
16
+++ b/docs/system/arm/virt.rst
17
+++ b/fpu/softfloat-parts.c.inc
17
@@ -XXX,XX +XXX,XX @@ mte
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
18
highmem
19
float_status *s)
19
Set ``on``/``off`` to enable/disable placing devices and RAM in physical
20
{
20
address space above 32 bits. The default is ``on`` for machine types
21
bool have_snan = false;
21
- later than ``virt-2.12``.
22
- int cmp, which;
22
+ later than ``virt-2.12`` when the CPU supports an address space
23
+ FloatPartsN *ret;
23
+ bigger than 32 bits (i.e. 64-bit CPUs, and 32-bit CPUs with the
24
+ int cmp;
24
+ Large Physical Address Extension (LPAE) feature). If you want to
25
25
+ boot a 32-bit kernel which does not have ``CONFIG_LPAE`` enabled on
26
if (is_snan(a->cls) || is_snan(b->cls)) {
26
+ a CPU type which implements LPAE, you will need to manually set
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
27
+ this to ``off``; otherwise some devices, such as the PCI controller,
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
28
+ will not be accessible.
29
switch (s->float_2nan_prop_rule) {
29
30
case float_2nan_prop_s_ab:
30
compact-highmem
31
if (have_snan) {
31
Set ``on``/``off`` to enable/disable the compact layout for high memory regions.
32
- which = is_snan(a->cls) ? 0 : 1;
33
+ ret = is_snan(a->cls) ? a : b;
34
break;
35
}
36
/* fall through */
37
case float_2nan_prop_ab:
38
- which = is_nan(a->cls) ? 0 : 1;
39
+ ret = is_nan(a->cls) ? a : b;
40
break;
41
case float_2nan_prop_s_ba:
42
if (have_snan) {
43
- which = is_snan(b->cls) ? 1 : 0;
44
+ ret = is_snan(b->cls) ? b : a;
45
break;
46
}
47
/* fall through */
48
case float_2nan_prop_ba:
49
- which = is_nan(b->cls) ? 1 : 0;
50
+ ret = is_nan(b->cls) ? b : a;
51
break;
52
case float_2nan_prop_x87:
53
/*
54
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
55
*/
56
if (is_snan(a->cls)) {
57
if (!is_snan(b->cls)) {
58
- which = is_qnan(b->cls) ? 1 : 0;
59
+ ret = is_qnan(b->cls) ? b : a;
60
break;
61
}
62
} else if (is_qnan(a->cls)) {
63
if (is_snan(b->cls) || !is_qnan(b->cls)) {
64
- which = 0;
65
+ ret = a;
66
break;
67
}
68
} else {
69
- which = 1;
70
+ ret = b;
71
break;
72
}
73
cmp = frac_cmp(a, b);
74
if (cmp == 0) {
75
cmp = a->sign < b->sign;
76
}
77
- which = cmp > 0 ? 0 : 1;
78
+ ret = cmp > 0 ? a : b;
79
break;
80
default:
81
g_assert_not_reached();
82
}
83
84
- if (which) {
85
- a = b;
86
+ if (is_snan(ret->cls)) {
87
+ parts_silence_nan(ret, s);
88
}
89
- if (is_snan(a->cls)) {
90
- parts_silence_nan(a, s);
91
- }
92
- return a;
93
+ return ret;
94
}
95
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
32
--
97
--
33
2.34.1
98
2.34.1
34
99
35
100
diff view generated by jsdifflib
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Although very similar to the STM32F4xx EXTI, STM32L4x5 EXTI generates
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
more than 32 event/interrupt requests and thus uses more registers
4
update my email address, and update the mailmap to match.
5
than STM32F4xx EXTI which generates 23 event/interrupt requests.
6
5
7
Acked-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
8
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
9
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20240109160658.311932-2-ines.varhol@telecom-paris.fr
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
docs/system/arm/b-l475e-iot01a.rst | 5 +-
14
MAINTAINERS | 2 +-
15
include/hw/misc/stm32l4x5_exti.h | 51 +++++
15
.mailmap | 5 +++--
16
hw/misc/stm32l4x5_exti.c | 290 +++++++++++++++++++++++++++++
16
2 files changed, 4 insertions(+), 3 deletions(-)
17
hw/misc/Kconfig | 3 +
18
hw/misc/meson.build | 1 +
19
hw/misc/trace-events | 5 +
20
6 files changed, 352 insertions(+), 3 deletions(-)
21
create mode 100644 include/hw/misc/stm32l4x5_exti.h
22
create mode 100644 hw/misc/stm32l4x5_exti.c
23
17
24
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
18
diff --git a/MAINTAINERS b/MAINTAINERS
25
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
26
--- a/docs/system/arm/b-l475e-iot01a.rst
20
--- a/MAINTAINERS
27
+++ b/docs/system/arm/b-l475e-iot01a.rst
21
+++ b/MAINTAINERS
28
@@ -XXX,XX +XXX,XX @@ USART, I2C, SPI, CAN and USB OTG, as well as a variety of sensors.
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
29
Supported devices
23
SBSA-REF
30
"""""""""""""""""
24
M: Radoslaw Biernacki <rad@semihalf.com>
31
25
M: Peter Maydell <peter.maydell@linaro.org>
32
-Currently, B-L475E-IOT01A machine's implementation is minimal,
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
33
-it only supports the following device:
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
34
+Currently B-L475E-IOT01A machine's only supports the following devices:
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
35
29
L: qemu-arm@nongnu.org
36
- Cortex-M4F based STM32L4x5 SoC
30
S: Maintained
37
+- STM32L4x5 EXTI (Extended interrupts and events controller)
31
diff --git a/.mailmap b/.mailmap
38
39
Missing devices
40
"""""""""""""""
41
42
The B-L475E-IOT01A does *not* support the following devices:
43
44
-- Extended interrupts and events controller (EXTI)
45
- Reset and clock control (RCC)
46
- Serial ports (UART)
47
- System configuration controller (SYSCFG)
48
diff --git a/include/hw/misc/stm32l4x5_exti.h b/include/hw/misc/stm32l4x5_exti.h
49
new file mode 100644
50
index XXXXXXX..XXXXXXX
51
--- /dev/null
52
+++ b/include/hw/misc/stm32l4x5_exti.h
53
@@ -XXX,XX +XXX,XX @@
54
+/*
55
+ * STM32L4x5 EXTI (Extended interrupts and events controller)
56
+ *
57
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
58
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
59
+ *
60
+ * SPDX-License-Identifier: GPL-2.0-or-later
61
+ *
62
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
63
+ * See the COPYING file in the top-level directory.
64
+ *
65
+ * This work is based on the stm32f4xx_exti by Alistair Francis.
66
+ * Original code is licensed under the MIT License:
67
+ *
68
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
69
+ */
70
+
71
+/*
72
+ * The reference used is the STMicroElectronics RM0351 Reference manual
73
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
74
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
75
+ */
76
+
77
+#ifndef HW_STM32L4X5_EXTI_H
78
+#define HW_STM32L4X5_EXTI_H
79
+
80
+#include "hw/sysbus.h"
81
+#include "qom/object.h"
82
+
83
+#define TYPE_STM32L4X5_EXTI "stm32l4x5-exti"
84
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5ExtiState, STM32L4X5_EXTI)
85
+
86
+#define EXTI_NUM_INTERRUPT_OUT_LINES 40
87
+#define EXTI_NUM_REGISTER 2
88
+
89
+struct Stm32l4x5ExtiState {
90
+ SysBusDevice parent_obj;
91
+
92
+ MemoryRegion mmio;
93
+
94
+ uint32_t imr[EXTI_NUM_REGISTER];
95
+ uint32_t emr[EXTI_NUM_REGISTER];
96
+ uint32_t rtsr[EXTI_NUM_REGISTER];
97
+ uint32_t ftsr[EXTI_NUM_REGISTER];
98
+ uint32_t swier[EXTI_NUM_REGISTER];
99
+ uint32_t pr[EXTI_NUM_REGISTER];
100
+
101
+ qemu_irq irq[EXTI_NUM_INTERRUPT_OUT_LINES];
102
+};
103
+
104
+#endif
105
diff --git a/hw/misc/stm32l4x5_exti.c b/hw/misc/stm32l4x5_exti.c
106
new file mode 100644
107
index XXXXXXX..XXXXXXX
108
--- /dev/null
109
+++ b/hw/misc/stm32l4x5_exti.c
110
@@ -XXX,XX +XXX,XX @@
111
+/*
112
+ * STM32L4x5 EXTI (Extended interrupts and events controller)
113
+ *
114
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
115
+ * Copyright (c) 2023 Samuel Tardieu <samuel.tardieu@telecom-paris.fr>
116
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
117
+ *
118
+ * SPDX-License-Identifier: GPL-2.0-or-later
119
+ *
120
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
121
+ * See the COPYING file in the top-level directory.
122
+ *
123
+ * This work is based on the stm32f4xx_exti by Alistair Francis.
124
+ * Original code is licensed under the MIT License:
125
+ *
126
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
127
+ */
128
+
129
+/*
130
+ * The reference used is the STMicroElectronics RM0351 Reference manual
131
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
132
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
133
+ */
134
+
135
+#include "qemu/osdep.h"
136
+#include "qemu/log.h"
137
+#include "trace.h"
138
+#include "hw/irq.h"
139
+#include "migration/vmstate.h"
140
+#include "hw/misc/stm32l4x5_exti.h"
141
+
142
+#define EXTI_IMR1 0x00
143
+#define EXTI_EMR1 0x04
144
+#define EXTI_RTSR1 0x08
145
+#define EXTI_FTSR1 0x0C
146
+#define EXTI_SWIER1 0x10
147
+#define EXTI_PR1 0x14
148
+#define EXTI_IMR2 0x20
149
+#define EXTI_EMR2 0x24
150
+#define EXTI_RTSR2 0x28
151
+#define EXTI_FTSR2 0x2C
152
+#define EXTI_SWIER2 0x30
153
+#define EXTI_PR2 0x34
154
+
155
+#define EXTI_NUM_GPIO_EVENT_IN_LINES 16
156
+#define EXTI_MAX_IRQ_PER_BANK 32
157
+#define EXTI_IRQS_BANK0 32
158
+#define EXTI_IRQS_BANK1 8
159
+
160
+static const unsigned irqs_per_bank[EXTI_NUM_REGISTER] = {
161
+ EXTI_IRQS_BANK0,
162
+ EXTI_IRQS_BANK1,
163
+};
164
+
165
+static const uint32_t exti_romask[EXTI_NUM_REGISTER] = {
166
+ 0xff820000, /* 0b11111111_10000010_00000000_00000000 */
167
+ 0x00000087, /* 0b00000000_00000000_00000000_10000111 */
168
+};
169
+
170
+static unsigned regbank_index_by_irq(unsigned irq)
171
+{
172
+ return irq >= EXTI_MAX_IRQ_PER_BANK ? 1 : 0;
173
+}
174
+
175
+static unsigned regbank_index_by_addr(hwaddr addr)
176
+{
177
+ return addr >= EXTI_IMR2 ? 1 : 0;
178
+}
179
+
180
+static unsigned valid_mask(unsigned bank)
181
+{
182
+ return MAKE_64BIT_MASK(0, irqs_per_bank[bank]);
183
+}
184
+
185
+static unsigned configurable_mask(unsigned bank)
186
+{
187
+ return valid_mask(bank) & ~exti_romask[bank];
188
+}
189
+
190
+static void stm32l4x5_exti_reset_hold(Object *obj)
191
+{
192
+ Stm32l4x5ExtiState *s = STM32L4X5_EXTI(obj);
193
+
194
+ for (unsigned bank = 0; bank < EXTI_NUM_REGISTER; bank++) {
195
+ s->imr[bank] = exti_romask[bank];
196
+ s->emr[bank] = 0x00000000;
197
+ s->rtsr[bank] = 0x00000000;
198
+ s->ftsr[bank] = 0x00000000;
199
+ s->swier[bank] = 0x00000000;
200
+ s->pr[bank] = 0x00000000;
201
+ }
202
+}
203
+
204
+static void stm32l4x5_exti_set_irq(void *opaque, int irq, int level)
205
+{
206
+ Stm32l4x5ExtiState *s = opaque;
207
+ const unsigned bank = regbank_index_by_irq(irq);
208
+ const int oirq = irq;
209
+
210
+ trace_stm32l4x5_exti_set_irq(irq, level);
211
+
212
+ /* Shift the value to enable access in x2 registers. */
213
+ irq %= EXTI_MAX_IRQ_PER_BANK;
214
+
215
+ /* If the interrupt is masked, pr won't be raised */
216
+ if (!extract32(s->imr[bank], irq, 1)) {
217
+ return;
218
+ }
219
+
220
+ if (((1 << irq) & s->rtsr[bank]) && level) {
221
+ /* Rising Edge */
222
+ s->pr[bank] |= 1 << irq;
223
+ qemu_irq_pulse(s->irq[oirq]);
224
+ } else if (((1 << irq) & s->ftsr[bank]) && !level) {
225
+ /* Falling Edge */
226
+ s->pr[bank] |= 1 << irq;
227
+ qemu_irq_pulse(s->irq[oirq]);
228
+ }
229
+ /*
230
+ * In the following situations :
231
+ * - falling edge but rising trigger selected
232
+ * - rising edge but falling trigger selected
233
+ * - no trigger selected
234
+ * No action is required
235
+ */
236
+}
237
+
238
+static uint64_t stm32l4x5_exti_read(void *opaque, hwaddr addr,
239
+ unsigned int size)
240
+{
241
+ Stm32l4x5ExtiState *s = opaque;
242
+ uint32_t r = 0;
243
+ const unsigned bank = regbank_index_by_addr(addr);
244
+
245
+ switch (addr) {
246
+ case EXTI_IMR1:
247
+ case EXTI_IMR2:
248
+ r = s->imr[bank];
249
+ break;
250
+ case EXTI_EMR1:
251
+ case EXTI_EMR2:
252
+ r = s->emr[bank];
253
+ break;
254
+ case EXTI_RTSR1:
255
+ case EXTI_RTSR2:
256
+ r = s->rtsr[bank];
257
+ break;
258
+ case EXTI_FTSR1:
259
+ case EXTI_FTSR2:
260
+ r = s->ftsr[bank];
261
+ break;
262
+ case EXTI_SWIER1:
263
+ case EXTI_SWIER2:
264
+ r = s->swier[bank];
265
+ break;
266
+ case EXTI_PR1:
267
+ case EXTI_PR2:
268
+ r = s->pr[bank];
269
+ break;
270
+
271
+ default:
272
+ qemu_log_mask(LOG_GUEST_ERROR,
273
+ "STM32L4X5_exti_read: Bad offset 0x%" HWADDR_PRIx "\n",
274
+ addr);
275
+ break;
276
+ }
277
+
278
+ trace_stm32l4x5_exti_read(addr, r);
279
+
280
+ return r;
281
+}
282
+
283
+static void stm32l4x5_exti_write(void *opaque, hwaddr addr,
284
+ uint64_t val64, unsigned int size)
285
+{
286
+ Stm32l4x5ExtiState *s = opaque;
287
+ const unsigned bank = regbank_index_by_addr(addr);
288
+
289
+ trace_stm32l4x5_exti_write(addr, val64);
290
+
291
+ switch (addr) {
292
+ case EXTI_IMR1:
293
+ case EXTI_IMR2:
294
+ s->imr[bank] = val64 & valid_mask(bank);
295
+ return;
296
+ case EXTI_EMR1:
297
+ case EXTI_EMR2:
298
+ s->emr[bank] = val64 & valid_mask(bank);
299
+ return;
300
+ case EXTI_RTSR1:
301
+ case EXTI_RTSR2:
302
+ s->rtsr[bank] = val64 & configurable_mask(bank);
303
+ return;
304
+ case EXTI_FTSR1:
305
+ case EXTI_FTSR2:
306
+ s->ftsr[bank] = val64 & configurable_mask(bank);
307
+ return;
308
+ case EXTI_SWIER1:
309
+ case EXTI_SWIER2: {
310
+ const uint32_t set = val64 & configurable_mask(bank);
311
+ const uint32_t pend = set & ~s->swier[bank] & s->imr[bank] &
312
+ ~s->pr[bank];
313
+ s->swier[bank] = set;
314
+ s->pr[bank] |= pend;
315
+ for (unsigned i = 0; i < irqs_per_bank[bank]; i++) {
316
+ if (extract32(pend, i, 1)) {
317
+ qemu_irq_pulse(s->irq[i + 32 * bank]);
318
+ }
319
+ }
320
+ return;
321
+ }
322
+ case EXTI_PR1:
323
+ case EXTI_PR2: {
324
+ const uint32_t cleared = s->pr[bank] & val64 & configurable_mask(bank);
325
+ /* This bit is cleared by writing a 1 to it */
326
+ s->pr[bank] &= ~cleared;
327
+ /* Software triggered interrupts are cleared as well */
328
+ s->swier[bank] &= ~cleared;
329
+ return;
330
+ }
331
+ default:
332
+ qemu_log_mask(LOG_GUEST_ERROR,
333
+ "STM32L4X5_exti_write: Bad offset 0x%" HWADDR_PRIx "\n",
334
+ addr);
335
+ }
336
+}
337
+
338
+static const MemoryRegionOps stm32l4x5_exti_ops = {
339
+ .read = stm32l4x5_exti_read,
340
+ .write = stm32l4x5_exti_write,
341
+ .endianness = DEVICE_NATIVE_ENDIAN,
342
+ .impl.min_access_size = 4,
343
+ .impl.max_access_size = 4,
344
+ .impl.unaligned = false,
345
+ .valid.min_access_size = 4,
346
+ .valid.max_access_size = 4,
347
+ .valid.unaligned = false,
348
+};
349
+
350
+static void stm32l4x5_exti_init(Object *obj)
351
+{
352
+ Stm32l4x5ExtiState *s = STM32L4X5_EXTI(obj);
353
+
354
+ for (size_t i = 0; i < EXTI_NUM_INTERRUPT_OUT_LINES; i++) {
355
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]);
356
+ }
357
+
358
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_exti_ops, s,
359
+ TYPE_STM32L4X5_EXTI, 0x400);
360
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
361
+
362
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_exti_set_irq,
363
+ EXTI_NUM_GPIO_EVENT_IN_LINES);
364
+}
365
+
366
+static const VMStateDescription vmstate_stm32l4x5_exti = {
367
+ .name = TYPE_STM32L4X5_EXTI,
368
+ .version_id = 1,
369
+ .minimum_version_id = 1,
370
+ .fields = (VMStateField[]) {
371
+ VMSTATE_UINT32_ARRAY(imr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
372
+ VMSTATE_UINT32_ARRAY(emr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
373
+ VMSTATE_UINT32_ARRAY(rtsr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
374
+ VMSTATE_UINT32_ARRAY(ftsr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
375
+ VMSTATE_UINT32_ARRAY(swier, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
376
+ VMSTATE_UINT32_ARRAY(pr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
377
+ VMSTATE_END_OF_LIST()
378
+ }
379
+};
380
+
381
+static void stm32l4x5_exti_class_init(ObjectClass *klass, void *data)
382
+{
383
+ DeviceClass *dc = DEVICE_CLASS(klass);
384
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
385
+
386
+ dc->vmsd = &vmstate_stm32l4x5_exti;
387
+ rc->phases.hold = stm32l4x5_exti_reset_hold;
388
+}
389
+
390
+static const TypeInfo stm32l4x5_exti_types[] = {
391
+ {
392
+ .name = TYPE_STM32L4X5_EXTI,
393
+ .parent = TYPE_SYS_BUS_DEVICE,
394
+ .instance_size = sizeof(Stm32l4x5ExtiState),
395
+ .instance_init = stm32l4x5_exti_init,
396
+ .class_init = stm32l4x5_exti_class_init,
397
+ }
398
+};
399
+
400
+DEFINE_TYPES(stm32l4x5_exti_types)
401
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
402
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
403
--- a/hw/misc/Kconfig
33
--- a/.mailmap
404
+++ b/hw/misc/Kconfig
34
+++ b/.mailmap
405
@@ -XXX,XX +XXX,XX @@ config STM32F4XX_SYSCFG
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
406
config STM32F4XX_EXTI
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
407
bool
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
408
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
409
+config STM32L4X5_EXTI
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
410
+ bool
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
411
+
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
412
config MIPS_ITU
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
413
bool
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
414
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
415
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
416
index XXXXXXX..XXXXXXX 100644
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
417
--- a/hw/misc/meson.build
418
+++ b/hw/misc/meson.build
419
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files(
420
system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
421
system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
422
system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
423
+system_ss.add(when: 'CONFIG_STM32L4X5_EXTI', if_true: files('stm32l4x5_exti.c'))
424
system_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c'))
425
system_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c'))
426
427
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
428
index XXXXXXX..XXXXXXX 100644
429
--- a/hw/misc/trace-events
430
+++ b/hw/misc/trace-events
431
@@ -XXX,XX +XXX,XX @@ stm32f4xx_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
432
stm32f4xx_exti_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
433
stm32f4xx_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
434
435
+# stm32l4x5_exti.c
436
+stm32l4x5_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
437
+stm32l4x5_exti_read(uint64_t addr, uint64_t data) "reg read: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
438
+stm32l4x5_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
439
+
440
# tz-mpc.c
441
tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u"
442
tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs write: offset 0x%x data 0x%" PRIx64 " size %u"
443
--
47
--
444
2.34.1
48
2.34.1
445
49
446
50
diff view generated by jsdifflib
1
We don't currently document the syntax of .hx files anywhere
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
except in a few comments at the top of individual .hx files.
3
We don't even have somewhere in the developer docs where we
4
could do this.
5
2
6
Add a new files docs/devel/docs.rst which can be a place to
3
Previously, maintainer role was paused due to inactive email id. Commit id:
7
document how our docs build process works. For the moment,
4
c009d715721861984c4987bcc78b7ee183e86d75.
8
put in only a brief introductory paragraph and the documentation
9
of the .hx files. We could later add to this file by for
10
example describing how the QAPI-schema-to-docs process works,
11
or anything else that developers might need to know about
12
how to add documentation.
13
5
14
Make the .hx files refer to this doc file, and clean
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
15
up their header comments to be more accurate for the
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
16
usage in each file and less cut-n-pasted.
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Luc Michel <luc.michel@amd.com>
20
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
21
Message-id: 20231212162313.1742462-1-peter.maydell@linaro.org
22
---
10
---
23
MAINTAINERS | 1 +
11
MAINTAINERS | 2 ++
24
docs/devel/docs.rst | 60 ++++++++++++++++++++++++++++++++++++++
12
1 file changed, 2 insertions(+)
25
docs/devel/index-build.rst | 1 +
26
hmp-commands-info.hx | 10 +++----
27
hmp-commands.hx | 10 +++----
28
qemu-img-cmds.hx | 2 ++
29
qemu-options.hx | 2 ++
30
7 files changed, 76 insertions(+), 10 deletions(-)
31
create mode 100644 docs/devel/docs.rst
32
13
33
diff --git a/MAINTAINERS b/MAINTAINERS
14
diff --git a/MAINTAINERS b/MAINTAINERS
34
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
35
--- a/MAINTAINERS
16
--- a/MAINTAINERS
36
+++ b/MAINTAINERS
17
+++ b/MAINTAINERS
37
@@ -XXX,XX +XXX,XX @@ F: docs/conf.py
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
38
F: docs/*/conf.py
19
39
F: docs/sphinx/
20
Xilinx CAN
40
F: docs/_templates/
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
41
+F: docs/devel/docs.rst
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
42
23
S: Maintained
43
Miscellaneous
24
F: hw/net/can/xlnx-*
44
-------------
25
F: include/hw/net/xlnx-*
45
diff --git a/docs/devel/docs.rst b/docs/devel/docs.rst
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
46
new file mode 100644
27
CAN bus subsystem and hardware
47
index XXXXXXX..XXXXXXX
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
48
--- /dev/null
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
49
+++ b/docs/devel/docs.rst
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
50
@@ -XXX,XX +XXX,XX @@
31
S: Maintained
51
+
32
W: https://canbus.pages.fel.cvut.cz/
52
+==================
33
F: net/can/*
53
+QEMU Documentation
54
+==================
55
+
56
+QEMU's documentation is written in reStructuredText format and
57
+built using the Sphinx documentation generator. We generate both
58
+the HTML manual and the manpages from the some documentation sources.
59
+
60
+hxtool and .hx files
61
+--------------------
62
+
63
+The documentation for QEMU command line options and Human Monitor Protocol
64
+(HMP) commands is written in files with the ``.hx`` suffix. These
65
+are processed in two ways:
66
+
67
+ * ``scripts/hxtool`` creates C header files from them, which are included
68
+ in QEMU to do things like handle the ``--help`` option output
69
+ * a Sphinx extension in ``docs/sphinx/hxtool.py`` generates rST output
70
+ to be included in the HTML or manpage documentation
71
+
72
+The syntax of these ``.hx`` files is simple. It is broadly an
73
+alternation of C code put into the C output and rST format text
74
+put into the documention. A few special directives are recognised;
75
+these are all-caps and must be at the beginning of the line.
76
+
77
+``HXCOMM`` is the comment marker. The line, including any arbitrary
78
+text after the marker, is discarded and appears neither in the C output
79
+nor the documentation output.
80
+
81
+``SRST`` starts a reStructuredText section. Following lines
82
+are put into the documentation verbatim, and discarded from the C output.
83
+
84
+``ERST`` ends the documentation section started with ``SRST``,
85
+and switches back to a C code section.
86
+
87
+``DEFHEADING()`` defines a heading that should appear in both the
88
+``--help`` output and in the documentation. This directive should
89
+be in the C code block. If there is a string inside the brackets,
90
+this is the heading to use. If this string is empty, it produces
91
+a blank line in the ``--help`` output and is ignored for the rST
92
+output.
93
+
94
+``ARCHHEADING()`` is a variant of ``DEFHEADING()`` which produces
95
+the heading only if the specified guest architecture was compiled
96
+into QEMU. This should be avoided in new documentation.
97
+
98
+Within C code sections, you should check the comments at the top
99
+of the file to see what the expected usage is, because this
100
+varies between files. For instance in ``qemu-options.hx`` we use
101
+the ``DEF()`` macro to define each option and specify its ``--help``
102
+text, but in ``hmp-commands.hx`` the C code sections are elements
103
+of an array of structs of type ``HMPCommand`` which define the
104
+name, behaviour and help text for each monitor command.
105
+
106
+In the file ``qemu-options.hx``, do not try to define a
107
+reStructuredText label within a documentation section. This file
108
+is included into two separate Sphinx documents, and some
109
+versions of Sphinx will complain about the duplicate label
110
+that results.
111
diff --git a/docs/devel/index-build.rst b/docs/devel/index-build.rst
112
index XXXXXXX..XXXXXXX 100644
113
--- a/docs/devel/index-build.rst
114
+++ b/docs/devel/index-build.rst
115
@@ -XXX,XX +XXX,XX @@ the basics if you are adding new files and targets to the build.
116
117
build-system
118
kconfig
119
+ docs
120
testing
121
acpi-bits
122
qtest
123
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
124
index XXXXXXX..XXXXXXX 100644
125
--- a/hmp-commands-info.hx
126
+++ b/hmp-commands-info.hx
127
@@ -XXX,XX +XXX,XX @@
128
-HXCOMM Use DEFHEADING() to define headings in both help text and rST.
129
-HXCOMM Text between SRST and ERST is copied to the rST version and
130
-HXCOMM discarded from C version.
131
-HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
132
-HXCOMM monitor info commands
133
+HXCOMM See docs/devel/docs.rst for the format of this file.
134
+HXCOMM
135
+HXCOMM This file defines the contents of an array of HMPCommand structs
136
+HXCOMM which specify the name, behaviour and help text for HMP commands.
137
+HXCOMM Text between SRST and ERST is rST format documentation.
138
HXCOMM HXCOMM can be used for comments, discarded from both rST and C.
139
HXCOMM
140
HXCOMM In this file, generally SRST fragments should have two extra
141
diff --git a/hmp-commands.hx b/hmp-commands.hx
142
index XXXXXXX..XXXXXXX 100644
143
--- a/hmp-commands.hx
144
+++ b/hmp-commands.hx
145
@@ -XXX,XX +XXX,XX @@
146
-HXCOMM Use DEFHEADING() to define headings in both help text and rST.
147
-HXCOMM Text between SRST and ERST is copied to the rST version and
148
-HXCOMM discarded from C version.
149
-HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
150
-HXCOMM monitor commands
151
+HXCOMM See docs/devel/docs.rst for the format of this file.
152
+HXCOMM
153
+HXCOMM This file defines the contents of an array of HMPCommand structs
154
+HXCOMM which specify the name, behaviour and help text for HMP commands.
155
+HXCOMM Text between SRST and ERST is rST format documentation.
156
HXCOMM HXCOMM can be used for comments, discarded from both rST and C.
157
158
159
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
160
index XXXXXXX..XXXXXXX 100644
161
--- a/qemu-img-cmds.hx
162
+++ b/qemu-img-cmds.hx
163
@@ -XXX,XX +XXX,XX @@
164
+HXCOMM See docs/devel/docs.rst for the format of this file.
165
+HXCOMM
166
HXCOMM Keep the list of subcommands sorted by name.
167
HXCOMM Use DEFHEADING() to define headings in both help text and rST
168
HXCOMM Text between SRST and ERST are copied to rST version and
169
diff --git a/qemu-options.hx b/qemu-options.hx
170
index XXXXXXX..XXXXXXX 100644
171
--- a/qemu-options.hx
172
+++ b/qemu-options.hx
173
@@ -XXX,XX +XXX,XX @@
174
+HXCOMM See docs/devel/docs.rst for the format of this file.
175
+HXCOMM
176
HXCOMM Use DEFHEADING() to define headings in both help text and rST.
177
HXCOMM Text between SRST and ERST is copied to the rST version and
178
HXCOMM discarded from C version.
179
--
34
--
180
2.34.1
35
2.34.1
diff view generated by jsdifflib