1
Hi; this pullreq includes FEAT_LSE2 support, the new
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
2
bpim2u board, and some other smaller patchsets.
2
handling series. (Lots more in my to-review queue, but I don't
3
like pullreqs growing too close to a hundred patches at a time :-))
3
4
4
thanks
5
thanks
5
-- PMM
6
-- PMM
6
7
7
The following changes since commit 369081c4558e7e940fa36ce59bf17b2e390f55d3:
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
8
9
9
Merge tag 'pull-tcg-20230605' of https://gitlab.com/rth7680/qemu into staging (2023-06-05 13:16:56 -0700)
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
10
11
11
are available in the Git repository at:
12
are available in the Git repository at:
12
13
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230606
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
14
15
15
for you to fetch changes up to f9ac778898cb28307e0f91421aba34d43c34b679:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
16
17
17
target/arm: trap DCC access in user mode emulation (2023-06-06 10:19:40 +0100)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
18
19
19
----------------------------------------------------------------
20
----------------------------------------------------------------
20
target-arm queue:
21
target-arm queue:
21
* Support gdbstub (guest debug) in HVF
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
22
* xnlx-versal: Support CANFD controller
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
23
* bpim2u: New board model: Banana Pi BPI-M2 Ultra
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
24
* Emulate FEAT_LSE2
25
* fpu: Minor NaN-related cleanups
25
* allow DC CVA[D]P in user mode emulation
26
* MAINTAINERS: email address updates
26
* trap DCC access in user mode emulation
27
27
28
----------------------------------------------------------------
28
----------------------------------------------------------------
29
Francesco Cagnin (4):
29
Bernhard Beschow (5):
30
arm: move KVM breakpoints helpers
30
hw/net/lan9118: Extract lan9118_phy
31
hvf: handle access for more registers
31
hw/net/lan9118_phy: Reuse in imx_fec and consolidate implementations
32
hvf: add breakpoint handlers
32
hw/net/lan9118_phy: Fix off-by-one error in MII_ANLPAR register
33
hvf: add guest debugging handlers for Apple Silicon hosts
33
hw/net/lan9118_phy: Reuse MII constants
34
hw/net/lan9118_phy: Add missing 100 mbps full duplex advertisement
34
35
35
Richard Henderson (20):
36
Leif Lindholm (1):
36
target/arm: Add commentary for CPUARMState.exclusive_high
37
MAINTAINERS: update email address for Leif Lindholm
37
target/arm: Add feature test for FEAT_LSE2
38
target/arm: Introduce finalize_memop_{atom,pair}
39
target/arm: Use tcg_gen_qemu_ld_i128 for LDXP
40
target/arm: Use tcg_gen_qemu_{st, ld}_i128 for do_fp_{st, ld}
41
target/arm: Use tcg_gen_qemu_st_i128 for STZG, STZ2G
42
target/arm: Use tcg_gen_qemu_{ld, st}_i128 in gen_sve_{ld, st}r
43
target/arm: Sink gen_mte_check1 into load/store_exclusive
44
target/arm: Load/store integer pair with one tcg operation
45
target/arm: Hoist finalize_memop out of do_gpr_{ld, st}
46
target/arm: Hoist finalize_memop out of do_fp_{ld, st}
47
target/arm: Pass memop to gen_mte_check1*
48
target/arm: Pass single_memop to gen_mte_checkN
49
target/arm: Check alignment in helper_mte_check
50
target/arm: Add SCTLR.nAA to TBFLAG_A64
51
target/arm: Relax ordered/atomic alignment checks for LSE2
52
target/arm: Move mte check for store-exclusive
53
tests/tcg/aarch64: Use stz2g in mte-7.c
54
tests/tcg/multiarch: Adjust sigbus.c
55
target/arm: Enable FEAT_LSE2 for -cpu max
56
38
57
Vikram Garhwal (4):
39
Peter Maydell (54):
58
hw/net/can: Introduce Xilinx Versal CANFD controller
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
59
xlnx-versal: Connect Xilinx VERSAL CANFD controllers
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
60
MAINTAINERS: Include canfd tests under Xilinx CAN
42
softfloat: Allow runtime choice of inf * 0 + NaN result
61
tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller
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
62
94
63
Zhuojia Shen (3):
95
Richard Henderson (11):
64
target/arm: allow DC CVA[D]P in user mode emulation
96
target/arm: Copy entire float_status in is_ebf
65
tests/tcg/aarch64: add DC CVA[D]P tests
97
softfloat: Inline pickNaNMulAdd
66
target/arm: trap DCC access in user mode emulation
98
softfloat: Use goto for default nan case in pick_nan_muladd
99
softfloat: Remove which from parts_pick_nan_muladd
100
softfloat: Pad array size in pick_nan_muladd
101
softfloat: Move propagateFloatx80NaN to softfloat.c
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
103
softfloat: Inline pickNaN
104
softfloat: Share code between parts_pick_nan cases
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
106
softfloat: Replace WHICH with RET in parts_pick_nan
67
107
68
qianfan Zhao (11):
108
Vikram Garhwal (1):
69
hw: arm: Add bananapi M2-Ultra and allwinner-r40 support
109
MAINTAINERS: Add correct email address for Vikram Garhwal
70
hw/arm/allwinner-r40: add Clock Control Unit
71
hw: allwinner-r40: Complete uart devices
72
hw: arm: allwinner-r40: Add i2c0 device
73
hw/misc: Rename axp209 to axp22x and add support AXP221 PMU
74
hw/arm/allwinner-r40: add SDRAM controller device
75
hw: sd: allwinner-sdhost: Add sun50i-a64 SoC support
76
hw: arm: allwinner-r40: Add emac and gmac support
77
hw: arm: allwinner-sramc: Add SRAM Controller support for R40
78
tests: avocado: boot_linux_console: Add test case for bpim2u
79
docs: system: arm: Introduce bananapi_m2u
80
110
81
MAINTAINERS | 2 +-
111
MAINTAINERS | 4 +-
82
docs/system/arm/bananapi_m2u.rst | 139 +++
112
include/fpu/softfloat-helpers.h | 38 +++-
83
docs/system/arm/emulation.rst | 1 +
113
include/fpu/softfloat-types.h | 89 +++++++-
84
docs/system/arm/xlnx-versal-virt.rst | 31 +
114
include/hw/net/imx_fec.h | 9 +-
85
docs/system/target-arm.rst | 1 +
115
include/hw/net/lan9118_phy.h | 37 ++++
86
include/hw/arm/allwinner-r40.h | 143 +++
116
include/hw/net/mii.h | 6 +
87
include/hw/arm/xlnx-versal.h | 12 +
117
target/mips/fpu_helper.h | 20 ++
88
include/hw/misc/allwinner-r40-ccu.h | 65 +
118
target/sparc/helper.h | 4 +-
89
include/hw/misc/allwinner-r40-dramc.h | 108 ++
119
fpu/softfloat.c | 19 ++
90
include/hw/misc/allwinner-sramc.h | 69 ++
120
hw/net/imx_fec.c | 146 ++------------
91
include/hw/net/xlnx-versal-canfd.h | 87 ++
121
hw/net/lan9118.c | 137 ++-----------
92
include/hw/sd/allwinner-sdhost.h | 9 +
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
93
include/sysemu/hvf.h | 37 +
123
linux-user/arm/nwfpe/fpa11.c | 5 +
94
include/sysemu/hvf_int.h | 2 +
124
target/alpha/cpu.c | 2 +
95
target/arm/cpu.h | 16 +-
125
target/arm/cpu.c | 10 +
96
target/arm/hvf_arm.h | 7 +
126
target/arm/tcg/vec_helper.c | 20 +-
97
target/arm/internals.h | 53 +-
127
target/hexagon/cpu.c | 2 +
98
target/arm/tcg/helper-a64.h | 3 +
128
target/hppa/fpu_helper.c | 12 ++
99
target/arm/tcg/translate-a64.h | 4 +-
129
target/i386/tcg/fpu_helper.c | 12 ++
100
target/arm/tcg/translate.h | 65 +-
130
target/loongarch/tcg/fpu_helper.c | 14 +-
101
accel/hvf/hvf-accel-ops.c | 119 ++
131
target/m68k/cpu.c | 14 +-
102
accel/hvf/hvf-all.c | 23 +
132
target/m68k/fpu_helper.c | 6 +-
103
hw/arm/allwinner-r40.c | 526 ++++++++
133
target/m68k/helper.c | 6 +-
104
hw/arm/bananapi_m2u.c | 145 +++
134
target/microblaze/cpu.c | 2 +
105
hw/arm/xlnx-versal-virt.c | 53 +
135
target/mips/msa.c | 10 +
106
hw/arm/xlnx-versal.c | 37 +
136
target/openrisc/cpu.c | 2 +
107
hw/misc/allwinner-r40-ccu.c | 209 ++++
137
target/ppc/cpu_init.c | 19 ++
108
hw/misc/allwinner-r40-dramc.c | 513 ++++++++
138
target/ppc/fpu_helper.c | 3 +-
109
hw/misc/allwinner-sramc.c | 184 +++
139
target/riscv/cpu.c | 2 +
110
hw/misc/axp209.c | 238 ----
140
target/rx/cpu.c | 2 +
111
hw/misc/axp2xx.c | 283 +++++
141
target/s390x/cpu.c | 5 +
112
hw/net/can/xlnx-versal-canfd.c | 2107 +++++++++++++++++++++++++++++++++
142
target/sh4/cpu.c | 2 +
113
hw/sd/allwinner-sdhost.c | 72 +-
143
target/sparc/cpu.c | 6 +
114
target/arm/cpu.c | 2 +
144
target/sparc/fop_helper.c | 8 +-
115
target/arm/debug_helper.c | 5 +
145
target/sparc/translate.c | 4 +-
116
target/arm/helper.c | 6 +-
146
target/tricore/helper.c | 2 +
117
target/arm/hvf/hvf.c | 750 +++++++++++-
147
target/xtensa/cpu.c | 4 +
118
target/arm/hyp_gdbstub.c | 253 ++++
148
target/xtensa/fpu_helper.c | 3 +-
119
target/arm/kvm64.c | 276 -----
149
tests/fp/fp-bench.c | 7 +
120
target/arm/tcg/cpu64.c | 1 +
150
tests/fp/fp-test-log2.c | 1 +
121
target/arm/tcg/helper-a64.c | 7 +
151
tests/fp/fp-test.c | 7 +
122
target/arm/tcg/hflags.c | 6 +
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
123
target/arm/tcg/mte_helper.c | 18 +
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
124
target/arm/tcg/translate-a64.c | 477 +++++---
154
.mailmap | 5 +-
125
target/arm/tcg/translate-sve.c | 106 +-
155
hw/net/Kconfig | 5 +
126
target/arm/tcg/translate.c | 1 +
156
hw/net/meson.build | 1 +
127
target/i386/hvf/hvf.c | 33 +
157
hw/net/trace-events | 10 +-
128
tests/qtest/xlnx-canfd-test.c | 423 +++++++
158
47 files changed, 778 insertions(+), 730 deletions(-)
129
tests/tcg/aarch64/dcpodp.c | 63 +
159
create mode 100644 include/hw/net/lan9118_phy.h
130
tests/tcg/aarch64/dcpop.c | 63 +
160
create mode 100644 hw/net/lan9118_phy.c
131
tests/tcg/aarch64/mte-7.c | 3 +-
132
tests/tcg/multiarch/sigbus.c | 13 +-
133
hw/arm/Kconfig | 14 +-
134
hw/arm/meson.build | 1 +
135
hw/misc/Kconfig | 5 +-
136
hw/misc/meson.build | 5 +-
137
hw/misc/trace-events | 26 +-
138
hw/net/can/meson.build | 1 +
139
hw/net/can/trace-events | 7 +
140
target/arm/meson.build | 3 +-
141
tests/avocado/boot_linux_console.py | 176 +++
142
tests/qtest/meson.build | 1 +
143
tests/tcg/aarch64/Makefile.target | 11 +
144
63 files changed, 7386 insertions(+), 733 deletions(-)
145
create mode 100644 docs/system/arm/bananapi_m2u.rst
146
create mode 100644 include/hw/arm/allwinner-r40.h
147
create mode 100644 include/hw/misc/allwinner-r40-ccu.h
148
create mode 100644 include/hw/misc/allwinner-r40-dramc.h
149
create mode 100644 include/hw/misc/allwinner-sramc.h
150
create mode 100644 include/hw/net/xlnx-versal-canfd.h
151
create mode 100644 hw/arm/allwinner-r40.c
152
create mode 100644 hw/arm/bananapi_m2u.c
153
create mode 100644 hw/misc/allwinner-r40-ccu.c
154
create mode 100644 hw/misc/allwinner-r40-dramc.c
155
create mode 100644 hw/misc/allwinner-sramc.c
156
delete mode 100644 hw/misc/axp209.c
157
create mode 100644 hw/misc/axp2xx.c
158
create mode 100644 hw/net/can/xlnx-versal-canfd.c
159
create mode 100644 target/arm/hyp_gdbstub.c
160
create mode 100644 tests/qtest/xlnx-canfd-test.c
161
create mode 100644 tests/tcg/aarch64/dcpodp.c
162
create mode 100644 tests/tcg/aarch64/dcpop.c
diff view generated by jsdifflib
1
From: qianfan Zhao <qianfanguijin@163.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
The CCU provides the registers to program the PLLs and the controls
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
most of the clock generation, division, distribution, synchronization
4
a common implementation by extracting a device model into its own files.
5
and gating.
6
5
7
This commit adds support for the Clock Control Unit which emulates
6
Some migration state has been moved into the new device model which breaks
8
a simple read/write register interface.
7
migration compatibility for the following machines:
8
* smdkc210
9
* realview-*
10
* vexpress-*
11
* kzm
12
* mps2-*
9
13
10
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
14
While breaking migration ABI, fix the size of the MII registers to be 16 bit,
11
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
15
as defined by IEEE 802.3u.
16
17
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
18
Tested-by: Guenter Roeck <linux@roeck-us.net>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
22
---
14
include/hw/arm/allwinner-r40.h | 2 +
23
include/hw/net/lan9118_phy.h | 37 ++++++++
15
include/hw/misc/allwinner-r40-ccu.h | 65 +++++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
16
hw/arm/allwinner-r40.c | 8 +-
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
17
hw/misc/allwinner-r40-ccu.c | 209 ++++++++++++++++++++++++++++
26
hw/net/Kconfig | 4 +
18
hw/misc/meson.build | 1 +
27
hw/net/meson.build | 1 +
19
5 files changed, 284 insertions(+), 1 deletion(-)
28
5 files changed, 233 insertions(+), 115 deletions(-)
20
create mode 100644 include/hw/misc/allwinner-r40-ccu.h
29
create mode 100644 include/hw/net/lan9118_phy.h
21
create mode 100644 hw/misc/allwinner-r40-ccu.c
30
create mode 100644 hw/net/lan9118_phy.c
22
31
23
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/allwinner-r40.h
26
+++ b/include/hw/arm/allwinner-r40.h
27
@@ -XXX,XX +XXX,XX @@
28
#include "hw/timer/allwinner-a10-pit.h"
29
#include "hw/intc/arm_gic.h"
30
#include "hw/sd/allwinner-sdhost.h"
31
+#include "hw/misc/allwinner-r40-ccu.h"
32
#include "target/arm/cpu.h"
33
#include "sysemu/block-backend.h"
34
35
@@ -XXX,XX +XXX,XX @@ struct AwR40State {
36
const hwaddr *memmap;
37
AwA10PITState timer;
38
AwSdHostState mmc[AW_R40_NUM_MMCS];
39
+ AwR40ClockCtlState ccu;
40
GICState gic;
41
MemoryRegion sram_a1;
42
MemoryRegion sram_a2;
43
diff --git a/include/hw/misc/allwinner-r40-ccu.h b/include/hw/misc/allwinner-r40-ccu.h
44
new file mode 100644
33
new file mode 100644
45
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
46
--- /dev/null
35
--- /dev/null
47
+++ b/include/hw/misc/allwinner-r40-ccu.h
36
+++ b/include/hw/net/lan9118_phy.h
48
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
49
+/*
38
+/*
50
+ * Allwinner R40 Clock Control Unit emulation
39
+ * SMSC LAN9118 PHY emulation
51
+ *
40
+ *
52
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
42
+ * Written by Paul Brook
53
+ *
43
+ *
54
+ * This program is free software: you can redistribute it and/or modify
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
55
+ * it under the terms of the GNU General Public License as published by
45
+ * See the COPYING file in the top-level directory.
56
+ * the Free Software Foundation, either version 2 of the License, or
57
+ * (at your option) any later version.
58
+ *
59
+ * This program is distributed in the hope that it will be useful,
60
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
61
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62
+ * GNU General Public License for more details.
63
+ *
64
+ * You should have received a copy of the GNU General Public License
65
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
66
+ */
46
+ */
67
+
47
+
68
+#ifndef HW_MISC_ALLWINNER_R40_CCU_H
48
+#ifndef HW_NET_LAN9118_PHY_H
69
+#define HW_MISC_ALLWINNER_R40_CCU_H
49
+#define HW_NET_LAN9118_PHY_H
70
+
50
+
71
+#include "qom/object.h"
51
+#include "qom/object.h"
72
+#include "hw/sysbus.h"
52
+#include "hw/sysbus.h"
73
+
53
+
74
+/**
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
75
+ * @name Constants
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
76
+ * @{
56
+
77
+ */
57
+typedef struct Lan9118PhyState {
78
+
79
+/** Size of register I/O address space used by CCU device */
80
+#define AW_R40_CCU_IOSIZE (0x400)
81
+
82
+/** Total number of known registers */
83
+#define AW_R40_CCU_REGS_NUM (AW_R40_CCU_IOSIZE / sizeof(uint32_t))
84
+
85
+/** @} */
86
+
87
+/**
88
+ * @name Object model
89
+ * @{
90
+ */
91
+
92
+#define TYPE_AW_R40_CCU "allwinner-r40-ccu"
93
+OBJECT_DECLARE_SIMPLE_TYPE(AwR40ClockCtlState, AW_R40_CCU)
94
+
95
+/** @} */
96
+
97
+/**
98
+ * Allwinner R40 CCU object instance state.
99
+ */
100
+struct AwR40ClockCtlState {
101
+ /*< private >*/
102
+ SysBusDevice parent_obj;
58
+ SysBusDevice parent_obj;
103
+ /*< public >*/
59
+
104
+
60
+ uint16_t status;
105
+ /** Maps I/O registers in physical memory */
61
+ uint16_t control;
106
+ MemoryRegion iomem;
62
+ uint16_t advertise;
107
+
63
+ uint16_t ints;
108
+ /** Array of hardware registers */
64
+ uint16_t int_mask;
109
+ uint32_t regs[AW_R40_CCU_REGS_NUM];
65
+ qemu_irq irq;
110
+
66
+ bool link_down;
111
+};
67
+} Lan9118PhyState;
112
+
68
+
113
+#endif /* HW_MISC_ALLWINNER_R40_CCU_H */
69
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down);
114
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
70
+void lan9118_phy_reset(Lan9118PhyState *s);
71
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg);
72
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val);
73
+
74
+#endif
75
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
115
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
116
--- a/hw/arm/allwinner-r40.c
77
--- a/hw/net/lan9118.c
117
+++ b/hw/arm/allwinner-r40.c
78
+++ b/hw/net/lan9118.c
118
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_r40_memmap[] = {
79
@@ -XXX,XX +XXX,XX @@
119
[AW_R40_DEV_MMC1] = 0x01c10000,
80
#include "net/net.h"
120
[AW_R40_DEV_MMC2] = 0x01c11000,
81
#include "net/eth.h"
121
[AW_R40_DEV_MMC3] = 0x01c12000,
82
#include "hw/irq.h"
122
+ [AW_R40_DEV_CCU] = 0x01c20000,
83
+#include "hw/net/lan9118_phy.h"
123
[AW_R40_DEV_PIT] = 0x01c20c00,
84
#include "hw/net/lan9118.h"
124
[AW_R40_DEV_UART0] = 0x01c28000,
85
#include "hw/ptimer.h"
125
[AW_R40_DEV_GIC_DIST] = 0x01c81000,
86
#include "hw/qdev-properties.h"
126
@@ -XXX,XX +XXX,XX @@ static struct AwR40Unimplemented r40_unimplemented[] = {
87
@@ -XXX,XX +XXX,XX @@ do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
127
{ "usb2-host", 0x01c1c000, 4 * KiB },
88
#define MAC_CR_RXEN 0x00000004
128
{ "cs1", 0x01c1d000, 4 * KiB },
89
#define MAC_CR_RESERVED 0x7f404213
129
{ "spi3", 0x01c1f000, 4 * KiB },
90
130
- { "ccu", 0x01c20000, 1 * KiB },
91
-#define PHY_INT_ENERGYON 0x80
131
{ "rtc", 0x01c20400, 1 * KiB },
92
-#define PHY_INT_AUTONEG_COMPLETE 0x40
132
{ "pio", 0x01c20800, 1 * KiB },
93
-#define PHY_INT_FAULT 0x20
133
{ "owa", 0x01c21000, 1 * KiB },
94
-#define PHY_INT_DOWN 0x10
134
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_init(Object *obj)
95
-#define PHY_INT_AUTONEG_LP 0x08
135
object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
96
-#define PHY_INT_PARFAULT 0x04
136
"clk1-freq");
97
-#define PHY_INT_AUTONEG_PAGE 0x02
137
98
-
138
+ object_initialize_child(obj, "ccu", &s->ccu, TYPE_AW_R40_CCU);
99
#define GPT_TIMER_EN 0x20000000
139
+
100
140
for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
101
/*
141
object_initialize_child(obj, mmc_names[i], &s->mmc[i],
102
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
142
TYPE_AW_SDHOST_SUN5I);
103
uint32_t mac_mii_data;
143
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_realize(DeviceState *dev, Error **errp)
104
uint32_t mac_flow;
144
memory_region_add_subregion(get_system_memory(),
105
145
s->memmap[AW_R40_DEV_SRAM_A4], &s->sram_a4);
106
- uint32_t phy_status;
146
107
- uint32_t phy_control;
147
+ /* Clock Control Unit */
108
- uint32_t phy_advertise;
148
+ sysbus_realize(SYS_BUS_DEVICE(&s->ccu), &error_fatal);
109
- uint32_t phy_int;
149
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_R40_DEV_CCU]);
110
- uint32_t phy_int_mask;
150
+
111
+ Lan9118PhyState mii;
151
/* SD/MMC */
112
+ IRQState mii_irq;
152
for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
113
153
qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->gic),
114
int32_t eeprom_writable;
154
diff --git a/hw/misc/allwinner-r40-ccu.c b/hw/misc/allwinner-r40-ccu.c
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
155
new file mode 100644
312
new file mode 100644
156
index XXXXXXX..XXXXXXX
313
index XXXXXXX..XXXXXXX
157
--- /dev/null
314
--- /dev/null
158
+++ b/hw/misc/allwinner-r40-ccu.c
315
+++ b/hw/net/lan9118_phy.c
159
@@ -XXX,XX +XXX,XX @@
316
@@ -XXX,XX +XXX,XX @@
160
+/*
317
+/*
161
+ * Allwinner R40 Clock Control Unit emulation
318
+ * SMSC LAN9118 PHY emulation
162
+ *
319
+ *
163
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
321
+ * Written by Paul Brook
164
+ *
322
+ *
165
+ * This program is free software: you can redistribute it and/or modify
323
+ * This code is licensed under the GNU GPL v2
166
+ * it under the terms of the GNU General Public License as published by
167
+ * the Free Software Foundation, either version 2 of the License, or
168
+ * (at your option) any later version.
169
+ *
324
+ *
170
+ * This program is distributed in the hope that it will be useful,
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
171
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
326
+ * GNU GPL, version 2 or (at your option) any later version.
172
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
173
+ * GNU General Public License for more details.
174
+ *
175
+ * You should have received a copy of the GNU General Public License
176
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
177
+ */
327
+ */
178
+
328
+
179
+#include "qemu/osdep.h"
329
+#include "qemu/osdep.h"
180
+#include "qemu/units.h"
330
+#include "hw/net/lan9118_phy.h"
181
+#include "hw/sysbus.h"
331
+#include "hw/irq.h"
332
+#include "hw/resettable.h"
182
+#include "migration/vmstate.h"
333
+#include "migration/vmstate.h"
183
+#include "qemu/log.h"
334
+#include "qemu/log.h"
184
+#include "qemu/module.h"
335
+
185
+#include "hw/misc/allwinner-r40-ccu.h"
336
+#define PHY_INT_ENERGYON (1 << 7)
186
+
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
187
+/* CCU register offsets */
338
+#define PHY_INT_FAULT (1 << 5)
188
+enum {
339
+#define PHY_INT_DOWN (1 << 4)
189
+ REG_PLL_CPUX_CTRL = 0x0000,
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
190
+ REG_PLL_AUDIO_CTRL = 0x0008,
341
+#define PHY_INT_PARFAULT (1 << 2)
191
+ REG_PLL_VIDEO0_CTRL = 0x0010,
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
192
+ REG_PLL_VE_CTRL = 0x0018,
343
+
193
+ REG_PLL_DDR0_CTRL = 0x0020,
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
194
+ REG_PLL_PERIPH0_CTRL = 0x0028,
345
+{
195
+ REG_PLL_PERIPH1_CTRL = 0x002c,
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
196
+ REG_PLL_VIDEO1_CTRL = 0x0030,
347
+}
197
+ REG_PLL_SATA_CTRL = 0x0034,
348
+
198
+ REG_PLL_GPU_CTRL = 0x0038,
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
199
+ REG_PLL_MIPI_CTRL = 0x0040,
350
+{
200
+ REG_PLL_DE_CTRL = 0x0048,
351
+ uint16_t val;
201
+ REG_PLL_DDR1_CTRL = 0x004c,
352
+
202
+ REG_AHB1_APB1_CFG = 0x0054,
353
+ switch (reg) {
203
+ REG_APB2_CFG = 0x0058,
354
+ case 0: /* Basic Control */
204
+ REG_MMC0_CLK = 0x0088,
355
+ return s->control;
205
+ REG_MMC1_CLK = 0x008c,
356
+ case 1: /* Basic Status */
206
+ REG_MMC2_CLK = 0x0090,
357
+ return s->status;
207
+ REG_MMC3_CLK = 0x0094,
358
+ case 2: /* ID1 */
208
+ REG_USBPHY_CFG = 0x00cc,
359
+ return 0x0007;
209
+ REG_PLL_DDR_AUX = 0x00f0,
360
+ case 3: /* ID2 */
210
+ REG_DRAM_CFG = 0x00f4,
361
+ return 0xc0d1;
211
+ REG_PLL_DDR1_CFG = 0x00f8,
362
+ case 4: /* Auto-neg advertisement */
212
+ REG_DRAM_CLK_GATING = 0x0100,
363
+ return s->advertise;
213
+ REG_GMAC_CLK = 0x0164,
364
+ case 5: /* Auto-neg Link Partner Ability */
214
+ REG_SYS_32K_CLK = 0x0310,
365
+ return 0x0f71;
215
+ REG_PLL_LOCK_CTRL = 0x0320,
366
+ case 6: /* Auto-neg Expansion */
216
+};
367
+ return 1;
217
+
368
+ /* TODO 17, 18, 27, 29, 30, 31 */
218
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
369
+ case 29: /* Interrupt source. */
219
+
370
+ val = s->ints;
220
+/* CCU register flags */
371
+ s->ints = 0;
221
+enum {
372
+ lan9118_phy_update_irq(s);
222
+ REG_PLL_ENABLE = (1 << 31),
373
+ return val;
223
+ REG_PLL_LOCK = (1 << 28),
374
+ case 30: /* Interrupt mask */
224
+};
375
+ return s->int_mask;
225
+
376
+ default:
226
+static uint64_t allwinner_r40_ccu_read(void *opaque, hwaddr offset,
377
+ qemu_log_mask(LOG_GUEST_ERROR,
227
+ unsigned size)
378
+ "lan9118_phy_read: PHY read reg %d\n", reg);
228
+{
229
+ const AwR40ClockCtlState *s = AW_R40_CCU(opaque);
230
+ const uint32_t idx = REG_INDEX(offset);
231
+
232
+ switch (offset) {
233
+ case 0x324 ... AW_R40_CCU_IOSIZE:
234
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
235
+ __func__, (uint32_t)offset);
236
+ return 0;
379
+ return 0;
237
+ }
380
+ }
238
+
381
+}
239
+ return s->regs[idx];
382
+
240
+}
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
241
+
384
+{
242
+static void allwinner_r40_ccu_write(void *opaque, hwaddr offset,
385
+ switch (reg) {
243
+ uint64_t val, unsigned size)
386
+ case 0: /* Basic Control */
244
+{
387
+ if (val & 0x8000) {
245
+ AwR40ClockCtlState *s = AW_R40_CCU(opaque);
388
+ lan9118_phy_reset(s);
246
+
389
+ break;
247
+ switch (offset) {
390
+ }
248
+ case REG_DRAM_CFG: /* DRAM Configuration(for DDR0) */
391
+ s->control = val & 0x7980;
249
+ /* bit16: SDRCLK_UPD (SDRCLK configuration 0 update) */
392
+ /* Complete autonegotiation immediately. */
250
+ val &= ~(1 << 16);
393
+ if (val & 0x1000) {
251
+ break;
394
+ s->status |= 0x0020;
252
+ case REG_PLL_DDR1_CTRL: /* DDR1 Control register */
253
+ /* bit30: SDRPLL_UPD */
254
+ val &= ~(1 << 30);
255
+ if (val & REG_PLL_ENABLE) {
256
+ val |= REG_PLL_LOCK;
257
+ }
395
+ }
258
+ break;
396
+ break;
259
+ case REG_PLL_CPUX_CTRL:
397
+ case 4: /* Auto-neg advertisement */
260
+ case REG_PLL_AUDIO_CTRL:
398
+ s->advertise = (val & 0x2d7f) | 0x80;
261
+ case REG_PLL_VE_CTRL:
262
+ case REG_PLL_VIDEO0_CTRL:
263
+ case REG_PLL_DDR0_CTRL:
264
+ case REG_PLL_PERIPH0_CTRL:
265
+ case REG_PLL_PERIPH1_CTRL:
266
+ case REG_PLL_VIDEO1_CTRL:
267
+ case REG_PLL_SATA_CTRL:
268
+ case REG_PLL_GPU_CTRL:
269
+ case REG_PLL_MIPI_CTRL:
270
+ case REG_PLL_DE_CTRL:
271
+ if (val & REG_PLL_ENABLE) {
272
+ val |= REG_PLL_LOCK;
273
+ }
274
+ break;
399
+ break;
275
+ case 0x324 ... AW_R40_CCU_IOSIZE:
400
+ /* TODO 17, 18, 27, 31 */
276
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
401
+ case 30: /* Interrupt mask */
277
+ __func__, (uint32_t)offset);
402
+ s->int_mask = val & 0xff;
403
+ lan9118_phy_update_irq(s);
278
+ break;
404
+ break;
279
+ default:
405
+ default:
280
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
406
+ qemu_log_mask(LOG_GUEST_ERROR,
281
+ __func__, (uint32_t)offset);
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
282
+ break;
283
+ }
408
+ }
284
+
409
+}
285
+ s->regs[REG_INDEX(offset)] = (uint32_t) val;
410
+
286
+}
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
287
+
412
+{
288
+static const MemoryRegionOps allwinner_r40_ccu_ops = {
413
+ s->link_down = link_down;
289
+ .read = allwinner_r40_ccu_read,
414
+
290
+ .write = allwinner_r40_ccu_write,
415
+ /* Autonegotiation status mirrors link status. */
291
+ .endianness = DEVICE_NATIVE_ENDIAN,
416
+ if (link_down) {
292
+ .valid = {
417
+ s->status &= ~0x0024;
293
+ .min_access_size = 4,
418
+ s->ints |= PHY_INT_DOWN;
294
+ .max_access_size = 4,
419
+ } else {
295
+ },
420
+ s->status |= 0x0024;
296
+ .impl.min_access_size = 4,
421
+ s->ints |= PHY_INT_ENERGYON;
297
+};
422
+ s->ints |= PHY_INT_AUTONEG_COMPLETE;
298
+
423
+ }
299
+static void allwinner_r40_ccu_reset(DeviceState *dev)
424
+ lan9118_phy_update_irq(s);
300
+{
425
+}
301
+ AwR40ClockCtlState *s = AW_R40_CCU(dev);
426
+
302
+
427
+void lan9118_phy_reset(Lan9118PhyState *s)
303
+ memset(s->regs, 0, sizeof(s->regs));
428
+{
304
+
429
+ s->control = 0x3000;
305
+ /* Set default values for registers */
430
+ s->status = 0x7809;
306
+ s->regs[REG_INDEX(REG_PLL_CPUX_CTRL)] = 0x00001000;
431
+ s->advertise = 0x01e1;
307
+ s->regs[REG_INDEX(REG_PLL_AUDIO_CTRL)] = 0x00035514;
432
+ s->int_mask = 0;
308
+ s->regs[REG_INDEX(REG_PLL_VIDEO0_CTRL)] = 0x03006207;
433
+ s->ints = 0;
309
+ s->regs[REG_INDEX(REG_PLL_VE_CTRL)] = 0x03006207;
434
+ lan9118_phy_update_link(s, s->link_down);
310
+ s->regs[REG_INDEX(REG_PLL_DDR0_CTRL)] = 0x00001000,
435
+}
311
+ s->regs[REG_INDEX(REG_PLL_PERIPH0_CTRL)] = 0x00041811;
436
+
312
+ s->regs[REG_INDEX(REG_PLL_PERIPH1_CTRL)] = 0x00041811;
437
+static void lan9118_phy_reset_hold(Object *obj, ResetType type)
313
+ s->regs[REG_INDEX(REG_PLL_VIDEO1_CTRL)] = 0x03006207;
438
+{
314
+ s->regs[REG_INDEX(REG_PLL_SATA_CTRL)] = 0x00001811;
439
+ Lan9118PhyState *s = LAN9118_PHY(obj);
315
+ s->regs[REG_INDEX(REG_PLL_GPU_CTRL)] = 0x03006207;
440
+
316
+ s->regs[REG_INDEX(REG_PLL_MIPI_CTRL)] = 0x00000515;
441
+ lan9118_phy_reset(s);
317
+ s->regs[REG_INDEX(REG_PLL_DE_CTRL)] = 0x03006207;
442
+}
318
+ s->regs[REG_INDEX(REG_PLL_DDR1_CTRL)] = 0x00001800;
443
+
319
+ s->regs[REG_INDEX(REG_AHB1_APB1_CFG)] = 0x00001010;
444
+static void lan9118_phy_init(Object *obj)
320
+ s->regs[REG_INDEX(REG_APB2_CFG)] = 0x01000000;
445
+{
321
+ s->regs[REG_INDEX(REG_PLL_DDR_AUX)] = 0x00000001;
446
+ Lan9118PhyState *s = LAN9118_PHY(obj);
322
+ s->regs[REG_INDEX(REG_PLL_DDR1_CFG)] = 0x0ccca000;
447
+
323
+ s->regs[REG_INDEX(REG_SYS_32K_CLK)] = 0x0000000f;
448
+ qdev_init_gpio_out(DEVICE(s), &s->irq, 1);
324
+}
449
+}
325
+
450
+
326
+static void allwinner_r40_ccu_init(Object *obj)
451
+static const VMStateDescription vmstate_lan9118_phy = {
327
+{
452
+ .name = "lan9118-phy",
328
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
329
+ AwR40ClockCtlState *s = AW_R40_CCU(obj);
330
+
331
+ /* Memory mapping */
332
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_r40_ccu_ops, s,
333
+ TYPE_AW_R40_CCU, AW_R40_CCU_IOSIZE);
334
+ sysbus_init_mmio(sbd, &s->iomem);
335
+}
336
+
337
+static const VMStateDescription allwinner_r40_ccu_vmstate = {
338
+ .name = "allwinner-r40-ccu",
339
+ .version_id = 1,
453
+ .version_id = 1,
340
+ .minimum_version_id = 1,
454
+ .minimum_version_id = 1,
341
+ .fields = (VMStateField[]) {
455
+ .fields = (const VMStateField[]) {
342
+ VMSTATE_UINT32_ARRAY(regs, AwR40ClockCtlState, AW_R40_CCU_REGS_NUM),
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
343
+ VMSTATE_END_OF_LIST()
462
+ VMSTATE_END_OF_LIST()
344
+ }
463
+ }
345
+};
464
+};
346
+
465
+
347
+static void allwinner_r40_ccu_class_init(ObjectClass *klass, void *data)
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
348
+{
467
+{
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
349
+ DeviceClass *dc = DEVICE_CLASS(klass);
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
350
+
470
+
351
+ dc->reset = allwinner_r40_ccu_reset;
471
+ rc->phases.hold = lan9118_phy_reset_hold;
352
+ dc->vmsd = &allwinner_r40_ccu_vmstate;
472
+ dc->vmsd = &vmstate_lan9118_phy;
353
+}
473
+}
354
+
474
+
355
+static const TypeInfo allwinner_r40_ccu_info = {
475
+static const TypeInfo types[] = {
356
+ .name = TYPE_AW_R40_CCU,
476
+ {
357
+ .parent = TYPE_SYS_BUS_DEVICE,
477
+ .name = TYPE_LAN9118_PHY,
358
+ .instance_init = allwinner_r40_ccu_init,
478
+ .parent = TYPE_SYS_BUS_DEVICE,
359
+ .instance_size = sizeof(AwR40ClockCtlState),
479
+ .instance_size = sizeof(Lan9118PhyState),
360
+ .class_init = allwinner_r40_ccu_class_init,
480
+ .instance_init = lan9118_phy_init,
481
+ .class_init = lan9118_phy_class_init,
482
+ }
361
+};
483
+};
362
+
484
+
363
+static void allwinner_r40_ccu_register(void)
485
+DEFINE_TYPES(types)
364
+{
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
365
+ type_register_static(&allwinner_r40_ccu_info);
366
+}
367
+
368
+type_init(allwinner_r40_ccu_register)
369
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
370
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
371
--- a/hw/misc/meson.build
488
--- a/hw/net/Kconfig
372
+++ b/hw/misc/meson.build
489
+++ b/hw/net/Kconfig
373
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
374
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
491
config SMC91C111
375
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-sysctrl.c'))
492
bool
376
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sid.c'))
493
377
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40-ccu.c'))
494
+config LAN9118_PHY
378
softmmu_ss.add(when: 'CONFIG_AXP209_PMU', if_true: files('axp209.c'))
495
+ bool
379
softmmu_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
496
+
380
softmmu_ss.add(when: 'CONFIG_NSERIES', if_true: files('cbus.c'))
497
config LAN9118
498
bool
499
+ select LAN9118_PHY
500
select PTIMER
501
502
config NE2000_ISA
503
diff --git a/hw/net/meson.build b/hw/net/meson.build
504
index XXXXXXX..XXXXXXX 100644
505
--- a/hw/net/meson.build
506
+++ b/hw/net/meson.build
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
508
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
512
system_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c'))
513
system_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c'))
514
system_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c'))
381
--
515
--
382
2.34.1
516
2.34.1
diff view generated by jsdifflib
1
From: Zhuojia Shen <chaosdefinition@hotmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
DC CVAP and DC CVADP instructions can be executed in EL0 on Linux,
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
either directly when SCTLR_EL1.UCI == 1 or emulated by the kernel (see
4
imx_fec having more logging and tracing. Merge these improvements into
5
user_cache_maint_handler() in arch/arm64/kernel/traps.c).
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
6
6
7
This patch enables execution of the two instructions in user mode
7
Some migration state how resides in the new device model which breaks migration
8
emulation.
8
compatibility for the following machines:
9
* imx25-pdk
10
* sabrelite
11
* mcimx7d-sabre
12
* mcimx6ul-evk
9
13
10
Signed-off-by: Zhuojia Shen <chaosdefinition@hotmail.com>
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20241102125724.532843-3-shentey@gmail.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
19
---
15
target/arm/helper.c | 6 ++----
20
include/hw/net/imx_fec.h | 9 ++-
16
1 file changed, 2 insertions(+), 4 deletions(-)
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
22
hw/net/lan9118_phy.c | 82 ++++++++++++++++------
23
hw/net/Kconfig | 1 +
24
hw/net/trace-events | 10 +--
25
5 files changed, 85 insertions(+), 163 deletions(-)
17
26
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
19
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
29
--- a/include/hw/net/imx_fec.h
21
+++ b/target/arm/helper.c
30
+++ b/include/hw/net/imx_fec.h
22
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo rndr_reginfo[] = {
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
23
.access = PL0_R, .readfn = rndr_readfn },
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
},
24
};
80
};
25
81
26
-#ifndef CONFIG_USER_ONLY
82
-#define PHY_INT_ENERGYON (1 << 7)
27
static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
83
-#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
28
uint64_t value)
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)
29
{
99
{
30
@@ -XXX,XX +XXX,XX @@ static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
100
- imx_eth_update(s);
31
/* This won't be crossing page boundaries */
101
-}
32
haddr = probe_read(env, vaddr, dline_size, mem_idx, GETPC());
102
-
33
if (haddr) {
103
-static void imx_phy_update_link(IMXFECState *s)
34
+#ifndef CONFIG_USER_ONLY
104
-{
35
105
- /* Autonegotiation status mirrors link status. */
36
ram_addr_t offset;
106
- if (qemu_get_queue(s->nic)->link_down) {
37
MemoryRegion *mr;
107
- trace_imx_phy_update_link("down");
38
@@ -XXX,XX +XXX,XX @@ static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
108
- s->phy_status &= ~0x0024;
39
if (mr) {
109
- s->phy_int |= PHY_INT_DOWN;
40
memory_region_writeback(mr, offset, dline_size);
110
- } else {
111
- trace_imx_phy_update_link("up");
112
- s->phy_status |= 0x0024;
113
- s->phy_int |= PHY_INT_ENERGYON;
114
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
115
- }
116
- imx_phy_update_irq(s);
117
+ imx_eth_update(opaque);
118
}
119
120
static void imx_eth_set_link(NetClientState *nc)
121
{
122
- imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
123
-}
124
-
125
-static void imx_phy_reset(IMXFECState *s)
126
-{
127
- trace_imx_phy_reset();
128
-
129
- s->phy_status = 0x7809;
130
- s->phy_control = 0x3000;
131
- s->phy_advertise = 0x01e1;
132
- s->phy_int_mask = 0;
133
- s->phy_int = 0;
134
- imx_phy_update_link(s);
135
+ lan9118_phy_update_link(&IMX_FEC(qemu_get_nic_opaque(nc))->mii,
136
+ nc->link_down);
137
}
138
139
static uint32_t imx_phy_read(IMXFECState *s, int reg)
140
{
141
- uint32_t val;
142
uint32_t phy = reg / 32;
143
144
if (!s->phy_connected) {
145
@@ -XXX,XX +XXX,XX @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
146
147
reg %= 32;
148
149
- switch (reg) {
150
- case 0: /* Basic Control */
151
- val = s->phy_control;
152
- break;
153
- case 1: /* Basic Status */
154
- val = s->phy_status;
155
- break;
156
- case 2: /* ID1 */
157
- val = 0x0007;
158
- break;
159
- case 3: /* ID2 */
160
- val = 0xc0d1;
161
- break;
162
- case 4: /* Auto-neg advertisement */
163
- val = s->phy_advertise;
164
- break;
165
- case 5: /* Auto-neg Link Partner Ability */
166
- val = 0x0f71;
167
- break;
168
- case 6: /* Auto-neg Expansion */
169
- val = 1;
170
- break;
171
- case 29: /* Interrupt source. */
172
- val = s->phy_int;
173
- s->phy_int = 0;
174
- imx_phy_update_irq(s);
175
- break;
176
- case 30: /* Interrupt mask */
177
- val = s->phy_int_mask;
178
- break;
179
- case 17:
180
- case 18:
181
- case 27:
182
- case 31:
183
- qemu_log_mask(LOG_UNIMP, "[%s.phy]%s: reg %d not implemented\n",
184
- TYPE_IMX_FEC, __func__, reg);
185
- val = 0;
186
- break;
187
- default:
188
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
189
- TYPE_IMX_FEC, __func__, reg);
190
- val = 0;
191
- break;
192
- }
193
-
194
- trace_imx_phy_read(val, phy, reg);
195
-
196
- return val;
197
+ return lan9118_phy_read(&s->mii, reg);
198
}
199
200
static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
201
@@ -XXX,XX +XXX,XX @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
202
203
reg %= 32;
204
205
- trace_imx_phy_write(val, phy, reg);
206
-
207
- switch (reg) {
208
- case 0: /* Basic Control */
209
- if (val & 0x8000) {
210
- imx_phy_reset(s);
211
- } else {
212
- s->phy_control = val & 0x7980;
213
- /* Complete autonegotiation immediately. */
214
- if (val & 0x1000) {
215
- s->phy_status |= 0x0020;
216
- }
217
- }
218
- break;
219
- case 4: /* Auto-neg advertisement */
220
- s->phy_advertise = (val & 0x2d7f) | 0x80;
221
- break;
222
- case 30: /* Interrupt mask */
223
- s->phy_int_mask = val & 0xff;
224
- imx_phy_update_irq(s);
225
- break;
226
- case 17:
227
- case 18:
228
- case 27:
229
- case 31:
230
- qemu_log_mask(LOG_UNIMP, "[%s.phy)%s: reg %d not implemented\n",
231
- TYPE_IMX_FEC, __func__, reg);
232
- break;
233
- default:
234
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
235
- TYPE_IMX_FEC, __func__, reg);
236
- break;
237
- }
238
+ lan9118_phy_write(&s->mii, reg, val);
239
}
240
241
static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
242
@@ -XXX,XX +XXX,XX @@ static void imx_eth_reset(DeviceState *d)
243
244
s->rx_descriptor = 0;
245
memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
246
-
247
- /* We also reset the PHY */
248
- imx_phy_reset(s);
249
}
250
251
static uint32_t imx_default_read(IMXFECState *s, uint32_t index)
252
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
253
sysbus_init_irq(sbd, &s->irq[0]);
254
sysbus_init_irq(sbd, &s->irq[1]);
255
256
+ qemu_init_irq(&s->mii_irq, imx_phy_update_irq, s, 0);
257
+ object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
258
+ if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
259
+ return;
260
+ }
261
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
262
+
263
qemu_macaddr_default_if_unset(&s->conf.macaddr);
264
265
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
266
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/hw/net/lan9118_phy.c
269
+++ b/hw/net/lan9118_phy.c
270
@@ -XXX,XX +XXX,XX @@
271
* Copyright (c) 2009 CodeSourcery, LLC.
272
* Written by Paul Brook
273
*
274
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
275
+ *
276
* This code is licensed under the GNU GPL v2
277
*
278
* Contributions after 2012-01-13 are licensed under the terms of the
279
@@ -XXX,XX +XXX,XX @@
280
#include "hw/resettable.h"
281
#include "migration/vmstate.h"
282
#include "qemu/log.h"
283
+#include "trace.h"
284
285
#define PHY_INT_ENERGYON (1 << 7)
286
#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
287
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
288
289
switch (reg) {
290
case 0: /* Basic Control */
291
- return s->control;
292
+ val = s->control;
293
+ break;
294
case 1: /* Basic Status */
295
- return s->status;
296
+ val = s->status;
297
+ break;
298
case 2: /* ID1 */
299
- return 0x0007;
300
+ val = 0x0007;
301
+ break;
302
case 3: /* ID2 */
303
- return 0xc0d1;
304
+ val = 0xc0d1;
305
+ break;
306
case 4: /* Auto-neg advertisement */
307
- return s->advertise;
308
+ val = s->advertise;
309
+ break;
310
case 5: /* Auto-neg Link Partner Ability */
311
- return 0x0f71;
312
+ val = 0x0f71;
313
+ break;
314
case 6: /* Auto-neg Expansion */
315
- return 1;
316
- /* TODO 17, 18, 27, 29, 30, 31 */
317
+ val = 1;
318
+ break;
319
case 29: /* Interrupt source. */
320
val = s->ints;
321
s->ints = 0;
322
lan9118_phy_update_irq(s);
323
- return val;
324
+ break;
325
case 30: /* Interrupt mask */
326
- return s->int_mask;
327
+ val = s->int_mask;
328
+ break;
329
+ case 17:
330
+ case 18:
331
+ case 27:
332
+ case 31:
333
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
334
+ __func__, reg);
335
+ val = 0;
336
+ break;
337
default:
338
- qemu_log_mask(LOG_GUEST_ERROR,
339
- "lan9118_phy_read: PHY read reg %d\n", reg);
340
- return 0;
341
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
342
+ __func__, reg);
343
+ val = 0;
344
+ break;
345
}
346
+
347
+ trace_lan9118_phy_read(val, reg);
348
+
349
+ return val;
350
}
351
352
void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
353
{
354
+ trace_lan9118_phy_write(val, reg);
355
+
356
switch (reg) {
357
case 0: /* Basic Control */
358
if (val & 0x8000) {
359
lan9118_phy_reset(s);
360
- break;
361
- }
362
- s->control = val & 0x7980;
363
- /* Complete autonegotiation immediately. */
364
- if (val & 0x1000) {
365
- s->status |= 0x0020;
366
+ } else {
367
+ s->control = val & 0x7980;
368
+ /* Complete autonegotiation immediately. */
369
+ if (val & 0x1000) {
370
+ s->status |= 0x0020;
371
+ }
41
}
372
}
42
+#endif /*CONFIG_USER_ONLY*/
373
break;
374
case 4: /* Auto-neg advertisement */
375
s->advertise = (val & 0x2d7f) | 0x80;
376
break;
377
- /* TODO 17, 18, 27, 31 */
378
case 30: /* Interrupt mask */
379
s->int_mask = val & 0xff;
380
lan9118_phy_update_irq(s);
381
break;
382
+ case 17:
383
+ case 18:
384
+ case 27:
385
+ case 31:
386
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
387
+ __func__, reg);
388
+ break;
389
default:
390
- qemu_log_mask(LOG_GUEST_ERROR,
391
- "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
392
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
393
+ __func__, reg);
394
+ break;
43
}
395
}
44
}
396
}
45
397
46
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dcpodp_reg[] = {
398
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
47
.fgt = FGT_DCCVADP,
399
48
.accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
400
/* Autonegotiation status mirrors link status. */
49
};
401
if (link_down) {
50
-#endif /*CONFIG_USER_ONLY*/
402
+ trace_lan9118_phy_update_link("down");
51
403
s->status &= ~0x0024;
52
static CPAccessResult access_aa64_tid5(CPUARMState *env, const ARMCPRegInfo *ri,
404
s->ints |= PHY_INT_DOWN;
53
bool isread)
405
} else {
54
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
406
+ trace_lan9118_phy_update_link("up");
55
if (cpu_isar_feature(aa64_tlbios, cpu)) {
407
s->status |= 0x0024;
56
define_arm_cp_regs(cpu, tlbios_reginfo);
408
s->ints |= PHY_INT_ENERGYON;
57
}
409
s->ints |= PHY_INT_AUTONEG_COMPLETE;
58
-#ifndef CONFIG_USER_ONLY
410
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
59
/* Data Cache clean instructions up to PoP */
411
60
if (cpu_isar_feature(aa64_dcpop, cpu)) {
412
void lan9118_phy_reset(Lan9118PhyState *s)
61
define_one_arm_cp_reg(cpu, dcpop_reg);
413
{
62
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
414
+ trace_lan9118_phy_reset();
63
define_one_arm_cp_reg(cpu, dcpodp_reg);
415
+
64
}
416
s->control = 0x3000;
65
}
417
s->status = 0x7809;
66
-#endif /*CONFIG_USER_ONLY*/
418
s->advertise = 0x01e1;
67
419
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_phy = {
68
/*
420
.version_id = 1,
69
* If full MTE is enabled, add all of the system registers.
421
.minimum_version_id = 1,
422
.fields = (const VMStateField[]) {
423
- VMSTATE_UINT16(control, Lan9118PhyState),
424
VMSTATE_UINT16(status, Lan9118PhyState),
425
+ VMSTATE_UINT16(control, Lan9118PhyState),
426
VMSTATE_UINT16(advertise, Lan9118PhyState),
427
VMSTATE_UINT16(ints, Lan9118PhyState),
428
VMSTATE_UINT16(int_mask, Lan9118PhyState),
429
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
430
index XXXXXXX..XXXXXXX 100644
431
--- a/hw/net/Kconfig
432
+++ b/hw/net/Kconfig
433
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_SUN8I_EMAC
434
435
config IMX_FEC
436
bool
437
+ select LAN9118_PHY
438
439
config CADENCE
440
bool
441
diff --git a/hw/net/trace-events b/hw/net/trace-events
442
index XXXXXXX..XXXXXXX 100644
443
--- a/hw/net/trace-events
444
+++ b/hw/net/trace-events
445
@@ -XXX,XX +XXX,XX @@ allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
446
allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
447
allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
448
449
+# lan9118_phy.c
450
+lan9118_phy_read(uint16_t val, int reg) "[0x%02x] -> 0x%04" PRIx16
451
+lan9118_phy_write(uint16_t val, int reg) "[0x%02x] <- 0x%04" PRIx16
452
+lan9118_phy_update_link(const char *s) "%s"
453
+lan9118_phy_reset(void) ""
454
+
455
# lance.c
456
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=0x%"PRIx64"val=0x%04x"
457
lance_mem_writew(uint64_t addr, uint32_t val) "addr=0x%"PRIx64"val=0x%04x"
458
@@ -XXX,XX +XXX,XX @@ i82596_set_multicast(uint16_t count) "Added %d multicast entries"
459
i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
460
461
# imx_fec.c
462
-imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
463
imx_phy_read_num(int phy, int configured) "read request from unconfigured phy %d (configured %d)"
464
-imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => phy[%d].reg[%d]"
465
imx_phy_write_num(int phy, int configured) "write request to unconfigured phy %d (configured %d)"
466
-imx_phy_update_link(const char *s) "%s"
467
-imx_phy_reset(void) ""
468
imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x"
469
imx_enet_read_bd(uint64_t addr, int flags, int len, int data, int options, int status) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x option 0x%04x status 0x%04x"
470
imx_eth_tx_bd_busy(void) "tx_bd ran out of descriptors to transmit"
70
--
471
--
71
2.34.1
472
2.34.1
diff view generated by jsdifflib
1
From: Zhuojia Shen <chaosdefinition@hotmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Test execution of DC CVAP and DC CVADP instructions under user mode
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
emulation.
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
5
5
6
Signed-off-by: Zhuojia Shen <chaosdefinition@hotmail.com>
6
Fixes: 2a424990170b "LAN9118 emulation"
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Tested-by: Guenter Roeck <linux@roeck-us.net>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241102125724.532843-4-shentey@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
tests/tcg/aarch64/dcpodp.c | 63 +++++++++++++++++++++++++++++++
13
hw/net/lan9118_phy.c | 2 +-
12
tests/tcg/aarch64/dcpop.c | 63 +++++++++++++++++++++++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
13
tests/tcg/aarch64/Makefile.target | 11 ++++++
14
3 files changed, 137 insertions(+)
15
create mode 100644 tests/tcg/aarch64/dcpodp.c
16
create mode 100644 tests/tcg/aarch64/dcpop.c
17
15
18
diff --git a/tests/tcg/aarch64/dcpodp.c b/tests/tcg/aarch64/dcpodp.c
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/tcg/aarch64/dcpodp.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * Test execution of DC CVADP instruction.
26
+ *
27
+ * Copyright (c) 2023 Zhuojia Shen <chaosdefinition@hotmail.com>
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
29
+ */
30
+
31
+#include <asm/hwcap.h>
32
+#include <sys/auxv.h>
33
+
34
+#include <signal.h>
35
+#include <stdbool.h>
36
+#include <stdio.h>
37
+#include <stdlib.h>
38
+
39
+#ifndef HWCAP2_DCPODP
40
+#define HWCAP2_DCPODP (1 << 0)
41
+#endif
42
+
43
+bool should_fail = false;
44
+
45
+static void signal_handler(int sig, siginfo_t *si, void *data)
46
+{
47
+ ucontext_t *uc = (ucontext_t *)data;
48
+
49
+ if (should_fail) {
50
+ uc->uc_mcontext.pc += 4;
51
+ } else {
52
+ exit(EXIT_FAILURE);
53
+ }
54
+}
55
+
56
+static int do_dc_cvadp(void)
57
+{
58
+ struct sigaction sa = {
59
+ .sa_flags = SA_SIGINFO,
60
+ .sa_sigaction = signal_handler,
61
+ };
62
+
63
+ sigemptyset(&sa.sa_mask);
64
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
65
+ perror("sigaction");
66
+ return EXIT_FAILURE;
67
+ }
68
+
69
+ asm volatile("dc cvadp, %0\n\t" :: "r"(&sa));
70
+
71
+ should_fail = true;
72
+ asm volatile("dc cvadp, %0\n\t" :: "r"(NULL));
73
+ should_fail = false;
74
+
75
+ return EXIT_SUCCESS;
76
+}
77
+
78
+int main(void)
79
+{
80
+ if (getauxval(AT_HWCAP2) & HWCAP2_DCPODP) {
81
+ return do_dc_cvadp();
82
+ } else {
83
+ printf("SKIP: no HWCAP2_DCPODP on this system\n");
84
+ return EXIT_SUCCESS;
85
+ }
86
+}
87
diff --git a/tests/tcg/aarch64/dcpop.c b/tests/tcg/aarch64/dcpop.c
88
new file mode 100644
89
index XXXXXXX..XXXXXXX
90
--- /dev/null
91
+++ b/tests/tcg/aarch64/dcpop.c
92
@@ -XXX,XX +XXX,XX @@
93
+/*
94
+ * Test execution of DC CVAP instruction.
95
+ *
96
+ * Copyright (c) 2023 Zhuojia Shen <chaosdefinition@hotmail.com>
97
+ * SPDX-License-Identifier: GPL-2.0-or-later
98
+ */
99
+
100
+#include <asm/hwcap.h>
101
+#include <sys/auxv.h>
102
+
103
+#include <signal.h>
104
+#include <stdbool.h>
105
+#include <stdio.h>
106
+#include <stdlib.h>
107
+
108
+#ifndef HWCAP_DCPOP
109
+#define HWCAP_DCPOP (1 << 16)
110
+#endif
111
+
112
+bool should_fail = false;
113
+
114
+static void signal_handler(int sig, siginfo_t *si, void *data)
115
+{
116
+ ucontext_t *uc = (ucontext_t *)data;
117
+
118
+ if (should_fail) {
119
+ uc->uc_mcontext.pc += 4;
120
+ } else {
121
+ exit(EXIT_FAILURE);
122
+ }
123
+}
124
+
125
+static int do_dc_cvap(void)
126
+{
127
+ struct sigaction sa = {
128
+ .sa_flags = SA_SIGINFO,
129
+ .sa_sigaction = signal_handler,
130
+ };
131
+
132
+ sigemptyset(&sa.sa_mask);
133
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
134
+ perror("sigaction");
135
+ return EXIT_FAILURE;
136
+ }
137
+
138
+ asm volatile("dc cvap, %0\n\t" :: "r"(&sa));
139
+
140
+ should_fail = true;
141
+ asm volatile("dc cvap, %0\n\t" :: "r"(NULL));
142
+ should_fail = false;
143
+
144
+ return EXIT_SUCCESS;
145
+}
146
+
147
+int main(void)
148
+{
149
+ if (getauxval(AT_HWCAP) & HWCAP_DCPOP) {
150
+ return do_dc_cvap();
151
+ } else {
152
+ printf("SKIP: no HWCAP_DCPOP on this system\n");
153
+ return EXIT_SUCCESS;
154
+ }
155
+}
156
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
157
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
158
--- a/tests/tcg/aarch64/Makefile.target
18
--- a/hw/net/lan9118_phy.c
159
+++ b/tests/tcg/aarch64/Makefile.target
19
+++ b/hw/net/lan9118_phy.c
160
@@ -XXX,XX +XXX,XX @@ config-cc.mak: Makefile
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
161
    $(quiet-@)( \
21
val = s->advertise;
162
     $(call cc-option,-march=armv8.1-a+sve, CROSS_CC_HAS_SVE); \
22
break;
163
     $(call cc-option,-march=armv8.1-a+sve2, CROSS_CC_HAS_SVE2); \
23
case 5: /* Auto-neg Link Partner Ability */
164
+     $(call cc-option,-march=armv8.2-a, CROSS_CC_HAS_ARMV8_2); \
24
- val = 0x0f71;
165
     $(call cc-option,-march=armv8.3-a, CROSS_CC_HAS_ARMV8_3); \
25
+ val = 0x0fe1;
166
+     $(call cc-option,-march=armv8.5-a, CROSS_CC_HAS_ARMV8_5); \
26
break;
167
     $(call cc-option,-mbranch-protection=standard, CROSS_CC_HAS_ARMV8_BTI); \
27
case 6: /* Auto-neg Expansion */
168
     $(call cc-option,-march=armv8.5-a+memtag, CROSS_CC_HAS_ARMV8_MTE); \
28
val = 1;
169
     $(call cc-option,-march=armv9-a+sme, CROSS_CC_HAS_ARMV9_SME)) 3> config-cc.mak
170
-include config-cc.mak
171
172
+ifneq ($(CROSS_CC_HAS_ARMV8_2),)
173
+AARCH64_TESTS += dcpop
174
+dcpop: CFLAGS += -march=armv8.2-a
175
+endif
176
+ifneq ($(CROSS_CC_HAS_ARMV8_5),)
177
+AARCH64_TESTS += dcpodp
178
+dcpodp: CFLAGS += -march=armv8.5-a
179
+endif
180
+
181
# Pauth Tests
182
ifneq ($(CROSS_CC_HAS_ARMV8_3),)
183
AARCH64_TESTS += pauth-1 pauth-2 pauth-4 pauth-5
184
--
29
--
185
2.34.1
30
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Document the meaning of exclusive_high in a big-endian context,
3
Prefer named constants over magic values for better readability.
4
and why we can't change it now.
5
4
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Message-id: 20230530191438.411344-2-richard.henderson@linaro.org
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>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/cpu.h | 8 ++++++++
11
include/hw/net/mii.h | 6 +++++
12
1 file changed, 8 insertions(+)
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
13
2 files changed, 46 insertions(+), 23 deletions(-)
13
14
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
--- a/include/hw/net/mii.h
17
+++ b/target/arm/cpu.h
18
+++ b/include/hw/net/mii.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
19
@@ -XXX,XX +XXX,XX @@
19
uint64_t zcr_el[4]; /* ZCR_EL[1-3] */
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
20
uint64_t smcr_el[4]; /* SMCR_EL[1-3] */
21
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
21
} vfp;
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
22
+
42
+
23
uint64_t exclusive_addr;
43
/* RealTek 8211E */
24
uint64_t exclusive_val;
44
#define RTL8211E_PHYID1 0x001c
25
+ /*
45
#define RTL8211E_PHYID2 0xc915
26
+ * Contains the 'val' for the second 64-bit register of LDXP, which comes
46
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
27
+ * from the higher address, not the high part of a complete 128-bit value.
47
index XXXXXXX..XXXXXXX 100644
28
+ * In some ways it might be more convenient to record the exclusive value
48
--- a/hw/net/lan9118_phy.c
29
+ * as the low and high halves of a 128 bit data value, but the current
49
+++ b/hw/net/lan9118_phy.c
30
+ * semantics of these fields are baked into the migration format.
50
@@ -XXX,XX +XXX,XX @@
31
+ */
51
32
uint64_t exclusive_high;
52
#include "qemu/osdep.h"
33
53
#include "hw/net/lan9118_phy.h"
34
/* iwMMXt coprocessor state. */
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);
35
--
166
--
36
2.34.1
167
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Round len_align to 16 instead of 8, handling an odd 8-byte as part
3
The real device advertises this mode and the device model already advertises
4
of the tail. Use MO_ATOM_NONE to indicate that all of these memory
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
ops have only byte atomicity.
5
make the model more realistic.
6
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 20230530191438.411344-8-richard.henderson@linaro.org
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/tcg/translate-sve.c | 95 +++++++++++++++++++++++++---------
13
hw/net/lan9118_phy.c | 4 ++--
13
1 file changed, 70 insertions(+), 25 deletions(-)
14
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
15
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/tcg/translate-sve.c
18
--- a/hw/net/lan9118_phy.c
18
+++ b/target/arm/tcg/translate-sve.c
19
+++ b/hw/net/lan9118_phy.c
19
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(UCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz,
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
20
void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
21
break;
21
int len, int rn, int imm)
22
case MII_ANAR:
22
{
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
23
- int len_align = QEMU_ALIGN_DOWN(len, 8);
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
24
- int len_remain = len % 8;
25
- MII_ANAR_SELECT))
25
- int nparts = len / 8 + ctpop8(len_remain);
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
26
+ int len_align = QEMU_ALIGN_DOWN(len, 16);
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
27
+ int len_remain = len % 16;
28
| MII_ANAR_TX;
28
+ int nparts = len / 16 + ctpop8(len_remain);
29
break;
29
int midx = get_mem_index(s);
30
case 30: /* Interrupt mask */
30
TCGv_i64 dirty_addr, clean_addr, t0, t1;
31
+ TCGv_i128 t16;
32
33
dirty_addr = tcg_temp_new_i64();
34
tcg_gen_addi_i64(dirty_addr, cpu_reg_sp(s, rn), imm);
35
@@ -XXX,XX +XXX,XX @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
36
int i;
37
38
t0 = tcg_temp_new_i64();
39
- for (i = 0; i < len_align; i += 8) {
40
- tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
41
+ t1 = tcg_temp_new_i64();
42
+ t16 = tcg_temp_new_i128();
43
+
44
+ for (i = 0; i < len_align; i += 16) {
45
+ tcg_gen_qemu_ld_i128(t16, clean_addr, midx,
46
+ MO_LE | MO_128 | MO_ATOM_NONE);
47
+ tcg_gen_extr_i128_i64(t0, t1, t16);
48
tcg_gen_st_i64(t0, base, vofs + i);
49
- tcg_gen_addi_i64(clean_addr, clean_addr, 8);
50
+ tcg_gen_st_i64(t1, base, vofs + i + 8);
51
+ tcg_gen_addi_i64(clean_addr, clean_addr, 16);
52
}
53
} else {
54
TCGLabel *loop = gen_new_label();
55
@@ -XXX,XX +XXX,XX @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
56
tcg_gen_movi_ptr(i, 0);
57
gen_set_label(loop);
58
59
- t0 = tcg_temp_new_i64();
60
- tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
61
- tcg_gen_addi_i64(clean_addr, clean_addr, 8);
62
+ t16 = tcg_temp_new_i128();
63
+ tcg_gen_qemu_ld_i128(t16, clean_addr, midx,
64
+ MO_LE | MO_128 | MO_ATOM_NONE);
65
+ tcg_gen_addi_i64(clean_addr, clean_addr, 16);
66
67
tp = tcg_temp_new_ptr();
68
tcg_gen_add_ptr(tp, base, i);
69
- tcg_gen_addi_ptr(i, i, 8);
70
+ tcg_gen_addi_ptr(i, i, 16);
71
+
72
+ t0 = tcg_temp_new_i64();
73
+ t1 = tcg_temp_new_i64();
74
+ tcg_gen_extr_i128_i64(t0, t1, t16);
75
+
76
tcg_gen_st_i64(t0, tp, vofs);
77
+ tcg_gen_st_i64(t1, tp, vofs + 8);
78
79
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
80
}
81
@@ -XXX,XX +XXX,XX @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
82
* Predicate register loads can be any multiple of 2.
83
* Note that we still store the entire 64-bit unit into cpu_env.
84
*/
85
+ if (len_remain >= 8) {
86
+ t0 = tcg_temp_new_i64();
87
+ tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ | MO_ATOM_NONE);
88
+ tcg_gen_st_i64(t0, base, vofs + len_align);
89
+ len_remain -= 8;
90
+ len_align += 8;
91
+ if (len_remain) {
92
+ tcg_gen_addi_i64(clean_addr, clean_addr, 8);
93
+ }
94
+ }
95
if (len_remain) {
96
t0 = tcg_temp_new_i64();
97
switch (len_remain) {
98
@@ -XXX,XX +XXX,XX @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
99
case 4:
100
case 8:
101
tcg_gen_qemu_ld_i64(t0, clean_addr, midx,
102
- MO_LE | ctz32(len_remain));
103
+ MO_LE | ctz32(len_remain) | MO_ATOM_NONE);
104
break;
105
106
case 6:
107
t1 = tcg_temp_new_i64();
108
- tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUL);
109
+ tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUL | MO_ATOM_NONE);
110
tcg_gen_addi_i64(clean_addr, clean_addr, 4);
111
- tcg_gen_qemu_ld_i64(t1, clean_addr, midx, MO_LEUW);
112
+ tcg_gen_qemu_ld_i64(t1, clean_addr, midx, MO_LEUW | MO_ATOM_NONE);
113
tcg_gen_deposit_i64(t0, t0, t1, 32, 32);
114
break;
115
116
@@ -XXX,XX +XXX,XX @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
117
void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
118
int len, int rn, int imm)
119
{
120
- int len_align = QEMU_ALIGN_DOWN(len, 8);
121
- int len_remain = len % 8;
122
- int nparts = len / 8 + ctpop8(len_remain);
123
+ int len_align = QEMU_ALIGN_DOWN(len, 16);
124
+ int len_remain = len % 16;
125
+ int nparts = len / 16 + ctpop8(len_remain);
126
int midx = get_mem_index(s);
127
- TCGv_i64 dirty_addr, clean_addr, t0;
128
+ TCGv_i64 dirty_addr, clean_addr, t0, t1;
129
+ TCGv_i128 t16;
130
131
dirty_addr = tcg_temp_new_i64();
132
tcg_gen_addi_i64(dirty_addr, cpu_reg_sp(s, rn), imm);
133
@@ -XXX,XX +XXX,XX @@ void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
134
int i;
135
136
t0 = tcg_temp_new_i64();
137
+ t1 = tcg_temp_new_i64();
138
+ t16 = tcg_temp_new_i128();
139
for (i = 0; i < len_align; i += 8) {
140
tcg_gen_ld_i64(t0, base, vofs + i);
141
- tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ);
142
- tcg_gen_addi_i64(clean_addr, clean_addr, 8);
143
+ tcg_gen_ld_i64(t1, base, vofs + i + 8);
144
+ tcg_gen_concat_i64_i128(t16, t0, t1);
145
+ tcg_gen_qemu_st_i128(t16, clean_addr, midx,
146
+ MO_LE | MO_128 | MO_ATOM_NONE);
147
+ tcg_gen_addi_i64(clean_addr, clean_addr, 16);
148
}
149
} else {
150
TCGLabel *loop = gen_new_label();
151
@@ -XXX,XX +XXX,XX @@ void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
152
gen_set_label(loop);
153
154
t0 = tcg_temp_new_i64();
155
+ t1 = tcg_temp_new_i64();
156
tp = tcg_temp_new_ptr();
157
tcg_gen_add_ptr(tp, base, i);
158
tcg_gen_ld_i64(t0, tp, vofs);
159
- tcg_gen_addi_ptr(i, i, 8);
160
+ tcg_gen_ld_i64(t1, tp, vofs + 8);
161
+ tcg_gen_addi_ptr(i, i, 16);
162
163
- tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ);
164
- tcg_gen_addi_i64(clean_addr, clean_addr, 8);
165
+ t16 = tcg_temp_new_i128();
166
+ tcg_gen_concat_i64_i128(t16, t0, t1);
167
+
168
+ tcg_gen_qemu_st_i128(t16, clean_addr, midx, MO_LEUQ);
169
+ tcg_gen_addi_i64(clean_addr, clean_addr, 16);
170
171
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
172
}
173
174
/* Predicate register stores can be any multiple of 2. */
175
+ if (len_remain >= 8) {
176
+ t0 = tcg_temp_new_i64();
177
+ tcg_gen_st_i64(t0, base, vofs + len_align);
178
+ tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ | MO_ATOM_NONE);
179
+ len_remain -= 8;
180
+ len_align += 8;
181
+ if (len_remain) {
182
+ tcg_gen_addi_i64(clean_addr, clean_addr, 8);
183
+ }
184
+ }
185
if (len_remain) {
186
t0 = tcg_temp_new_i64();
187
tcg_gen_ld_i64(t0, base, vofs + len_align);
188
@@ -XXX,XX +XXX,XX @@ void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
189
case 4:
190
case 8:
191
tcg_gen_qemu_st_i64(t0, clean_addr, midx,
192
- MO_LE | ctz32(len_remain));
193
+ MO_LE | ctz32(len_remain) | MO_ATOM_NONE);
194
break;
195
196
case 6:
197
- tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUL);
198
+ tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUL | MO_ATOM_NONE);
199
tcg_gen_addi_i64(clean_addr, clean_addr, 4);
200
tcg_gen_shri_i64(t0, t0, 32);
201
- tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUW);
202
+ tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUW | MO_ATOM_NONE);
203
break;
204
205
default:
206
--
31
--
207
2.34.1
32
2.34.1
diff view generated by jsdifflib
1
From: Francesco Cagnin <fcagnin@quarkslab.com>
1
For IEEE fused multiply-add, the (0 * inf) + NaN case should raise
2
Invalid for the multiplication of 0 by infinity. Currently we handle
3
this in the per-architecture ifdef ladder in pickNaNMulAdd().
4
However, since this isn't really architecture specific we can hoist
5
it up to the generic code.
2
6
3
Required for guest debugging. The code has been structured like the KVM
7
For the cases where the infzero test in pickNaNMulAdd was
4
counterpart.
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".
5
13
6
Signed-off-by: Francesco Cagnin <fcagnin@quarkslab.com>
14
For Arm, this looks like it might be a behaviour change because we
7
Message-id: 20230601153107.81955-4-fcagnin@quarkslab.com
15
used to set float_flag_invalid | float_flag_invalid_imz only if C is
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Message-id: 20241202131347.498124-2-peter.maydell@linaro.org
10
---
37
---
11
include/sysemu/hvf.h | 22 ++++++++
38
fpu/softfloat-parts.c.inc | 13 +++++++------
12
include/sysemu/hvf_int.h | 1 +
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
13
accel/hvf/hvf-accel-ops.c | 109 ++++++++++++++++++++++++++++++++++++++
40
2 files changed, 8 insertions(+), 34 deletions(-)
14
accel/hvf/hvf-all.c | 17 ++++++
15
target/arm/hvf/hvf.c | 63 ++++++++++++++++++++++
16
target/i386/hvf/hvf.c | 24 +++++++++
17
6 files changed, 236 insertions(+)
18
41
19
diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
20
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
21
--- a/include/sysemu/hvf.h
44
--- a/fpu/softfloat-parts.c.inc
22
+++ b/include/sysemu/hvf.h
45
+++ b/fpu/softfloat-parts.c.inc
23
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
24
#include "qom/object.h"
47
int ab_mask, int abc_mask)
25
48
{
26
#ifdef NEED_CPU_H
49
int which;
27
+#include "cpu.h"
50
+ bool infzero = (ab_mask == float_cmask_infzero);
28
51
29
#ifdef CONFIG_HVF
52
if (unlikely(abc_mask & float_cmask_snan)) {
30
uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
31
@@ -XXX,XX +XXX,XX @@ typedef struct HVFState HVFState;
32
DECLARE_INSTANCE_CHECKER(HVFState, HVF_STATE,
33
TYPE_HVF_ACCEL)
34
35
+#ifdef NEED_CPU_H
36
+struct hvf_sw_breakpoint {
37
+ target_ulong pc;
38
+ target_ulong saved_insn;
39
+ int use_count;
40
+ QTAILQ_ENTRY(hvf_sw_breakpoint) entry;
41
+};
42
+
43
+struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu,
44
+ target_ulong pc);
45
+int hvf_sw_breakpoints_active(CPUState *cpu);
46
+
47
+int hvf_arch_insert_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp);
48
+int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp);
49
+int hvf_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len,
50
+ int type);
51
+int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len,
52
+ int type);
53
+void hvf_arch_remove_all_hw_breakpoints(void);
54
+#endif /* NEED_CPU_H */
55
+
56
#endif
57
diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/sysemu/hvf_int.h
60
+++ b/include/sysemu/hvf_int.h
61
@@ -XXX,XX +XXX,XX @@ struct HVFState {
62
63
hvf_vcpu_caps *hvf_caps;
64
uint64_t vtimer_offset;
65
+ QTAILQ_HEAD(, hvf_sw_breakpoint) hvf_sw_breakpoints;
66
};
67
extern HVFState *hvf_state;
68
69
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/accel/hvf/hvf-accel-ops.c
72
+++ b/accel/hvf/hvf-accel-ops.c
73
@@ -XXX,XX +XXX,XX @@
74
#include "qemu/main-loop.h"
75
#include "exec/address-spaces.h"
76
#include "exec/exec-all.h"
77
+#include "exec/gdbstub.h"
78
#include "sysemu/cpus.h"
79
#include "sysemu/hvf.h"
80
#include "sysemu/hvf_int.h"
81
@@ -XXX,XX +XXX,XX @@ static int hvf_accel_init(MachineState *ms)
82
s->slots[x].slot_id = x;
83
}
54
}
84
55
85
+ QTAILQ_INIT(&s->hvf_sw_breakpoints);
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
86
+
57
- ab_mask == float_cmask_infzero, s);
87
hvf_state = s;
58
+ if (infzero) {
88
memory_listener_register(&hvf_memory_listener, &address_space_memory);
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
89
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
90
@@ -XXX,XX +XXX,XX @@ static void hvf_start_vcpu_thread(CPUState *cpu)
91
cpu, QEMU_THREAD_JOINABLE);
92
}
93
94
+static int hvf_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len)
95
+{
96
+ struct hvf_sw_breakpoint *bp;
97
+ int err;
98
+
99
+ if (type == GDB_BREAKPOINT_SW) {
100
+ bp = hvf_find_sw_breakpoint(cpu, addr);
101
+ if (bp) {
102
+ bp->use_count++;
103
+ return 0;
104
+ }
105
+
106
+ bp = g_new(struct hvf_sw_breakpoint, 1);
107
+ bp->pc = addr;
108
+ bp->use_count = 1;
109
+ err = hvf_arch_insert_sw_breakpoint(cpu, bp);
110
+ if (err) {
111
+ g_free(bp);
112
+ return err;
113
+ }
114
+
115
+ QTAILQ_INSERT_HEAD(&hvf_state->hvf_sw_breakpoints, bp, entry);
116
+ } else {
117
+ err = hvf_arch_insert_hw_breakpoint(addr, len, type);
118
+ if (err) {
119
+ return err;
120
+ }
121
+ }
61
+ }
122
+
62
+
123
+ CPU_FOREACH(cpu) {
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
124
+ err = hvf_update_guest_debug(cpu);
64
125
+ if (err) {
65
if (s->default_nan_mode || which == 3) {
126
+ return err;
66
- /*
127
+ }
67
- * Note that this check is after pickNaNMulAdd so that function
128
+ }
68
- * has an opportunity to set the Invalid flag for infzero.
129
+ return 0;
69
- */
130
+}
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
- }
131
+
112
+
132
+static int hvf_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len)
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
133
+{
114
if (is_snan(c_cls)) {
134
+ struct hvf_sw_breakpoint *bp;
115
return 2;
135
+ int err;
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
136
+
117
* to return an input NaN if we have one (ie c) rather than generating
137
+ if (type == GDB_BREAKPOINT_SW) {
118
* a default NaN
138
+ bp = hvf_find_sw_breakpoint(cpu, addr);
119
*/
139
+ if (!bp) {
120
- if (infzero) {
140
+ return -ENOENT;
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
141
+ }
122
- return 2;
142
+
123
- }
143
+ if (bp->use_count > 1) {
124
144
+ bp->use_count--;
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
145
+ return 0;
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
146
+ }
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
147
+
128
return 1;
148
+ err = hvf_arch_remove_sw_breakpoint(cpu, bp);
129
}
149
+ if (err) {
130
#elif defined(TARGET_RISCV)
150
+ return err;
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
151
+ }
132
- if (infzero) {
152
+
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
153
+ QTAILQ_REMOVE(&hvf_state->hvf_sw_breakpoints, bp, entry);
134
- }
154
+ g_free(bp);
135
return 3; /* default NaN */
155
+ } else {
136
#elif defined(TARGET_S390X)
156
+ err = hvf_arch_remove_hw_breakpoint(addr, len, type);
137
if (infzero) {
157
+ if (err) {
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
158
+ return err;
139
return 3;
159
+ }
140
}
160
+ }
141
161
+
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
162
+ CPU_FOREACH(cpu) {
143
return 2;
163
+ err = hvf_update_guest_debug(cpu);
144
}
164
+ if (err) {
145
#elif defined(TARGET_SPARC)
165
+ return err;
146
- /* For (inf,0,nan) return c. */
166
+ }
147
- if (infzero) {
167
+ }
148
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
168
+ return 0;
149
- return 2;
169
+}
150
- }
170
+
151
/* Prefer SNaN over QNaN, order C, B, A. */
171
+static void hvf_remove_all_breakpoints(CPUState *cpu)
152
if (is_snan(c_cls)) {
172
+{
153
return 2;
173
+ struct hvf_sw_breakpoint *bp, *next;
154
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
174
+ CPUState *tmpcpu;
155
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
175
+
156
* an input NaN if we have one (ie c).
176
+ QTAILQ_FOREACH_SAFE(bp, &hvf_state->hvf_sw_breakpoints, entry, next) {
157
*/
177
+ if (hvf_arch_remove_sw_breakpoint(cpu, bp) != 0) {
158
- if (infzero) {
178
+ /* Try harder to find a CPU that currently sees the breakpoint. */
159
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
179
+ CPU_FOREACH(tmpcpu)
160
- return 2;
180
+ {
161
- }
181
+ if (hvf_arch_remove_sw_breakpoint(tmpcpu, bp) == 0) {
162
if (status->use_first_nan) {
182
+ break;
163
if (is_nan(a_cls)) {
183
+ }
164
return 0;
184
+ }
185
+ }
186
+ QTAILQ_REMOVE(&hvf_state->hvf_sw_breakpoints, bp, entry);
187
+ g_free(bp);
188
+ }
189
+ hvf_arch_remove_all_hw_breakpoints();
190
+
191
+ CPU_FOREACH(cpu) {
192
+ hvf_update_guest_debug(cpu);
193
+ }
194
+}
195
+
196
static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
197
{
198
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
199
@@ -XXX,XX +XXX,XX @@ static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
200
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
201
ops->synchronize_state = hvf_cpu_synchronize_state;
202
ops->synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm;
203
+
204
+ ops->insert_breakpoint = hvf_insert_breakpoint;
205
+ ops->remove_breakpoint = hvf_remove_breakpoint;
206
+ ops->remove_all_breakpoints = hvf_remove_all_breakpoints;
207
};
208
static const TypeInfo hvf_accel_ops_type = {
209
.name = ACCEL_OPS_NAME("hvf"),
210
diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
211
index XXXXXXX..XXXXXXX 100644
212
--- a/accel/hvf/hvf-all.c
213
+++ b/accel/hvf/hvf-all.c
214
@@ -XXX,XX +XXX,XX @@ void assert_hvf_ok(hv_return_t ret)
215
216
abort();
217
}
218
+
219
+struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu, target_ulong pc)
220
+{
221
+ struct hvf_sw_breakpoint *bp;
222
+
223
+ QTAILQ_FOREACH(bp, &hvf_state->hvf_sw_breakpoints, entry) {
224
+ if (bp->pc == pc) {
225
+ return bp;
226
+ }
227
+ }
228
+ return NULL;
229
+}
230
+
231
+int hvf_sw_breakpoints_active(CPUState *cpu)
232
+{
233
+ return !QTAILQ_EMPTY(&hvf_state->hvf_sw_breakpoints);
234
+}
235
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
236
index XXXXXXX..XXXXXXX 100644
237
--- a/target/arm/hvf/hvf.c
238
+++ b/target/arm/hvf/hvf.c
239
@@ -XXX,XX +XXX,XX @@
240
#include "trace/trace-target_arm_hvf.h"
241
#include "migration/vmstate.h"
242
243
+#include "exec/gdbstub.h"
244
+
245
#define HVF_SYSREG(crn, crm, op0, op1, op2) \
246
ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
247
#define PL1_WRITE_MASK 0x4
248
@@ -XXX,XX +XXX,XX @@ int hvf_arch_init(void)
249
qemu_add_vm_change_state_handler(hvf_vm_state_change, &vtimer);
250
return 0;
251
}
252
+
253
+static const uint32_t brk_insn = 0xd4200000;
254
+
255
+int hvf_arch_insert_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp)
256
+{
257
+ if (cpu_memory_rw_debug(cpu, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
258
+ cpu_memory_rw_debug(cpu, bp->pc, (uint8_t *)&brk_insn, 4, 1)) {
259
+ return -EINVAL;
260
+ }
261
+ return 0;
262
+}
263
+
264
+int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp)
265
+{
266
+ static uint32_t brk;
267
+
268
+ if (cpu_memory_rw_debug(cpu, bp->pc, (uint8_t *)&brk, 4, 0) ||
269
+ brk != brk_insn ||
270
+ cpu_memory_rw_debug(cpu, bp->pc, (uint8_t *)&bp->saved_insn, 4, 1)) {
271
+ return -EINVAL;
272
+ }
273
+ return 0;
274
+}
275
+
276
+int hvf_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int type)
277
+{
278
+ switch (type) {
279
+ case GDB_BREAKPOINT_HW:
280
+ return insert_hw_breakpoint(addr);
281
+ case GDB_WATCHPOINT_READ:
282
+ case GDB_WATCHPOINT_WRITE:
283
+ case GDB_WATCHPOINT_ACCESS:
284
+ return insert_hw_watchpoint(addr, len, type);
285
+ default:
286
+ return -ENOSYS;
287
+ }
288
+}
289
+
290
+int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len, int type)
291
+{
292
+ switch (type) {
293
+ case GDB_BREAKPOINT_HW:
294
+ return delete_hw_breakpoint(addr);
295
+ case GDB_WATCHPOINT_READ:
296
+ case GDB_WATCHPOINT_WRITE:
297
+ case GDB_WATCHPOINT_ACCESS:
298
+ return delete_hw_watchpoint(addr, len, type);
299
+ default:
300
+ return -ENOSYS;
301
+ }
302
+}
303
+
304
+void hvf_arch_remove_all_hw_breakpoints(void)
305
+{
306
+ if (cur_hw_wps > 0) {
307
+ g_array_remove_range(hw_watchpoints, 0, cur_hw_wps);
308
+ }
309
+ if (cur_hw_bps > 0) {
310
+ g_array_remove_range(hw_breakpoints, 0, cur_hw_bps);
311
+ }
312
+}
313
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
314
index XXXXXXX..XXXXXXX 100644
315
--- a/target/i386/hvf/hvf.c
316
+++ b/target/i386/hvf/hvf.c
317
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
318
319
return ret;
320
}
321
+
322
+int hvf_arch_insert_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp)
323
+{
324
+ return -ENOSYS;
325
+}
326
+
327
+int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp)
328
+{
329
+ return -ENOSYS;
330
+}
331
+
332
+int hvf_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int type)
333
+{
334
+ return -ENOSYS;
335
+}
336
+
337
+int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len, int type)
338
+{
339
+ return -ENOSYS;
340
+}
341
+
342
+void hvf_arch_remove_all_hw_breakpoints(void)
343
+{
344
+}
345
--
165
--
346
2.34.1
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: qianfan Zhao <qianfanguijin@163.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
Allwinner R40 (sun8i) SoC features a Quad-Core Cortex-A7 ARM CPU,
3
architectures thus do different things:
4
and a Mali400 MP2 GPU from ARM. It's also known as the Allwinner T3
4
* some return the default NaN
5
for In-Car Entertainment usage, A40i and A40pro are variants that
5
* some return the input NaN
6
differ in applicable temperatures range (industrial and military).
6
* Arm returns the default NaN if the input NaN is quiet,
7
7
and the input NaN if it is signalling
8
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
8
9
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
We want to make this logic be runtime selected rather than
10
hardcoded into the binary, because:
11
* this will let us have multiple targets in one QEMU binary
12
* the Arm FEAT_AFP architectural feature includes letting
13
the guest select a NaN propagation rule at runtime
14
15
In this commit we add an enum for the propagation rule, the field in
16
float_status, and the corresponding getters and setters. We change
17
pickNaNMulAdd to honour this, but because all targets still leave
18
this field at its default 0 value, the fallback logic will pick the
19
rule type with the old ifdef ladder.
20
21
Note that four architectures both use the muladd softfloat functions
22
and did not have a branch of the ifdef ladder to specify their
23
behaviour (and so were ending up with the "default" case, probably
24
wrongly): i386, HPPA, SH4 and Tricore. SH4 and Tricore both set
25
default_nan_mode, and so will never get into pickNaNMulAdd(). For
26
HPPA and i386 we retain the same behaviour as the old default-case,
27
which is to not ever return the default NaN. This might not be
28
correct but it is not a behaviour change.
29
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Message-id: 20241202131347.498124-4-peter.maydell@linaro.org
11
---
33
---
12
include/hw/arm/allwinner-r40.h | 110 +++++++++
34
include/fpu/softfloat-helpers.h | 11 ++++
13
hw/arm/allwinner-r40.c | 415 +++++++++++++++++++++++++++++++++
35
include/fpu/softfloat-types.h | 23 +++++++++
14
hw/arm/bananapi_m2u.c | 129 ++++++++++
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
15
hw/arm/Kconfig | 10 +
37
3 files changed, 95 insertions(+), 30 deletions(-)
16
hw/arm/meson.build | 1 +
38
17
5 files changed, 665 insertions(+)
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
18
create mode 100644 include/hw/arm/allwinner-r40.h
40
index XXXXXXX..XXXXXXX 100644
19
create mode 100644 hw/arm/allwinner-r40.c
41
--- a/include/fpu/softfloat-helpers.h
20
create mode 100644 hw/arm/bananapi_m2u.c
42
+++ b/include/fpu/softfloat-helpers.h
21
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
22
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
44
status->float_2nan_prop_rule = rule;
23
new file mode 100644
45
}
24
index XXXXXXX..XXXXXXX
46
25
--- /dev/null
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
26
+++ b/include/hw/arm/allwinner-r40.h
48
+ float_status *status)
27
@@ -XXX,XX +XXX,XX @@
49
+{
50
+ status->float_infzeronan_rule = rule;
51
+}
52
+
53
static inline void set_flush_to_zero(bool val, float_status *status)
54
{
55
status->flush_to_zero = val;
56
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
57
return status->float_2nan_prop_rule;
58
}
59
60
+static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
61
+{
62
+ return status->float_infzeronan_rule;
63
+}
64
+
65
static inline bool get_flush_to_zero(float_status *status)
66
{
67
return status->flush_to_zero;
68
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/fpu/softfloat-types.h
71
+++ b/include/fpu/softfloat-types.h
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
73
float_2nan_prop_x87,
74
} Float2NaNPropRule;
75
28
+/*
76
+/*
29
+ * Allwinner R40/A40i/T3 System on Chip emulation
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
78
+ * This must be a NaN, but implementations differ on whether this
79
+ * is the input NaN or the default NaN.
30
+ *
80
+ *
31
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
81
+ * You don't need to set this if default_nan_mode is enabled.
32
+ *
82
+ * When not in default-NaN mode, it is an error for the target
33
+ * This program is free software: you can redistribute it and/or modify
83
+ * not to set the rule in float_status if it uses muladd, and we
34
+ * it under the terms of the GNU General Public License as published by
84
+ * will assert if we need to handle an input NaN and no rule was
35
+ * the Free Software Foundation, either version 2 of the License, or
85
+ * selected.
36
+ * (at your option) any later version.
37
+ *
38
+ * This program is distributed in the hope that it will be useful,
39
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
40
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
+ * GNU General Public License for more details.
42
+ *
43
+ * You should have received a copy of the GNU General Public License
44
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
45
+ */
86
+ */
46
+
87
+typedef enum __attribute__((__packed__)) {
47
+#ifndef HW_ARM_ALLWINNER_R40_H
88
+ /* No propagation rule specified */
48
+#define HW_ARM_ALLWINNER_R40_H
89
+ float_infzeronan_none = 0,
49
+
90
+ /* Result is never the default NaN (so always the input NaN) */
50
+#include "qom/object.h"
91
+ float_infzeronan_dnan_never,
51
+#include "hw/arm/boot.h"
92
+ /* Result is always the default NaN */
52
+#include "hw/timer/allwinner-a10-pit.h"
93
+ float_infzeronan_dnan_always,
53
+#include "hw/intc/arm_gic.h"
94
+ /* Result is the default NaN if the input NaN is quiet */
54
+#include "hw/sd/allwinner-sdhost.h"
95
+ float_infzeronan_dnan_if_qnan,
55
+#include "target/arm/cpu.h"
96
+} FloatInfZeroNaNRule;
56
+#include "sysemu/block-backend.h"
97
+
57
+
98
/*
58
+enum {
99
* Floating Point Status. Individual architectures may maintain
59
+ AW_R40_DEV_SRAM_A1,
100
* several versions of float_status for different functions. The
60
+ AW_R40_DEV_SRAM_A2,
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
61
+ AW_R40_DEV_SRAM_A3,
102
FloatRoundMode float_rounding_mode;
62
+ AW_R40_DEV_SRAM_A4,
103
FloatX80RoundPrec floatx80_rounding_precision;
63
+ AW_R40_DEV_MMC0,
104
Float2NaNPropRule float_2nan_prop_rule;
64
+ AW_R40_DEV_MMC1,
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
65
+ AW_R40_DEV_MMC2,
106
bool tininess_before_rounding;
66
+ AW_R40_DEV_MMC3,
107
/* should denormalised results go to zero and set the inexact flag? */
67
+ AW_R40_DEV_CCU,
108
bool flush_to_zero;
68
+ AW_R40_DEV_PIT,
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
69
+ AW_R40_DEV_UART0,
110
index XXXXXXX..XXXXXXX 100644
70
+ AW_R40_DEV_GIC_DIST,
111
--- a/fpu/softfloat-specialize.c.inc
71
+ AW_R40_DEV_GIC_CPU,
112
+++ b/fpu/softfloat-specialize.c.inc
72
+ AW_R40_DEV_GIC_HYP,
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
73
+ AW_R40_DEV_GIC_VCPU,
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
74
+ AW_R40_DEV_SDRAM
115
bool infzero, float_status *status)
75
+};
116
{
76
+
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
77
+#define AW_R40_NUM_CPUS (4)
118
+
78
+
119
/*
79
+/**
120
* We guarantee not to require the target to tell us how to
80
+ * Allwinner R40 object model
121
* pick a NaN if we're always returning the default NaN.
81
+ * @{
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
82
+ */
123
* specify.
83
+
124
*/
84
+/** Object type for the Allwinner R40 SoC */
125
assert(!status->default_nan_mode);
85
+#define TYPE_AW_R40 "allwinner-r40"
126
+
86
+
127
+ if (rule == float_infzeronan_none) {
87
+/** Convert input object to Allwinner R40 state object */
128
+ /*
88
+OBJECT_DECLARE_SIMPLE_TYPE(AwR40State, AW_R40)
129
+ * Temporarily fall back to ifdef ladder
89
+
130
+ */
90
+/** @} */
131
#if defined(TARGET_ARM)
91
+
132
- /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
92
+/**
133
- * the default NaN
93
+ * Allwinner R40 object
134
- */
94
+ *
135
- if (infzero && is_qnan(c_cls)) {
95
+ * This struct contains the state of all the devices
136
- return 3;
96
+ * which are currently emulated by the R40 SoC code.
137
+ /*
97
+ */
138
+ * For ARM, the (inf,zero,qnan) case returns the default NaN,
98
+#define AW_R40_NUM_MMCS 4
139
+ * but (inf,zero,snan) returns the input NaN.
99
+
140
+ */
100
+struct AwR40State {
141
+ rule = float_infzeronan_dnan_if_qnan;
101
+ /*< private >*/
142
+#elif defined(TARGET_MIPS)
102
+ DeviceState parent_obj;
143
+ if (snan_bit_is_one(status)) {
103
+ /*< public >*/
144
+ /*
104
+
145
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
105
+ ARMCPU cpus[AW_R40_NUM_CPUS];
146
+ * case sets InvalidOp and returns the default NaN
106
+ const hwaddr *memmap;
147
+ */
107
+ AwA10PITState timer;
148
+ rule = float_infzeronan_dnan_always;
108
+ AwSdHostState mmc[AW_R40_NUM_MMCS];
149
+ } else {
109
+ GICState gic;
150
+ /*
110
+ MemoryRegion sram_a1;
151
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
111
+ MemoryRegion sram_a2;
152
+ * case sets InvalidOp and returns the input value 'c'
112
+ MemoryRegion sram_a3;
153
+ */
113
+ MemoryRegion sram_a4;
154
+ rule = float_infzeronan_dnan_never;
114
+};
115
+
116
+/**
117
+ * Emulate Boot ROM firmware setup functionality.
118
+ *
119
+ * A real Allwinner R40 SoC contains a Boot ROM
120
+ * which is the first code that runs right after
121
+ * the SoC is powered on. The Boot ROM is responsible
122
+ * for loading user code (e.g. a bootloader) from any
123
+ * of the supported external devices and writing the
124
+ * downloaded code to internal SRAM. After loading the SoC
125
+ * begins executing the code written to SRAM.
126
+ *
127
+ * This function emulates the Boot ROM by copying 32 KiB
128
+ * of data from the given block device and writes it to
129
+ * the start of the first internal SRAM memory.
130
+ *
131
+ * @s: Allwinner R40 state object pointer
132
+ * @blk: Block backend device object pointer
133
+ * @unit: the mmc control's unit
134
+ */
135
+bool allwinner_r40_bootrom_setup(AwR40State *s, BlockBackend *blk, int unit);
136
+
137
+#endif /* HW_ARM_ALLWINNER_R40_H */
138
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
139
new file mode 100644
140
index XXXXXXX..XXXXXXX
141
--- /dev/null
142
+++ b/hw/arm/allwinner-r40.c
143
@@ -XXX,XX +XXX,XX @@
144
+/*
145
+ * Allwinner R40/A40i/T3 System on Chip emulation
146
+ *
147
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
148
+ *
149
+ * This program is free software: you can redistribute it and/or modify
150
+ * it under the terms of the GNU General Public License as published by
151
+ * the Free Software Foundation, either version 2 of the License, or
152
+ * (at your option) any later version.
153
+ *
154
+ * This program is distributed in the hope that it will be useful,
155
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
156
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
157
+ * GNU General Public License for more details.
158
+ *
159
+ * You should have received a copy of the GNU General Public License
160
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
161
+ */
162
+
163
+#include "qemu/osdep.h"
164
+#include "qapi/error.h"
165
+#include "qemu/error-report.h"
166
+#include "qemu/bswap.h"
167
+#include "qemu/module.h"
168
+#include "qemu/units.h"
169
+#include "hw/qdev-core.h"
170
+#include "hw/sysbus.h"
171
+#include "hw/char/serial.h"
172
+#include "hw/misc/unimp.h"
173
+#include "hw/usb/hcd-ehci.h"
174
+#include "hw/loader.h"
175
+#include "sysemu/sysemu.h"
176
+#include "hw/arm/allwinner-r40.h"
177
+
178
+/* Memory map */
179
+const hwaddr allwinner_r40_memmap[] = {
180
+ [AW_R40_DEV_SRAM_A1] = 0x00000000,
181
+ [AW_R40_DEV_SRAM_A2] = 0x00004000,
182
+ [AW_R40_DEV_SRAM_A3] = 0x00008000,
183
+ [AW_R40_DEV_SRAM_A4] = 0x0000b400,
184
+ [AW_R40_DEV_MMC0] = 0x01c0f000,
185
+ [AW_R40_DEV_MMC1] = 0x01c10000,
186
+ [AW_R40_DEV_MMC2] = 0x01c11000,
187
+ [AW_R40_DEV_MMC3] = 0x01c12000,
188
+ [AW_R40_DEV_PIT] = 0x01c20c00,
189
+ [AW_R40_DEV_UART0] = 0x01c28000,
190
+ [AW_R40_DEV_GIC_DIST] = 0x01c81000,
191
+ [AW_R40_DEV_GIC_CPU] = 0x01c82000,
192
+ [AW_R40_DEV_GIC_HYP] = 0x01c84000,
193
+ [AW_R40_DEV_GIC_VCPU] = 0x01c86000,
194
+ [AW_R40_DEV_SDRAM] = 0x40000000
195
+};
196
+
197
+/* List of unimplemented devices */
198
+struct AwR40Unimplemented {
199
+ const char *device_name;
200
+ hwaddr base;
201
+ hwaddr size;
202
+};
203
+
204
+static struct AwR40Unimplemented r40_unimplemented[] = {
205
+ { "d-engine", 0x01000000, 4 * MiB },
206
+ { "d-inter", 0x01400000, 128 * KiB },
207
+ { "sram-c", 0x01c00000, 4 * KiB },
208
+ { "dma", 0x01c02000, 4 * KiB },
209
+ { "nfdc", 0x01c03000, 4 * KiB },
210
+ { "ts", 0x01c04000, 4 * KiB },
211
+ { "spi0", 0x01c05000, 4 * KiB },
212
+ { "spi1", 0x01c06000, 4 * KiB },
213
+ { "cs0", 0x01c09000, 4 * KiB },
214
+ { "keymem", 0x01c0a000, 4 * KiB },
215
+ { "emac", 0x01c0b000, 4 * KiB },
216
+ { "usb0-otg", 0x01c13000, 4 * KiB },
217
+ { "usb0-host", 0x01c14000, 4 * KiB },
218
+ { "crypto", 0x01c15000, 4 * KiB },
219
+ { "spi2", 0x01c17000, 4 * KiB },
220
+ { "sata", 0x01c18000, 4 * KiB },
221
+ { "usb1-host", 0x01c19000, 4 * KiB },
222
+ { "sid", 0x01c1b000, 4 * KiB },
223
+ { "usb2-host", 0x01c1c000, 4 * KiB },
224
+ { "cs1", 0x01c1d000, 4 * KiB },
225
+ { "spi3", 0x01c1f000, 4 * KiB },
226
+ { "ccu", 0x01c20000, 1 * KiB },
227
+ { "rtc", 0x01c20400, 1 * KiB },
228
+ { "pio", 0x01c20800, 1 * KiB },
229
+ { "owa", 0x01c21000, 1 * KiB },
230
+ { "ac97", 0x01c21400, 1 * KiB },
231
+ { "cir0", 0x01c21800, 1 * KiB },
232
+ { "cir1", 0x01c21c00, 1 * KiB },
233
+ { "pcm0", 0x01c22000, 1 * KiB },
234
+ { "pcm1", 0x01c22400, 1 * KiB },
235
+ { "pcm2", 0x01c22800, 1 * KiB },
236
+ { "audio", 0x01c22c00, 1 * KiB },
237
+ { "keypad", 0x01c23000, 1 * KiB },
238
+ { "pwm", 0x01c23400, 1 * KiB },
239
+ { "keyadc", 0x01c24400, 1 * KiB },
240
+ { "ths", 0x01c24c00, 1 * KiB },
241
+ { "rtp", 0x01c25000, 1 * KiB },
242
+ { "pmu", 0x01c25400, 1 * KiB },
243
+ { "cpu-cfg", 0x01c25c00, 1 * KiB },
244
+ { "uart0", 0x01c28000, 1 * KiB },
245
+ { "uart1", 0x01c28400, 1 * KiB },
246
+ { "uart2", 0x01c28800, 1 * KiB },
247
+ { "uart3", 0x01c28c00, 1 * KiB },
248
+ { "uart4", 0x01c29000, 1 * KiB },
249
+ { "uart5", 0x01c29400, 1 * KiB },
250
+ { "uart6", 0x01c29800, 1 * KiB },
251
+ { "uart7", 0x01c29c00, 1 * KiB },
252
+ { "ps20", 0x01c2a000, 1 * KiB },
253
+ { "ps21", 0x01c2a400, 1 * KiB },
254
+ { "twi0", 0x01c2ac00, 1 * KiB },
255
+ { "twi1", 0x01c2b000, 1 * KiB },
256
+ { "twi2", 0x01c2b400, 1 * KiB },
257
+ { "twi3", 0x01c2b800, 1 * KiB },
258
+ { "twi4", 0x01c2c000, 1 * KiB },
259
+ { "scr", 0x01c2c400, 1 * KiB },
260
+ { "tvd-top", 0x01c30000, 4 * KiB },
261
+ { "tvd0", 0x01c31000, 4 * KiB },
262
+ { "tvd1", 0x01c32000, 4 * KiB },
263
+ { "tvd2", 0x01c33000, 4 * KiB },
264
+ { "tvd3", 0x01c34000, 4 * KiB },
265
+ { "gpu", 0x01c40000, 64 * KiB },
266
+ { "gmac", 0x01c50000, 64 * KiB },
267
+ { "hstmr", 0x01c60000, 4 * KiB },
268
+ { "dram-com", 0x01c62000, 4 * KiB },
269
+ { "dram-ctl", 0x01c63000, 4 * KiB },
270
+ { "tcon-top", 0x01c70000, 4 * KiB },
271
+ { "lcd0", 0x01c71000, 4 * KiB },
272
+ { "lcd1", 0x01c72000, 4 * KiB },
273
+ { "tv0", 0x01c73000, 4 * KiB },
274
+ { "tv1", 0x01c74000, 4 * KiB },
275
+ { "tve-top", 0x01c90000, 16 * KiB },
276
+ { "tve0", 0x01c94000, 16 * KiB },
277
+ { "tve1", 0x01c98000, 16 * KiB },
278
+ { "mipi_dsi", 0x01ca0000, 4 * KiB },
279
+ { "mipi_dphy", 0x01ca1000, 4 * KiB },
280
+ { "ve", 0x01d00000, 1024 * KiB },
281
+ { "mp", 0x01e80000, 128 * KiB },
282
+ { "hdmi", 0x01ee0000, 128 * KiB },
283
+ { "prcm", 0x01f01400, 1 * KiB },
284
+ { "debug", 0x3f500000, 64 * KiB },
285
+ { "cpubist", 0x3f501000, 4 * KiB },
286
+ { "dcu", 0x3fff0000, 64 * KiB },
287
+ { "hstmr", 0x01c60000, 4 * KiB },
288
+ { "brom", 0xffff0000, 36 * KiB }
289
+};
290
+
291
+/* Per Processor Interrupts */
292
+enum {
293
+ AW_R40_GIC_PPI_MAINT = 9,
294
+ AW_R40_GIC_PPI_HYPTIMER = 10,
295
+ AW_R40_GIC_PPI_VIRTTIMER = 11,
296
+ AW_R40_GIC_PPI_SECTIMER = 13,
297
+ AW_R40_GIC_PPI_PHYSTIMER = 14
298
+};
299
+
300
+/* Shared Processor Interrupts */
301
+enum {
302
+ AW_R40_GIC_SPI_UART0 = 1,
303
+ AW_R40_GIC_SPI_TIMER0 = 22,
304
+ AW_R40_GIC_SPI_TIMER1 = 23,
305
+ AW_R40_GIC_SPI_MMC0 = 32,
306
+ AW_R40_GIC_SPI_MMC1 = 33,
307
+ AW_R40_GIC_SPI_MMC2 = 34,
308
+ AW_R40_GIC_SPI_MMC3 = 35,
309
+};
310
+
311
+/* Allwinner R40 general constants */
312
+enum {
313
+ AW_R40_GIC_NUM_SPI = 128
314
+};
315
+
316
+#define BOOT0_MAGIC "eGON.BT0"
317
+
318
+/* The low 8-bits of the 'boot_media' field in the SPL header */
319
+#define SUNXI_BOOTED_FROM_MMC0 0
320
+#define SUNXI_BOOTED_FROM_NAND 1
321
+#define SUNXI_BOOTED_FROM_MMC2 2
322
+#define SUNXI_BOOTED_FROM_SPI 3
323
+
324
+struct boot_file_head {
325
+ uint32_t b_instruction;
326
+ uint8_t magic[8];
327
+ uint32_t check_sum;
328
+ uint32_t length;
329
+ uint32_t pub_head_size;
330
+ uint32_t fel_script_address;
331
+ uint32_t fel_uEnv_length;
332
+ uint32_t dt_name_offset;
333
+ uint32_t dram_size;
334
+ uint32_t boot_media;
335
+ uint32_t string_pool[13];
336
+};
337
+
338
+bool allwinner_r40_bootrom_setup(AwR40State *s, BlockBackend *blk, int unit)
339
+{
340
+ const int64_t rom_size = 32 * KiB;
341
+ g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
342
+ struct boot_file_head *head = (struct boot_file_head *)buffer;
343
+
344
+ if (blk_pread(blk, 8 * KiB, rom_size, buffer, 0) < 0) {
345
+ error_setg(&error_fatal, "%s: failed to read BlockBackend data",
346
+ __func__);
347
+ return false;
348
+ }
349
+
350
+ /* we only check the magic string here. */
351
+ if (memcmp(head->magic, BOOT0_MAGIC, sizeof(head->magic))) {
352
+ return false;
353
+ }
354
+
355
+ /*
356
+ * Simulate the behavior of the bootROM, it will change the boot_media
357
+ * flag to indicate where the chip is booting from. R40 can boot from
358
+ * mmc0 or mmc2, the default value of boot_media is zero
359
+ * (SUNXI_BOOTED_FROM_MMC0), let's fix this flag when it is booting from
360
+ * the others.
361
+ */
362
+ if (unit == 2) {
363
+ head->boot_media = cpu_to_le32(SUNXI_BOOTED_FROM_MMC2);
364
+ } else {
365
+ head->boot_media = cpu_to_le32(SUNXI_BOOTED_FROM_MMC0);
366
+ }
367
+
368
+ rom_add_blob("allwinner-r40.bootrom", buffer, rom_size,
369
+ rom_size, s->memmap[AW_R40_DEV_SRAM_A1],
370
+ NULL, NULL, NULL, NULL, false);
371
+ return true;
372
+}
373
+
374
+static void allwinner_r40_init(Object *obj)
375
+{
376
+ static const char *mmc_names[AW_R40_NUM_MMCS] = {
377
+ "mmc0", "mmc1", "mmc2", "mmc3"
378
+ };
379
+ AwR40State *s = AW_R40(obj);
380
+
381
+ s->memmap = allwinner_r40_memmap;
382
+
383
+ for (int i = 0; i < AW_R40_NUM_CPUS; i++) {
384
+ object_initialize_child(obj, "cpu[*]", &s->cpus[i],
385
+ ARM_CPU_TYPE_NAME("cortex-a7"));
386
+ }
387
+
388
+ object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC);
389
+
390
+ object_initialize_child(obj, "timer", &s->timer, TYPE_AW_A10_PIT);
391
+ object_property_add_alias(obj, "clk0-freq", OBJECT(&s->timer),
392
+ "clk0-freq");
393
+ object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
394
+ "clk1-freq");
395
+
396
+ for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
397
+ object_initialize_child(obj, mmc_names[i], &s->mmc[i],
398
+ TYPE_AW_SDHOST_SUN5I);
399
+ }
400
+}
401
+
402
+static void allwinner_r40_realize(DeviceState *dev, Error **errp)
403
+{
404
+ AwR40State *s = AW_R40(dev);
405
+ unsigned i;
406
+
407
+ /* CPUs */
408
+ for (i = 0; i < AW_R40_NUM_CPUS; i++) {
409
+
410
+ /*
411
+ * Disable secondary CPUs. Guest EL3 firmware will start
412
+ * them via CPU reset control registers.
413
+ */
414
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
415
+ i > 0);
416
+
417
+ /* All exception levels required */
418
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el3", true);
419
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el2", true);
420
+
421
+ /* Mark realized */
422
+ qdev_realize(DEVICE(&s->cpus[i]), NULL, &error_fatal);
423
+ }
424
+
425
+ /* Generic Interrupt Controller */
426
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", AW_R40_GIC_NUM_SPI +
427
+ GIC_INTERNAL);
428
+ qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
429
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", AW_R40_NUM_CPUS);
430
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-security-extensions", false);
431
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-virtualization-extensions", true);
432
+ sysbus_realize(SYS_BUS_DEVICE(&s->gic), &error_fatal);
433
+
434
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0, s->memmap[AW_R40_DEV_GIC_DIST]);
435
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1, s->memmap[AW_R40_DEV_GIC_CPU]);
436
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2, s->memmap[AW_R40_DEV_GIC_HYP]);
437
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3, s->memmap[AW_R40_DEV_GIC_VCPU]);
438
+
439
+ /*
440
+ * Wire the outputs from each CPU's generic timer and the GICv2
441
+ * maintenance interrupt signal to the appropriate GIC PPI inputs,
442
+ * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
443
+ */
444
+ for (i = 0; i < AW_R40_NUM_CPUS; i++) {
445
+ DeviceState *cpudev = DEVICE(&s->cpus[i]);
446
+ int ppibase = AW_R40_GIC_NUM_SPI + i * GIC_INTERNAL + GIC_NR_SGIS;
447
+ int irq;
448
+ /*
449
+ * Mapping from the output timer irq lines from the CPU to the
450
+ * GIC PPI inputs used for this board.
451
+ */
452
+ const int timer_irq[] = {
453
+ [GTIMER_PHYS] = AW_R40_GIC_PPI_PHYSTIMER,
454
+ [GTIMER_VIRT] = AW_R40_GIC_PPI_VIRTTIMER,
455
+ [GTIMER_HYP] = AW_R40_GIC_PPI_HYPTIMER,
456
+ [GTIMER_SEC] = AW_R40_GIC_PPI_SECTIMER,
457
+ };
458
+
459
+ /* Connect CPU timer outputs to GIC PPI inputs */
460
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
461
+ qdev_connect_gpio_out(cpudev, irq,
462
+ qdev_get_gpio_in(DEVICE(&s->gic),
463
+ ppibase + timer_irq[irq]));
464
+ }
155
+ }
465
+
156
+#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
466
+ /* Connect GIC outputs to CPU interrupt inputs */
157
+ defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
467
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
158
+ defined(TARGET_I386) || defined(TARGET_LOONGARCH)
468
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
159
+ /*
469
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + AW_R40_NUM_CPUS,
160
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
470
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
161
+ * case sets InvalidOp and returns the input value 'c'
471
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (2 * AW_R40_NUM_CPUS),
162
+ */
472
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
163
+ /*
473
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (3 * AW_R40_NUM_CPUS),
164
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
474
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
165
+ * to return an input NaN if we have one (ie c) rather than generating
475
+
166
+ * a default NaN
476
+ /* GIC maintenance signal */
167
+ */
477
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (4 * AW_R40_NUM_CPUS),
168
+ rule = float_infzeronan_dnan_never;
478
+ qdev_get_gpio_in(DEVICE(&s->gic),
169
+#elif defined(TARGET_S390X)
479
+ ppibase + AW_R40_GIC_PPI_MAINT));
170
+ rule = float_infzeronan_dnan_always;
480
+ }
171
+#endif
481
+
172
}
482
+ /* Timer */
173
483
+ sysbus_realize(SYS_BUS_DEVICE(&s->timer), &error_fatal);
174
+ if (infzero) {
484
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, s->memmap[AW_R40_DEV_PIT]);
175
+ /*
485
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 0,
176
+ * Inf * 0 + NaN -- some implementations return the default NaN here,
486
+ qdev_get_gpio_in(DEVICE(&s->gic),
177
+ * and some return the input NaN.
487
+ AW_R40_GIC_SPI_TIMER0));
178
+ */
488
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 1,
179
+ switch (rule) {
489
+ qdev_get_gpio_in(DEVICE(&s->gic),
180
+ case float_infzeronan_dnan_never:
490
+ AW_R40_GIC_SPI_TIMER1));
181
+ return 2;
491
+
182
+ case float_infzeronan_dnan_always:
492
+ /* SRAM */
183
+ return 3;
493
+ memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
184
+ case float_infzeronan_dnan_if_qnan:
494
+ 16 * KiB, &error_abort);
185
+ return is_qnan(c_cls) ? 3 : 2;
495
+ memory_region_init_ram(&s->sram_a2, OBJECT(dev), "sram A2",
496
+ 16 * KiB, &error_abort);
497
+ memory_region_init_ram(&s->sram_a3, OBJECT(dev), "sram A3",
498
+ 13 * KiB, &error_abort);
499
+ memory_region_init_ram(&s->sram_a4, OBJECT(dev), "sram A4",
500
+ 3 * KiB, &error_abort);
501
+ memory_region_add_subregion(get_system_memory(),
502
+ s->memmap[AW_R40_DEV_SRAM_A1], &s->sram_a1);
503
+ memory_region_add_subregion(get_system_memory(),
504
+ s->memmap[AW_R40_DEV_SRAM_A2], &s->sram_a2);
505
+ memory_region_add_subregion(get_system_memory(),
506
+ s->memmap[AW_R40_DEV_SRAM_A3], &s->sram_a3);
507
+ memory_region_add_subregion(get_system_memory(),
508
+ s->memmap[AW_R40_DEV_SRAM_A4], &s->sram_a4);
509
+
510
+ /* SD/MMC */
511
+ for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
512
+ qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->gic),
513
+ AW_R40_GIC_SPI_MMC0 + i);
514
+ const hwaddr addr = s->memmap[AW_R40_DEV_MMC0 + i];
515
+
516
+ object_property_set_link(OBJECT(&s->mmc[i]), "dma-memory",
517
+ OBJECT(get_system_memory()), &error_fatal);
518
+ sysbus_realize(SYS_BUS_DEVICE(&s->mmc[i]), &error_fatal);
519
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc[i]), 0, addr);
520
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc[i]), 0, irq);
521
+ }
522
+
523
+ /* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
524
+ serial_mm_init(get_system_memory(), s->memmap[AW_R40_DEV_UART0], 2,
525
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_UART0),
526
+ 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
527
+
528
+ /* Unimplemented devices */
529
+ for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
530
+ create_unimplemented_device(r40_unimplemented[i].device_name,
531
+ r40_unimplemented[i].base,
532
+ r40_unimplemented[i].size);
533
+ }
534
+}
535
+
536
+static void allwinner_r40_class_init(ObjectClass *oc, void *data)
537
+{
538
+ DeviceClass *dc = DEVICE_CLASS(oc);
539
+
540
+ dc->realize = allwinner_r40_realize;
541
+ /* Reason: uses serial_hd() in realize function */
542
+ dc->user_creatable = false;
543
+}
544
+
545
+static const TypeInfo allwinner_r40_type_info = {
546
+ .name = TYPE_AW_R40,
547
+ .parent = TYPE_DEVICE,
548
+ .instance_size = sizeof(AwR40State),
549
+ .instance_init = allwinner_r40_init,
550
+ .class_init = allwinner_r40_class_init,
551
+};
552
+
553
+static void allwinner_r40_register_types(void)
554
+{
555
+ type_register_static(&allwinner_r40_type_info);
556
+}
557
+
558
+type_init(allwinner_r40_register_types)
559
diff --git a/hw/arm/bananapi_m2u.c b/hw/arm/bananapi_m2u.c
560
new file mode 100644
561
index XXXXXXX..XXXXXXX
562
--- /dev/null
563
+++ b/hw/arm/bananapi_m2u.c
564
@@ -XXX,XX +XXX,XX @@
565
+/*
566
+ * Bananapi M2U emulation
567
+ *
568
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
569
+ *
570
+ * This program is free software: you can redistribute it and/or modify
571
+ * it under the terms of the GNU General Public License as published by
572
+ * the Free Software Foundation, either version 2 of the License, or
573
+ * (at your option) any later version.
574
+ *
575
+ * This program is distributed in the hope that it will be useful,
576
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
577
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
578
+ * GNU General Public License for more details.
579
+ *
580
+ * You should have received a copy of the GNU General Public License
581
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
582
+ */
583
+
584
+#include "qemu/osdep.h"
585
+#include "qemu/units.h"
586
+#include "exec/address-spaces.h"
587
+#include "qapi/error.h"
588
+#include "qemu/error-report.h"
589
+#include "hw/boards.h"
590
+#include "hw/qdev-properties.h"
591
+#include "hw/arm/allwinner-r40.h"
592
+
593
+static struct arm_boot_info bpim2u_binfo;
594
+
595
+/*
596
+ * R40 can boot from mmc0 and mmc2, and bpim2u has two mmc interface, one is
597
+ * connected to sdcard and another mount an emmc media.
598
+ * Attach the mmc driver and try loading bootloader.
599
+ */
600
+static void mmc_attach_drive(AwR40State *s, AwSdHostState *mmc, int unit,
601
+ bool load_bootroom, bool *bootroom_loaded)
602
+{
603
+ DriveInfo *di = drive_get(IF_SD, 0, unit);
604
+ BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
605
+ BusState *bus;
606
+ DeviceState *carddev;
607
+
608
+ bus = qdev_get_child_bus(DEVICE(mmc), "sd-bus");
609
+ if (bus == NULL) {
610
+ error_report("No SD bus found in SOC object");
611
+ exit(1);
612
+ }
613
+
614
+ carddev = qdev_new(TYPE_SD_CARD);
615
+ qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
616
+ qdev_realize_and_unref(carddev, bus, &error_fatal);
617
+
618
+ if (load_bootroom && blk && blk_is_available(blk)) {
619
+ /* Use Boot ROM to copy data from SD card to SRAM */
620
+ *bootroom_loaded = allwinner_r40_bootrom_setup(s, blk, unit);
621
+ }
622
+}
623
+
624
+static void bpim2u_init(MachineState *machine)
625
+{
626
+ bool bootroom_loaded = false;
627
+ AwR40State *r40;
628
+
629
+ /* BIOS is not supported by this board */
630
+ if (machine->firmware) {
631
+ error_report("BIOS not supported for this machine");
632
+ exit(1);
633
+ }
634
+
635
+ /* Only allow Cortex-A7 for this board */
636
+ if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a7")) != 0) {
637
+ error_report("This board can only be used with cortex-a7 CPU");
638
+ exit(1);
639
+ }
640
+
641
+ r40 = AW_R40(object_new(TYPE_AW_R40));
642
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(r40));
643
+ object_unref(OBJECT(r40));
644
+
645
+ /* Setup timer properties */
646
+ object_property_set_int(OBJECT(r40), "clk0-freq", 32768, &error_abort);
647
+ object_property_set_int(OBJECT(r40), "clk1-freq", 24 * 1000 * 1000,
648
+ &error_abort);
649
+
650
+ /* Mark R40 object realized */
651
+ qdev_realize(DEVICE(r40), NULL, &error_abort);
652
+
653
+ /*
654
+ * Plug in SD card and try load bootrom, R40 has 4 mmc controllers but can
655
+ * only booting from mmc0 and mmc2.
656
+ */
657
+ for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
658
+ switch (i) {
659
+ case 0:
660
+ case 2:
661
+ mmc_attach_drive(r40, &r40->mmc[i], i,
662
+ !machine->kernel_filename && !bootroom_loaded,
663
+ &bootroom_loaded);
664
+ break;
665
+ default:
186
+ default:
666
+ mmc_attach_drive(r40, &r40->mmc[i], i, false, NULL);
187
+ g_assert_not_reached();
667
+ break;
668
+ }
188
+ }
669
+ }
189
+ }
670
+
190
+
671
+ /* SDRAM */
191
+#if defined(TARGET_ARM)
672
+ memory_region_add_subregion(get_system_memory(),
192
+
673
+ r40->memmap[AW_R40_DEV_SDRAM], machine->ram);
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
674
+
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
675
+ bpim2u_binfo.loader_start = r40->memmap[AW_R40_DEV_SDRAM];
195
*/
676
+ bpim2u_binfo.ram_size = machine->ram_size;
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
677
+ bpim2u_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
197
}
678
+ arm_load_kernel(ARM_CPU(first_cpu), machine, &bpim2u_binfo);
198
#elif defined(TARGET_MIPS)
679
+}
199
if (snan_bit_is_one(status)) {
680
+
200
- /*
681
+static void bpim2u_machine_init(MachineClass *mc)
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
682
+{
202
- * case sets InvalidOp and returns the default NaN
683
+ mc->desc = "Bananapi M2U (Cortex-A7)";
203
- */
684
+ mc->init = bpim2u_init;
204
- if (infzero) {
685
+ mc->min_cpus = AW_R40_NUM_CPUS;
205
- return 3;
686
+ mc->max_cpus = AW_R40_NUM_CPUS;
206
- }
687
+ mc->default_cpus = AW_R40_NUM_CPUS;
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
688
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
208
if (is_snan(a_cls)) {
689
+ mc->default_ram_size = 1 * GiB;
209
return 0;
690
+ mc->default_ram_id = "bpim2u.ram";
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
691
+}
211
return 2;
692
+
212
}
693
+DEFINE_MACHINE("bpim2u", bpim2u_machine_init)
213
} else {
694
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
214
- /*
695
index XXXXXXX..XXXXXXX 100644
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
696
--- a/hw/arm/Kconfig
216
- * case sets InvalidOp and returns the input value 'c'
697
+++ b/hw/arm/Kconfig
217
- */
698
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
699
select USB_EHCI_SYSBUS
219
if (is_snan(c_cls)) {
700
select SD
220
return 2;
701
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
702
+config ALLWINNER_R40
222
}
703
+ bool
223
}
704
+ default y if TCG && ARM
224
#elif defined(TARGET_LOONGARCH64)
705
+ select ALLWINNER_A10_PIT
225
- /*
706
+ select SERIAL
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
707
+ select ARM_TIMER
227
- * case sets InvalidOp and returns the input value 'c'
708
+ select ARM_GIC
228
- */
709
+ select UNIMP
229
-
710
+ select SD
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
711
+
231
if (is_snan(c_cls)) {
712
config RASPI
232
return 2;
713
bool
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
714
default y
234
return 1;
715
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
235
}
716
index XXXXXXX..XXXXXXX 100644
236
#elif defined(TARGET_PPC)
717
--- a/hw/arm/meson.build
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
718
+++ b/hw/arm/meson.build
238
- * to return an input NaN if we have one (ie c) rather than generating
719
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_OMAP', if_true: files('omap1.c', 'omap2.c'))
239
- * a default NaN
720
arm_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c'))
240
- */
721
arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubieboard.c'))
241
-
722
arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c'))
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
723
+arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 'bananapi_m2u.c'))
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
724
arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
244
*/
725
arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
726
arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
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)) {
727
--
256
--
728
2.34.1
257
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Explicitly set a rule in the softfloat tests for the inf-zero-nan
2
muladd special case. In meson.build we put -DTARGET_ARM in fpcflags,
3
and so we should select here the Arm rule of
4
float_infzeronan_dnan_if_qnan.
2
5
3
Push the mte check behind the exclusive_addr check.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Document the several ways that we are still out of spec
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
with this implementation.
8
Message-id: 20241202131347.498124-5-peter.maydell@linaro.org
9
---
10
tests/fp/fp-bench.c | 5 +++++
11
tests/fp/fp-test.c | 5 +++++
12
2 files changed, 10 insertions(+)
6
13
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230530191438.411344-18-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/tcg/translate-a64.c | 42 +++++++++++++++++++++++++++++-----
13
1 file changed, 36 insertions(+), 6 deletions(-)
14
15
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/tcg/translate-a64.c
16
--- a/tests/fp/fp-bench.c
18
+++ b/target/arm/tcg/translate-a64.c
17
+++ b/tests/fp/fp-bench.c
19
@@ -XXX,XX +XXX,XX @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
18
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
20
*/
19
{
21
TCGLabel *fail_label = gen_new_label();
20
bench_func_t f;
22
TCGLabel *done_label = gen_new_label();
21
23
- TCGv_i64 tmp, dirty_addr, clean_addr;
24
+ TCGv_i64 tmp, clean_addr;
25
MemOp memop;
26
27
- memop = (size + is_pair) | MO_ALIGN;
28
- memop = finalize_memop(s, memop);
29
-
30
- dirty_addr = cpu_reg_sp(s, rn);
31
- clean_addr = gen_mte_check1(s, dirty_addr, true, rn != 31, memop);
32
+ /*
22
+ /*
33
+ * FIXME: We are out of spec here. We have recorded only the address
23
+ * These implementation-defined choices for various things IEEE
34
+ * from load_exclusive, not the entire range, and we assume that the
24
+ * doesn't specify match those used by the Arm architecture.
35
+ * size of the access on both sides match. The architecture allows the
36
+ * store to be smaller than the load, so long as the stored bytes are
37
+ * within the range recorded by the load.
38
+ */
25
+ */
39
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
40
+ /* See AArch64.ExclusiveMonitorsPass() and AArch64.IsExclusiveVA(). */
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
41
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
28
42
tcg_gen_brcond_i64(TCG_COND_NE, clean_addr, cpu_exclusive_addr, fail_label);
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;
43
38
44
+ /*
39
+ /*
45
+ * The write, and any associated faults, only happen if the virtual
40
+ * These implementation-defined choices for various things IEEE
46
+ * and physical addresses pass the exclusive monitor check. These
41
+ * doesn't specify match those used by the Arm architecture.
47
+ * faults are exceedingly unlikely, because normally the guest uses
48
+ * the exact same address register for the load_exclusive, and we
49
+ * would have recognized these faults there.
50
+ *
51
+ * It is possible to trigger an alignment fault pre-LSE2, e.g. with an
52
+ * unaligned 4-byte write within the range of an aligned 8-byte load.
53
+ * With LSE2, the store would need to cross a 16-byte boundary when the
54
+ * load did not, which would mean the store is outside the range
55
+ * recorded for the monitor, which would have failed a corrected monitor
56
+ * check above. For now, we assume no size change and retain the
57
+ * MO_ALIGN to let tcg know what we checked in the load_exclusive.
58
+ *
59
+ * It is possible to trigger an MTE fault, by performing the load with
60
+ * a virtual address with a valid tag and performing the store with the
61
+ * same virtual address and a different invalid tag.
62
+ */
42
+ */
63
+ memop = size + is_pair;
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
64
+ if (memop == MO_128 || !dc_isar_feature(aa64_lse2, s)) {
44
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
65
+ memop |= MO_ALIGN;
45
66
+ }
46
genCases_setLevel(test_level);
67
+ memop = finalize_memop(s, memop);
47
verCases_maxErrorCount = n_max_errors;
68
+ gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, memop);
69
+
70
tmp = tcg_temp_new_i64();
71
if (is_pair) {
72
if (size == 2) {
73
--
48
--
74
2.34.1
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the Arm target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-6-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 3 +++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 4 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
21
+ * and the input NaN if it is signalling
22
*/
23
static void arm_set_default_fp_behaviours(float_status *s)
24
{
25
set_float_detect_tininess(float_tininess_before_rounding, s);
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
28
}
29
30
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
/*
37
* Temporarily fall back to ifdef ladder
38
*/
39
-#if defined(TARGET_ARM)
40
- /*
41
- * For ARM, the (inf,zero,qnan) case returns the default NaN,
42
- * but (inf,zero,snan) returns the input NaN.
43
- */
44
- rule = float_infzeronan_dnan_if_qnan;
45
-#elif defined(TARGET_MIPS)
46
+#if defined(TARGET_MIPS)
47
if (snan_bit_is_one(status)) {
48
/*
49
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
50
--
51
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
can remove the ifdef from pickNaNMulAdd().
2
3
3
This is required for LSE2, where the pair must be treated atomically if
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
it does not cross a 16-byte boundary. But it simplifies the code to do
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
this always.
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(-)
6
11
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230530191438.411344-10-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/tcg/translate-a64.c | 70 ++++++++++++++++++++++++++--------
13
1 file changed, 55 insertions(+), 15 deletions(-)
14
15
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/tcg/translate-a64.c
14
--- a/target/s390x/cpu.c
18
+++ b/target/arm/tcg/translate-a64.c
15
+++ b/target/s390x/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
20
} else {
17
set_float_detect_tininess(float_tininess_before_rounding,
21
TCGv_i64 tcg_rt = cpu_reg(s, rt);
18
&env->fpu_status);
22
TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
23
+ MemOp mop = size + 1;
20
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
24
+
21
+ &env->fpu_status);
25
+ /*
22
/* fall through */
26
+ * With LSE2, non-sign-extending pairs are treated atomically if
23
case RESET_TYPE_S390_CPU_NORMAL:
27
+ * aligned, and if unaligned one of the pair will be completely
24
env->psw.mask &= ~PSW_MASK_RI;
28
+ * within a 16-byte block and that element will be atomic.
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
29
+ * Otherwise each element is separately atomic.
26
index XXXXXXX..XXXXXXX 100644
30
+ * In all cases, issue one operation with the correct atomicity.
27
--- a/fpu/softfloat-specialize.c.inc
31
+ *
28
+++ b/fpu/softfloat-specialize.c.inc
32
+ * This treats sign-extending loads like zero-extending loads,
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
33
+ * since that reuses the most code below.
30
* a default NaN
34
+ */
31
*/
35
+ if (s->align_mem) {
32
rule = float_infzeronan_dnan_never;
36
+ mop |= (size == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
33
-#elif defined(TARGET_S390X)
37
+ }
34
- rule = float_infzeronan_dnan_always;
38
+ mop = finalize_memop_pair(s, mop);
35
#endif
39
40
if (is_load) {
41
- TCGv_i64 tmp = tcg_temp_new_i64();
42
+ if (size == 2) {
43
+ int o2 = s->be_data == MO_LE ? 32 : 0;
44
+ int o1 = o2 ^ 32;
45
46
- /* Do not modify tcg_rt before recognizing any exception
47
- * from the second load.
48
- */
49
- do_gpr_ld(s, tmp, clean_addr, size + is_signed * MO_SIGN,
50
- false, false, 0, false, false);
51
- tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
52
- do_gpr_ld(s, tcg_rt2, clean_addr, size + is_signed * MO_SIGN,
53
- false, false, 0, false, false);
54
+ tcg_gen_qemu_ld_i64(tcg_rt, clean_addr, get_mem_index(s), mop);
55
+ if (is_signed) {
56
+ tcg_gen_sextract_i64(tcg_rt2, tcg_rt, o2, 32);
57
+ tcg_gen_sextract_i64(tcg_rt, tcg_rt, o1, 32);
58
+ } else {
59
+ tcg_gen_extract_i64(tcg_rt2, tcg_rt, o2, 32);
60
+ tcg_gen_extract_i64(tcg_rt, tcg_rt, o1, 32);
61
+ }
62
+ } else {
63
+ TCGv_i128 tmp = tcg_temp_new_i128();
64
65
- tcg_gen_mov_i64(tcg_rt, tmp);
66
+ tcg_gen_qemu_ld_i128(tmp, clean_addr, get_mem_index(s), mop);
67
+ if (s->be_data == MO_LE) {
68
+ tcg_gen_extr_i128_i64(tcg_rt, tcg_rt2, tmp);
69
+ } else {
70
+ tcg_gen_extr_i128_i64(tcg_rt2, tcg_rt, tmp);
71
+ }
72
+ }
73
} else {
74
- do_gpr_st(s, tcg_rt, clean_addr, size,
75
- false, 0, false, false);
76
- tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
77
- do_gpr_st(s, tcg_rt2, clean_addr, size,
78
- false, 0, false, false);
79
+ if (size == 2) {
80
+ TCGv_i64 tmp = tcg_temp_new_i64();
81
+
82
+ if (s->be_data == MO_LE) {
83
+ tcg_gen_concat32_i64(tmp, tcg_rt, tcg_rt2);
84
+ } else {
85
+ tcg_gen_concat32_i64(tmp, tcg_rt2, tcg_rt);
86
+ }
87
+ tcg_gen_qemu_st_i64(tmp, clean_addr, get_mem_index(s), mop);
88
+ } else {
89
+ TCGv_i128 tmp = tcg_temp_new_i128();
90
+
91
+ if (s->be_data == MO_LE) {
92
+ tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
93
+ } else {
94
+ tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
95
+ }
96
+ tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
97
+ }
98
}
99
}
36
}
100
37
101
--
38
--
102
2.34.1
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: qianfan Zhao <qianfanguijin@163.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
Types of memory that the SDRAM controller supports are DDR2/DDR3
3
are NaNs. As a result different architectures have ended up with
4
and capacities of up to 2GiB. This commit adds emulation support
4
different rules for propagating NaNs.
5
of the Allwinner R40 SDRAM controller.
5
6
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
This driver only support 256M, 512M and 1024M memory now.
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
8
We want to make the propagation rule instead be selectable at
9
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
11
---
27
---
12
include/hw/arm/allwinner-r40.h | 13 +-
28
include/fpu/softfloat-helpers.h | 11 +++
13
include/hw/misc/allwinner-r40-dramc.h | 108 ++++++
29
include/fpu/softfloat-types.h | 55 +++++++++++
14
hw/arm/allwinner-r40.c | 21 +-
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
15
hw/arm/bananapi_m2u.c | 7 +
31
3 files changed, 107 insertions(+), 126 deletions(-)
16
hw/misc/allwinner-r40-dramc.c | 513 ++++++++++++++++++++++++++
32
17
hw/misc/meson.build | 1 +
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
18
hw/misc/trace-events | 14 +
19
7 files changed, 674 insertions(+), 3 deletions(-)
20
create mode 100644 include/hw/misc/allwinner-r40-dramc.h
21
create mode 100644 hw/misc/allwinner-r40-dramc.c
22
23
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
24
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/allwinner-r40.h
35
--- a/include/fpu/softfloat-helpers.h
26
+++ b/include/hw/arm/allwinner-r40.h
36
+++ b/include/fpu/softfloat-helpers.h
27
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
28
#include "hw/intc/arm_gic.h"
38
status->float_2nan_prop_rule = rule;
29
#include "hw/sd/allwinner-sdhost.h"
39
}
30
#include "hw/misc/allwinner-r40-ccu.h"
40
31
+#include "hw/misc/allwinner-r40-dramc.h"
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
32
#include "hw/i2c/allwinner-i2c.h"
42
+ float_status *status)
33
#include "target/arm/cpu.h"
43
+{
34
#include "sysemu/block-backend.h"
44
+ status->float_3nan_prop_rule = rule;
35
@@ -XXX,XX +XXX,XX @@ enum {
45
+}
36
AW_R40_DEV_GIC_CPU,
46
+
37
AW_R40_DEV_GIC_HYP,
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
38
AW_R40_DEV_GIC_VCPU,
48
float_status *status)
39
- AW_R40_DEV_SDRAM
49
{
40
+ AW_R40_DEV_SDRAM,
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
41
+ AW_R40_DEV_DRAMCOM,
51
return status->float_2nan_prop_rule;
42
+ AW_R40_DEV_DRAMCTL,
52
}
43
+ AW_R40_DEV_DRAMPHY,
53
44
};
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
45
55
+{
46
#define AW_R40_NUM_CPUS (4)
56
+ return status->float_3nan_prop_rule;
47
@@ -XXX,XX +XXX,XX @@ struct AwR40State {
57
+}
48
DeviceState parent_obj;
58
+
49
/*< public >*/
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
50
60
{
51
+ /** Physical base address for start of RAM */
61
return status->float_infzeronan_rule;
52
+ hwaddr ram_addr;
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
53
+
63
index XXXXXXX..XXXXXXX 100644
54
+ /** Total RAM size in megabytes */
64
--- a/include/fpu/softfloat-types.h
55
+ uint32_t ram_size;
65
+++ b/include/fpu/softfloat-types.h
56
+
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
57
ARMCPU cpus[AW_R40_NUM_CPUS];
67
#ifndef SOFTFLOAT_TYPES_H
58
const hwaddr *memmap;
68
#define SOFTFLOAT_TYPES_H
59
AwA10PITState timer;
69
60
AwSdHostState mmc[AW_R40_NUM_MMCS];
70
+#include "hw/registerfields.h"
61
AwR40ClockCtlState ccu;
71
+
62
+ AwR40DramCtlState dramc;
72
/*
63
AWI2CState i2c0;
73
* Software IEC/IEEE floating-point types.
64
GICState gic;
74
*/
65
MemoryRegion sram_a1;
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
66
diff --git a/include/hw/misc/allwinner-r40-dramc.h b/include/hw/misc/allwinner-r40-dramc.h
76
float_2nan_prop_x87,
67
new file mode 100644
77
} Float2NaNPropRule;
68
index XXXXXXX..XXXXXXX
78
69
--- /dev/null
70
+++ b/include/hw/misc/allwinner-r40-dramc.h
71
@@ -XXX,XX +XXX,XX @@
72
+/*
79
+/*
73
+ * Allwinner R40 SDRAM Controller emulation
80
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
81
+ * architectures have different rules for which input NaN is
82
+ * propagated to the output when there is more than one NaN on the
83
+ * input.
74
+ *
84
+ *
75
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
85
+ * If default_nan_mode is enabled then it is valid not to set a NaN
86
+ * propagation rule, because the softfloat code guarantees not to try
87
+ * to pick a NaN to propagate in default NaN mode. When not in
88
+ * default-NaN mode, it is an error for the target not to set the rule
89
+ * in float_status if it uses a muladd, and we will assert if we need
90
+ * to handle an input NaN and no rule was selected.
76
+ *
91
+ *
77
+ * This program is free software: you can redistribute it and/or modify
92
+ * The naming scheme for Float3NaNPropRule values is:
78
+ * it under the terms of the GNU General Public License as published by
93
+ * float_3nan_prop_s_abc:
79
+ * the Free Software Foundation, either version 2 of the License, or
94
+ * = "Prefer SNaN over QNaN, then operand A over B over C"
80
+ * (at your option) any later version.
95
+ * float_3nan_prop_abc:
96
+ * = "Prefer A over B over C regardless of SNaN vs QNAN"
81
+ *
97
+ *
82
+ * This program is distributed in the hope that it will be useful,
98
+ * For QEMU, the multiply-add operation is A * B + C.
83
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
84
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85
+ * GNU General Public License for more details.
86
+ *
87
+ * You should have received a copy of the GNU General Public License
88
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
89
+ */
99
+ */
90
+
100
+
91
+#ifndef HW_MISC_ALLWINNER_R40_DRAMC_H
101
+/*
92
+#define HW_MISC_ALLWINNER_R40_DRAMC_H
102
+ * We set the Float3NaNPropRule enum values up so we can select the
93
+
103
+ * right value in pickNaNMulAdd in a data driven way.
94
+#include "qom/object.h"
95
+#include "hw/sysbus.h"
96
+#include "exec/hwaddr.h"
97
+
98
+/**
99
+ * Constants
100
+ * @{
101
+ */
104
+ */
102
+
105
+FIELD(3NAN, 1ST, 0, 2) /* which operand is most preferred ? */
103
+/** Highest register address used by DRAMCOM module */
106
+FIELD(3NAN, 2ND, 2, 2) /* which operand is next most preferred ? */
104
+#define AW_R40_DRAMCOM_REGS_MAXADDR (0x804)
107
+FIELD(3NAN, 3RD, 4, 2) /* which operand is least preferred ? */
105
+
108
+FIELD(3NAN, SNAN, 6, 1) /* do we prefer SNaN over QNaN ? */
106
+/** Total number of known DRAMCOM registers */
109
+
107
+#define AW_R40_DRAMCOM_REGS_NUM (AW_R40_DRAMCOM_REGS_MAXADDR / \
110
+#define PROPRULE(X, Y, Z) \
108
+ sizeof(uint32_t))
111
+ ((X << R_3NAN_1ST_SHIFT) | (Y << R_3NAN_2ND_SHIFT) | (Z << R_3NAN_3RD_SHIFT))
109
+
112
+
110
+/** Highest register address used by DRAMCTL module */
113
+typedef enum __attribute__((__packed__)) {
111
+#define AW_R40_DRAMCTL_REGS_MAXADDR (0x88c)
114
+ float_3nan_prop_none = 0, /* No propagation rule specified */
112
+
115
+ float_3nan_prop_abc = PROPRULE(0, 1, 2),
113
+/** Total number of known DRAMCTL registers */
116
+ float_3nan_prop_acb = PROPRULE(0, 2, 1),
114
+#define AW_R40_DRAMCTL_REGS_NUM (AW_R40_DRAMCTL_REGS_MAXADDR / \
117
+ float_3nan_prop_bac = PROPRULE(1, 0, 2),
115
+ sizeof(uint32_t))
118
+ float_3nan_prop_bca = PROPRULE(1, 2, 0),
116
+
119
+ float_3nan_prop_cab = PROPRULE(2, 0, 1),
117
+/** Highest register address used by DRAMPHY module */
120
+ float_3nan_prop_cba = PROPRULE(2, 1, 0),
118
+#define AW_R40_DRAMPHY_REGS_MAXADDR (0x4)
121
+ float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,
119
+
122
+ float_3nan_prop_s_acb = float_3nan_prop_acb | R_3NAN_SNAN_MASK,
120
+/** Total number of known DRAMPHY registers */
123
+ float_3nan_prop_s_bac = float_3nan_prop_bac | R_3NAN_SNAN_MASK,
121
+#define AW_R40_DRAMPHY_REGS_NUM (AW_R40_DRAMPHY_REGS_MAXADDR / \
124
+ float_3nan_prop_s_bca = float_3nan_prop_bca | R_3NAN_SNAN_MASK,
122
+ sizeof(uint32_t))
125
+ float_3nan_prop_s_cab = float_3nan_prop_cab | R_3NAN_SNAN_MASK,
123
+
126
+ float_3nan_prop_s_cba = float_3nan_prop_cba | R_3NAN_SNAN_MASK,
124
+/** @} */
127
+} Float3NaNPropRule;
125
+
128
+
126
+/**
129
+#undef PROPRULE
127
+ * Object model
130
+
128
+ * @{
131
/*
129
+ */
132
* Rule for result of fused multiply-add 0 * Inf + NaN.
130
+
133
* This must be a NaN, but implementations differ on whether this
131
+#define TYPE_AW_R40_DRAMC "allwinner-r40-dramc"
134
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
132
+OBJECT_DECLARE_SIMPLE_TYPE(AwR40DramCtlState, AW_R40_DRAMC)
135
FloatRoundMode float_rounding_mode;
133
+
136
FloatX80RoundPrec floatx80_rounding_precision;
134
+/** @} */
137
Float2NaNPropRule float_2nan_prop_rule;
135
+
138
+ Float3NaNPropRule float_3nan_prop_rule;
136
+/**
139
FloatInfZeroNaNRule float_infzeronan_rule;
137
+ * Allwinner R40 SDRAM Controller object instance state.
140
bool tininess_before_rounding;
138
+ */
141
/* should denormalised results go to zero and set the inexact flag? */
139
+struct AwR40DramCtlState {
142
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
140
+ /*< private >*/
141
+ SysBusDevice parent_obj;
142
+ /*< public >*/
143
+
144
+ /** Physical base address for start of RAM */
145
+ hwaddr ram_addr;
146
+
147
+ /** Total RAM size in megabytes */
148
+ uint32_t ram_size;
149
+
150
+ uint8_t set_row_bits;
151
+ uint8_t set_bank_bits;
152
+ uint8_t set_col_bits;
153
+
154
+ /**
155
+ * @name Memory Regions
156
+ * @{
157
+ */
158
+ MemoryRegion dramcom_iomem; /**< DRAMCOM module I/O registers */
159
+ MemoryRegion dramctl_iomem; /**< DRAMCTL module I/O registers */
160
+ MemoryRegion dramphy_iomem; /**< DRAMPHY module I/O registers */
161
+ MemoryRegion dram_high; /**< The high 1G dram for dualrank detect */
162
+ MemoryRegion detect_cells; /**< DRAM memory cells for auto detect */
163
+
164
+ /** @} */
165
+
166
+ /**
167
+ * @name Hardware Registers
168
+ * @{
169
+ */
170
+
171
+ uint32_t dramcom[AW_R40_DRAMCOM_REGS_NUM]; /**< DRAMCOM registers */
172
+ uint32_t dramctl[AW_R40_DRAMCTL_REGS_NUM]; /**< DRAMCTL registers */
173
+ uint32_t dramphy[AW_R40_DRAMPHY_REGS_NUM] ;/**< DRAMPHY registers */
174
+
175
+ /** @} */
176
+
177
+};
178
+
179
+#endif /* HW_MISC_ALLWINNER_R40_DRAMC_H */
180
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
181
index XXXXXXX..XXXXXXX 100644
143
index XXXXXXX..XXXXXXX 100644
182
--- a/hw/arm/allwinner-r40.c
144
--- a/fpu/softfloat-specialize.c.inc
183
+++ b/hw/arm/allwinner-r40.c
145
+++ b/fpu/softfloat-specialize.c.inc
184
@@ -XXX,XX +XXX,XX @@
146
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
185
#include "hw/loader.h"
147
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
186
#include "sysemu/sysemu.h"
148
bool infzero, bool have_snan, float_status *status)
187
#include "hw/arm/allwinner-r40.h"
149
{
188
+#include "hw/misc/allwinner-r40-dramc.h"
150
+ FloatClass cls[3] = { a_cls, b_cls, c_cls };
189
151
+ Float3NaNPropRule rule = status->float_3nan_prop_rule;
190
/* Memory map */
152
+ int which;
191
const hwaddr allwinner_r40_memmap[] = {
153
+
192
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_r40_memmap[] = {
154
/*
193
[AW_R40_DEV_UART6] = 0x01c29800,
155
* We guarantee not to require the target to tell us how to
194
[AW_R40_DEV_UART7] = 0x01c29c00,
156
* pick a NaN if we're always returning the default NaN.
195
[AW_R40_DEV_TWI0] = 0x01c2ac00,
157
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
196
+ [AW_R40_DEV_DRAMCOM] = 0x01c62000,
158
}
197
+ [AW_R40_DEV_DRAMCTL] = 0x01c63000,
198
+ [AW_R40_DEV_DRAMPHY] = 0x01c65000,
199
[AW_R40_DEV_GIC_DIST] = 0x01c81000,
200
[AW_R40_DEV_GIC_CPU] = 0x01c82000,
201
[AW_R40_DEV_GIC_HYP] = 0x01c84000,
202
@@ -XXX,XX +XXX,XX @@ static struct AwR40Unimplemented r40_unimplemented[] = {
203
{ "gpu", 0x01c40000, 64 * KiB },
204
{ "gmac", 0x01c50000, 64 * KiB },
205
{ "hstmr", 0x01c60000, 4 * KiB },
206
- { "dram-com", 0x01c62000, 4 * KiB },
207
- { "dram-ctl", 0x01c63000, 4 * KiB },
208
{ "tcon-top", 0x01c70000, 4 * KiB },
209
{ "lcd0", 0x01c71000, 4 * KiB },
210
{ "lcd1", 0x01c72000, 4 * KiB },
211
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_init(Object *obj)
212
}
159
}
213
160
214
object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
161
+ if (rule == float_3nan_prop_none) {
215
+
162
#if defined(TARGET_ARM)
216
+ object_initialize_child(obj, "dramc", &s->dramc, TYPE_AW_R40_DRAMC);
163
-
217
+ object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc),
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
218
+ "ram-addr");
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
219
+ object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
166
- */
220
+ "ram-size");
167
- if (is_snan(c_cls)) {
168
- return 2;
169
- } else if (is_snan(a_cls)) {
170
- return 0;
171
- } else if (is_snan(b_cls)) {
172
- return 1;
173
- } else if (is_qnan(c_cls)) {
174
- return 2;
175
- } else if (is_qnan(a_cls)) {
176
- return 0;
177
- } else {
178
- return 1;
179
- }
180
+ /*
181
+ * This looks different from the ARM ARM pseudocode, because the ARM ARM
182
+ * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
183
+ */
184
+ rule = float_3nan_prop_s_cab;
185
#elif defined(TARGET_MIPS)
186
- if (snan_bit_is_one(status)) {
187
- /* Prefer sNaN over qNaN, in the a, b, c order. */
188
- if (is_snan(a_cls)) {
189
- return 0;
190
- } else if (is_snan(b_cls)) {
191
- return 1;
192
- } else if (is_snan(c_cls)) {
193
- return 2;
194
- } else if (is_qnan(a_cls)) {
195
- return 0;
196
- } else if (is_qnan(b_cls)) {
197
- return 1;
198
+ if (snan_bit_is_one(status)) {
199
+ rule = float_3nan_prop_s_abc;
200
} else {
201
- return 2;
202
+ rule = float_3nan_prop_s_cab;
203
}
204
- } else {
205
- /* Prefer sNaN over qNaN, in the c, a, b order. */
206
- if (is_snan(c_cls)) {
207
- return 2;
208
- } else if (is_snan(a_cls)) {
209
- return 0;
210
- } else if (is_snan(b_cls)) {
211
- return 1;
212
- } else if (is_qnan(c_cls)) {
213
- return 2;
214
- } else if (is_qnan(a_cls)) {
215
- return 0;
216
- } else {
217
- return 1;
218
- }
219
- }
220
#elif defined(TARGET_LOONGARCH64)
221
- /* Prefer sNaN over qNaN, in the c, a, b order. */
222
- if (is_snan(c_cls)) {
223
- return 2;
224
- } else if (is_snan(a_cls)) {
225
- return 0;
226
- } else if (is_snan(b_cls)) {
227
- return 1;
228
- } else if (is_qnan(c_cls)) {
229
- return 2;
230
- } else if (is_qnan(a_cls)) {
231
- return 0;
232
- } else {
233
- return 1;
234
- }
235
+ rule = float_3nan_prop_s_cab;
236
#elif defined(TARGET_PPC)
237
- /* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
238
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
239
- */
240
- if (is_nan(a_cls)) {
241
- return 0;
242
- } else if (is_nan(c_cls)) {
243
- return 2;
244
- } else {
245
- return 1;
246
- }
247
+ /*
248
+ * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
249
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
250
+ */
251
+ rule = float_3nan_prop_acb;
252
#elif defined(TARGET_S390X)
253
- if (is_snan(a_cls)) {
254
- return 0;
255
- } else if (is_snan(b_cls)) {
256
- return 1;
257
- } else if (is_snan(c_cls)) {
258
- return 2;
259
- } else if (is_qnan(a_cls)) {
260
- return 0;
261
- } else if (is_qnan(b_cls)) {
262
- return 1;
263
- } else {
264
- return 2;
265
- }
266
+ rule = float_3nan_prop_s_abc;
267
#elif defined(TARGET_SPARC)
268
- /* Prefer SNaN over QNaN, order C, B, A. */
269
- if (is_snan(c_cls)) {
270
- return 2;
271
- } else if (is_snan(b_cls)) {
272
- return 1;
273
- } else if (is_snan(a_cls)) {
274
- return 0;
275
- } else if (is_qnan(c_cls)) {
276
- return 2;
277
- } else if (is_qnan(b_cls)) {
278
- return 1;
279
- } else {
280
- return 0;
281
- }
282
+ rule = float_3nan_prop_s_cba;
283
#elif defined(TARGET_XTENSA)
284
- /*
285
- * For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
286
- * an input NaN if we have one (ie c).
287
- */
288
- if (status->use_first_nan) {
289
- if (is_nan(a_cls)) {
290
- return 0;
291
- } else if (is_nan(b_cls)) {
292
- return 1;
293
+ if (status->use_first_nan) {
294
+ rule = float_3nan_prop_abc;
295
} else {
296
- return 2;
297
+ rule = float_3nan_prop_cba;
298
}
299
- } else {
300
- if (is_nan(c_cls)) {
301
- return 2;
302
- } else if (is_nan(b_cls)) {
303
- return 1;
304
- } else {
305
- return 0;
306
- }
307
- }
308
#else
309
- /* A default implementation: prefer a to b to c.
310
- * This is unlikely to actually match any real implementation.
311
- */
312
- if (is_nan(a_cls)) {
313
- return 0;
314
- } else if (is_nan(b_cls)) {
315
- return 1;
316
- } else {
317
- return 2;
318
- }
319
+ rule = float_3nan_prop_abc;
320
#endif
321
+ }
322
+
323
+ assert(rule != float_3nan_prop_none);
324
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
325
+ /* We have at least one SNaN input and should prefer it */
326
+ do {
327
+ which = rule & R_3NAN_1ST_MASK;
328
+ rule >>= R_3NAN_1ST_LENGTH;
329
+ } while (!is_snan(cls[which]));
330
+ } else {
331
+ do {
332
+ which = rule & R_3NAN_1ST_MASK;
333
+ rule >>= R_3NAN_1ST_LENGTH;
334
+ } while (!is_nan(cls[which]));
335
+ }
336
+ return which;
221
}
337
}
222
338
223
static void allwinner_r40_realize(DeviceState *dev, Error **errp)
339
/*----------------------------------------------------------------------------
224
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_realize(DeviceState *dev, Error **errp)
225
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0,
226
qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_TWI0));
227
228
+ /* DRAMC */
229
+ sysbus_realize(SYS_BUS_DEVICE(&s->dramc), &error_fatal);
230
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0,
231
+ s->memmap[AW_R40_DEV_DRAMCOM]);
232
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1,
233
+ s->memmap[AW_R40_DEV_DRAMCTL]);
234
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2,
235
+ s->memmap[AW_R40_DEV_DRAMPHY]);
236
+
237
/* Unimplemented devices */
238
for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
239
create_unimplemented_device(r40_unimplemented[i].device_name,
240
diff --git a/hw/arm/bananapi_m2u.c b/hw/arm/bananapi_m2u.c
241
index XXXXXXX..XXXXXXX 100644
242
--- a/hw/arm/bananapi_m2u.c
243
+++ b/hw/arm/bananapi_m2u.c
244
@@ -XXX,XX +XXX,XX @@ static void bpim2u_init(MachineState *machine)
245
object_property_set_int(OBJECT(r40), "clk1-freq", 24 * 1000 * 1000,
246
&error_abort);
247
248
+ /* DRAMC */
249
+ r40->ram_size = machine->ram_size / MiB;
250
+ object_property_set_uint(OBJECT(r40), "ram-addr",
251
+ r40->memmap[AW_R40_DEV_SDRAM], &error_abort);
252
+ object_property_set_int(OBJECT(r40), "ram-size",
253
+ r40->ram_size, &error_abort);
254
+
255
/* Mark R40 object realized */
256
qdev_realize(DEVICE(r40), NULL, &error_abort);
257
258
diff --git a/hw/misc/allwinner-r40-dramc.c b/hw/misc/allwinner-r40-dramc.c
259
new file mode 100644
260
index XXXXXXX..XXXXXXX
261
--- /dev/null
262
+++ b/hw/misc/allwinner-r40-dramc.c
263
@@ -XXX,XX +XXX,XX @@
264
+/*
265
+ * Allwinner R40 SDRAM Controller emulation
266
+ *
267
+ * CCopyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
268
+ *
269
+ * This program is free software: you can redistribute it and/or modify
270
+ * it under the terms of the GNU General Public License as published by
271
+ * the Free Software Foundation, either version 2 of the License, or
272
+ * (at your option) any later version.
273
+ *
274
+ * This program is distributed in the hope that it will be useful,
275
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
276
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
277
+ * GNU General Public License for more details.
278
+ *
279
+ * You should have received a copy of the GNU General Public License
280
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
281
+ */
282
+
283
+#include "qemu/osdep.h"
284
+#include "qemu/units.h"
285
+#include "qemu/error-report.h"
286
+#include "hw/sysbus.h"
287
+#include "migration/vmstate.h"
288
+#include "qemu/log.h"
289
+#include "qemu/module.h"
290
+#include "exec/address-spaces.h"
291
+#include "hw/qdev-properties.h"
292
+#include "qapi/error.h"
293
+#include "qemu/bitops.h"
294
+#include "hw/misc/allwinner-r40-dramc.h"
295
+#include "trace.h"
296
+
297
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
298
+
299
+/* DRAMCOM register offsets */
300
+enum {
301
+ REG_DRAMCOM_CR = 0x0000, /* Control Register */
302
+};
303
+
304
+/* DRAMCOMM register flags */
305
+enum {
306
+ REG_DRAMCOM_CR_DUAL_RANK = (1 << 0),
307
+};
308
+
309
+/* DRAMCTL register offsets */
310
+enum {
311
+ REG_DRAMCTL_PIR = 0x0000, /* PHY Initialization Register */
312
+ REG_DRAMCTL_PGSR = 0x0010, /* PHY General Status Register */
313
+ REG_DRAMCTL_STATR = 0x0018, /* Status Register */
314
+ REG_DRAMCTL_PGCR = 0x0100, /* PHY general configuration registers */
315
+};
316
+
317
+/* DRAMCTL register flags */
318
+enum {
319
+ REG_DRAMCTL_PGSR_INITDONE = (1 << 0),
320
+ REG_DRAMCTL_PGSR_READ_TIMEOUT = (1 << 13),
321
+ REG_DRAMCTL_PGCR_ENABLE_READ_TIMEOUT = (1 << 25),
322
+};
323
+
324
+enum {
325
+ REG_DRAMCTL_STATR_ACTIVE = (1 << 0),
326
+};
327
+
328
+#define DRAM_MAX_ROW_BITS 16
329
+#define DRAM_MAX_COL_BITS 13 /* 8192 */
330
+#define DRAM_MAX_BANK 3
331
+
332
+static uint64_t dram_autodetect_cells[DRAM_MAX_ROW_BITS]
333
+ [DRAM_MAX_BANK]
334
+ [DRAM_MAX_COL_BITS];
335
+struct VirtualDDRChip {
336
+ uint32_t ram_size;
337
+ uint8_t bank_bits;
338
+ uint8_t row_bits;
339
+ uint8_t col_bits;
340
+};
341
+
342
+/*
343
+ * Only power of 2 RAM sizes from 256MiB up to 2048MiB are supported,
344
+ * 2GiB memory is not supported due to dual rank feature.
345
+ */
346
+static const struct VirtualDDRChip dummy_ddr_chips[] = {
347
+ {
348
+ .ram_size = 256,
349
+ .bank_bits = 3,
350
+ .row_bits = 12,
351
+ .col_bits = 13,
352
+ }, {
353
+ .ram_size = 512,
354
+ .bank_bits = 3,
355
+ .row_bits = 13,
356
+ .col_bits = 13,
357
+ }, {
358
+ .ram_size = 1024,
359
+ .bank_bits = 3,
360
+ .row_bits = 14,
361
+ .col_bits = 13,
362
+ }, {
363
+ 0
364
+ }
365
+};
366
+
367
+static const struct VirtualDDRChip *get_match_ddr(uint32_t ram_size)
368
+{
369
+ const struct VirtualDDRChip *ddr;
370
+
371
+ for (ddr = &dummy_ddr_chips[0]; ddr->ram_size; ddr++) {
372
+ if (ddr->ram_size == ram_size) {
373
+ return ddr;
374
+ }
375
+ }
376
+
377
+ return NULL;
378
+}
379
+
380
+static uint64_t *address_to_autodetect_cells(AwR40DramCtlState *s,
381
+ const struct VirtualDDRChip *ddr,
382
+ uint32_t offset)
383
+{
384
+ int row_index = 0, bank_index = 0, col_index = 0;
385
+ uint32_t row_addr, bank_addr, col_addr;
386
+
387
+ row_addr = extract32(offset, s->set_col_bits + s->set_bank_bits,
388
+ s->set_row_bits);
389
+ bank_addr = extract32(offset, s->set_col_bits, s->set_bank_bits);
390
+ col_addr = extract32(offset, 0, s->set_col_bits);
391
+
392
+ for (int i = 0; i < ddr->row_bits; i++) {
393
+ if (row_addr & BIT(i)) {
394
+ row_index = i;
395
+ }
396
+ }
397
+
398
+ for (int i = 0; i < ddr->bank_bits; i++) {
399
+ if (bank_addr & BIT(i)) {
400
+ bank_index = i;
401
+ }
402
+ }
403
+
404
+ for (int i = 0; i < ddr->col_bits; i++) {
405
+ if (col_addr & BIT(i)) {
406
+ col_index = i;
407
+ }
408
+ }
409
+
410
+ trace_allwinner_r40_dramc_offset_to_cell(offset, row_index, bank_index,
411
+ col_index);
412
+ return &dram_autodetect_cells[row_index][bank_index][col_index];
413
+}
414
+
415
+static void allwinner_r40_dramc_map_rows(AwR40DramCtlState *s, uint8_t row_bits,
416
+ uint8_t bank_bits, uint8_t col_bits)
417
+{
418
+ const struct VirtualDDRChip *ddr = get_match_ddr(s->ram_size);
419
+ bool enable_detect_cells;
420
+
421
+ trace_allwinner_r40_dramc_map_rows(row_bits, bank_bits, col_bits);
422
+
423
+ if (!ddr) {
424
+ return;
425
+ }
426
+
427
+ s->set_row_bits = row_bits;
428
+ s->set_bank_bits = bank_bits;
429
+ s->set_col_bits = col_bits;
430
+
431
+ enable_detect_cells = ddr->bank_bits != bank_bits
432
+ || ddr->row_bits != row_bits
433
+ || ddr->col_bits != col_bits;
434
+
435
+ if (enable_detect_cells) {
436
+ trace_allwinner_r40_dramc_detect_cells_enable();
437
+ } else {
438
+ trace_allwinner_r40_dramc_detect_cells_disable();
439
+ }
440
+
441
+ memory_region_set_enabled(&s->detect_cells, enable_detect_cells);
442
+}
443
+
444
+static uint64_t allwinner_r40_dramcom_read(void *opaque, hwaddr offset,
445
+ unsigned size)
446
+{
447
+ const AwR40DramCtlState *s = AW_R40_DRAMC(opaque);
448
+ const uint32_t idx = REG_INDEX(offset);
449
+
450
+ if (idx >= AW_R40_DRAMCOM_REGS_NUM) {
451
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
452
+ __func__, (uint32_t)offset);
453
+ return 0;
454
+ }
455
+
456
+ trace_allwinner_r40_dramcom_read(offset, s->dramcom[idx], size);
457
+ return s->dramcom[idx];
458
+}
459
+
460
+static void allwinner_r40_dramcom_write(void *opaque, hwaddr offset,
461
+ uint64_t val, unsigned size)
462
+{
463
+ AwR40DramCtlState *s = AW_R40_DRAMC(opaque);
464
+ const uint32_t idx = REG_INDEX(offset);
465
+
466
+ trace_allwinner_r40_dramcom_write(offset, val, size);
467
+
468
+ if (idx >= AW_R40_DRAMCOM_REGS_NUM) {
469
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
470
+ __func__, (uint32_t)offset);
471
+ return;
472
+ }
473
+
474
+ switch (offset) {
475
+ case REG_DRAMCOM_CR: /* Control Register */
476
+ if (!(val & REG_DRAMCOM_CR_DUAL_RANK)) {
477
+ allwinner_r40_dramc_map_rows(s, ((val >> 4) & 0xf) + 1,
478
+ ((val >> 2) & 0x1) + 2,
479
+ (((val >> 8) & 0xf) + 3));
480
+ }
481
+ break;
482
+ };
483
+
484
+ s->dramcom[idx] = (uint32_t) val;
485
+}
486
+
487
+static uint64_t allwinner_r40_dramctl_read(void *opaque, hwaddr offset,
488
+ unsigned size)
489
+{
490
+ const AwR40DramCtlState *s = AW_R40_DRAMC(opaque);
491
+ const uint32_t idx = REG_INDEX(offset);
492
+
493
+ if (idx >= AW_R40_DRAMCTL_REGS_NUM) {
494
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
495
+ __func__, (uint32_t)offset);
496
+ return 0;
497
+ }
498
+
499
+ trace_allwinner_r40_dramctl_read(offset, s->dramctl[idx], size);
500
+ return s->dramctl[idx];
501
+}
502
+
503
+static void allwinner_r40_dramctl_write(void *opaque, hwaddr offset,
504
+ uint64_t val, unsigned size)
505
+{
506
+ AwR40DramCtlState *s = AW_R40_DRAMC(opaque);
507
+ const uint32_t idx = REG_INDEX(offset);
508
+
509
+ trace_allwinner_r40_dramctl_write(offset, val, size);
510
+
511
+ if (idx >= AW_R40_DRAMCTL_REGS_NUM) {
512
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
513
+ __func__, (uint32_t)offset);
514
+ return;
515
+ }
516
+
517
+ switch (offset) {
518
+ case REG_DRAMCTL_PIR: /* PHY Initialization Register */
519
+ s->dramctl[REG_INDEX(REG_DRAMCTL_PGSR)] |= REG_DRAMCTL_PGSR_INITDONE;
520
+ s->dramctl[REG_INDEX(REG_DRAMCTL_STATR)] |= REG_DRAMCTL_STATR_ACTIVE;
521
+ break;
522
+ }
523
+
524
+ s->dramctl[idx] = (uint32_t) val;
525
+}
526
+
527
+static uint64_t allwinner_r40_dramphy_read(void *opaque, hwaddr offset,
528
+ unsigned size)
529
+{
530
+ const AwR40DramCtlState *s = AW_R40_DRAMC(opaque);
531
+ const uint32_t idx = REG_INDEX(offset);
532
+
533
+ if (idx >= AW_R40_DRAMPHY_REGS_NUM) {
534
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
535
+ __func__, (uint32_t)offset);
536
+ return 0;
537
+ }
538
+
539
+ trace_allwinner_r40_dramphy_read(offset, s->dramphy[idx], size);
540
+ return s->dramphy[idx];
541
+}
542
+
543
+static void allwinner_r40_dramphy_write(void *opaque, hwaddr offset,
544
+ uint64_t val, unsigned size)
545
+{
546
+ AwR40DramCtlState *s = AW_R40_DRAMC(opaque);
547
+ const uint32_t idx = REG_INDEX(offset);
548
+
549
+ trace_allwinner_r40_dramphy_write(offset, val, size);
550
+
551
+ if (idx >= AW_R40_DRAMPHY_REGS_NUM) {
552
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
553
+ __func__, (uint32_t)offset);
554
+ return;
555
+ }
556
+
557
+ s->dramphy[idx] = (uint32_t) val;
558
+}
559
+
560
+static const MemoryRegionOps allwinner_r40_dramcom_ops = {
561
+ .read = allwinner_r40_dramcom_read,
562
+ .write = allwinner_r40_dramcom_write,
563
+ .endianness = DEVICE_NATIVE_ENDIAN,
564
+ .valid = {
565
+ .min_access_size = 4,
566
+ .max_access_size = 4,
567
+ },
568
+ .impl.min_access_size = 4,
569
+};
570
+
571
+static const MemoryRegionOps allwinner_r40_dramctl_ops = {
572
+ .read = allwinner_r40_dramctl_read,
573
+ .write = allwinner_r40_dramctl_write,
574
+ .endianness = DEVICE_NATIVE_ENDIAN,
575
+ .valid = {
576
+ .min_access_size = 4,
577
+ .max_access_size = 4,
578
+ },
579
+ .impl.min_access_size = 4,
580
+};
581
+
582
+static const MemoryRegionOps allwinner_r40_dramphy_ops = {
583
+ .read = allwinner_r40_dramphy_read,
584
+ .write = allwinner_r40_dramphy_write,
585
+ .endianness = DEVICE_NATIVE_ENDIAN,
586
+ .valid = {
587
+ .min_access_size = 4,
588
+ .max_access_size = 4,
589
+ },
590
+ .impl.min_access_size = 4,
591
+};
592
+
593
+static uint64_t allwinner_r40_detect_read(void *opaque, hwaddr offset,
594
+ unsigned size)
595
+{
596
+ AwR40DramCtlState *s = AW_R40_DRAMC(opaque);
597
+ const struct VirtualDDRChip *ddr = get_match_ddr(s->ram_size);
598
+ uint64_t data = 0;
599
+
600
+ if (ddr) {
601
+ data = *address_to_autodetect_cells(s, ddr, (uint32_t)offset);
602
+ }
603
+
604
+ trace_allwinner_r40_dramc_detect_cell_read(offset, data);
605
+ return data;
606
+}
607
+
608
+static void allwinner_r40_detect_write(void *opaque, hwaddr offset,
609
+ uint64_t data, unsigned size)
610
+{
611
+ AwR40DramCtlState *s = AW_R40_DRAMC(opaque);
612
+ const struct VirtualDDRChip *ddr = get_match_ddr(s->ram_size);
613
+
614
+ if (ddr) {
615
+ uint64_t *cell = address_to_autodetect_cells(s, ddr, (uint32_t)offset);
616
+ trace_allwinner_r40_dramc_detect_cell_write(offset, data);
617
+ *cell = data;
618
+ }
619
+}
620
+
621
+static const MemoryRegionOps allwinner_r40_detect_ops = {
622
+ .read = allwinner_r40_detect_read,
623
+ .write = allwinner_r40_detect_write,
624
+ .endianness = DEVICE_NATIVE_ENDIAN,
625
+ .valid = {
626
+ .min_access_size = 4,
627
+ .max_access_size = 4,
628
+ },
629
+ .impl.min_access_size = 4,
630
+};
631
+
632
+/*
633
+ * mctl_r40_detect_rank_count in u-boot will write the high 1G of DDR
634
+ * to detect wether the board support dual_rank or not. Create a virtual memory
635
+ * if the board's ram_size less or equal than 1G, and set read time out flag of
636
+ * REG_DRAMCTL_PGSR when the user touch this high dram.
637
+ */
638
+static uint64_t allwinner_r40_dualrank_detect_read(void *opaque, hwaddr offset,
639
+ unsigned size)
640
+{
641
+ AwR40DramCtlState *s = AW_R40_DRAMC(opaque);
642
+ uint32_t reg;
643
+
644
+ reg = s->dramctl[REG_INDEX(REG_DRAMCTL_PGCR)];
645
+ if (reg & REG_DRAMCTL_PGCR_ENABLE_READ_TIMEOUT) { /* Enable read time out */
646
+ /*
647
+ * this driver only support one rank, mark READ_TIMEOUT when try
648
+ * read the second rank.
649
+ */
650
+ s->dramctl[REG_INDEX(REG_DRAMCTL_PGSR)]
651
+ |= REG_DRAMCTL_PGSR_READ_TIMEOUT;
652
+ }
653
+
654
+ return 0;
655
+}
656
+
657
+static const MemoryRegionOps allwinner_r40_dualrank_detect_ops = {
658
+ .read = allwinner_r40_dualrank_detect_read,
659
+ .endianness = DEVICE_NATIVE_ENDIAN,
660
+ .valid = {
661
+ .min_access_size = 4,
662
+ .max_access_size = 4,
663
+ },
664
+ .impl.min_access_size = 4,
665
+};
666
+
667
+static void allwinner_r40_dramc_reset(DeviceState *dev)
668
+{
669
+ AwR40DramCtlState *s = AW_R40_DRAMC(dev);
670
+
671
+ /* Set default values for registers */
672
+ memset(&s->dramcom, 0, sizeof(s->dramcom));
673
+ memset(&s->dramctl, 0, sizeof(s->dramctl));
674
+ memset(&s->dramphy, 0, sizeof(s->dramphy));
675
+}
676
+
677
+static void allwinner_r40_dramc_realize(DeviceState *dev, Error **errp)
678
+{
679
+ AwR40DramCtlState *s = AW_R40_DRAMC(dev);
680
+
681
+ if (!get_match_ddr(s->ram_size)) {
682
+ error_report("%s: ram-size %u MiB is not supported",
683
+ __func__, s->ram_size);
684
+ exit(1);
685
+ }
686
+
687
+ /* detect_cells */
688
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s), 3, s->ram_addr, 10);
689
+ memory_region_set_enabled(&s->detect_cells, false);
690
+
691
+ /*
692
+ * We only support DRAM size up to 1G now, so prepare a high memory page
693
+ * after 1G for dualrank detect. index = 4
694
+ */
695
+ memory_region_init_io(&s->dram_high, OBJECT(s),
696
+ &allwinner_r40_dualrank_detect_ops, s,
697
+ "DRAMHIGH", KiB);
698
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->dram_high);
699
+ sysbus_mmio_map(SYS_BUS_DEVICE(s), 4, s->ram_addr + GiB);
700
+}
701
+
702
+static void allwinner_r40_dramc_init(Object *obj)
703
+{
704
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
705
+ AwR40DramCtlState *s = AW_R40_DRAMC(obj);
706
+
707
+ /* DRAMCOM registers, index 0 */
708
+ memory_region_init_io(&s->dramcom_iomem, OBJECT(s),
709
+ &allwinner_r40_dramcom_ops, s,
710
+ "DRAMCOM", 4 * KiB);
711
+ sysbus_init_mmio(sbd, &s->dramcom_iomem);
712
+
713
+ /* DRAMCTL registers, index 1 */
714
+ memory_region_init_io(&s->dramctl_iomem, OBJECT(s),
715
+ &allwinner_r40_dramctl_ops, s,
716
+ "DRAMCTL", 4 * KiB);
717
+ sysbus_init_mmio(sbd, &s->dramctl_iomem);
718
+
719
+ /* DRAMPHY registers. index 2 */
720
+ memory_region_init_io(&s->dramphy_iomem, OBJECT(s),
721
+ &allwinner_r40_dramphy_ops, s,
722
+ "DRAMPHY", 4 * KiB);
723
+ sysbus_init_mmio(sbd, &s->dramphy_iomem);
724
+
725
+ /* R40 support max 2G memory but we only support up to 1G now. index 3 */
726
+ memory_region_init_io(&s->detect_cells, OBJECT(s),
727
+ &allwinner_r40_detect_ops, s,
728
+ "DRAMCELLS", 1 * GiB);
729
+ sysbus_init_mmio(sbd, &s->detect_cells);
730
+}
731
+
732
+static Property allwinner_r40_dramc_properties[] = {
733
+ DEFINE_PROP_UINT64("ram-addr", AwR40DramCtlState, ram_addr, 0x0),
734
+ DEFINE_PROP_UINT32("ram-size", AwR40DramCtlState, ram_size, 256), /* MiB */
735
+ DEFINE_PROP_END_OF_LIST()
736
+};
737
+
738
+static const VMStateDescription allwinner_r40_dramc_vmstate = {
739
+ .name = "allwinner-r40-dramc",
740
+ .version_id = 1,
741
+ .minimum_version_id = 1,
742
+ .fields = (VMStateField[]) {
743
+ VMSTATE_UINT32_ARRAY(dramcom, AwR40DramCtlState,
744
+ AW_R40_DRAMCOM_REGS_NUM),
745
+ VMSTATE_UINT32_ARRAY(dramctl, AwR40DramCtlState,
746
+ AW_R40_DRAMCTL_REGS_NUM),
747
+ VMSTATE_UINT32_ARRAY(dramphy, AwR40DramCtlState,
748
+ AW_R40_DRAMPHY_REGS_NUM),
749
+ VMSTATE_END_OF_LIST()
750
+ }
751
+};
752
+
753
+static void allwinner_r40_dramc_class_init(ObjectClass *klass, void *data)
754
+{
755
+ DeviceClass *dc = DEVICE_CLASS(klass);
756
+
757
+ dc->reset = allwinner_r40_dramc_reset;
758
+ dc->vmsd = &allwinner_r40_dramc_vmstate;
759
+ dc->realize = allwinner_r40_dramc_realize;
760
+ device_class_set_props(dc, allwinner_r40_dramc_properties);
761
+}
762
+
763
+static const TypeInfo allwinner_r40_dramc_info = {
764
+ .name = TYPE_AW_R40_DRAMC,
765
+ .parent = TYPE_SYS_BUS_DEVICE,
766
+ .instance_init = allwinner_r40_dramc_init,
767
+ .instance_size = sizeof(AwR40DramCtlState),
768
+ .class_init = allwinner_r40_dramc_class_init,
769
+};
770
+
771
+static void allwinner_r40_dramc_register(void)
772
+{
773
+ type_register_static(&allwinner_r40_dramc_info);
774
+}
775
+
776
+type_init(allwinner_r40_dramc_register)
777
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
778
index XXXXXXX..XXXXXXX 100644
779
--- a/hw/misc/meson.build
780
+++ b/hw/misc/meson.build
781
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c
782
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-sysctrl.c'))
783
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sid.c'))
784
softmmu_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40-ccu.c'))
785
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40-dramc.c'))
786
softmmu_ss.add(when: 'CONFIG_AXP2XX_PMU', if_true: files('axp2xx.c'))
787
softmmu_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
788
softmmu_ss.add(when: 'CONFIG_NSERIES', if_true: files('cbus.c'))
789
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
790
index XXXXXXX..XXXXXXX 100644
791
--- a/hw/misc/trace-events
792
+++ b/hw/misc/trace-events
793
@@ -XXX,XX +XXX,XX @@ allwinner_h3_dramctl_write(uint64_t offset, uint64_t data, unsigned size) "Write
794
allwinner_h3_dramphy_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
795
allwinner_h3_dramphy_write(uint64_t offset, uint64_t data, unsigned size) "write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
796
797
+# allwinner-r40-dramc.c
798
+allwinner_r40_dramc_detect_cells_disable(void) "Disable detect cells"
799
+allwinner_r40_dramc_detect_cells_enable(void) "Enable detect cells"
800
+allwinner_r40_dramc_map_rows(uint8_t row_bits, uint8_t bank_bits, uint8_t col_bits) "DRAM layout: row_bits %d, bank_bits %d, col_bits %d"
801
+allwinner_r40_dramc_offset_to_cell(uint64_t offset, int row, int bank, int col) "offset 0x%" PRIx64 " row %d bank %d col %d"
802
+allwinner_r40_dramc_detect_cell_write(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " data 0x%" PRIx64 ""
803
+allwinner_r40_dramc_detect_cell_read(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " data 0x%" PRIx64 ""
804
+allwinner_r40_dramcom_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
805
+allwinner_r40_dramcom_write(uint64_t offset, uint64_t data, unsigned size) "Write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
806
+allwinner_r40_dramctl_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
807
+allwinner_r40_dramctl_write(uint64_t offset, uint64_t data, unsigned size) "Write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
808
+allwinner_r40_dramphy_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
809
+allwinner_r40_dramphy_write(uint64_t offset, uint64_t data, unsigned size) "write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
810
+
811
# allwinner-sid.c
812
allwinner_sid_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
813
allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
814
--
340
--
815
2.34.1
341
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
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.
2
4
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20230530191438.411344-21-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
7
---
8
---
8
docs/system/arm/emulation.rst | 1 +
9
tests/fp/fp-bench.c | 1 +
9
target/arm/tcg/cpu64.c | 1 +
10
tests/fp/fp-test.c | 1 +
10
2 files changed, 2 insertions(+)
11
2 files changed, 2 insertions(+)
11
12
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
13
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/system/arm/emulation.rst
15
--- a/tests/fp/fp-bench.c
15
+++ b/docs/system/arm/emulation.rst
16
+++ b/tests/fp/fp-bench.c
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
17
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
17
- FEAT_LRCPC (Load-acquire RCpc instructions)
18
* doesn't specify match those used by the Arm architecture.
18
- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
19
*/
19
- FEAT_LSE (Large System Extensions)
20
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
20
+- FEAT_LSE2 (Large System Extensions v2)
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
21
- FEAT_LVA (Large Virtual Address space)
22
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
22
- FEAT_MTE (Memory Tagging Extension)
23
23
- FEAT_MTE2 (Memory Tagging Extension)
24
f = bench_funcs[operation][precision];
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
25
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
25
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/tcg/cpu64.c
27
--- a/tests/fp/fp-test.c
27
+++ b/target/arm/tcg/cpu64.c
28
+++ b/tests/fp/fp-test.c
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
29
@@ -XXX,XX +XXX,XX @@ void run_test(void)
29
t = FIELD_DP64(t, ID_AA64MMFR2, IESB, 1); /* FEAT_IESB */
30
* doesn't specify match those used by the Arm architecture.
30
t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1); /* FEAT_LVA */
31
*/
31
t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* FEAT_TTST */
32
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
32
+ t = FIELD_DP64(t, ID_AA64MMFR2, AT, 1); /* FEAT_LSE2 */
33
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
33
t = FIELD_DP64(t, ID_AA64MMFR2, IDS, 1); /* FEAT_IDST */
34
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
34
t = FIELD_DP64(t, ID_AA64MMFR2, FWB, 1); /* FEAT_S2FWB */
35
35
t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */
36
genCases_setLevel(test_level);
36
--
37
--
37
2.34.1
38
2.34.1
diff view generated by jsdifflib
1
From: Zhuojia Shen <chaosdefinition@hotmail.com>
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
Accessing EL0-accessible Debug Communication Channel (DCC) registers in
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
user mode emulation is currently enabled. However, it does not match
5
Linux behavior as Linux sets MDSCR_EL1.TDCC on startup to disable EL0
6
access to DCC (see __cpu_setup() in arch/arm64/mm/proc.S).
7
8
This patch fixes access_tdcc() to check MDSCR_EL1.TDCC for EL0 and sets
9
MDSCR_EL1.TDCC for user mode emulation to match Linux.
10
11
Signed-off-by: Zhuojia Shen <chaosdefinition@hotmail.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: DS7PR12MB630905198DD8E69F6817544CAC4EA@DS7PR12MB6309.namprd12.prod.outlook.com
6
Message-id: 20241202131347.498124-18-peter.maydell@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
7
---
16
target/arm/cpu.c | 2 ++
8
target/arm/cpu.c | 5 +++++
17
target/arm/debug_helper.c | 5 +++++
9
fpu/softfloat-specialize.c.inc | 8 +-------
18
2 files changed, 7 insertions(+)
10
2 files changed, 6 insertions(+), 7 deletions(-)
19
11
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
14
--- a/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset_hold(Object *obj)
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
25
* This is not yet exposed from the Linux kernel in any way.
17
* * tininess-before-rounding
26
*/
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
27
env->cp15.sctlr_el[1] |= SCTLR_TSCXT;
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
28
+ /* Disable access to Debug Communication Channel (DCC). */
20
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
29
+ env->cp15.mdscr_el1 |= 1 << 12;
21
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
30
#else
22
+ * but note that for QEMU muladd is a * b + c, whereas for
31
/* Reset into the highest available EL */
23
+ * the pseudocode function the arguments are in the order c, a, b.
32
if (arm_feature(env, ARM_FEATURE_EL3)) {
24
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
33
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
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
34
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/debug_helper.c
37
--- a/fpu/softfloat-specialize.c.inc
36
+++ b/target/arm/debug_helper.c
38
+++ b/fpu/softfloat-specialize.c.inc
37
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri,
39
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
38
* is implemented then these are controlled by MDCR_EL2.TDCC for
39
* EL2 and MDCR_EL3.TDCC for EL3. They are also controlled by
40
* the general debug access trap bits MDCR_EL2.TDA and MDCR_EL3.TDA.
41
+ * For EL0, they are also controlled by MDSCR_EL1.TDCC.
42
*/
43
static CPAccessResult access_tdcc(CPUARMState *env, const ARMCPRegInfo *ri,
44
bool isread)
45
{
46
int el = arm_current_el(env);
47
uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
48
+ bool mdscr_el1_tdcc = extract32(env->cp15.mdscr_el1, 12, 1);
49
bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) ||
50
(arm_hcr_el2_eff(env) & HCR_TGE);
51
bool mdcr_el2_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&
52
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_tdcc(CPUARMState *env, const ARMCPRegInfo *ri,
53
bool mdcr_el3_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&
54
(env->cp15.mdcr_el3 & MDCR_TDCC);
55
56
+ if (el < 1 && mdscr_el1_tdcc) {
57
+ return CP_ACCESS_TRAP;
58
+ }
59
if (el < 2 && (mdcr_el2_tda || mdcr_el2_tdcc)) {
60
return CP_ACCESS_TRAP_EL2;
61
}
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 {
62
--
54
--
63
2.34.1
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
1
From: qianfan Zhao <qianfanguijin@163.com>
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
R40 has eight UARTs, support both 16450 and 16550 compatible modes.
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(-)
4
12
5
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
include/hw/arm/allwinner-r40.h | 8 ++++++++
9
hw/arm/allwinner-r40.c | 34 +++++++++++++++++++++++++++++++---
10
2 files changed, 39 insertions(+), 3 deletions(-)
11
12
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/allwinner-r40.h
15
--- a/target/mips/fpu_helper.h
15
+++ b/include/hw/arm/allwinner-r40.h
16
+++ b/target/mips/fpu_helper.h
16
@@ -XXX,XX +XXX,XX @@ enum {
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
17
AW_R40_DEV_CCU,
18
{
18
AW_R40_DEV_PIT,
19
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
19
AW_R40_DEV_UART0,
20
FloatInfZeroNaNRule izn_rule;
20
+ AW_R40_DEV_UART1,
21
+ Float3NaNPropRule nan3_rule;
21
+ AW_R40_DEV_UART2,
22
22
+ AW_R40_DEV_UART3,
23
/*
23
+ AW_R40_DEV_UART4,
24
* With nan2008, SNaNs are silenced in the usual way.
24
+ AW_R40_DEV_UART5,
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
25
+ AW_R40_DEV_UART6,
26
*/
26
+ AW_R40_DEV_UART7,
27
izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
27
AW_R40_DEV_GIC_DIST,
28
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
28
AW_R40_DEV_GIC_CPU,
29
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
29
AW_R40_DEV_GIC_HYP,
30
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
30
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(AwR40State, AW_R40)
31
+
31
* which are currently emulated by the R40 SoC code.
32
}
32
*/
33
33
#define AW_R40_NUM_MMCS 4
34
static inline void restore_fp_status(CPUMIPSState *env)
34
+#define AW_R40_NUM_UARTS 8
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
35
36
struct AwR40State {
37
/*< private >*/
38
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
39
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/arm/allwinner-r40.c
37
--- a/target/mips/msa.c
41
+++ b/hw/arm/allwinner-r40.c
38
+++ b/target/mips/msa.c
42
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_r40_memmap[] = {
39
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
43
[AW_R40_DEV_CCU] = 0x01c20000,
40
set_float_2nan_prop_rule(float_2nan_prop_s_ab,
44
[AW_R40_DEV_PIT] = 0x01c20c00,
41
&env->active_tc.msa_fp_status);
45
[AW_R40_DEV_UART0] = 0x01c28000,
42
46
+ [AW_R40_DEV_UART1] = 0x01c28400,
43
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
47
+ [AW_R40_DEV_UART2] = 0x01c28800,
44
+ &env->active_tc.msa_fp_status);
48
+ [AW_R40_DEV_UART3] = 0x01c28c00,
45
+
49
+ [AW_R40_DEV_UART4] = 0x01c29000,
46
/* clear float_status exception flags */
50
+ [AW_R40_DEV_UART5] = 0x01c29400,
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
51
+ [AW_R40_DEV_UART6] = 0x01c29800,
48
52
+ [AW_R40_DEV_UART7] = 0x01c29c00,
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
53
[AW_R40_DEV_GIC_DIST] = 0x01c81000,
50
index XXXXXXX..XXXXXXX 100644
54
[AW_R40_DEV_GIC_CPU] = 0x01c82000,
51
--- a/fpu/softfloat-specialize.c.inc
55
[AW_R40_DEV_GIC_HYP] = 0x01c84000,
52
+++ b/fpu/softfloat-specialize.c.inc
56
@@ -XXX,XX +XXX,XX @@ enum {
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
57
/* Shared Processor Interrupts */
58
enum {
59
AW_R40_GIC_SPI_UART0 = 1,
60
+ AW_R40_GIC_SPI_UART1 = 2,
61
+ AW_R40_GIC_SPI_UART2 = 3,
62
+ AW_R40_GIC_SPI_UART3 = 4,
63
+ AW_R40_GIC_SPI_UART4 = 17,
64
+ AW_R40_GIC_SPI_UART5 = 18,
65
+ AW_R40_GIC_SPI_UART6 = 19,
66
+ AW_R40_GIC_SPI_UART7 = 20,
67
AW_R40_GIC_SPI_TIMER0 = 22,
68
AW_R40_GIC_SPI_TIMER1 = 23,
69
AW_R40_GIC_SPI_MMC0 = 32,
70
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_realize(DeviceState *dev, Error **errp)
71
}
54
}
72
55
73
/* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
56
if (rule == float_3nan_prop_none) {
74
- serial_mm_init(get_system_memory(), s->memmap[AW_R40_DEV_UART0], 2,
57
-#if defined(TARGET_MIPS)
75
- qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_UART0),
58
- if (snan_bit_is_one(status)) {
76
- 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
59
- rule = float_3nan_prop_s_abc;
77
+ for (int i = 0; i < AW_R40_NUM_UARTS; i++) {
60
- } else {
78
+ static const int uart_irqs[AW_R40_NUM_UARTS] = {
61
- rule = float_3nan_prop_s_cab;
79
+ AW_R40_GIC_SPI_UART0,
62
- }
80
+ AW_R40_GIC_SPI_UART1,
63
-#elif defined(TARGET_XTENSA)
81
+ AW_R40_GIC_SPI_UART2,
64
+#if defined(TARGET_XTENSA)
82
+ AW_R40_GIC_SPI_UART3,
65
if (status->use_first_nan) {
83
+ AW_R40_GIC_SPI_UART4,
66
rule = float_3nan_prop_abc;
84
+ AW_R40_GIC_SPI_UART5,
67
} else {
85
+ AW_R40_GIC_SPI_UART6,
86
+ AW_R40_GIC_SPI_UART7,
87
+ };
88
+ const hwaddr addr = s->memmap[AW_R40_DEV_UART0 + i];
89
+
90
+ serial_mm_init(get_system_memory(), addr, 2,
91
+ qdev_get_gpio_in(DEVICE(&s->gic), uart_irqs[i]),
92
+ 115200, serial_hd(i), DEVICE_NATIVE_ENDIAN);
93
+ }
94
95
/* Unimplemented devices */
96
for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
97
--
68
--
98
2.34.1
69
2.34.1
diff view generated by jsdifflib
1
From: qianfan Zhao <qianfanguijin@163.com>
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
A64's sd register was similar to H3, and it introduced a new register
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
named SAMP_DL_REG location at 0x144. The dma descriptor buffer size of
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
mmc2 is only 8K and the other mmc controllers has 64K.
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
7
---
8
target/xtensa/fpu_helper.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 8 --------
10
2 files changed, 2 insertions(+), 8 deletions(-)
6
11
7
Also fix allwinner-r40's mmc controller type.
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
8
9
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/sd/allwinner-sdhost.h | 9 ++++
13
hw/arm/allwinner-r40.c | 2 +-
14
hw/sd/allwinner-sdhost.c | 72 ++++++++++++++++++++++++++++++--
15
3 files changed, 79 insertions(+), 4 deletions(-)
16
17
diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/sd/allwinner-sdhost.h
14
--- a/target/xtensa/fpu_helper.c
20
+++ b/include/hw/sd/allwinner-sdhost.h
15
+++ b/target/xtensa/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
22
/** Allwinner sun5i family and newer (A13, H2+, H3, etc) */
17
set_use_first_nan(use_first, &env->fp_status);
23
#define TYPE_AW_SDHOST_SUN5I TYPE_AW_SDHOST "-sun5i"
18
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
24
19
&env->fp_status);
25
+/** Allwinner sun50i-a64 */
20
+ set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
26
+#define TYPE_AW_SDHOST_SUN50I_A64 TYPE_AW_SDHOST "-sun50i-a64"
21
+ &env->fp_status);
27
+
22
}
28
+/** Allwinner sun50i-a64 emmc */
23
29
+#define TYPE_AW_SDHOST_SUN50I_A64_EMMC TYPE_AW_SDHOST "-sun50i-a64-emmc"
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
30
+
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
/** @} */
32
33
/**
34
@@ -XXX,XX +XXX,XX @@ struct AwSdHostState {
35
uint32_t startbit_detect; /**< eMMC DDR Start Bit Detection Control */
36
uint32_t response_crc; /**< Response CRC */
37
uint32_t data_crc[8]; /**< Data CRC */
38
+ uint32_t sample_delay; /**< Sample delay control */
39
uint32_t status_crc; /**< Status CRC */
40
41
/** @} */
42
@@ -XXX,XX +XXX,XX @@ struct AwSdHostClass {
43
size_t max_desc_size;
44
bool is_sun4i;
45
46
+ /** does the IP block support autocalibration? */
47
+ bool can_calibrate;
48
};
49
50
#endif /* HW_SD_ALLWINNER_SDHOST_H */
51
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
52
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/arm/allwinner-r40.c
27
--- a/fpu/softfloat-specialize.c.inc
54
+++ b/hw/arm/allwinner-r40.c
28
+++ b/fpu/softfloat-specialize.c.inc
55
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_init(Object *obj)
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
56
57
for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
58
object_initialize_child(obj, mmc_names[i], &s->mmc[i],
59
- TYPE_AW_SDHOST_SUN5I);
60
+ TYPE_AW_SDHOST_SUN50I_A64);
61
}
30
}
62
31
63
object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
32
if (rule == float_3nan_prop_none) {
64
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
33
-#if defined(TARGET_XTENSA)
65
index XXXXXXX..XXXXXXX 100644
34
- if (status->use_first_nan) {
66
--- a/hw/sd/allwinner-sdhost.c
35
- rule = float_3nan_prop_abc;
67
+++ b/hw/sd/allwinner-sdhost.c
36
- } else {
68
@@ -XXX,XX +XXX,XX @@ enum {
37
- rule = float_3nan_prop_cba;
69
REG_SD_DATA1_CRC = 0x12C, /* CRC Data 1 from card/eMMC */
38
- }
70
REG_SD_DATA0_CRC = 0x130, /* CRC Data 0 from card/eMMC */
39
-#else
71
REG_SD_CRC_STA = 0x134, /* CRC status from card/eMMC during write */
40
rule = float_3nan_prop_abc;
72
+ REG_SD_SAMP_DL = 0x144, /* Sample Delay Control (sun50i-a64) */
41
-#endif
73
REG_SD_FIFO = 0x200, /* Read/Write FIFO */
74
};
75
76
@@ -XXX,XX +XXX,XX @@ enum {
77
REG_SD_RES_CRC_RST = 0x0,
78
REG_SD_DATA_CRC_RST = 0x0,
79
REG_SD_CRC_STA_RST = 0x0,
80
+ REG_SD_SAMPLE_DL_RST = 0x00002000,
81
REG_SD_FIFO_RST = 0x0,
82
};
83
84
@@ -XXX,XX +XXX,XX @@ static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
85
{
86
AwSdHostState *s = AW_SDHOST(opaque);
87
AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s);
88
+ bool out_of_bounds = false;
89
uint32_t res = 0;
90
91
switch (offset) {
92
@@ -XXX,XX +XXX,XX @@ static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
93
case REG_SD_FIFO: /* Read/Write FIFO */
94
res = allwinner_sdhost_fifo_read(s);
95
break;
96
+ case REG_SD_SAMP_DL: /* Sample Delay */
97
+ if (sc->can_calibrate) {
98
+ res = s->sample_delay;
99
+ } else {
100
+ out_of_bounds = true;
101
+ }
102
+ break;
103
default:
104
- qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
105
- HWADDR_PRIx"\n", __func__, offset);
106
+ out_of_bounds = true;
107
res = 0;
108
break;
109
}
42
}
110
43
111
+ if (out_of_bounds) {
44
assert(rule != float_3nan_prop_none);
112
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
113
+ HWADDR_PRIx"\n", __func__, offset);
114
+ }
115
+
116
trace_allwinner_sdhost_read(offset, res, size);
117
return res;
118
}
119
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_write(void *opaque, hwaddr offset,
120
{
121
AwSdHostState *s = AW_SDHOST(opaque);
122
AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s);
123
+ bool out_of_bounds = false;
124
125
trace_allwinner_sdhost_write(offset, value, size);
126
127
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_write(void *opaque, hwaddr offset,
128
case REG_SD_DATA0_CRC: /* CRC Data 0 from card/eMMC */
129
case REG_SD_CRC_STA: /* CRC status from card/eMMC in write operation */
130
break;
131
+ case REG_SD_SAMP_DL: /* Sample delay control */
132
+ if (sc->can_calibrate) {
133
+ s->sample_delay = value;
134
+ } else {
135
+ out_of_bounds = true;
136
+ }
137
+ break;
138
default:
139
+ out_of_bounds = true;
140
+ break;
141
+ }
142
+
143
+ if (out_of_bounds) {
144
qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
145
HWADDR_PRIx"\n", __func__, offset);
146
- break;
147
}
148
}
149
150
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_allwinner_sdhost = {
151
VMSTATE_UINT32(response_crc, AwSdHostState),
152
VMSTATE_UINT32_ARRAY(data_crc, AwSdHostState, 8),
153
VMSTATE_UINT32(status_crc, AwSdHostState),
154
+ VMSTATE_UINT32(sample_delay, AwSdHostState),
155
VMSTATE_END_OF_LIST()
156
}
157
};
158
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_realize(DeviceState *dev, Error **errp)
159
static void allwinner_sdhost_reset(DeviceState *dev)
160
{
161
AwSdHostState *s = AW_SDHOST(dev);
162
+ AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s);
163
164
s->global_ctl = REG_SD_GCTL_RST;
165
s->clock_ctl = REG_SD_CKCR_RST;
166
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_reset(DeviceState *dev)
167
}
168
169
s->status_crc = REG_SD_CRC_STA_RST;
170
+
171
+ if (sc->can_calibrate) {
172
+ s->sample_delay = REG_SD_SAMPLE_DL_RST;
173
+ }
174
}
175
176
static void allwinner_sdhost_bus_class_init(ObjectClass *klass, void *data)
177
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_sun4i_class_init(ObjectClass *klass, void *data)
178
AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
179
sc->max_desc_size = 8 * KiB;
180
sc->is_sun4i = true;
181
+ sc->can_calibrate = false;
182
}
183
184
static void allwinner_sdhost_sun5i_class_init(ObjectClass *klass, void *data)
185
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_sun5i_class_init(ObjectClass *klass, void *data)
186
AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
187
sc->max_desc_size = 64 * KiB;
188
sc->is_sun4i = false;
189
+ sc->can_calibrate = false;
190
+}
191
+
192
+static void allwinner_sdhost_sun50i_a64_class_init(ObjectClass *klass,
193
+ void *data)
194
+{
195
+ AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
196
+ sc->max_desc_size = 64 * KiB;
197
+ sc->is_sun4i = false;
198
+ sc->can_calibrate = true;
199
+}
200
+
201
+static void allwinner_sdhost_sun50i_a64_emmc_class_init(ObjectClass *klass,
202
+ void *data)
203
+{
204
+ AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
205
+ sc->max_desc_size = 8 * KiB;
206
+ sc->is_sun4i = false;
207
+ sc->can_calibrate = true;
208
}
209
210
static const TypeInfo allwinner_sdhost_info = {
211
@@ -XXX,XX +XXX,XX @@ static const TypeInfo allwinner_sdhost_sun5i_info = {
212
.class_init = allwinner_sdhost_sun5i_class_init,
213
};
214
215
+static const TypeInfo allwinner_sdhost_sun50i_a64_info = {
216
+ .name = TYPE_AW_SDHOST_SUN50I_A64,
217
+ .parent = TYPE_AW_SDHOST,
218
+ .class_init = allwinner_sdhost_sun50i_a64_class_init,
219
+};
220
+
221
+static const TypeInfo allwinner_sdhost_sun50i_a64_emmc_info = {
222
+ .name = TYPE_AW_SDHOST_SUN50I_A64_EMMC,
223
+ .parent = TYPE_AW_SDHOST,
224
+ .class_init = allwinner_sdhost_sun50i_a64_emmc_class_init,
225
+};
226
+
227
static const TypeInfo allwinner_sdhost_bus_info = {
228
.name = TYPE_AW_SDHOST_BUS,
229
.parent = TYPE_SD_BUS,
230
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_register_types(void)
231
type_register_static(&allwinner_sdhost_info);
232
type_register_static(&allwinner_sdhost_sun4i_info);
233
type_register_static(&allwinner_sdhost_sun5i_info);
234
+ type_register_static(&allwinner_sdhost_sun50i_a64_info);
235
+ type_register_static(&allwinner_sdhost_sun50i_a64_emmc_info);
236
type_register_static(&allwinner_sdhost_bus_info);
237
}
238
239
--
45
--
240
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
From: qianfan Zhao <qianfanguijin@163.com>
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
This patch adds minimal support for AXP-221 PMU and connect it to
4
HPPA is the only target that was using the default branch of the
4
bananapi M2U board.
5
ifdef ladder (other targets either do not use muladd or set
6
default_nan_mode), so we can remove the ifdef fallback entirely now
7
(allowing the "rule not set" case to fall into the default of the
8
switch statement and assert).
5
9
6
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
10
We add a TODO note that the HPPA rule is probably wrong; this is
11
not a behavioural change for this refactoring.
12
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
8
---
16
---
9
hw/arm/bananapi_m2u.c | 6 +
17
target/hppa/fpu_helper.c | 8 ++++++++
10
hw/misc/axp209.c | 238 -----------------------------------
18
fpu/softfloat-specialize.c.inc | 4 ----
11
hw/misc/axp2xx.c | 283 ++++++++++++++++++++++++++++++++++++++++++
19
2 files changed, 8 insertions(+), 4 deletions(-)
12
hw/arm/Kconfig | 3 +-
13
hw/misc/Kconfig | 2 +-
14
hw/misc/meson.build | 2 +-
15
hw/misc/trace-events | 8 +-
16
7 files changed, 297 insertions(+), 245 deletions(-)
17
delete mode 100644 hw/misc/axp209.c
18
create mode 100644 hw/misc/axp2xx.c
19
20
20
diff --git a/hw/arm/bananapi_m2u.c b/hw/arm/bananapi_m2u.c
21
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/bananapi_m2u.c
23
--- a/target/hppa/fpu_helper.c
23
+++ b/hw/arm/bananapi_m2u.c
24
+++ b/target/hppa/fpu_helper.c
24
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
25
#include "qapi/error.h"
26
* HPPA does note implement a CPU reset method at all...
26
#include "qemu/error-report.h"
27
*/
27
#include "hw/boards.h"
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
28
+#include "hw/i2c/i2c.h"
29
+ /*
29
#include "hw/qdev-properties.h"
30
+ * TODO: The HPPA architecture reference only documents its NaN
30
#include "hw/arm/allwinner-r40.h"
31
+ * propagation rule for 2-operand operations. Testing on real hardware
31
32
+ * might be necessary to confirm whether this order for muladd is correct.
32
@@ -XXX,XX +XXX,XX @@ static void bpim2u_init(MachineState *machine)
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
33
{
34
+ * from the documented rules for 2-operand operations.
34
bool bootroom_loaded = false;
35
+ */
35
AwR40State *r40;
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
36
+ I2CBus *i2c;
37
/* For inf * 0 + NaN, return the input NaN */
37
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
38
/* BIOS is not supported by this board */
39
}
39
if (machine->firmware) {
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
40
@@ -XXX,XX +XXX,XX @@ static void bpim2u_init(MachineState *machine)
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,
41
}
45
}
42
}
46
}
43
47
44
+ /* Connect AXP221 */
48
- if (rule == float_3nan_prop_none) {
45
+ i2c = I2C_BUS(qdev_get_child_bus(DEVICE(&r40->i2c0), "i2c"));
49
- rule = float_3nan_prop_abc;
46
+ i2c_slave_create_simple(i2c, "axp221_pmu", 0x34);
47
+
48
/* SDRAM */
49
memory_region_add_subregion(get_system_memory(),
50
r40->memmap[AW_R40_DEV_SDRAM], machine->ram);
51
diff --git a/hw/misc/axp209.c b/hw/misc/axp209.c
52
deleted file mode 100644
53
index XXXXXXX..XXXXXXX
54
--- a/hw/misc/axp209.c
55
+++ /dev/null
56
@@ -XXX,XX +XXX,XX @@
57
-/*
58
- * AXP-209 PMU Emulation
59
- *
60
- * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
61
- *
62
- * Permission is hereby granted, free of charge, to any person obtaining a
63
- * copy of this software and associated documentation files (the "Software"),
64
- * to deal in the Software without restriction, including without limitation
65
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
66
- * and/or sell copies of the Software, and to permit persons to whom the
67
- * Software is furnished to do so, subject to the following conditions:
68
- *
69
- * The above copyright notice and this permission notice shall be included in
70
- * all copies or substantial portions of the Software.
71
- *
72
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
77
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
78
- * DEALINGS IN THE SOFTWARE.
79
- *
80
- * SPDX-License-Identifier: MIT
81
- */
82
-
83
-#include "qemu/osdep.h"
84
-#include "qemu/log.h"
85
-#include "trace.h"
86
-#include "hw/i2c/i2c.h"
87
-#include "migration/vmstate.h"
88
-
89
-#define TYPE_AXP209_PMU "axp209_pmu"
90
-
91
-#define AXP209(obj) \
92
- OBJECT_CHECK(AXP209I2CState, (obj), TYPE_AXP209_PMU)
93
-
94
-/* registers */
95
-enum {
96
- REG_POWER_STATUS = 0x0u,
97
- REG_OPERATING_MODE,
98
- REG_OTG_VBUS_STATUS,
99
- REG_CHIP_VERSION,
100
- REG_DATA_CACHE_0,
101
- REG_DATA_CACHE_1,
102
- REG_DATA_CACHE_2,
103
- REG_DATA_CACHE_3,
104
- REG_DATA_CACHE_4,
105
- REG_DATA_CACHE_5,
106
- REG_DATA_CACHE_6,
107
- REG_DATA_CACHE_7,
108
- REG_DATA_CACHE_8,
109
- REG_DATA_CACHE_9,
110
- REG_DATA_CACHE_A,
111
- REG_DATA_CACHE_B,
112
- REG_POWER_OUTPUT_CTRL = 0x12u,
113
- REG_DC_DC2_OUT_V_CTRL = 0x23u,
114
- REG_DC_DC2_DVS_CTRL = 0x25u,
115
- REG_DC_DC3_OUT_V_CTRL = 0x27u,
116
- REG_LDO2_4_OUT_V_CTRL,
117
- REG_LDO3_OUT_V_CTRL,
118
- REG_VBUS_CH_MGMT = 0x30u,
119
- REG_SHUTDOWN_V_CTRL,
120
- REG_SHUTDOWN_CTRL,
121
- REG_CHARGE_CTRL_1,
122
- REG_CHARGE_CTRL_2,
123
- REG_SPARE_CHARGE_CTRL,
124
- REG_PEK_KEY_CTRL,
125
- REG_DC_DC_FREQ_SET,
126
- REG_CHR_TEMP_TH_SET,
127
- REG_CHR_HIGH_TEMP_TH_CTRL,
128
- REG_IPSOUT_WARN_L1,
129
- REG_IPSOUT_WARN_L2,
130
- REG_DISCHR_TEMP_TH_SET,
131
- REG_DISCHR_HIGH_TEMP_TH_CTRL,
132
- REG_IRQ_BANK_1_CTRL = 0x40u,
133
- REG_IRQ_BANK_2_CTRL,
134
- REG_IRQ_BANK_3_CTRL,
135
- REG_IRQ_BANK_4_CTRL,
136
- REG_IRQ_BANK_5_CTRL,
137
- REG_IRQ_BANK_1_STAT = 0x48u,
138
- REG_IRQ_BANK_2_STAT,
139
- REG_IRQ_BANK_3_STAT,
140
- REG_IRQ_BANK_4_STAT,
141
- REG_IRQ_BANK_5_STAT,
142
- REG_ADC_ACIN_V_H = 0x56u,
143
- REG_ADC_ACIN_V_L,
144
- REG_ADC_ACIN_CURR_H,
145
- REG_ADC_ACIN_CURR_L,
146
- REG_ADC_VBUS_V_H,
147
- REG_ADC_VBUS_V_L,
148
- REG_ADC_VBUS_CURR_H,
149
- REG_ADC_VBUS_CURR_L,
150
- REG_ADC_INT_TEMP_H,
151
- REG_ADC_INT_TEMP_L,
152
- REG_ADC_TEMP_SENS_V_H = 0x62u,
153
- REG_ADC_TEMP_SENS_V_L,
154
- REG_ADC_BAT_V_H = 0x78u,
155
- REG_ADC_BAT_V_L,
156
- REG_ADC_BAT_DISCHR_CURR_H,
157
- REG_ADC_BAT_DISCHR_CURR_L,
158
- REG_ADC_BAT_CHR_CURR_H,
159
- REG_ADC_BAT_CHR_CURR_L,
160
- REG_ADC_IPSOUT_V_H,
161
- REG_ADC_IPSOUT_V_L,
162
- REG_DC_DC_MOD_SEL = 0x80u,
163
- REG_ADC_EN_1,
164
- REG_ADC_EN_2,
165
- REG_ADC_SR_CTRL,
166
- REG_ADC_IN_RANGE,
167
- REG_GPIO1_ADC_IRQ_RISING_TH,
168
- REG_GPIO1_ADC_IRQ_FALLING_TH,
169
- REG_TIMER_CTRL = 0x8au,
170
- REG_VBUS_CTRL_MON_SRP,
171
- REG_OVER_TEMP_SHUTDOWN = 0x8fu,
172
- REG_GPIO0_FEAT_SET,
173
- REG_GPIO_OUT_HIGH_SET,
174
- REG_GPIO1_FEAT_SET,
175
- REG_GPIO2_FEAT_SET,
176
- REG_GPIO_SIG_STATE_SET_MON,
177
- REG_GPIO3_SET,
178
- REG_COULOMB_CNTR_CTRL = 0xb8u,
179
- REG_POWER_MEAS_RES,
180
- NR_REGS
181
-};
182
-
183
-#define AXP209_CHIP_VERSION_ID (0x01)
184
-#define AXP209_DC_DC2_OUT_V_CTRL_RESET (0x16)
185
-#define AXP209_IRQ_BANK_1_CTRL_RESET (0xd8)
186
-
187
-/* A simple I2C slave which returns values of ID or CNT register. */
188
-typedef struct AXP209I2CState {
189
- /*< private >*/
190
- I2CSlave i2c;
191
- /*< public >*/
192
- uint8_t regs[NR_REGS]; /* peripheral registers */
193
- uint8_t ptr; /* current register index */
194
- uint8_t count; /* counter used for tx/rx */
195
-} AXP209I2CState;
196
-
197
-/* Reset all counters and load ID register */
198
-static void axp209_reset_enter(Object *obj, ResetType type)
199
-{
200
- AXP209I2CState *s = AXP209(obj);
201
-
202
- memset(s->regs, 0, NR_REGS);
203
- s->ptr = 0;
204
- s->count = 0;
205
- s->regs[REG_CHIP_VERSION] = AXP209_CHIP_VERSION_ID;
206
- s->regs[REG_DC_DC2_OUT_V_CTRL] = AXP209_DC_DC2_OUT_V_CTRL_RESET;
207
- s->regs[REG_IRQ_BANK_1_CTRL] = AXP209_IRQ_BANK_1_CTRL_RESET;
208
-}
209
-
210
-/* Handle events from master. */
211
-static int axp209_event(I2CSlave *i2c, enum i2c_event event)
212
-{
213
- AXP209I2CState *s = AXP209(i2c);
214
-
215
- s->count = 0;
216
-
217
- return 0;
218
-}
219
-
220
-/* Called when master requests read */
221
-static uint8_t axp209_rx(I2CSlave *i2c)
222
-{
223
- AXP209I2CState *s = AXP209(i2c);
224
- uint8_t ret = 0xff;
225
-
226
- if (s->ptr < NR_REGS) {
227
- ret = s->regs[s->ptr++];
228
- }
50
- }
229
-
51
-
230
- trace_axp209_rx(s->ptr - 1, ret);
52
assert(rule != float_3nan_prop_none);
231
-
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
232
- return ret;
54
/* We have at least one SNaN input and should prefer it */
233
-}
234
-
235
-/*
236
- * Called when master sends write.
237
- * Update ptr with byte 0, then perform write with second byte.
238
- */
239
-static int axp209_tx(I2CSlave *i2c, uint8_t data)
240
-{
241
- AXP209I2CState *s = AXP209(i2c);
242
-
243
- if (s->count == 0) {
244
- /* Store register address */
245
- s->ptr = data;
246
- s->count++;
247
- trace_axp209_select(data);
248
- } else {
249
- trace_axp209_tx(s->ptr, data);
250
- if (s->ptr == REG_DC_DC2_OUT_V_CTRL) {
251
- s->regs[s->ptr++] = data;
252
- }
253
- }
254
-
255
- return 0;
256
-}
257
-
258
-static const VMStateDescription vmstate_axp209 = {
259
- .name = TYPE_AXP209_PMU,
260
- .version_id = 1,
261
- .fields = (VMStateField[]) {
262
- VMSTATE_UINT8_ARRAY(regs, AXP209I2CState, NR_REGS),
263
- VMSTATE_UINT8(count, AXP209I2CState),
264
- VMSTATE_UINT8(ptr, AXP209I2CState),
265
- VMSTATE_END_OF_LIST()
266
- }
267
-};
268
-
269
-static void axp209_class_init(ObjectClass *oc, void *data)
270
-{
271
- DeviceClass *dc = DEVICE_CLASS(oc);
272
- I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
273
- ResettableClass *rc = RESETTABLE_CLASS(oc);
274
-
275
- rc->phases.enter = axp209_reset_enter;
276
- dc->vmsd = &vmstate_axp209;
277
- isc->event = axp209_event;
278
- isc->recv = axp209_rx;
279
- isc->send = axp209_tx;
280
-}
281
-
282
-static const TypeInfo axp209_info = {
283
- .name = TYPE_AXP209_PMU,
284
- .parent = TYPE_I2C_SLAVE,
285
- .instance_size = sizeof(AXP209I2CState),
286
- .class_init = axp209_class_init
287
-};
288
-
289
-static void axp209_register_devices(void)
290
-{
291
- type_register_static(&axp209_info);
292
-}
293
-
294
-type_init(axp209_register_devices);
295
diff --git a/hw/misc/axp2xx.c b/hw/misc/axp2xx.c
296
new file mode 100644
297
index XXXXXXX..XXXXXXX
298
--- /dev/null
299
+++ b/hw/misc/axp2xx.c
300
@@ -XXX,XX +XXX,XX @@
301
+/*
302
+ * AXP-2XX PMU Emulation, supported lists:
303
+ * AXP209
304
+ * AXP221
305
+ *
306
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
307
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
308
+ *
309
+ * Permission is hereby granted, free of charge, to any person obtaining a
310
+ * copy of this software and associated documentation files (the "Software"),
311
+ * to deal in the Software without restriction, including without limitation
312
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
313
+ * and/or sell copies of the Software, and to permit persons to whom the
314
+ * Software is furnished to do so, subject to the following conditions:
315
+ *
316
+ * The above copyright notice and this permission notice shall be included in
317
+ * all copies or substantial portions of the Software.
318
+ *
319
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
320
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
321
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
322
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
323
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
324
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
325
+ * DEALINGS IN THE SOFTWARE.
326
+ *
327
+ * SPDX-License-Identifier: MIT
328
+ */
329
+
330
+#include "qemu/osdep.h"
331
+#include "qemu/log.h"
332
+#include "qom/object.h"
333
+#include "trace.h"
334
+#include "hw/i2c/i2c.h"
335
+#include "migration/vmstate.h"
336
+
337
+#define TYPE_AXP2XX "axp2xx_pmu"
338
+#define TYPE_AXP209_PMU "axp209_pmu"
339
+#define TYPE_AXP221_PMU "axp221_pmu"
340
+
341
+OBJECT_DECLARE_TYPE(AXP2xxI2CState, AXP2xxClass, AXP2XX)
342
+
343
+#define NR_REGS (0xff)
344
+
345
+/* A simple I2C slave which returns values of ID or CNT register. */
346
+typedef struct AXP2xxI2CState {
347
+ /*< private >*/
348
+ I2CSlave i2c;
349
+ /*< public >*/
350
+ uint8_t regs[NR_REGS]; /* peripheral registers */
351
+ uint8_t ptr; /* current register index */
352
+ uint8_t count; /* counter used for tx/rx */
353
+} AXP2xxI2CState;
354
+
355
+typedef struct AXP2xxClass {
356
+ /*< private >*/
357
+ I2CSlaveClass parent_class;
358
+ /*< public >*/
359
+ void (*reset_enter)(AXP2xxI2CState *s, ResetType type);
360
+} AXP2xxClass;
361
+
362
+#define AXP209_CHIP_VERSION_ID (0x01)
363
+#define AXP209_DC_DC2_OUT_V_CTRL_RESET (0x16)
364
+
365
+/* Reset all counters and load ID register */
366
+static void axp209_reset_enter(AXP2xxI2CState *s, ResetType type)
367
+{
368
+ memset(s->regs, 0, NR_REGS);
369
+ s->ptr = 0;
370
+ s->count = 0;
371
+
372
+ s->regs[0x03] = AXP209_CHIP_VERSION_ID;
373
+ s->regs[0x23] = AXP209_DC_DC2_OUT_V_CTRL_RESET;
374
+
375
+ s->regs[0x30] = 0x60;
376
+ s->regs[0x32] = 0x46;
377
+ s->regs[0x34] = 0x41;
378
+ s->regs[0x35] = 0x22;
379
+ s->regs[0x36] = 0x5d;
380
+ s->regs[0x37] = 0x08;
381
+ s->regs[0x38] = 0xa5;
382
+ s->regs[0x39] = 0x1f;
383
+ s->regs[0x3a] = 0x68;
384
+ s->regs[0x3b] = 0x5f;
385
+ s->regs[0x3c] = 0xfc;
386
+ s->regs[0x3d] = 0x16;
387
+ s->regs[0x40] = 0xd8;
388
+ s->regs[0x42] = 0xff;
389
+ s->regs[0x43] = 0x3b;
390
+ s->regs[0x80] = 0xe0;
391
+ s->regs[0x82] = 0x83;
392
+ s->regs[0x83] = 0x80;
393
+ s->regs[0x84] = 0x32;
394
+ s->regs[0x86] = 0xff;
395
+ s->regs[0x90] = 0x07;
396
+ s->regs[0x91] = 0xa0;
397
+ s->regs[0x92] = 0x07;
398
+ s->regs[0x93] = 0x07;
399
+}
400
+
401
+#define AXP221_PWR_STATUS_ACIN_PRESENT BIT(7)
402
+#define AXP221_PWR_STATUS_ACIN_AVAIL BIT(6)
403
+#define AXP221_PWR_STATUS_VBUS_PRESENT BIT(5)
404
+#define AXP221_PWR_STATUS_VBUS_USED BIT(4)
405
+#define AXP221_PWR_STATUS_BAT_CHARGING BIT(2)
406
+#define AXP221_PWR_STATUS_ACIN_VBUS_POWERED BIT(1)
407
+
408
+/* Reset all counters and load ID register */
409
+static void axp221_reset_enter(AXP2xxI2CState *s, ResetType type)
410
+{
411
+ memset(s->regs, 0, NR_REGS);
412
+ s->ptr = 0;
413
+ s->count = 0;
414
+
415
+ /* input power status register */
416
+ s->regs[0x00] = AXP221_PWR_STATUS_ACIN_PRESENT
417
+ | AXP221_PWR_STATUS_ACIN_AVAIL
418
+ | AXP221_PWR_STATUS_ACIN_VBUS_POWERED;
419
+
420
+ s->regs[0x01] = 0x00; /* no battery is connected */
421
+
422
+ /*
423
+ * CHIPID register, no documented on datasheet, but it is checked in
424
+ * u-boot spl. I had read it from AXP221s and got 0x06 value.
425
+ * So leave 06h here.
426
+ */
427
+ s->regs[0x03] = 0x06;
428
+
429
+ s->regs[0x10] = 0xbf;
430
+ s->regs[0x13] = 0x01;
431
+ s->regs[0x30] = 0x60;
432
+ s->regs[0x31] = 0x03;
433
+ s->regs[0x32] = 0x43;
434
+ s->regs[0x33] = 0xc6;
435
+ s->regs[0x34] = 0x45;
436
+ s->regs[0x35] = 0x0e;
437
+ s->regs[0x36] = 0x5d;
438
+ s->regs[0x37] = 0x08;
439
+ s->regs[0x38] = 0xa5;
440
+ s->regs[0x39] = 0x1f;
441
+ s->regs[0x3c] = 0xfc;
442
+ s->regs[0x3d] = 0x16;
443
+ s->regs[0x80] = 0x80;
444
+ s->regs[0x82] = 0xe0;
445
+ s->regs[0x84] = 0x32;
446
+ s->regs[0x8f] = 0x01;
447
+
448
+ s->regs[0x90] = 0x07;
449
+ s->regs[0x91] = 0x1f;
450
+ s->regs[0x92] = 0x07;
451
+ s->regs[0x93] = 0x1f;
452
+
453
+ s->regs[0x40] = 0xd8;
454
+ s->regs[0x41] = 0xff;
455
+ s->regs[0x42] = 0x03;
456
+ s->regs[0x43] = 0x03;
457
+
458
+ s->regs[0xb8] = 0xc0;
459
+ s->regs[0xb9] = 0x64;
460
+ s->regs[0xe6] = 0xa0;
461
+}
462
+
463
+static void axp2xx_reset_enter(Object *obj, ResetType type)
464
+{
465
+ AXP2xxI2CState *s = AXP2XX(obj);
466
+ AXP2xxClass *sc = AXP2XX_GET_CLASS(s);
467
+
468
+ sc->reset_enter(s, type);
469
+}
470
+
471
+/* Handle events from master. */
472
+static int axp2xx_event(I2CSlave *i2c, enum i2c_event event)
473
+{
474
+ AXP2xxI2CState *s = AXP2XX(i2c);
475
+
476
+ s->count = 0;
477
+
478
+ return 0;
479
+}
480
+
481
+/* Called when master requests read */
482
+static uint8_t axp2xx_rx(I2CSlave *i2c)
483
+{
484
+ AXP2xxI2CState *s = AXP2XX(i2c);
485
+ uint8_t ret = 0xff;
486
+
487
+ if (s->ptr < NR_REGS) {
488
+ ret = s->regs[s->ptr++];
489
+ }
490
+
491
+ trace_axp2xx_rx(s->ptr - 1, ret);
492
+
493
+ return ret;
494
+}
495
+
496
+/*
497
+ * Called when master sends write.
498
+ * Update ptr with byte 0, then perform write with second byte.
499
+ */
500
+static int axp2xx_tx(I2CSlave *i2c, uint8_t data)
501
+{
502
+ AXP2xxI2CState *s = AXP2XX(i2c);
503
+
504
+ if (s->count == 0) {
505
+ /* Store register address */
506
+ s->ptr = data;
507
+ s->count++;
508
+ trace_axp2xx_select(data);
509
+ } else {
510
+ trace_axp2xx_tx(s->ptr, data);
511
+ s->regs[s->ptr++] = data;
512
+ }
513
+
514
+ return 0;
515
+}
516
+
517
+static const VMStateDescription vmstate_axp2xx = {
518
+ .name = TYPE_AXP2XX,
519
+ .version_id = 1,
520
+ .fields = (VMStateField[]) {
521
+ VMSTATE_UINT8_ARRAY(regs, AXP2xxI2CState, NR_REGS),
522
+ VMSTATE_UINT8(ptr, AXP2xxI2CState),
523
+ VMSTATE_UINT8(count, AXP2xxI2CState),
524
+ VMSTATE_END_OF_LIST()
525
+ }
526
+};
527
+
528
+static void axp2xx_class_init(ObjectClass *oc, void *data)
529
+{
530
+ DeviceClass *dc = DEVICE_CLASS(oc);
531
+ I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
532
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
533
+
534
+ rc->phases.enter = axp2xx_reset_enter;
535
+ dc->vmsd = &vmstate_axp2xx;
536
+ isc->event = axp2xx_event;
537
+ isc->recv = axp2xx_rx;
538
+ isc->send = axp2xx_tx;
539
+}
540
+
541
+static const TypeInfo axp2xx_info = {
542
+ .name = TYPE_AXP2XX,
543
+ .parent = TYPE_I2C_SLAVE,
544
+ .instance_size = sizeof(AXP2xxI2CState),
545
+ .class_size = sizeof(AXP2xxClass),
546
+ .class_init = axp2xx_class_init,
547
+ .abstract = true,
548
+};
549
+
550
+static void axp209_class_init(ObjectClass *oc, void *data)
551
+{
552
+ AXP2xxClass *sc = AXP2XX_CLASS(oc);
553
+
554
+ sc->reset_enter = axp209_reset_enter;
555
+}
556
+
557
+static const TypeInfo axp209_info = {
558
+ .name = TYPE_AXP209_PMU,
559
+ .parent = TYPE_AXP2XX,
560
+ .class_init = axp209_class_init
561
+};
562
+
563
+static void axp221_class_init(ObjectClass *oc, void *data)
564
+{
565
+ AXP2xxClass *sc = AXP2XX_CLASS(oc);
566
+
567
+ sc->reset_enter = axp221_reset_enter;
568
+}
569
+
570
+static const TypeInfo axp221_info = {
571
+ .name = TYPE_AXP221_PMU,
572
+ .parent = TYPE_AXP2XX,
573
+ .class_init = axp221_class_init,
574
+};
575
+
576
+static void axp2xx_register_devices(void)
577
+{
578
+ type_register_static(&axp2xx_info);
579
+ type_register_static(&axp209_info);
580
+ type_register_static(&axp221_info);
581
+}
582
+
583
+type_init(axp2xx_register_devices);
584
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
585
index XXXXXXX..XXXXXXX 100644
586
--- a/hw/arm/Kconfig
587
+++ b/hw/arm/Kconfig
588
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
589
select ALLWINNER_WDT
590
select ALLWINNER_EMAC
591
select ALLWINNER_I2C
592
- select AXP209_PMU
593
+ select AXP2XX_PMU
594
select SERIAL
595
select UNIMP
596
597
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_R40
598
bool
599
default y if TCG && ARM
600
select ALLWINNER_A10_PIT
601
+ select AXP2XX_PMU
602
select SERIAL
603
select ARM_TIMER
604
select ARM_GIC
605
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
606
index XXXXXXX..XXXXXXX 100644
607
--- a/hw/misc/Kconfig
608
+++ b/hw/misc/Kconfig
609
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10_CCM
610
config ALLWINNER_A10_DRAMC
611
bool
612
613
-config AXP209_PMU
614
+config AXP2XX_PMU
615
bool
616
depends on I2C
617
618
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
619
index XXXXXXX..XXXXXXX 100644
620
--- a/hw/misc/meson.build
621
+++ b/hw/misc/meson.build
622
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c
623
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-sysctrl.c'))
624
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sid.c'))
625
softmmu_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40-ccu.c'))
626
-softmmu_ss.add(when: 'CONFIG_AXP209_PMU', if_true: files('axp209.c'))
627
+softmmu_ss.add(when: 'CONFIG_AXP2XX_PMU', if_true: files('axp2xx.c'))
628
softmmu_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
629
softmmu_ss.add(when: 'CONFIG_NSERIES', if_true: files('cbus.c'))
630
softmmu_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
631
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
632
index XXXXXXX..XXXXXXX 100644
633
--- a/hw/misc/trace-events
634
+++ b/hw/misc/trace-events
635
@@ -XXX,XX +XXX,XX @@ allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%"
636
avr_power_read(uint8_t value) "power_reduc read value:%u"
637
avr_power_write(uint8_t value) "power_reduc write value:%u"
638
639
-# axp209.c
640
-axp209_rx(uint8_t reg, uint8_t data) "Read reg 0x%" PRIx8 " : 0x%" PRIx8
641
-axp209_select(uint8_t reg) "Accessing reg 0x%" PRIx8
642
-axp209_tx(uint8_t reg, uint8_t data) "Write reg 0x%" PRIx8 " : 0x%" PRIx8
643
+# axp2xx
644
+axp2xx_rx(uint8_t reg, uint8_t data) "Read reg 0x%" PRIx8 " : 0x%" PRIx8
645
+axp2xx_select(uint8_t reg) "Accessing reg 0x%" PRIx8
646
+axp2xx_tx(uint8_t reg, uint8_t data) "Write reg 0x%" PRIx8 " : 0x%" PRIx8
647
648
# eccmemctl.c
649
ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x"
650
--
55
--
651
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: Richard Henderson <richard.henderson@linaro.org>
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
Pass the completed memop to gen_mte_check1_mmuidx.
8
To do this we need to pass the CPU env pointer in to the helper.
4
For the moment, do nothing more than extract the size.
5
9
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230530191438.411344-13-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
10
---
13
---
11
target/arm/tcg/translate-a64.h | 2 +-
14
target/sparc/helper.h | 4 ++--
12
target/arm/tcg/translate-a64.c | 82 ++++++++++++++++++----------------
15
target/sparc/fop_helper.c | 8 ++++----
13
target/arm/tcg/translate-sve.c | 7 +--
16
target/sparc/translate.c | 4 ++--
14
3 files changed, 49 insertions(+), 42 deletions(-)
17
3 files changed, 8 insertions(+), 8 deletions(-)
15
18
16
diff --git a/target/arm/tcg/translate-a64.h b/target/arm/tcg/translate-a64.h
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/tcg/translate-a64.h
21
--- a/target/sparc/helper.h
19
+++ b/target/arm/tcg/translate-a64.h
22
+++ b/target/sparc/helper.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool sme_smza_enabled_check(DisasContext *s)
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
21
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
22
TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
23
TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
24
- bool tag_checked, int log2_size);
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
25
+ bool tag_checked, MemOp memop);
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
26
TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
27
bool tag_checked, int size);
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
28
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
29
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
32
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
30
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/tcg/translate-a64.c
36
--- a/target/sparc/fop_helper.c
32
+++ b/target/arm/tcg/translate-a64.c
37
+++ b/target/sparc/fop_helper.c
33
@@ -XXX,XX +XXX,XX @@ static void gen_probe_access(DisasContext *s, TCGv_i64 ptr,
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
34
*/
39
return finish_fcmp(env, r, GETPC());
35
static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, TCGv_i64 addr,
40
}
36
bool is_write, bool tag_checked,
41
37
- int log2_size, bool is_unpriv,
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
38
+ MemOp memop, bool is_unpriv,
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
39
int core_idx)
40
{
44
{
41
if (tag_checked && s->mte_active[is_unpriv]) {
45
/*
42
@@ -XXX,XX +XXX,XX @@ static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, TCGv_i64 addr,
46
* FLCMP never raises an exception nor modifies any FSR fields.
43
desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
47
* Perform the comparison with a dummy fp environment.
44
desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
48
*/
45
desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
49
- float_status discard = { };
46
- desc = FIELD_DP32(desc, MTEDESC, SIZEM1, (1 << log2_size) - 1);
50
+ float_status discard = env->fp_status;
47
+ desc = FIELD_DP32(desc, MTEDESC, SIZEM1, memop_size(memop) - 1);
51
FloatRelation r;
48
52
49
ret = tcg_temp_new_i64();
53
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
50
gen_helper_mte_check(ret, cpu_env, tcg_constant_i32(desc), addr);
54
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
51
@@ -XXX,XX +XXX,XX @@ static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, TCGv_i64 addr,
55
g_assert_not_reached();
52
}
56
}
53
57
54
TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
55
- bool tag_checked, int log2_size)
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
56
+ bool tag_checked, MemOp memop)
57
{
60
{
58
- return gen_mte_check1_mmuidx(s, addr, is_write, tag_checked, log2_size,
61
- float_status discard = { };
59
+ return gen_mte_check1_mmuidx(s, addr, is_write, tag_checked, memop,
62
+ float_status discard = env->fp_status;
60
false, get_mem_index(s));
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);
61
}
77
}
62
78
63
@@ -XXX,XX +XXX,XX @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2, int rn,
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
64
int size, bool is_pair)
80
65
{
81
src1 = gen_load_fpr_D(dc, a->rs1);
66
int idx = get_mem_index(s);
82
src2 = gen_load_fpr_D(dc, a->rs2);
67
- MemOp memop;
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
68
TCGv_i64 dirty_addr, clean_addr;
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
69
+ MemOp memop;
85
return advance_pc(dc);
70
+
71
+ /*
72
+ * For pairs:
73
+ * if size == 2, the operation is single-copy atomic for the doubleword.
74
+ * if size == 3, the operation is single-copy atomic for *each* doubleword,
75
+ * not the entire quadword, however it must be quadword aligned.
76
+ */
77
+ memop = size + is_pair;
78
+ if (memop == MO_128) {
79
+ memop = finalize_memop_atom(s, MO_128 | MO_ALIGN,
80
+ MO_ATOM_IFALIGN_PAIR);
81
+ } else {
82
+ memop = finalize_memop(s, memop | MO_ALIGN);
83
+ }
84
85
s->is_ldex = true;
86
dirty_addr = cpu_reg_sp(s, rn);
87
- clean_addr = gen_mte_check1(s, dirty_addr, false, rn != 31, size);
88
+ clean_addr = gen_mte_check1(s, dirty_addr, false, rn != 31, memop);
89
90
g_assert(size <= 3);
91
if (is_pair) {
92
g_assert(size >= 2);
93
if (size == 2) {
94
- /* The pair must be single-copy atomic for the doubleword. */
95
- memop = finalize_memop(s, MO_64 | MO_ALIGN);
96
tcg_gen_qemu_ld_i64(cpu_exclusive_val, clean_addr, idx, memop);
97
if (s->be_data == MO_LE) {
98
tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
99
@@ -XXX,XX +XXX,XX @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2, int rn,
100
tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 0, 32);
101
}
102
} else {
103
- /*
104
- * The pair must be single-copy atomic for *each* doubleword, not
105
- * the entire quadword, however it must be quadword aligned.
106
- * Expose the complete load to tcg, for ease of tlb lookup,
107
- * but indicate that only 8-byte atomicity is required.
108
- */
109
TCGv_i128 t16 = tcg_temp_new_i128();
110
111
- memop = finalize_memop_atom(s, MO_128 | MO_ALIGN_16,
112
- MO_ATOM_IFALIGN_PAIR);
113
tcg_gen_qemu_ld_i128(t16, clean_addr, idx, memop);
114
115
if (s->be_data == MO_LE) {
116
@@ -XXX,XX +XXX,XX @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2, int rn,
117
tcg_gen_mov_i64(cpu_reg(s, rt2), cpu_exclusive_high);
118
}
119
} else {
120
- memop = finalize_memop(s, size | MO_ALIGN);
121
tcg_gen_qemu_ld_i64(cpu_exclusive_val, clean_addr, idx, memop);
122
tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
123
}
124
@@ -XXX,XX +XXX,XX @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
125
TCGLabel *fail_label = gen_new_label();
126
TCGLabel *done_label = gen_new_label();
127
TCGv_i64 tmp, dirty_addr, clean_addr;
128
+ MemOp memop;
129
+
130
+ memop = (size + is_pair) | MO_ALIGN;
131
+ memop = finalize_memop(s, memop);
132
133
dirty_addr = cpu_reg_sp(s, rn);
134
- clean_addr = gen_mte_check1(s, dirty_addr, true, rn != 31, size);
135
+ clean_addr = gen_mte_check1(s, dirty_addr, true, rn != 31, memop);
136
137
tcg_gen_brcond_i64(TCG_COND_NE, clean_addr, cpu_exclusive_addr, fail_label);
138
139
@@ -XXX,XX +XXX,XX @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
140
}
141
tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr,
142
cpu_exclusive_val, tmp,
143
- get_mem_index(s),
144
- MO_64 | MO_ALIGN | s->be_data);
145
+ get_mem_index(s), memop);
146
tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
147
} else {
148
TCGv_i128 t16 = tcg_temp_new_i128();
149
@@ -XXX,XX +XXX,XX @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
150
}
151
152
tcg_gen_atomic_cmpxchg_i128(t16, cpu_exclusive_addr, c16, t16,
153
- get_mem_index(s),
154
- MO_128 | MO_ALIGN | s->be_data);
155
+ get_mem_index(s), memop);
156
157
a = tcg_temp_new_i64();
158
b = tcg_temp_new_i64();
159
@@ -XXX,XX +XXX,XX @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
160
}
161
} else {
162
tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr, cpu_exclusive_val,
163
- cpu_reg(s, rt), get_mem_index(s),
164
- size | MO_ALIGN | s->be_data);
165
+ cpu_reg(s, rt), get_mem_index(s), memop);
166
tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
167
}
168
tcg_gen_mov_i64(cpu_reg(s, rd), tmp);
169
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap(DisasContext *s, int rs, int rt,
170
TCGv_i64 tcg_rt = cpu_reg(s, rt);
171
int memidx = get_mem_index(s);
172
TCGv_i64 clean_addr;
173
+ MemOp memop;
174
175
if (rn == 31) {
176
gen_check_sp_alignment(s);
177
}
178
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, size);
179
- tcg_gen_atomic_cmpxchg_i64(tcg_rs, clean_addr, tcg_rs, tcg_rt, memidx,
180
- size | MO_ALIGN | s->be_data);
181
+ memop = finalize_memop(s, size | MO_ALIGN);
182
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, memop);
183
+ tcg_gen_atomic_cmpxchg_i64(tcg_rs, clean_addr, tcg_rs, tcg_rt,
184
+ memidx, memop);
185
}
86
}
186
87
187
static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
188
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
189
TCGv_i64 t2 = cpu_reg(s, rt + 1);
190
TCGv_i64 clean_addr;
191
int memidx = get_mem_index(s);
192
+ MemOp memop;
193
194
if (rn == 31) {
195
gen_check_sp_alignment(s);
196
}
197
198
/* This is a single atomic access, despite the "pair". */
199
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, size + 1);
200
+ memop = finalize_memop(s, (size + 1) | MO_ALIGN);
201
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, memop);
202
203
if (size == 2) {
204
TCGv_i64 cmp = tcg_temp_new_i64();
205
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
206
tcg_gen_concat32_i64(cmp, s2, s1);
207
}
208
209
- tcg_gen_atomic_cmpxchg_i64(cmp, clean_addr, cmp, val, memidx,
210
- MO_64 | MO_ALIGN | s->be_data);
211
+ tcg_gen_atomic_cmpxchg_i64(cmp, clean_addr, cmp, val, memidx, memop);
212
213
if (s->be_data == MO_LE) {
214
tcg_gen_extr32_i64(s1, s2, cmp);
215
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
216
tcg_gen_concat_i64_i128(cmp, s2, s1);
217
}
218
219
- tcg_gen_atomic_cmpxchg_i128(cmp, clean_addr, cmp, val, memidx,
220
- MO_128 | MO_ALIGN | s->be_data);
221
+ tcg_gen_atomic_cmpxchg_i128(cmp, clean_addr, cmp, val, memidx, memop);
222
223
if (s->be_data == MO_LE) {
224
tcg_gen_extr_i128_i64(s1, s2, cmp);
225
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
226
/* TODO: ARMv8.4-LSE SCTLR.nAA */
227
memop = finalize_memop(s, size | MO_ALIGN);
228
clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
229
- true, rn != 31, size);
230
+ true, rn != 31, memop);
231
do_gpr_st(s, cpu_reg(s, rt), clean_addr, memop, true, rt,
232
disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
233
return;
234
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
235
/* TODO: ARMv8.4-LSE SCTLR.nAA */
236
memop = finalize_memop(s, size | MO_ALIGN);
237
clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
238
- false, rn != 31, size);
239
+ false, rn != 31, memop);
240
do_gpr_ld(s, cpu_reg(s, rt), clean_addr, memop, false, true,
241
rt, disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
242
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
243
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
244
tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
245
246
memop = finalize_memop(s, size + is_signed * MO_SIGN);
247
- clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, size);
248
+ clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, memop);
249
250
if (is_vector) {
251
if (is_store) {
252
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
253
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
254
255
memop = finalize_memop(s, size + is_signed * MO_SIGN);
256
- clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, size);
257
+ clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, memop);
258
259
if (is_vector) {
260
if (is_store) {
261
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
262
if (rn == 31) {
263
gen_check_sp_alignment(s);
264
}
265
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), false, rn != 31, size);
266
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), false, rn != 31, mop);
267
268
if (o3_opc == 014) {
269
/*
270
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn,
271
272
/* Note that "clean" and "dirty" here refer to TBI not PAC. */
273
clean_addr = gen_mte_check1(s, dirty_addr, false,
274
- is_wback || rn != 31, size);
275
+ is_wback || rn != 31, memop);
276
277
tcg_rt = cpu_reg(s, rt);
278
do_gpr_ld(s, tcg_rt, clean_addr, memop,
279
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
280
index XXXXXXX..XXXXXXX 100644
281
--- a/target/arm/tcg/translate-sve.c
282
+++ b/target/arm/tcg/translate-sve.c
283
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a)
284
unsigned msz = dtype_msz(a->dtype);
285
TCGLabel *over;
286
TCGv_i64 temp, clean_addr;
287
+ MemOp memop;
288
289
if (!dc_isar_feature(aa64_sve, s)) {
290
return false;
291
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a)
292
/* Load the data. */
293
temp = tcg_temp_new_i64();
294
tcg_gen_addi_i64(temp, cpu_reg_sp(s, a->rn), a->imm << msz);
295
- clean_addr = gen_mte_check1(s, temp, false, true, msz);
296
297
- tcg_gen_qemu_ld_i64(temp, clean_addr, get_mem_index(s),
298
- finalize_memop(s, dtype_mop[a->dtype]));
299
+ memop = finalize_memop(s, dtype_mop[a->dtype]);
300
+ clean_addr = gen_mte_check1(s, temp, false, true, memop);
301
+ tcg_gen_qemu_ld_i64(temp, clean_addr, get_mem_index(s), memop);
302
303
/* Broadcast to *all* elements. */
304
tcg_gen_gvec_dup_i64(esz, vec_full_reg_offset(s, a->rd),
305
--
88
--
306
2.34.1
89
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
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.
2
8
3
We have many other instances of stg in the testsuite;
9
Use env->fp_status instead of the dummy fp_status.
4
change these to provide an instance of stz2g.
5
10
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230530191438.411344-19-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
10
---
14
---
11
tests/tcg/aarch64/mte-7.c | 3 +--
15
target/ppc/fpu_helper.c | 3 +--
12
1 file changed, 1 insertion(+), 2 deletions(-)
16
1 file changed, 1 insertion(+), 2 deletions(-)
13
17
14
diff --git a/tests/tcg/aarch64/mte-7.c b/tests/tcg/aarch64/mte-7.c
18
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/tcg/aarch64/mte-7.c
20
--- a/target/ppc/fpu_helper.c
17
+++ b/tests/tcg/aarch64/mte-7.c
21
+++ b/target/ppc/fpu_helper.c
18
@@ -XXX,XX +XXX,XX @@ int main(int ac, char **av)
22
@@ -XXX,XX +XXX,XX @@ void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \
19
p = (void *)((unsigned long)p | (1ul << 56));
23
} else if (tp##_is_infinity(arg)) { \
20
24
fprf = neg ? 0x09 << FPSCR_FPRF : 0x05 << FPSCR_FPRF; \
21
/* Store tag in sequential granules. */
25
} else { \
22
- asm("stg %0, [%0]" : : "r"(p + 0x0ff0));
26
- float_status dummy = { }; /* snan_bit_is_one = 0 */ \
23
- asm("stg %0, [%0]" : : "r"(p + 0x1000));
27
- if (tp##_is_signaling_nan(arg, &dummy)) { \
24
+ asm("stz2g %0, [%0]" : : "r"(p + 0x0ff0));
28
+ if (tp##_is_signaling_nan(arg, &env->fp_status)) { \
25
29
fprf = 0x00 << FPSCR_FPRF; \
26
/*
30
} else { \
27
* Perform an unaligned store with tag 1 crossing the pages.
31
fprf = 0x11 << FPSCR_FPRF; \
28
--
32
--
29
2.34.1
33
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Let finalize_memop_atom be the new basic function, with
3
Now that float_status has a bunch of fp parameters,
4
finalize_memop and finalize_memop_pair testing FEAT_LSE2
4
it is easier to copy an existing structure than create
5
to apply the appropriate atomicity.
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.
6
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
10
Message-id: 20230530191438.411344-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
14
---
13
target/arm/tcg/translate.h | 39 +++++++++++++++++++++++++++++-----
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
14
target/arm/tcg/translate-a64.c | 2 ++
16
1 file changed, 7 insertions(+), 13 deletions(-)
15
target/arm/tcg/translate.c | 1 +
16
3 files changed, 37 insertions(+), 5 deletions(-)
17
17
18
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/tcg/translate.h
20
--- a/target/arm/tcg/vec_helper.c
21
+++ b/target/arm/tcg/translate.h
21
+++ b/target/arm/tcg/vec_helper.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
23
uint64_t features; /* CPU features bits */
23
* no effect on AArch32 instructions.
24
bool aarch64;
24
*/
25
bool thumb;
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
26
+ bool lse2;
26
- *statusp = (float_status){
27
/* Because unallocated encodings generate different exception syndrome
27
- .tininess_before_rounding = float_tininess_before_rounding,
28
* information from traps due to FP being disabled, we can't do a single
28
- .float_rounding_mode = float_round_to_odd_inf,
29
* "is fp access disabled" check at a high level in the decode tree.
29
- .flush_to_zero = true,
30
@@ -XXX,XX +XXX,XX @@ static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour)
30
- .flush_inputs_to_zero = true,
31
- .default_nan_mode = true,
32
- };
33
+
34
+ *statusp = env->vfp.fp_status;
35
+ set_default_nan_mode(true, statusp);
36
37
if (ebf) {
38
- float_status *fpst = &env->vfp.fp_status;
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
42
-
43
/* EBF=1 needs to do a step with round-to-odd semantics */
44
*oddstatusp = *statusp;
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
46
+ } else {
47
+ set_flush_to_zero(true, statusp);
48
+ set_flush_inputs_to_zero(true, statusp);
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
50
}
51
-
52
return ebf;
31
}
53
}
32
33
/**
34
- * finalize_memop:
35
+ * finalize_memop_atom:
36
* @s: DisasContext
37
* @opc: size+sign+align of the memory operation
38
+ * @atom: atomicity of the memory operation
39
*
40
- * Build the complete MemOp for a memory operation, including alignment
41
- * and endianness.
42
+ * Build the complete MemOp for a memory operation, including alignment,
43
+ * endianness, and atomicity.
44
*
45
* If (op & MO_AMASK) then the operation already contains the required
46
* alignment, e.g. for AccType_ATOMIC. Otherwise, this an optionally
47
@@ -XXX,XX +XXX,XX @@ static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour)
48
* and this is applied here. Note that there is no way to indicate that
49
* no alignment should ever be enforced; this must be handled manually.
50
*/
51
-static inline MemOp finalize_memop(DisasContext *s, MemOp opc)
52
+static inline MemOp finalize_memop_atom(DisasContext *s, MemOp opc, MemOp atom)
53
{
54
if (s->align_mem && !(opc & MO_AMASK)) {
55
opc |= MO_ALIGN;
56
}
57
- return opc | s->be_data;
58
+ return opc | atom | s->be_data;
59
+}
60
+
61
+/**
62
+ * finalize_memop:
63
+ * @s: DisasContext
64
+ * @opc: size+sign+align of the memory operation
65
+ *
66
+ * Like finalize_memop_atom, but with default atomicity.
67
+ */
68
+static inline MemOp finalize_memop(DisasContext *s, MemOp opc)
69
+{
70
+ MemOp atom = s->lse2 ? MO_ATOM_WITHIN16 : MO_ATOM_IFALIGN;
71
+ return finalize_memop_atom(s, opc, atom);
72
+}
73
+
74
+/**
75
+ * finalize_memop_pair:
76
+ * @s: DisasContext
77
+ * @opc: size+sign+align of the memory operation
78
+ *
79
+ * Like finalize_memop_atom, but with atomicity for a pair.
80
+ * C.f. Pseudocode for Mem[], operand ispair.
81
+ */
82
+static inline MemOp finalize_memop_pair(DisasContext *s, MemOp opc)
83
+{
84
+ MemOp atom = s->lse2 ? MO_ATOM_WITHIN16_PAIR : MO_ATOM_IFALIGN_PAIR;
85
+ return finalize_memop_atom(s, opc, atom);
86
}
87
88
/**
89
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/tcg/translate-a64.c
92
+++ b/target/arm/tcg/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
94
tcg_debug_assert(dc->tbid & 1);
95
#endif
96
97
+ dc->lse2 = dc_isar_feature(aa64_lse2, dc);
98
+
99
/* Single step state. The code-generation logic here is:
100
* SS_ACTIVE == 0:
101
* generate code with no special handling for single-stepping (except
102
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/tcg/translate.c
105
+++ b/target/arm/tcg/translate.c
106
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
107
dc->sme_trap_nonstreaming =
108
EX_TBFLAG_A32(tb_flags, SME_TRAP_NONSTREAMING);
109
}
110
+ dc->lse2 = false; /* applies only to aarch64 */
111
dc->cp_regs = cpu->cp_regs;
112
dc->features = env->features;
113
54
114
--
55
--
115
2.34.1
56
2.34.1
116
57
117
58
diff view generated by jsdifflib
1
From: Francesco Cagnin <fcagnin@quarkslab.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
Guests can now be debugged through the gdbstub. Support is added for
7
Add a field to float_status to specify the default NaN value; fall
4
single-stepping, software breakpoints, hardware breakpoints and
8
back to the old ifdef behaviour if these are not set.
5
watchpoints. The code has been structured like the KVM counterpart.
6
9
7
While guest debugging is enabled, the guest can still read and write the
10
The default NaN value is specified by setting a uint8_t to a
8
DBG*_EL1 registers but they don't have any effect.
11
pattern corresponding to the sign and upper fraction parts of
12
the NaN; the lower bits of the fraction are set from bit 0 of
13
the pattern.
9
14
10
Signed-off-by: Francesco Cagnin <fcagnin@quarkslab.com>
11
Message-id: 20230601153107.81955-5-fcagnin@quarkslab.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20241202131347.498124-35-peter.maydell@linaro.org
14
---
18
---
15
include/sysemu/hvf.h | 15 ++
19
include/fpu/softfloat-helpers.h | 11 +++++++
16
include/sysemu/hvf_int.h | 1 +
20
include/fpu/softfloat-types.h | 10 ++++++
17
target/arm/hvf_arm.h | 7 +
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
18
accel/hvf/hvf-accel-ops.c | 10 +
22
3 files changed, 54 insertions(+), 22 deletions(-)
19
accel/hvf/hvf-all.c | 6 +
20
target/arm/hvf/hvf.c | 474 +++++++++++++++++++++++++++++++++++++-
21
target/i386/hvf/hvf.c | 9 +
22
7 files changed, 520 insertions(+), 2 deletions(-)
23
23
24
diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
25
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/sysemu/hvf.h
26
--- a/include/fpu/softfloat-helpers.h
27
+++ b/include/sysemu/hvf.h
27
+++ b/include/fpu/softfloat-helpers.h
28
@@ -XXX,XX +XXX,XX @@ int hvf_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len,
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
29
int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len,
29
status->float_infzeronan_rule = rule;
30
int type);
31
void hvf_arch_remove_all_hw_breakpoints(void);
32
+
33
+/*
34
+ * hvf_update_guest_debug:
35
+ * @cs: CPUState for the CPU to update
36
+ *
37
+ * Update guest to enable or disable debugging. Per-arch specifics will be
38
+ * handled by calling down to hvf_arch_update_guest_debug.
39
+ */
40
+int hvf_update_guest_debug(CPUState *cpu);
41
+void hvf_arch_update_guest_debug(CPUState *cpu);
42
+
43
+/*
44
+ * Return whether the guest supports debugging.
45
+ */
46
+bool hvf_arch_supports_guest_debug(void);
47
#endif /* NEED_CPU_H */
48
49
#endif
50
diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/sysemu/hvf_int.h
53
+++ b/include/sysemu/hvf_int.h
54
@@ -XXX,XX +XXX,XX @@ struct hvf_vcpu_state {
55
void *exit;
56
bool vtimer_masked;
57
sigset_t unblock_ipi_mask;
58
+ bool guest_debug_enabled;
59
};
60
61
void assert_hvf_ok(hv_return_t ret);
62
diff --git a/target/arm/hvf_arm.h b/target/arm/hvf_arm.h
63
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/hvf_arm.h
65
+++ b/target/arm/hvf_arm.h
66
@@ -XXX,XX +XXX,XX @@
67
68
#include "cpu.h"
69
70
+/**
71
+ * hvf_arm_init_debug() - initialize guest debug capabilities
72
+ *
73
+ * Should be called only once before using guest debug capabilities.
74
+ */
75
+void hvf_arm_init_debug(void);
76
+
77
void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu);
78
79
#endif
80
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/accel/hvf/hvf-accel-ops.c
83
+++ b/accel/hvf/hvf-accel-ops.c
84
@@ -XXX,XX +XXX,XX @@ static int hvf_accel_init(MachineState *ms)
85
return hvf_arch_init();
86
}
30
}
87
31
88
+static inline int hvf_gdbstub_sstep_flags(void)
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
33
+ float_status *status)
89
+{
34
+{
90
+ return SSTEP_ENABLE | SSTEP_NOIRQ;
35
+ status->default_nan_pattern = dnan_pattern;
91
+}
36
+}
92
+
37
+
93
static void hvf_accel_class_init(ObjectClass *oc, void *data)
38
static inline void set_flush_to_zero(bool val, float_status *status)
94
{
39
{
95
AccelClass *ac = ACCEL_CLASS(oc);
40
status->flush_to_zero = val;
96
ac->name = "HVF";
41
@@ -XXX,XX +XXX,XX @@ static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status
97
ac->init_machine = hvf_accel_init;
42
return status->float_infzeronan_rule;
98
ac->allowed = &hvf_allowed;
99
+ ac->gdbstub_supported_sstep_flags = hvf_gdbstub_sstep_flags;
100
}
43
}
101
44
102
static const TypeInfo hvf_accel_type = {
45
+static inline uint8_t get_float_default_nan_pattern(float_status *status)
103
@@ -XXX,XX +XXX,XX @@ static int hvf_init_vcpu(CPUState *cpu)
104
cpu->vcpu_dirty = 1;
105
assert_hvf_ok(r);
106
107
+ cpu->hvf->guest_debug_enabled = false;
108
+
109
return hvf_arch_init_vcpu(cpu);
110
}
111
112
@@ -XXX,XX +XXX,XX @@ static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
113
ops->insert_breakpoint = hvf_insert_breakpoint;
114
ops->remove_breakpoint = hvf_remove_breakpoint;
115
ops->remove_all_breakpoints = hvf_remove_all_breakpoints;
116
+ ops->update_guest_debug = hvf_update_guest_debug;
117
+ ops->supports_guest_debug = hvf_arch_supports_guest_debug;
118
};
119
static const TypeInfo hvf_accel_ops_type = {
120
.name = ACCEL_OPS_NAME("hvf"),
121
diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/accel/hvf/hvf-all.c
124
+++ b/accel/hvf/hvf-all.c
125
@@ -XXX,XX +XXX,XX @@ int hvf_sw_breakpoints_active(CPUState *cpu)
126
{
127
return !QTAILQ_EMPTY(&hvf_state->hvf_sw_breakpoints);
128
}
129
+
130
+int hvf_update_guest_debug(CPUState *cpu)
131
+{
46
+{
132
+ hvf_arch_update_guest_debug(cpu);
47
+ return status->default_nan_pattern;
133
+ return 0;
134
+}
135
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/target/arm/hvf/hvf.c
138
+++ b/target/arm/hvf/hvf.c
139
@@ -XXX,XX +XXX,XX @@
140
141
#include "exec/gdbstub.h"
142
143
+#define MDSCR_EL1_SS_SHIFT 0
144
+#define MDSCR_EL1_MDE_SHIFT 15
145
+
146
+static uint16_t dbgbcr_regs[] = {
147
+ HV_SYS_REG_DBGBCR0_EL1,
148
+ HV_SYS_REG_DBGBCR1_EL1,
149
+ HV_SYS_REG_DBGBCR2_EL1,
150
+ HV_SYS_REG_DBGBCR3_EL1,
151
+ HV_SYS_REG_DBGBCR4_EL1,
152
+ HV_SYS_REG_DBGBCR5_EL1,
153
+ HV_SYS_REG_DBGBCR6_EL1,
154
+ HV_SYS_REG_DBGBCR7_EL1,
155
+ HV_SYS_REG_DBGBCR8_EL1,
156
+ HV_SYS_REG_DBGBCR9_EL1,
157
+ HV_SYS_REG_DBGBCR10_EL1,
158
+ HV_SYS_REG_DBGBCR11_EL1,
159
+ HV_SYS_REG_DBGBCR12_EL1,
160
+ HV_SYS_REG_DBGBCR13_EL1,
161
+ HV_SYS_REG_DBGBCR14_EL1,
162
+ HV_SYS_REG_DBGBCR15_EL1,
163
+};
164
+static uint16_t dbgbvr_regs[] = {
165
+ HV_SYS_REG_DBGBVR0_EL1,
166
+ HV_SYS_REG_DBGBVR1_EL1,
167
+ HV_SYS_REG_DBGBVR2_EL1,
168
+ HV_SYS_REG_DBGBVR3_EL1,
169
+ HV_SYS_REG_DBGBVR4_EL1,
170
+ HV_SYS_REG_DBGBVR5_EL1,
171
+ HV_SYS_REG_DBGBVR6_EL1,
172
+ HV_SYS_REG_DBGBVR7_EL1,
173
+ HV_SYS_REG_DBGBVR8_EL1,
174
+ HV_SYS_REG_DBGBVR9_EL1,
175
+ HV_SYS_REG_DBGBVR10_EL1,
176
+ HV_SYS_REG_DBGBVR11_EL1,
177
+ HV_SYS_REG_DBGBVR12_EL1,
178
+ HV_SYS_REG_DBGBVR13_EL1,
179
+ HV_SYS_REG_DBGBVR14_EL1,
180
+ HV_SYS_REG_DBGBVR15_EL1,
181
+};
182
+static uint16_t dbgwcr_regs[] = {
183
+ HV_SYS_REG_DBGWCR0_EL1,
184
+ HV_SYS_REG_DBGWCR1_EL1,
185
+ HV_SYS_REG_DBGWCR2_EL1,
186
+ HV_SYS_REG_DBGWCR3_EL1,
187
+ HV_SYS_REG_DBGWCR4_EL1,
188
+ HV_SYS_REG_DBGWCR5_EL1,
189
+ HV_SYS_REG_DBGWCR6_EL1,
190
+ HV_SYS_REG_DBGWCR7_EL1,
191
+ HV_SYS_REG_DBGWCR8_EL1,
192
+ HV_SYS_REG_DBGWCR9_EL1,
193
+ HV_SYS_REG_DBGWCR10_EL1,
194
+ HV_SYS_REG_DBGWCR11_EL1,
195
+ HV_SYS_REG_DBGWCR12_EL1,
196
+ HV_SYS_REG_DBGWCR13_EL1,
197
+ HV_SYS_REG_DBGWCR14_EL1,
198
+ HV_SYS_REG_DBGWCR15_EL1,
199
+};
200
+static uint16_t dbgwvr_regs[] = {
201
+ HV_SYS_REG_DBGWVR0_EL1,
202
+ HV_SYS_REG_DBGWVR1_EL1,
203
+ HV_SYS_REG_DBGWVR2_EL1,
204
+ HV_SYS_REG_DBGWVR3_EL1,
205
+ HV_SYS_REG_DBGWVR4_EL1,
206
+ HV_SYS_REG_DBGWVR5_EL1,
207
+ HV_SYS_REG_DBGWVR6_EL1,
208
+ HV_SYS_REG_DBGWVR7_EL1,
209
+ HV_SYS_REG_DBGWVR8_EL1,
210
+ HV_SYS_REG_DBGWVR9_EL1,
211
+ HV_SYS_REG_DBGWVR10_EL1,
212
+ HV_SYS_REG_DBGWVR11_EL1,
213
+ HV_SYS_REG_DBGWVR12_EL1,
214
+ HV_SYS_REG_DBGWVR13_EL1,
215
+ HV_SYS_REG_DBGWVR14_EL1,
216
+ HV_SYS_REG_DBGWVR15_EL1,
217
+};
218
+
219
+static inline int hvf_arm_num_brps(hv_vcpu_config_t config)
220
+{
221
+ uint64_t val;
222
+ hv_return_t ret;
223
+ ret = hv_vcpu_config_get_feature_reg(config, HV_FEATURE_REG_ID_AA64DFR0_EL1,
224
+ &val);
225
+ assert_hvf_ok(ret);
226
+ return FIELD_EX64(val, ID_AA64DFR0, BRPS) + 1;
227
+}
48
+}
228
+
49
+
229
+static inline int hvf_arm_num_wrps(hv_vcpu_config_t config)
50
static inline bool get_flush_to_zero(float_status *status)
230
+{
51
{
231
+ uint64_t val;
52
return status->flush_to_zero;
232
+ hv_return_t ret;
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
233
+ ret = hv_vcpu_config_get_feature_reg(config, HV_FEATURE_REG_ID_AA64DFR0_EL1,
54
index XXXXXXX..XXXXXXX 100644
234
+ &val);
55
--- a/include/fpu/softfloat-types.h
235
+ assert_hvf_ok(ret);
56
+++ b/include/fpu/softfloat-types.h
236
+ return FIELD_EX64(val, ID_AA64DFR0, WRPS) + 1;
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
237
+}
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);
238
+
136
+
239
+void hvf_arm_init_debug(void)
137
+ sign = dnan_pattern >> 7;
240
+{
138
+ /*
241
+ hv_vcpu_config_t config;
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
242
+ config = hv_vcpu_config_create();
140
+ * and replecate bit [0] down into [55:0]
243
+
141
+ */
244
+ max_hw_bps = hvf_arm_num_brps(config);
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
245
+ hw_breakpoints =
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
246
+ g_array_sized_new(true, true, sizeof(HWBreakpoint), max_hw_bps);
144
247
+
145
*p = (FloatParts64) {
248
+ max_hw_wps = hvf_arm_num_wrps(config);
146
.cls = float_class_qnan,
249
+ hw_watchpoints =
250
+ g_array_sized_new(true, true, sizeof(HWWatchpoint), max_hw_wps);
251
+}
252
+
253
#define HVF_SYSREG(crn, crm, op0, op1, op2) \
254
ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
255
#define PL1_WRITE_MASK 0x4
256
@@ -XXX,XX +XXX,XX @@ int hvf_get_registers(CPUState *cpu)
257
continue;
258
}
259
260
+ if (cpu->hvf->guest_debug_enabled) {
261
+ /* Handle debug registers */
262
+ switch (hvf_sreg_match[i].reg) {
263
+ case HV_SYS_REG_DBGBVR0_EL1:
264
+ case HV_SYS_REG_DBGBCR0_EL1:
265
+ case HV_SYS_REG_DBGWVR0_EL1:
266
+ case HV_SYS_REG_DBGWCR0_EL1:
267
+ case HV_SYS_REG_DBGBVR1_EL1:
268
+ case HV_SYS_REG_DBGBCR1_EL1:
269
+ case HV_SYS_REG_DBGWVR1_EL1:
270
+ case HV_SYS_REG_DBGWCR1_EL1:
271
+ case HV_SYS_REG_DBGBVR2_EL1:
272
+ case HV_SYS_REG_DBGBCR2_EL1:
273
+ case HV_SYS_REG_DBGWVR2_EL1:
274
+ case HV_SYS_REG_DBGWCR2_EL1:
275
+ case HV_SYS_REG_DBGBVR3_EL1:
276
+ case HV_SYS_REG_DBGBCR3_EL1:
277
+ case HV_SYS_REG_DBGWVR3_EL1:
278
+ case HV_SYS_REG_DBGWCR3_EL1:
279
+ case HV_SYS_REG_DBGBVR4_EL1:
280
+ case HV_SYS_REG_DBGBCR4_EL1:
281
+ case HV_SYS_REG_DBGWVR4_EL1:
282
+ case HV_SYS_REG_DBGWCR4_EL1:
283
+ case HV_SYS_REG_DBGBVR5_EL1:
284
+ case HV_SYS_REG_DBGBCR5_EL1:
285
+ case HV_SYS_REG_DBGWVR5_EL1:
286
+ case HV_SYS_REG_DBGWCR5_EL1:
287
+ case HV_SYS_REG_DBGBVR6_EL1:
288
+ case HV_SYS_REG_DBGBCR6_EL1:
289
+ case HV_SYS_REG_DBGWVR6_EL1:
290
+ case HV_SYS_REG_DBGWCR6_EL1:
291
+ case HV_SYS_REG_DBGBVR7_EL1:
292
+ case HV_SYS_REG_DBGBCR7_EL1:
293
+ case HV_SYS_REG_DBGWVR7_EL1:
294
+ case HV_SYS_REG_DBGWCR7_EL1:
295
+ case HV_SYS_REG_DBGBVR8_EL1:
296
+ case HV_SYS_REG_DBGBCR8_EL1:
297
+ case HV_SYS_REG_DBGWVR8_EL1:
298
+ case HV_SYS_REG_DBGWCR8_EL1:
299
+ case HV_SYS_REG_DBGBVR9_EL1:
300
+ case HV_SYS_REG_DBGBCR9_EL1:
301
+ case HV_SYS_REG_DBGWVR9_EL1:
302
+ case HV_SYS_REG_DBGWCR9_EL1:
303
+ case HV_SYS_REG_DBGBVR10_EL1:
304
+ case HV_SYS_REG_DBGBCR10_EL1:
305
+ case HV_SYS_REG_DBGWVR10_EL1:
306
+ case HV_SYS_REG_DBGWCR10_EL1:
307
+ case HV_SYS_REG_DBGBVR11_EL1:
308
+ case HV_SYS_REG_DBGBCR11_EL1:
309
+ case HV_SYS_REG_DBGWVR11_EL1:
310
+ case HV_SYS_REG_DBGWCR11_EL1:
311
+ case HV_SYS_REG_DBGBVR12_EL1:
312
+ case HV_SYS_REG_DBGBCR12_EL1:
313
+ case HV_SYS_REG_DBGWVR12_EL1:
314
+ case HV_SYS_REG_DBGWCR12_EL1:
315
+ case HV_SYS_REG_DBGBVR13_EL1:
316
+ case HV_SYS_REG_DBGBCR13_EL1:
317
+ case HV_SYS_REG_DBGWVR13_EL1:
318
+ case HV_SYS_REG_DBGWCR13_EL1:
319
+ case HV_SYS_REG_DBGBVR14_EL1:
320
+ case HV_SYS_REG_DBGBCR14_EL1:
321
+ case HV_SYS_REG_DBGWVR14_EL1:
322
+ case HV_SYS_REG_DBGWCR14_EL1:
323
+ case HV_SYS_REG_DBGBVR15_EL1:
324
+ case HV_SYS_REG_DBGBCR15_EL1:
325
+ case HV_SYS_REG_DBGWVR15_EL1:
326
+ case HV_SYS_REG_DBGWCR15_EL1: {
327
+ /*
328
+ * If the guest is being debugged, the vCPU's debug registers
329
+ * are holding the gdbstub's view of the registers (set in
330
+ * hvf_arch_update_guest_debug()).
331
+ * Since the environment is used to store only the guest's view
332
+ * of the registers, don't update it with the values from the
333
+ * vCPU but simply keep the values from the previous
334
+ * environment.
335
+ */
336
+ const ARMCPRegInfo *ri;
337
+ ri = get_arm_cp_reginfo(arm_cpu->cp_regs, hvf_sreg_match[i].key);
338
+ val = read_raw_cp_reg(env, ri);
339
+
340
+ arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx] = val;
341
+ continue;
342
+ }
343
+ }
344
+ }
345
+
346
ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, &val);
347
assert_hvf_ok(ret);
348
349
@@ -XXX,XX +XXX,XX @@ int hvf_put_registers(CPUState *cpu)
350
continue;
351
}
352
353
+ if (cpu->hvf->guest_debug_enabled) {
354
+ /* Handle debug registers */
355
+ switch (hvf_sreg_match[i].reg) {
356
+ case HV_SYS_REG_DBGBVR0_EL1:
357
+ case HV_SYS_REG_DBGBCR0_EL1:
358
+ case HV_SYS_REG_DBGWVR0_EL1:
359
+ case HV_SYS_REG_DBGWCR0_EL1:
360
+ case HV_SYS_REG_DBGBVR1_EL1:
361
+ case HV_SYS_REG_DBGBCR1_EL1:
362
+ case HV_SYS_REG_DBGWVR1_EL1:
363
+ case HV_SYS_REG_DBGWCR1_EL1:
364
+ case HV_SYS_REG_DBGBVR2_EL1:
365
+ case HV_SYS_REG_DBGBCR2_EL1:
366
+ case HV_SYS_REG_DBGWVR2_EL1:
367
+ case HV_SYS_REG_DBGWCR2_EL1:
368
+ case HV_SYS_REG_DBGBVR3_EL1:
369
+ case HV_SYS_REG_DBGBCR3_EL1:
370
+ case HV_SYS_REG_DBGWVR3_EL1:
371
+ case HV_SYS_REG_DBGWCR3_EL1:
372
+ case HV_SYS_REG_DBGBVR4_EL1:
373
+ case HV_SYS_REG_DBGBCR4_EL1:
374
+ case HV_SYS_REG_DBGWVR4_EL1:
375
+ case HV_SYS_REG_DBGWCR4_EL1:
376
+ case HV_SYS_REG_DBGBVR5_EL1:
377
+ case HV_SYS_REG_DBGBCR5_EL1:
378
+ case HV_SYS_REG_DBGWVR5_EL1:
379
+ case HV_SYS_REG_DBGWCR5_EL1:
380
+ case HV_SYS_REG_DBGBVR6_EL1:
381
+ case HV_SYS_REG_DBGBCR6_EL1:
382
+ case HV_SYS_REG_DBGWVR6_EL1:
383
+ case HV_SYS_REG_DBGWCR6_EL1:
384
+ case HV_SYS_REG_DBGBVR7_EL1:
385
+ case HV_SYS_REG_DBGBCR7_EL1:
386
+ case HV_SYS_REG_DBGWVR7_EL1:
387
+ case HV_SYS_REG_DBGWCR7_EL1:
388
+ case HV_SYS_REG_DBGBVR8_EL1:
389
+ case HV_SYS_REG_DBGBCR8_EL1:
390
+ case HV_SYS_REG_DBGWVR8_EL1:
391
+ case HV_SYS_REG_DBGWCR8_EL1:
392
+ case HV_SYS_REG_DBGBVR9_EL1:
393
+ case HV_SYS_REG_DBGBCR9_EL1:
394
+ case HV_SYS_REG_DBGWVR9_EL1:
395
+ case HV_SYS_REG_DBGWCR9_EL1:
396
+ case HV_SYS_REG_DBGBVR10_EL1:
397
+ case HV_SYS_REG_DBGBCR10_EL1:
398
+ case HV_SYS_REG_DBGWVR10_EL1:
399
+ case HV_SYS_REG_DBGWCR10_EL1:
400
+ case HV_SYS_REG_DBGBVR11_EL1:
401
+ case HV_SYS_REG_DBGBCR11_EL1:
402
+ case HV_SYS_REG_DBGWVR11_EL1:
403
+ case HV_SYS_REG_DBGWCR11_EL1:
404
+ case HV_SYS_REG_DBGBVR12_EL1:
405
+ case HV_SYS_REG_DBGBCR12_EL1:
406
+ case HV_SYS_REG_DBGWVR12_EL1:
407
+ case HV_SYS_REG_DBGWCR12_EL1:
408
+ case HV_SYS_REG_DBGBVR13_EL1:
409
+ case HV_SYS_REG_DBGBCR13_EL1:
410
+ case HV_SYS_REG_DBGWVR13_EL1:
411
+ case HV_SYS_REG_DBGWCR13_EL1:
412
+ case HV_SYS_REG_DBGBVR14_EL1:
413
+ case HV_SYS_REG_DBGBCR14_EL1:
414
+ case HV_SYS_REG_DBGWVR14_EL1:
415
+ case HV_SYS_REG_DBGWCR14_EL1:
416
+ case HV_SYS_REG_DBGBVR15_EL1:
417
+ case HV_SYS_REG_DBGBCR15_EL1:
418
+ case HV_SYS_REG_DBGWVR15_EL1:
419
+ case HV_SYS_REG_DBGWCR15_EL1:
420
+ /*
421
+ * If the guest is being debugged, the vCPU's debug registers
422
+ * are already holding the gdbstub's view of the registers (set
423
+ * in hvf_arch_update_guest_debug()).
424
+ */
425
+ continue;
426
+ }
427
+ }
428
+
429
val = arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx];
430
ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, val);
431
assert_hvf_ok(ret);
432
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
433
{
434
ARMCPU *arm_cpu = ARM_CPU(cpu);
435
CPUARMState *env = &arm_cpu->env;
436
+ int ret;
437
hv_vcpu_exit_t *hvf_exit = cpu->hvf->exit;
438
hv_return_t r;
439
bool advance_pc = false;
440
441
- if (hvf_inject_interrupts(cpu)) {
442
+ if (!(cpu->singlestep_enabled & SSTEP_NOIRQ) &&
443
+ hvf_inject_interrupts(cpu)) {
444
return EXCP_INTERRUPT;
445
}
446
447
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
448
uint64_t syndrome = hvf_exit->exception.syndrome;
449
uint32_t ec = syn_get_ec(syndrome);
450
451
+ ret = 0;
452
qemu_mutex_lock_iothread();
453
switch (exit_reason) {
454
case HV_EXIT_REASON_EXCEPTION:
455
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
456
hvf_sync_vtimer(cpu);
457
458
switch (ec) {
459
+ case EC_SOFTWARESTEP: {
460
+ ret = EXCP_DEBUG;
461
+
462
+ if (!cpu->singlestep_enabled) {
463
+ error_report("EC_SOFTWARESTEP but single-stepping not enabled");
464
+ }
465
+ break;
466
+ }
467
+ case EC_AA64_BKPT: {
468
+ ret = EXCP_DEBUG;
469
+
470
+ cpu_synchronize_state(cpu);
471
+
472
+ if (!hvf_find_sw_breakpoint(cpu, env->pc)) {
473
+ /* Re-inject into the guest */
474
+ ret = 0;
475
+ hvf_raise_exception(cpu, EXCP_BKPT, syn_aa64_bkpt(0));
476
+ }
477
+ break;
478
+ }
479
+ case EC_BREAKPOINT: {
480
+ ret = EXCP_DEBUG;
481
+
482
+ cpu_synchronize_state(cpu);
483
+
484
+ if (!find_hw_breakpoint(cpu, env->pc)) {
485
+ error_report("EC_BREAKPOINT but unknown hw breakpoint");
486
+ }
487
+ break;
488
+ }
489
+ case EC_WATCHPOINT: {
490
+ ret = EXCP_DEBUG;
491
+
492
+ cpu_synchronize_state(cpu);
493
+
494
+ CPUWatchpoint *wp =
495
+ find_hw_watchpoint(cpu, hvf_exit->exception.virtual_address);
496
+ if (!wp) {
497
+ error_report("EXCP_DEBUG but unknown hw watchpoint");
498
+ }
499
+ cpu->watchpoint_hit = wp;
500
+ break;
501
+ }
502
case EC_DATAABORT: {
503
bool isv = syndrome & ARM_EL_ISV;
504
bool iswrite = (syndrome >> 6) & 1;
505
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
506
pc += 4;
507
r = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_PC, pc);
508
assert_hvf_ok(r);
509
+
510
+ /* Handle single-stepping over instructions which trigger a VM exit */
511
+ if (cpu->singlestep_enabled) {
512
+ ret = EXCP_DEBUG;
513
+ }
514
}
515
516
- return 0;
517
+ return ret;
518
}
519
520
static const VMStateDescription vmstate_hvf_vtimer = {
521
@@ -XXX,XX +XXX,XX @@ int hvf_arch_init(void)
522
hvf_state->vtimer_offset = mach_absolute_time();
523
vmstate_register(NULL, 0, &vmstate_hvf_vtimer, &vtimer);
524
qemu_add_vm_change_state_handler(hvf_vm_state_change, &vtimer);
525
+
526
+ hvf_arm_init_debug();
527
+
528
return 0;
529
}
530
531
@@ -XXX,XX +XXX,XX @@ void hvf_arch_remove_all_hw_breakpoints(void)
532
g_array_remove_range(hw_breakpoints, 0, cur_hw_bps);
533
}
534
}
535
+
536
+/*
537
+ * Update the vCPU with the gdbstub's view of debug registers. This view
538
+ * consists of all hardware breakpoints and watchpoints inserted so far while
539
+ * debugging the guest.
540
+ */
541
+static void hvf_put_gdbstub_debug_registers(CPUState *cpu)
542
+{
543
+ hv_return_t r = HV_SUCCESS;
544
+ int i;
545
+
546
+ for (i = 0; i < cur_hw_bps; i++) {
547
+ HWBreakpoint *bp = get_hw_bp(i);
548
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgbcr_regs[i], bp->bcr);
549
+ assert_hvf_ok(r);
550
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgbvr_regs[i], bp->bvr);
551
+ assert_hvf_ok(r);
552
+ }
553
+ for (i = cur_hw_bps; i < max_hw_bps; i++) {
554
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgbcr_regs[i], 0);
555
+ assert_hvf_ok(r);
556
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgbvr_regs[i], 0);
557
+ assert_hvf_ok(r);
558
+ }
559
+
560
+ for (i = 0; i < cur_hw_wps; i++) {
561
+ HWWatchpoint *wp = get_hw_wp(i);
562
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgwcr_regs[i], wp->wcr);
563
+ assert_hvf_ok(r);
564
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgwvr_regs[i], wp->wvr);
565
+ assert_hvf_ok(r);
566
+ }
567
+ for (i = cur_hw_wps; i < max_hw_wps; i++) {
568
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgwcr_regs[i], 0);
569
+ assert_hvf_ok(r);
570
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgwvr_regs[i], 0);
571
+ assert_hvf_ok(r);
572
+ }
573
+}
574
+
575
+/*
576
+ * Update the vCPU with the guest's view of debug registers. This view is kept
577
+ * in the environment at all times.
578
+ */
579
+static void hvf_put_guest_debug_registers(CPUState *cpu)
580
+{
581
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
582
+ CPUARMState *env = &arm_cpu->env;
583
+ hv_return_t r = HV_SUCCESS;
584
+ int i;
585
+
586
+ for (i = 0; i < max_hw_bps; i++) {
587
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgbcr_regs[i],
588
+ env->cp15.dbgbcr[i]);
589
+ assert_hvf_ok(r);
590
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgbvr_regs[i],
591
+ env->cp15.dbgbvr[i]);
592
+ assert_hvf_ok(r);
593
+ }
594
+
595
+ for (i = 0; i < max_hw_wps; i++) {
596
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgwcr_regs[i],
597
+ env->cp15.dbgwcr[i]);
598
+ assert_hvf_ok(r);
599
+ r = hv_vcpu_set_sys_reg(cpu->hvf->fd, dbgwvr_regs[i],
600
+ env->cp15.dbgwvr[i]);
601
+ assert_hvf_ok(r);
602
+ }
603
+}
604
+
605
+static inline bool hvf_arm_hw_debug_active(CPUState *cpu)
606
+{
607
+ return ((cur_hw_wps > 0) || (cur_hw_bps > 0));
608
+}
609
+
610
+static void hvf_arch_set_traps(void)
611
+{
612
+ CPUState *cpu;
613
+ bool should_enable_traps = false;
614
+ hv_return_t r = HV_SUCCESS;
615
+
616
+ /* Check whether guest debugging is enabled for at least one vCPU; if it
617
+ * is, enable exiting the guest on all vCPUs */
618
+ CPU_FOREACH(cpu) {
619
+ should_enable_traps |= cpu->hvf->guest_debug_enabled;
620
+ }
621
+ CPU_FOREACH(cpu) {
622
+ /* Set whether debug exceptions exit the guest */
623
+ r = hv_vcpu_set_trap_debug_exceptions(cpu->hvf->fd,
624
+ should_enable_traps);
625
+ assert_hvf_ok(r);
626
+
627
+ /* Set whether accesses to debug registers exit the guest */
628
+ r = hv_vcpu_set_trap_debug_reg_accesses(cpu->hvf->fd,
629
+ should_enable_traps);
630
+ assert_hvf_ok(r);
631
+ }
632
+}
633
+
634
+void hvf_arch_update_guest_debug(CPUState *cpu)
635
+{
636
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
637
+ CPUARMState *env = &arm_cpu->env;
638
+
639
+ /* Check whether guest debugging is enabled */
640
+ cpu->hvf->guest_debug_enabled = cpu->singlestep_enabled ||
641
+ hvf_sw_breakpoints_active(cpu) ||
642
+ hvf_arm_hw_debug_active(cpu);
643
+
644
+ /* Update debug registers */
645
+ if (cpu->hvf->guest_debug_enabled) {
646
+ hvf_put_gdbstub_debug_registers(cpu);
647
+ } else {
648
+ hvf_put_guest_debug_registers(cpu);
649
+ }
650
+
651
+ cpu_synchronize_state(cpu);
652
+
653
+ /* Enable/disable single-stepping */
654
+ if (cpu->singlestep_enabled) {
655
+ env->cp15.mdscr_el1 =
656
+ deposit64(env->cp15.mdscr_el1, MDSCR_EL1_SS_SHIFT, 1, 1);
657
+ pstate_write(env, pstate_read(env) | PSTATE_SS);
658
+ } else {
659
+ env->cp15.mdscr_el1 =
660
+ deposit64(env->cp15.mdscr_el1, MDSCR_EL1_SS_SHIFT, 1, 0);
661
+ }
662
+
663
+ /* Enable/disable Breakpoint exceptions */
664
+ if (hvf_arm_hw_debug_active(cpu)) {
665
+ env->cp15.mdscr_el1 =
666
+ deposit64(env->cp15.mdscr_el1, MDSCR_EL1_MDE_SHIFT, 1, 1);
667
+ } else {
668
+ env->cp15.mdscr_el1 =
669
+ deposit64(env->cp15.mdscr_el1, MDSCR_EL1_MDE_SHIFT, 1, 0);
670
+ }
671
+
672
+ hvf_arch_set_traps();
673
+}
674
+
675
+inline bool hvf_arch_supports_guest_debug(void)
676
+{
677
+ return true;
678
+}
679
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
680
index XXXXXXX..XXXXXXX 100644
681
--- a/target/i386/hvf/hvf.c
682
+++ b/target/i386/hvf/hvf.c
683
@@ -XXX,XX +XXX,XX @@ int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len, int type)
684
void hvf_arch_remove_all_hw_breakpoints(void)
685
{
686
}
687
+
688
+void hvf_arch_update_guest_debug(CPUState *cpu)
689
+{
690
+}
691
+
692
+inline bool hvf_arch_supports_guest_debug(void)
693
+{
694
+ return false;
695
+}
696
--
147
--
697
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
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Set the default NaN pattern explicitly for the arm target.
2
This includes setting it for the old linux-user nwfpe emulation.
3
For nwfpe, our default doesn't match the real kernel, but we
4
avoid making a behaviour change in this commit.
2
5
3
While we don't require 16-byte atomicity here, using a single larger
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
operation simplifies the code. Introduce finalize_memop_asimd for this.
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(+)
5
13
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230530191438.411344-6-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/tcg/translate.h | 24 +++++++++++++++++++++++
12
target/arm/tcg/translate-a64.c | 35 +++++++++++-----------------------
13
2 files changed, 35 insertions(+), 24 deletions(-)
14
15
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/tcg/translate.h
16
--- a/linux-user/arm/nwfpe/fpa11.c
18
+++ b/target/arm/tcg/translate.h
17
+++ b/linux-user/arm/nwfpe/fpa11.c
19
@@ -XXX,XX +XXX,XX @@ static inline MemOp finalize_memop_pair(DisasContext *s, MemOp opc)
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
20
return finalize_memop_atom(s, opc, atom);
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);
21
}
27
}
22
28
23
+/**
29
void SetRoundingMode(const unsigned int opcode)
24
+ * finalize_memop_asimd:
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
25
+ * @s: DisasContext
26
+ * @opc: size+sign+align of the memory operation
27
+ *
28
+ * Like finalize_memop_atom, but with atomicity of AccessType_ASIMD.
29
+ */
30
+static inline MemOp finalize_memop_asimd(DisasContext *s, MemOp opc)
31
+{
32
+ /*
33
+ * In the pseudocode for Mem[], with AccessType_ASIMD, size == 16,
34
+ * if IsAligned(8), the first case provides separate atomicity for
35
+ * the pair of 64-bit accesses. If !IsAligned(8), the middle cases
36
+ * do not apply, and we're left with the final case of no atomicity.
37
+ * Thus MO_ATOM_IFALIGN_PAIR.
38
+ *
39
+ * For other sizes, normal LSE2 rules apply.
40
+ */
41
+ if ((opc & MO_SIZE) == MO_128) {
42
+ return finalize_memop_atom(s, opc, MO_ATOM_IFALIGN_PAIR);
43
+ }
44
+ return finalize_memop(s, opc);
45
+}
46
+
47
/**
48
* asimd_imm_const: Expand an encoded SIMD constant value
49
*
50
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
51
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/tcg/translate-a64.c
32
--- a/target/arm/cpu.c
53
+++ b/target/arm/tcg/translate-a64.c
33
+++ b/target/arm/cpu.c
54
@@ -XXX,XX +XXX,XX @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
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)
55
{
41
{
56
/* This writes the bottom N bits of a 128 bit wide vector to memory */
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
57
TCGv_i64 tmplo = tcg_temp_new_i64();
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
58
- MemOp mop;
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
59
+ MemOp mop = finalize_memop_asimd(s, size);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
60
46
+ set_float_default_nan_pattern(0b01000000, s);
61
tcg_gen_ld_i64(tmplo, cpu_env, fp_reg_offset(s, srcidx, MO_64));
62
63
- if (size < 4) {
64
- mop = finalize_memop(s, size);
65
+ if (size < MO_128) {
66
tcg_gen_qemu_st_i64(tmplo, tcg_addr, get_mem_index(s), mop);
67
} else {
68
- bool be = s->be_data == MO_BE;
69
- TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
70
TCGv_i64 tmphi = tcg_temp_new_i64();
71
+ TCGv_i128 t16 = tcg_temp_new_i128();
72
73
tcg_gen_ld_i64(tmphi, cpu_env, fp_reg_hi_offset(s, srcidx));
74
+ tcg_gen_concat_i64_i128(t16, tmplo, tmphi);
75
76
- mop = s->be_data | MO_UQ;
77
- tcg_gen_qemu_st_i64(be ? tmphi : tmplo, tcg_addr, get_mem_index(s),
78
- mop | (s->align_mem ? MO_ALIGN_16 : 0));
79
- tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
80
- tcg_gen_qemu_st_i64(be ? tmplo : tmphi, tcg_hiaddr,
81
- get_mem_index(s), mop);
82
+ tcg_gen_qemu_st_i128(t16, tcg_addr, get_mem_index(s), mop);
83
}
84
}
47
}
85
48
86
@@ -XXX,XX +XXX,XX @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
87
/* This always zero-extends and writes to a full 128 bit wide vector */
88
TCGv_i64 tmplo = tcg_temp_new_i64();
89
TCGv_i64 tmphi = NULL;
90
- MemOp mop;
91
+ MemOp mop = finalize_memop_asimd(s, size);
92
93
- if (size < 4) {
94
- mop = finalize_memop(s, size);
95
+ if (size < MO_128) {
96
tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), mop);
97
} else {
98
- bool be = s->be_data == MO_BE;
99
- TCGv_i64 tcg_hiaddr;
100
+ TCGv_i128 t16 = tcg_temp_new_i128();
101
+
102
+ tcg_gen_qemu_ld_i128(t16, tcg_addr, get_mem_index(s), mop);
103
104
tmphi = tcg_temp_new_i64();
105
- tcg_hiaddr = tcg_temp_new_i64();
106
-
107
- mop = s->be_data | MO_UQ;
108
- tcg_gen_qemu_ld_i64(be ? tmphi : tmplo, tcg_addr, get_mem_index(s),
109
- mop | (s->align_mem ? MO_ALIGN_16 : 0));
110
- tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
111
- tcg_gen_qemu_ld_i64(be ? tmplo : tmphi, tcg_hiaddr,
112
- get_mem_index(s), mop);
113
+ tcg_gen_extr_i128_i64(tmplo, tmphi, t16);
114
}
115
116
tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
117
--
50
--
118
2.34.1
51
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for loongarch.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-42-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/loongarch/tcg/fpu_helper.c
13
+++ b/target/loongarch/tcg/fpu_helper.c
14
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
15
*/
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
17
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
18
+ /* Default NaN: sign bit clear, msb frac bit set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
}
21
22
int ieee_ex_to_loongarch(int xcpt)
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for m68k.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-43-peter.maydell@linaro.org
6
---
7
target/m68k/cpu.c | 2 ++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 3 insertions(+), 1 deletion(-)
10
11
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/m68k/cpu.c
14
+++ b/target/m68k/cpu.c
15
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
16
* preceding paragraph for nonsignaling NaNs.
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
+ /* Default NaN: sign bit clear, all frac bits set */
20
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
21
22
nan = floatx80_default_nan(&env->fp_status);
23
for (i = 0; i < 8; i++) {
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
29
uint8_t dnan_pattern = status->default_nan_pattern;
30
31
if (dnan_pattern == 0) {
32
-#if defined(TARGET_SPARC) || defined(TARGET_M68K)
33
+#if defined(TARGET_SPARC)
34
/* Sign bit clear, all frac bits set */
35
dnan_pattern = 0b01111111;
36
#elif defined(TARGET_HEXAGON)
37
--
38
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Set the default NaN pattern explicitly for MIPS. Note that this
2
is our only target which currently changes the default NaN
3
at runtime (which it was previously doing indirectly when it
4
changed the snan_bit_is_one setting).
2
5
3
With -cpu max and FEAT_LSE2, the __aarch64__ section will only raise
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
an alignment exception when the load crosses a 16-byte boundary.
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(+)
5
13
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230530191438.411344-20-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
tests/tcg/multiarch/sigbus.c | 13 +++++++++----
12
1 file changed, 9 insertions(+), 4 deletions(-)
13
14
diff --git a/tests/tcg/multiarch/sigbus.c b/tests/tcg/multiarch/sigbus.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/tcg/multiarch/sigbus.c
16
--- a/target/mips/fpu_helper.h
17
+++ b/tests/tcg/multiarch/sigbus.c
17
+++ b/target/mips/fpu_helper.h
18
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
#include <endian.h>
19
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
20
20
nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
21
21
set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
22
-unsigned long long x = 0x8877665544332211ull;
22
+ /*
23
-void * volatile p = (void *)&x + 1;
23
+ * With nan2008, the default NaN value has the sign bit clear and the
24
+char x[32] __attribute__((aligned(16))) = {
24
+ * frac msb set; with the older mode, the sign bit is clear, and all
25
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
25
+ * frac bits except the msb are set.
26
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
26
+ */
27
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
27
+ set_float_default_nan_pattern(nan2008 ? 0b01000000 : 0b00111111,
28
+ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
28
+ &env->active_fpu.fp_status);
29
+};
29
30
+void * volatile p = (void *)&x + 15;
30
}
31
31
32
void sigbus(int sig, siginfo_t *info, void *uc)
32
diff --git a/target/mips/msa.c b/target/mips/msa.c
33
{
33
index XXXXXXX..XXXXXXX 100644
34
@@ -XXX,XX +XXX,XX @@ int main()
34
--- a/target/mips/msa.c
35
* We might as well validate the unaligned load worked.
35
+++ b/target/mips/msa.c
36
*/
36
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
37
if (BYTE_ORDER == LITTLE_ENDIAN) {
37
/* Inf * 0 + NaN returns the input NaN */
38
- assert(tmp == 0x55443322);
38
set_float_infzeronan_rule(float_infzeronan_dnan_never,
39
+ assert(tmp == 0x13121110);
39
&env->active_tc.msa_fp_status);
40
} else {
40
+ /* Default NaN: sign bit clear, frac msb set */
41
- assert(tmp == 0x77665544);
41
+ set_float_default_nan_pattern(0b01000000,
42
+ assert(tmp == 0x10111213);
42
+ &env->active_tc.msa_fp_status);
43
}
44
return EXIT_SUCCESS;
45
}
43
}
46
--
44
--
47
2.34.1
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
1
From: qianfan Zhao <qianfanguijin@163.com>
1
Set the default NaN pattern explicitly for ppc.
2
2
3
R40 has two ethernet controllers named as emac and gmac. The emac is
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
compatibled with A10, and the GMAC is compatibled with H3.
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(+)
5
9
6
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
include/hw/arm/allwinner-r40.h | 6 ++++
10
hw/arm/allwinner-r40.c | 50 ++++++++++++++++++++++++++++++++--
11
hw/arm/bananapi_m2u.c | 3 ++
12
3 files changed, 57 insertions(+), 2 deletions(-)
13
14
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
15
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/allwinner-r40.h
12
--- a/target/ppc/cpu_init.c
17
+++ b/include/hw/arm/allwinner-r40.h
13
+++ b/target/ppc/cpu_init.c
18
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
19
#include "hw/misc/allwinner-r40-ccu.h"
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
#include "hw/misc/allwinner-r40-dramc.h"
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
21
#include "hw/i2c/allwinner-i2c.h"
17
22
+#include "hw/net/allwinner_emac.h"
18
+ /* Default NaN: sign bit clear, set frac msb */
23
+#include "hw/net/allwinner-sun8i-emac.h"
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
24
#include "target/arm/cpu.h"
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
25
#include "sysemu/block-backend.h"
26
27
@@ -XXX,XX +XXX,XX @@ enum {
28
AW_R40_DEV_SRAM_A2,
29
AW_R40_DEV_SRAM_A3,
30
AW_R40_DEV_SRAM_A4,
31
+ AW_R40_DEV_EMAC,
32
AW_R40_DEV_MMC0,
33
AW_R40_DEV_MMC1,
34
AW_R40_DEV_MMC2,
35
@@ -XXX,XX +XXX,XX @@ enum {
36
AW_R40_DEV_UART6,
37
AW_R40_DEV_UART7,
38
AW_R40_DEV_TWI0,
39
+ AW_R40_DEV_GMAC,
40
AW_R40_DEV_GIC_DIST,
41
AW_R40_DEV_GIC_CPU,
42
AW_R40_DEV_GIC_HYP,
43
@@ -XXX,XX +XXX,XX @@ struct AwR40State {
44
AwR40ClockCtlState ccu;
45
AwR40DramCtlState dramc;
46
AWI2CState i2c0;
47
+ AwEmacState emac;
48
+ AwSun8iEmacState gmac;
49
GICState gic;
50
MemoryRegion sram_a1;
51
MemoryRegion sram_a2;
52
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/allwinner-r40.c
55
+++ b/hw/arm/allwinner-r40.c
56
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_r40_memmap[] = {
57
[AW_R40_DEV_SRAM_A2] = 0x00004000,
58
[AW_R40_DEV_SRAM_A3] = 0x00008000,
59
[AW_R40_DEV_SRAM_A4] = 0x0000b400,
60
+ [AW_R40_DEV_EMAC] = 0x01c0b000,
61
[AW_R40_DEV_MMC0] = 0x01c0f000,
62
[AW_R40_DEV_MMC1] = 0x01c10000,
63
[AW_R40_DEV_MMC2] = 0x01c11000,
64
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_r40_memmap[] = {
65
[AW_R40_DEV_UART6] = 0x01c29800,
66
[AW_R40_DEV_UART7] = 0x01c29c00,
67
[AW_R40_DEV_TWI0] = 0x01c2ac00,
68
+ [AW_R40_DEV_GMAC] = 0x01c50000,
69
[AW_R40_DEV_DRAMCOM] = 0x01c62000,
70
[AW_R40_DEV_DRAMCTL] = 0x01c63000,
71
[AW_R40_DEV_DRAMPHY] = 0x01c65000,
72
@@ -XXX,XX +XXX,XX @@ static struct AwR40Unimplemented r40_unimplemented[] = {
73
{ "spi1", 0x01c06000, 4 * KiB },
74
{ "cs0", 0x01c09000, 4 * KiB },
75
{ "keymem", 0x01c0a000, 4 * KiB },
76
- { "emac", 0x01c0b000, 4 * KiB },
77
{ "usb0-otg", 0x01c13000, 4 * KiB },
78
{ "usb0-host", 0x01c14000, 4 * KiB },
79
{ "crypto", 0x01c15000, 4 * KiB },
80
@@ -XXX,XX +XXX,XX @@ static struct AwR40Unimplemented r40_unimplemented[] = {
81
{ "tvd2", 0x01c33000, 4 * KiB },
82
{ "tvd3", 0x01c34000, 4 * KiB },
83
{ "gpu", 0x01c40000, 64 * KiB },
84
- { "gmac", 0x01c50000, 64 * KiB },
85
{ "hstmr", 0x01c60000, 4 * KiB },
86
{ "tcon-top", 0x01c70000, 4 * KiB },
87
{ "lcd0", 0x01c71000, 4 * KiB },
88
@@ -XXX,XX +XXX,XX @@ enum {
89
AW_R40_GIC_SPI_MMC1 = 33,
90
AW_R40_GIC_SPI_MMC2 = 34,
91
AW_R40_GIC_SPI_MMC3 = 35,
92
+ AW_R40_GIC_SPI_EMAC = 55,
93
+ AW_R40_GIC_SPI_GMAC = 85,
94
};
95
96
/* Allwinner R40 general constants */
97
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_init(Object *obj)
98
99
object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
100
101
+ object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
102
+ object_initialize_child(obj, "gmac", &s->gmac, TYPE_AW_SUN8I_EMAC);
103
+ object_property_add_alias(obj, "gmac-phy-addr",
104
+ OBJECT(&s->gmac), "phy-addr");
105
+
21
+
106
object_initialize_child(obj, "dramc", &s->dramc, TYPE_AW_R40_DRAMC);
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
107
object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc),
23
ppc_spr_t *spr = &env->spr_cb[i];
108
"ram-addr");
109
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_init(Object *obj)
110
111
static void allwinner_r40_realize(DeviceState *dev, Error **errp)
112
{
113
+ const char *r40_nic_models[] = { "gmac", "emac", NULL };
114
AwR40State *s = AW_R40(dev);
115
unsigned i;
116
117
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_realize(DeviceState *dev, Error **errp)
118
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2,
119
s->memmap[AW_R40_DEV_DRAMPHY]);
120
121
+ /* nic support gmac and emac */
122
+ for (int i = 0; i < ARRAY_SIZE(r40_nic_models) - 1; i++) {
123
+ NICInfo *nic = &nd_table[i];
124
+
125
+ if (!nic->used) {
126
+ continue;
127
+ }
128
+ if (qemu_show_nic_models(nic->model, r40_nic_models)) {
129
+ exit(0);
130
+ }
131
+
132
+ switch (qemu_find_nic_model(nic, r40_nic_models, r40_nic_models[0])) {
133
+ case 0: /* gmac */
134
+ qdev_set_nic_properties(DEVICE(&s->gmac), nic);
135
+ break;
136
+ case 1: /* emac */
137
+ qdev_set_nic_properties(DEVICE(&s->emac), nic);
138
+ break;
139
+ default:
140
+ exit(1);
141
+ break;
142
+ }
143
+ }
144
+
145
+ /* GMAC */
146
+ object_property_set_link(OBJECT(&s->gmac), "dma-memory",
147
+ OBJECT(get_system_memory()), &error_fatal);
148
+ sysbus_realize(SYS_BUS_DEVICE(&s->gmac), &error_fatal);
149
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gmac), 0, s->memmap[AW_R40_DEV_GMAC]);
150
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gmac), 0,
151
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_GMAC));
152
+
153
+ /* EMAC */
154
+ sysbus_realize(SYS_BUS_DEVICE(&s->emac), &error_fatal);
155
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->emac), 0, s->memmap[AW_R40_DEV_EMAC]);
156
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->emac), 0,
157
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_EMAC));
158
+
159
/* Unimplemented devices */
160
for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
161
create_unimplemented_device(r40_unimplemented[i].device_name,
162
diff --git a/hw/arm/bananapi_m2u.c b/hw/arm/bananapi_m2u.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/hw/arm/bananapi_m2u.c
165
+++ b/hw/arm/bananapi_m2u.c
166
@@ -XXX,XX +XXX,XX @@ static void bpim2u_init(MachineState *machine)
167
object_property_set_int(OBJECT(r40), "ram-size",
168
r40->ram_size, &error_abort);
169
170
+ /* GMAC PHY */
171
+ object_property_set_uint(OBJECT(r40), "gmac-phy-addr", 1, &error_abort);
172
+
173
/* Mark R40 object realized */
174
qdev_realize(DEVICE(r40), NULL, &error_abort);
175
24
176
--
25
--
177
2.34.1
26
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
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.
2
4
3
Fixes a bug in that with SCTLR.A set, we should raise any
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
alignment fault before raising any MTE check fault.
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(+)
5
11
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230530191438.411344-15-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/internals.h | 3 ++-
12
target/arm/tcg/mte_helper.c | 18 ++++++++++++++++++
13
target/arm/tcg/translate-a64.c | 2 ++
14
3 files changed, 22 insertions(+), 1 deletion(-)
15
16
diff --git a/target/arm/internals.h b/target/arm/internals.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/internals.h
14
--- a/target/sh4/cpu.c
19
+++ b/target/arm/internals.h
15
+++ b/target/sh4/cpu.c
20
@@ -XXX,XX +XXX,XX @@ FIELD(MTEDESC, MIDX, 0, 4)
16
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
21
FIELD(MTEDESC, TBI, 4, 2)
17
set_flush_to_zero(1, &env->fp_status);
22
FIELD(MTEDESC, TCMA, 6, 2)
18
#endif
23
FIELD(MTEDESC, WRITE, 8, 1)
19
set_default_nan_mode(1, &env->fp_status);
24
-FIELD(MTEDESC, SIZEM1, 9, SIMD_DATA_BITS - 9) /* size - 1 */
20
+ /* sign bit clear, set all frac bits other than msb */
25
+FIELD(MTEDESC, ALIGN, 9, 3)
21
+ set_float_default_nan_pattern(0b00111111, &env->fp_status);
26
+FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12) /* size - 1 */
27
28
bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr);
29
uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra);
30
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/tcg/mte_helper.c
33
+++ b/target/arm/tcg/mte_helper.c
34
@@ -XXX,XX +XXX,XX @@ uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra)
35
36
uint64_t HELPER(mte_check)(CPUARMState *env, uint32_t desc, uint64_t ptr)
37
{
38
+ /*
39
+ * R_XCHFJ: Alignment check not caused by memory type is priority 1,
40
+ * higher than any translation fault. When MTE is disabled, tcg
41
+ * performs the alignment check during the code generated for the
42
+ * memory access. With MTE enabled, we must check this here before
43
+ * raising any translation fault in allocation_tag_mem.
44
+ */
45
+ unsigned align = FIELD_EX32(desc, MTEDESC, ALIGN);
46
+ if (unlikely(align)) {
47
+ align = (1u << align) - 1;
48
+ if (unlikely(ptr & align)) {
49
+ int idx = FIELD_EX32(desc, MTEDESC, MIDX);
50
+ bool w = FIELD_EX32(desc, MTEDESC, WRITE);
51
+ MMUAccessType type = w ? MMU_DATA_STORE : MMU_DATA_LOAD;
52
+ arm_cpu_do_unaligned_access(env_cpu(env), ptr, type, idx, GETPC());
53
+ }
54
+ }
55
+
56
return mte_check(env, desc, ptr, GETPC());
57
}
22
}
58
23
59
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
24
static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/tcg/translate-a64.c
62
+++ b/target/arm/tcg/translate-a64.c
63
@@ -XXX,XX +XXX,XX @@ static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, TCGv_i64 addr,
64
desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
65
desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
66
desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
67
+ desc = FIELD_DP32(desc, MTEDESC, ALIGN, get_alignment_bits(memop));
68
desc = FIELD_DP32(desc, MTEDESC, SIZEM1, memop_size(memop) - 1);
69
70
ret = tcg_temp_new_i64();
71
@@ -XXX,XX +XXX,XX @@ TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
72
desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
73
desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
74
desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
75
+ desc = FIELD_DP32(desc, MTEDESC, ALIGN, get_alignment_bits(single_mop));
76
desc = FIELD_DP32(desc, MTEDESC, SIZEM1, total_size - 1);
77
78
ret = tcg_temp_new_i64();
79
--
25
--
80
2.34.1
26
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Set the default NaN pattern explicitly for rx.
2
2
3
No need to duplicate this check across multiple call sites.
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(+)
4
9
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230530191438.411344-9-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/tcg/translate-a64.c | 44 ++++++++++++++++------------------
11
1 file changed, 21 insertions(+), 23 deletions(-)
12
13
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/translate-a64.c
12
--- a/target/rx/cpu.c
16
+++ b/target/arm/tcg/translate-a64.c
13
+++ b/target/rx/cpu.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
18
* races in multi-threaded linux-user and when MTTCG softmmu is
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
19
* enabled.
16
*/
20
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
21
-static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
18
+ /* Default NaN value: sign bit clear, set frac msb */
22
- TCGv_i64 addr, int size, bool is_pair)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
23
+static void gen_load_exclusive(DisasContext *s, int rt, int rt2, int rn,
24
+ int size, bool is_pair)
25
{
26
int idx = get_mem_index(s);
27
MemOp memop;
28
+ TCGv_i64 dirty_addr, clean_addr;
29
+
30
+ s->is_ldex = true;
31
+ dirty_addr = cpu_reg_sp(s, rn);
32
+ clean_addr = gen_mte_check1(s, dirty_addr, false, rn != 31, size);
33
34
g_assert(size <= 3);
35
if (is_pair) {
36
@@ -XXX,XX +XXX,XX @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
37
if (size == 2) {
38
/* The pair must be single-copy atomic for the doubleword. */
39
memop = finalize_memop(s, MO_64 | MO_ALIGN);
40
- tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
41
+ tcg_gen_qemu_ld_i64(cpu_exclusive_val, clean_addr, idx, memop);
42
if (s->be_data == MO_LE) {
43
tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
44
tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 32, 32);
45
@@ -XXX,XX +XXX,XX @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
46
47
memop = finalize_memop_atom(s, MO_128 | MO_ALIGN_16,
48
MO_ATOM_IFALIGN_PAIR);
49
- tcg_gen_qemu_ld_i128(t16, addr, idx, memop);
50
+ tcg_gen_qemu_ld_i128(t16, clean_addr, idx, memop);
51
52
if (s->be_data == MO_LE) {
53
tcg_gen_extr_i128_i64(cpu_exclusive_val,
54
@@ -XXX,XX +XXX,XX @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
55
}
56
} else {
57
memop = finalize_memop(s, size | MO_ALIGN);
58
- tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
59
+ tcg_gen_qemu_ld_i64(cpu_exclusive_val, clean_addr, idx, memop);
60
tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
61
}
62
- tcg_gen_mov_i64(cpu_exclusive_addr, addr);
63
+ tcg_gen_mov_i64(cpu_exclusive_addr, clean_addr);
64
}
20
}
65
21
66
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
67
- TCGv_i64 addr, int size, int is_pair)
68
+ int rn, int size, int is_pair)
69
{
70
/* if (env->exclusive_addr == addr && env->exclusive_val == [addr]
71
* && (!is_pair || env->exclusive_high == [addr + datasize])) {
72
@@ -XXX,XX +XXX,XX @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
73
*/
74
TCGLabel *fail_label = gen_new_label();
75
TCGLabel *done_label = gen_new_label();
76
- TCGv_i64 tmp;
77
+ TCGv_i64 tmp, dirty_addr, clean_addr;
78
79
- tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
80
+ dirty_addr = cpu_reg_sp(s, rn);
81
+ clean_addr = gen_mte_check1(s, dirty_addr, true, rn != 31, size);
82
+
83
+ tcg_gen_brcond_i64(TCG_COND_NE, clean_addr, cpu_exclusive_addr, fail_label);
84
85
tmp = tcg_temp_new_i64();
86
if (is_pair) {
87
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
88
if (is_lasr) {
89
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
90
}
91
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
92
- true, rn != 31, size);
93
- gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, false);
94
+ gen_store_exclusive(s, rs, rt, rt2, rn, size, false);
95
return;
96
97
case 0x4: /* LDXR */
98
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
99
if (rn == 31) {
100
gen_check_sp_alignment(s);
101
}
102
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
103
- false, rn != 31, size);
104
- s->is_ldex = true;
105
- gen_load_exclusive(s, rt, rt2, clean_addr, size, false);
106
+ gen_load_exclusive(s, rt, rt2, rn, size, false);
107
if (is_lasr) {
108
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
109
}
110
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
111
if (is_lasr) {
112
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
113
}
114
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
115
- true, rn != 31, size);
116
- gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, true);
117
+ gen_store_exclusive(s, rs, rt, rt2, rn, size, true);
118
return;
119
}
120
if (rt2 == 31
121
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
122
if (rn == 31) {
123
gen_check_sp_alignment(s);
124
}
125
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
126
- false, rn != 31, size);
127
- s->is_ldex = true;
128
- gen_load_exclusive(s, rt, rt2, clean_addr, size, true);
129
+ gen_load_exclusive(s, rt, rt2, rn, size, true);
130
if (is_lasr) {
131
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
132
}
133
--
23
--
134
2.34.1
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
1
From: qianfan Zhao <qianfanguijin@163.com>
1
Set the default NaN pattern explicitly for SPARC, and remove
2
the ifdef from parts64_default_nan.
2
3
3
Add documents for Banana Pi M2U
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(-)
4
11
5
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
6
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
7
[PMM: Minor format fixes to correct sphinx errors]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
docs/system/arm/bananapi_m2u.rst | 139 +++++++++++++++++++++++++++++++
11
docs/system/target-arm.rst | 1 +
12
2 files changed, 140 insertions(+)
13
create mode 100644 docs/system/arm/bananapi_m2u.rst
14
15
diff --git a/docs/system/arm/bananapi_m2u.rst b/docs/system/arm/bananapi_m2u.rst
16
new file mode 100644
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/docs/system/arm/bananapi_m2u.rst
20
@@ -XXX,XX +XXX,XX @@
21
+Banana Pi BPI-M2U (``bpim2u``)
22
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23
+
24
+Banana Pi BPI-M2 Ultra is a quad-core mini single board computer built with
25
+Allwinner A40i/R40/V40 SoC. It features 2GB of RAM and 8GB eMMC. It also
26
+has onboard WiFi and BT. On the ports side, the BPI-M2 Ultra has 2 USB A
27
+2.0 ports, 1 USB OTG port, 1 HDMI port, 1 audio jack, a DC power port,
28
+and last but not least, a SATA port.
29
+
30
+Supported devices
31
+"""""""""""""""""
32
+
33
+The Banana Pi M2U machine supports the following devices:
34
+
35
+ * SMP (Quad Core Cortex-A7)
36
+ * Generic Interrupt Controller configuration
37
+ * SRAM mappings
38
+ * SDRAM controller
39
+ * Timer device (re-used from Allwinner A10)
40
+ * UART
41
+ * SD/MMC storage controller
42
+ * EMAC ethernet
43
+ * GMAC ethernet
44
+ * Clock Control Unit
45
+ * TWI (I2C)
46
+
47
+Limitations
48
+"""""""""""
49
+
50
+Currently, Banana Pi M2U does *not* support the following features:
51
+
52
+- Graphical output via HDMI, GPU and/or the Display Engine
53
+- Audio output
54
+- Hardware Watchdog
55
+- Real Time Clock
56
+- USB 2.0 interfaces
57
+
58
+Also see the 'unimplemented' array in the Allwinner R40 SoC module
59
+for a complete list of unimplemented I/O devices: ``./hw/arm/allwinner-r40.c``
60
+
61
+Boot options
62
+""""""""""""
63
+
64
+The Banana Pi M2U machine can start using the standard -kernel functionality
65
+for loading a Linux kernel or ELF executable. Additionally, the Banana Pi M2U
66
+machine can also emulate the BootROM which is present on an actual Allwinner R40
67
+based SoC, which loads the bootloader from a SD card, specified via the -sd
68
+argument to qemu-system-arm.
69
+
70
+Running mainline Linux
71
+""""""""""""""""""""""
72
+
73
+To build a Linux mainline kernel that can be booted by the Banana Pi M2U machine,
74
+simply configure the kernel using the sunxi_defconfig configuration:
75
+
76
+.. code-block:: bash
77
+
78
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make mrproper
79
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make sunxi_defconfig
80
+
81
+To boot the newly build linux kernel in QEMU with the Banana Pi M2U machine, use:
82
+
83
+.. code-block:: bash
84
+
85
+ $ qemu-system-arm -M bpim2u -nographic \
86
+ -kernel /path/to/linux/arch/arm/boot/zImage \
87
+ -append 'console=ttyS0,115200' \
88
+ -dtb /path/to/linux/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dtb
89
+
90
+Banana Pi M2U images
91
+""""""""""""""""""""
92
+
93
+Note that the mainline kernel does not have a root filesystem. You can choose
94
+to build you own image with buildroot using the bananapi_m2_ultra_defconfig.
95
+Also see https://buildroot.org for more information.
96
+
97
+Another possibility is to run an OpenWrt image for Banana Pi M2U which
98
+can be downloaded from:
99
+
100
+ https://downloads.openwrt.org/releases/22.03.3/targets/sunxi/cortexa7/
101
+
102
+When using an image as an SD card, it must be resized to a power of two. This can be
103
+done with the ``qemu-img`` command. It is recommended to only increase the image size
104
+instead of shrinking it to a power of two, to avoid loss of data. For example,
105
+to prepare a downloaded Armbian image, first extract it and then increase
106
+its size to one gigabyte as follows:
107
+
108
+.. code-block:: bash
109
+
110
+ $ qemu-img resize \
111
+ openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img \
112
+ 1G
113
+
114
+Instead of providing a custom Linux kernel via the -kernel command you may also
115
+choose to let the Banana Pi M2U machine load the bootloader from SD card, just like
116
+a real board would do using the BootROM. Simply pass the selected image via the -sd
117
+argument and remove the -kernel, -append, -dbt and -initrd arguments:
118
+
119
+.. code-block:: bash
120
+
121
+ $ qemu-system-arm -M bpim2u -nic user -nographic \
122
+ -sd openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img
123
+
124
+Running U-Boot
125
+""""""""""""""
126
+
127
+U-Boot mainline can be build and configured using the Bananapi_M2_Ultra_defconfig
128
+using similar commands as describe above for Linux. Note that it is recommended
129
+for development/testing to select the following configuration setting in U-Boot:
130
+
131
+ Device Tree Control > Provider for DTB for DT Control > Embedded DTB
132
+
133
+The BootROM of allwinner R40 loading u-boot from the 8KiB offset of sdcard.
134
+Let's create an bootable disk image:
135
+
136
+.. code-block:: bash
137
+
138
+ $ dd if=/dev/zero of=sd.img bs=32M count=1
139
+ $ dd if=u-boot-sunxi-with-spl.bin of=sd.img bs=1k seek=8 conv=notrunc
140
+
141
+And then boot it.
142
+
143
+.. code-block:: bash
144
+
145
+ $ qemu-system-arm -M bpim2u -nographic -sd sd.img
146
+
147
+Banana Pi M2U integration tests
148
+"""""""""""""""""""""""""""""""
149
+
150
+The Banana Pi M2U machine has several integration tests included.
151
+To run the whole set of tests, build QEMU from source and simply
152
+provide the following command:
153
+
154
+.. code-block:: bash
155
+
156
+ $ cd qemu-build-dir
157
+ $ AVOCADO_ALLOW_LARGE_STORAGE=yes tests/venv/bin/avocado \
158
+ --verbose --show=app,console run -t machine:bpim2u \
159
+ ../tests/avocado/boot_linux_console.py
160
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
161
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
162
--- a/docs/system/target-arm.rst
14
--- a/target/sparc/cpu.c
163
+++ b/docs/system/target-arm.rst
15
+++ b/target/sparc/cpu.c
164
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
165
arm/versatile
17
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
166
arm/vexpress
18
/* For inf * 0 + NaN, return the input NaN */
167
arm/aspeed
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
168
+ arm/bananapi_m2u.rst
20
+ /* Default NaN value: sign bit clear, all frac bits set */
169
arm/sabrelite
21
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
170
arm/digic
22
171
arm/cubieboard
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
172
--
41
--
173
2.34.1
42
2.34.1
diff view generated by jsdifflib
1
From: qianfan Zhao <qianfanguijin@163.com>
1
Set the default NaN pattern explicitly for xtensa.
2
2
3
Only a few important registers are added, especially the SRAM_VER
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
register.
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(+)
5
9
6
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
7
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
include/hw/arm/allwinner-r40.h | 3 +
11
include/hw/misc/allwinner-sramc.h | 69 +++++++++++
12
hw/arm/allwinner-r40.c | 7 +-
13
hw/misc/allwinner-sramc.c | 184 ++++++++++++++++++++++++++++++
14
hw/arm/Kconfig | 1 +
15
hw/misc/Kconfig | 3 +
16
hw/misc/meson.build | 1 +
17
hw/misc/trace-events | 4 +
18
8 files changed, 271 insertions(+), 1 deletion(-)
19
create mode 100644 include/hw/misc/allwinner-sramc.h
20
create mode 100644 hw/misc/allwinner-sramc.c
21
22
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
23
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/arm/allwinner-r40.h
12
--- a/target/xtensa/cpu.c
25
+++ b/include/hw/arm/allwinner-r40.h
13
+++ b/target/xtensa/cpu.c
26
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
27
#include "hw/sd/allwinner-sdhost.h"
15
/* For inf * 0 + NaN, return the input NaN */
28
#include "hw/misc/allwinner-r40-ccu.h"
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
29
#include "hw/misc/allwinner-r40-dramc.h"
17
set_no_signaling_nans(!dfpu, &env->fp_status);
30
+#include "hw/misc/allwinner-sramc.h"
18
+ /* Default NaN value: sign bit clear, set frac msb */
31
#include "hw/i2c/allwinner-i2c.h"
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
32
#include "hw/net/allwinner_emac.h"
20
xtensa_use_first_nan(env, !dfpu);
33
#include "hw/net/allwinner-sun8i-emac.h"
34
@@ -XXX,XX +XXX,XX @@ enum {
35
AW_R40_DEV_SRAM_A2,
36
AW_R40_DEV_SRAM_A3,
37
AW_R40_DEV_SRAM_A4,
38
+ AW_R40_DEV_SRAMC,
39
AW_R40_DEV_EMAC,
40
AW_R40_DEV_MMC0,
41
AW_R40_DEV_MMC1,
42
@@ -XXX,XX +XXX,XX @@ struct AwR40State {
43
44
ARMCPU cpus[AW_R40_NUM_CPUS];
45
const hwaddr *memmap;
46
+ AwSRAMCState sramc;
47
AwA10PITState timer;
48
AwSdHostState mmc[AW_R40_NUM_MMCS];
49
AwR40ClockCtlState ccu;
50
diff --git a/include/hw/misc/allwinner-sramc.h b/include/hw/misc/allwinner-sramc.h
51
new file mode 100644
52
index XXXXXXX..XXXXXXX
53
--- /dev/null
54
+++ b/include/hw/misc/allwinner-sramc.h
55
@@ -XXX,XX +XXX,XX @@
56
+/*
57
+ * Allwinner SRAM controller emulation
58
+ *
59
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
60
+ *
61
+ * This program is free software: you can redistribute it and/or modify
62
+ * it under the terms of the GNU General Public License as published by
63
+ * the Free Software Foundation, either version 2 of the License, or
64
+ * (at your option) any later version.
65
+ *
66
+ * This program is distributed in the hope that it will be useful,
67
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
68
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69
+ * GNU General Public License for more details.
70
+ *
71
+ * You should have received a copy of the GNU General Public License
72
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
73
+ */
74
+
75
+#ifndef HW_MISC_ALLWINNER_SRAMC_H
76
+#define HW_MISC_ALLWINNER_SRAMC_H
77
+
78
+#include "qom/object.h"
79
+#include "hw/sysbus.h"
80
+#include "qemu/uuid.h"
81
+
82
+/**
83
+ * Object model
84
+ * @{
85
+ */
86
+#define TYPE_AW_SRAMC "allwinner-sramc"
87
+#define TYPE_AW_SRAMC_SUN8I_R40 TYPE_AW_SRAMC "-sun8i-r40"
88
+OBJECT_DECLARE_TYPE(AwSRAMCState, AwSRAMCClass, AW_SRAMC)
89
+
90
+/** @} */
91
+
92
+/**
93
+ * Allwinner SRAMC object instance state
94
+ */
95
+struct AwSRAMCState {
96
+ /*< private >*/
97
+ SysBusDevice parent_obj;
98
+ /*< public >*/
99
+
100
+ /** Maps I/O registers in physical memory */
101
+ MemoryRegion iomem;
102
+
103
+ /* registers */
104
+ uint32_t sram_ctl1;
105
+ uint32_t sram_ver;
106
+ uint32_t sram_soft_entry_reg0;
107
+};
108
+
109
+/**
110
+ * Allwinner SRAM Controller class-level struct.
111
+ *
112
+ * This struct is filled by each sunxi device specific code
113
+ * such that the generic code can use this struct to support
114
+ * all devices.
115
+ */
116
+struct AwSRAMCClass {
117
+ /*< private >*/
118
+ SysBusDeviceClass parent_class;
119
+ /*< public >*/
120
+
121
+ uint32_t sram_version_code;
122
+};
123
+
124
+#endif /* HW_MISC_ALLWINNER_SRAMC_H */
125
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/hw/arm/allwinner-r40.c
128
+++ b/hw/arm/allwinner-r40.c
129
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_r40_memmap[] = {
130
[AW_R40_DEV_SRAM_A2] = 0x00004000,
131
[AW_R40_DEV_SRAM_A3] = 0x00008000,
132
[AW_R40_DEV_SRAM_A4] = 0x0000b400,
133
+ [AW_R40_DEV_SRAMC] = 0x01c00000,
134
[AW_R40_DEV_EMAC] = 0x01c0b000,
135
[AW_R40_DEV_MMC0] = 0x01c0f000,
136
[AW_R40_DEV_MMC1] = 0x01c10000,
137
@@ -XXX,XX +XXX,XX @@ struct AwR40Unimplemented {
138
static struct AwR40Unimplemented r40_unimplemented[] = {
139
{ "d-engine", 0x01000000, 4 * MiB },
140
{ "d-inter", 0x01400000, 128 * KiB },
141
- { "sram-c", 0x01c00000, 4 * KiB },
142
{ "dma", 0x01c02000, 4 * KiB },
143
{ "nfdc", 0x01c03000, 4 * KiB },
144
{ "ts", 0x01c04000, 4 * KiB },
145
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_init(Object *obj)
146
"ram-addr");
147
object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
148
"ram-size");
149
+
150
+ object_initialize_child(obj, "sramc", &s->sramc, TYPE_AW_SRAMC_SUN8I_R40);
151
}
21
}
152
22
153
static void allwinner_r40_realize(DeviceState *dev, Error **errp)
154
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_realize(DeviceState *dev, Error **errp)
155
AW_R40_GIC_SPI_TIMER1));
156
157
/* SRAM */
158
+ sysbus_realize(SYS_BUS_DEVICE(&s->sramc), &error_fatal);
159
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sramc), 0, s->memmap[AW_R40_DEV_SRAMC]);
160
+
161
memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
162
16 * KiB, &error_abort);
163
memory_region_init_ram(&s->sram_a2, OBJECT(dev), "sram A2",
164
diff --git a/hw/misc/allwinner-sramc.c b/hw/misc/allwinner-sramc.c
165
new file mode 100644
166
index XXXXXXX..XXXXXXX
167
--- /dev/null
168
+++ b/hw/misc/allwinner-sramc.c
169
@@ -XXX,XX +XXX,XX @@
170
+/*
171
+ * Allwinner R40 SRAM controller emulation
172
+ *
173
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
174
+ *
175
+ * This program is free software: you can redistribute it and/or modify
176
+ * it under the terms of the GNU General Public License as published by
177
+ * the Free Software Foundation, either version 2 of the License, or
178
+ * (at your option) any later version.
179
+ *
180
+ * This program is distributed in the hope that it will be useful,
181
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
182
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
183
+ * GNU General Public License for more details.
184
+ *
185
+ * You should have received a copy of the GNU General Public License
186
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
187
+ */
188
+
189
+#include "qemu/osdep.h"
190
+#include "qemu/units.h"
191
+#include "hw/sysbus.h"
192
+#include "migration/vmstate.h"
193
+#include "qemu/log.h"
194
+#include "qemu/module.h"
195
+#include "qapi/error.h"
196
+#include "hw/qdev-properties.h"
197
+#include "hw/qdev-properties-system.h"
198
+#include "hw/misc/allwinner-sramc.h"
199
+#include "trace.h"
200
+
201
+/*
202
+ * register offsets
203
+ * https://linux-sunxi.org/SRAM_Controller_Register_Guide
204
+ */
205
+enum {
206
+ REG_SRAM_CTL1_CFG = 0x04, /* SRAM Control register 1 */
207
+ REG_SRAM_VER = 0x24, /* SRAM Version register */
208
+ REG_SRAM_R40_SOFT_ENTRY_REG0 = 0xbc,
209
+};
210
+
211
+/* REG_SRAMC_VERSION bit defines */
212
+#define SRAM_VER_READ_ENABLE (1 << 15)
213
+#define SRAM_VER_VERSION_SHIFT 16
214
+#define SRAM_VERSION_SUN8I_R40 0x1701
215
+
216
+static uint64_t allwinner_sramc_read(void *opaque, hwaddr offset,
217
+ unsigned size)
218
+{
219
+ AwSRAMCState *s = AW_SRAMC(opaque);
220
+ AwSRAMCClass *sc = AW_SRAMC_GET_CLASS(s);
221
+ uint64_t val = 0;
222
+
223
+ switch (offset) {
224
+ case REG_SRAM_CTL1_CFG:
225
+ val = s->sram_ctl1;
226
+ break;
227
+ case REG_SRAM_VER:
228
+ /* bit15: lock bit, set this bit before reading this register */
229
+ if (s->sram_ver & SRAM_VER_READ_ENABLE) {
230
+ val = SRAM_VER_READ_ENABLE |
231
+ (sc->sram_version_code << SRAM_VER_VERSION_SHIFT);
232
+ }
233
+ break;
234
+ case REG_SRAM_R40_SOFT_ENTRY_REG0:
235
+ val = s->sram_soft_entry_reg0;
236
+ break;
237
+ default:
238
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
239
+ __func__, (uint32_t)offset);
240
+ return 0;
241
+ }
242
+
243
+ trace_allwinner_sramc_read(offset, val);
244
+
245
+ return val;
246
+}
247
+
248
+static void allwinner_sramc_write(void *opaque, hwaddr offset,
249
+ uint64_t val, unsigned size)
250
+{
251
+ AwSRAMCState *s = AW_SRAMC(opaque);
252
+
253
+ trace_allwinner_sramc_write(offset, val);
254
+
255
+ switch (offset) {
256
+ case REG_SRAM_CTL1_CFG:
257
+ s->sram_ctl1 = val;
258
+ break;
259
+ case REG_SRAM_VER:
260
+ /* Only the READ_ENABLE bit is writeable */
261
+ s->sram_ver = val & SRAM_VER_READ_ENABLE;
262
+ break;
263
+ case REG_SRAM_R40_SOFT_ENTRY_REG0:
264
+ s->sram_soft_entry_reg0 = val;
265
+ break;
266
+ default:
267
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
268
+ __func__, (uint32_t)offset);
269
+ break;
270
+ }
271
+}
272
+
273
+static const MemoryRegionOps allwinner_sramc_ops = {
274
+ .read = allwinner_sramc_read,
275
+ .write = allwinner_sramc_write,
276
+ .endianness = DEVICE_NATIVE_ENDIAN,
277
+ .valid = {
278
+ .min_access_size = 4,
279
+ .max_access_size = 4,
280
+ },
281
+ .impl.min_access_size = 4,
282
+};
283
+
284
+static const VMStateDescription allwinner_sramc_vmstate = {
285
+ .name = "allwinner-sramc",
286
+ .version_id = 1,
287
+ .minimum_version_id = 1,
288
+ .fields = (VMStateField[]) {
289
+ VMSTATE_UINT32(sram_ver, AwSRAMCState),
290
+ VMSTATE_UINT32(sram_soft_entry_reg0, AwSRAMCState),
291
+ VMSTATE_END_OF_LIST()
292
+ }
293
+};
294
+
295
+static void allwinner_sramc_reset(DeviceState *dev)
296
+{
297
+ AwSRAMCState *s = AW_SRAMC(dev);
298
+ AwSRAMCClass *sc = AW_SRAMC_GET_CLASS(s);
299
+
300
+ switch (sc->sram_version_code) {
301
+ case SRAM_VERSION_SUN8I_R40:
302
+ s->sram_ctl1 = 0x1300;
303
+ break;
304
+ }
305
+}
306
+
307
+static void allwinner_sramc_class_init(ObjectClass *klass, void *data)
308
+{
309
+ DeviceClass *dc = DEVICE_CLASS(klass);
310
+
311
+ dc->reset = allwinner_sramc_reset;
312
+ dc->vmsd = &allwinner_sramc_vmstate;
313
+}
314
+
315
+static void allwinner_sramc_init(Object *obj)
316
+{
317
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
318
+ AwSRAMCState *s = AW_SRAMC(obj);
319
+
320
+ /* Memory mapping */
321
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_sramc_ops, s,
322
+ TYPE_AW_SRAMC, 1 * KiB);
323
+ sysbus_init_mmio(sbd, &s->iomem);
324
+}
325
+
326
+static const TypeInfo allwinner_sramc_info = {
327
+ .name = TYPE_AW_SRAMC,
328
+ .parent = TYPE_SYS_BUS_DEVICE,
329
+ .instance_init = allwinner_sramc_init,
330
+ .instance_size = sizeof(AwSRAMCState),
331
+ .class_init = allwinner_sramc_class_init,
332
+};
333
+
334
+static void allwinner_r40_sramc_class_init(ObjectClass *klass, void *data)
335
+{
336
+ AwSRAMCClass *sc = AW_SRAMC_CLASS(klass);
337
+
338
+ sc->sram_version_code = SRAM_VERSION_SUN8I_R40;
339
+}
340
+
341
+static const TypeInfo allwinner_r40_sramc_info = {
342
+ .name = TYPE_AW_SRAMC_SUN8I_R40,
343
+ .parent = TYPE_AW_SRAMC,
344
+ .class_init = allwinner_r40_sramc_class_init,
345
+};
346
+
347
+static void allwinner_sramc_register(void)
348
+{
349
+ type_register_static(&allwinner_sramc_info);
350
+ type_register_static(&allwinner_r40_sramc_info);
351
+}
352
+
353
+type_init(allwinner_sramc_register)
354
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
355
index XXXXXXX..XXXXXXX 100644
356
--- a/hw/arm/Kconfig
357
+++ b/hw/arm/Kconfig
358
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
359
config ALLWINNER_R40
360
bool
361
default y if TCG && ARM
362
+ select ALLWINNER_SRAMC
363
select ALLWINNER_A10_PIT
364
select AXP2XX_PMU
365
select SERIAL
366
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
367
index XXXXXXX..XXXXXXX 100644
368
--- a/hw/misc/Kconfig
369
+++ b/hw/misc/Kconfig
370
@@ -XXX,XX +XXX,XX @@ config VIRT_CTRL
371
config LASI
372
bool
373
374
+config ALLWINNER_SRAMC
375
+ bool
376
+
377
config ALLWINNER_A10_CCM
378
bool
379
380
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
381
index XXXXXXX..XXXXXXX 100644
382
--- a/hw/misc/meson.build
383
+++ b/hw/misc/meson.build
384
@@ -XXX,XX +XXX,XX @@ subdir('macio')
385
386
softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
387
388
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_SRAMC', if_true: files('allwinner-sramc.c'))
389
softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
390
softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_DRAMC', if_true: files('allwinner-a10-dramc.c'))
391
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
392
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
393
index XXXXXXX..XXXXXXX 100644
394
--- a/hw/misc/trace-events
395
+++ b/hw/misc/trace-events
396
@@ -XXX,XX +XXX,XX @@ allwinner_r40_dramphy_write(uint64_t offset, uint64_t data, unsigned size) "writ
397
allwinner_sid_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
398
allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
399
400
+# allwinner-sramc.c
401
+allwinner_sramc_read(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " data 0x%" PRIx64
402
+allwinner_sramc_write(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " data 0x%" PRIx64
403
+
404
# avr_power.c
405
avr_power_read(uint8_t value) "power_reduc read value:%u"
406
avr_power_write(uint8_t value) "power_reduc write value:%u"
407
--
23
--
408
2.34.1
24
2.34.1
diff view generated by jsdifflib
1
From: Vikram Garhwal <vikram.garhwal@amd.com>
1
Set the default NaN pattern explicitly for hexagon.
2
Remove the ifdef from parts64_default_nan(); the only
3
remaining unconverted targets all use the default case.
2
4
3
Connect CANFD0 and CANFD1 on the Versal-virt machine and update xlnx-versal-virt
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
document with CANFD command line examples.
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(-)
5
12
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com>
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
docs/system/arm/xlnx-versal-virt.rst | 31 ++++++++++++++++
12
include/hw/arm/xlnx-versal.h | 12 +++++++
13
hw/arm/xlnx-versal-virt.c | 53 ++++++++++++++++++++++++++++
14
hw/arm/xlnx-versal.c | 37 +++++++++++++++++++
15
4 files changed, 133 insertions(+)
16
17
diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/system/arm/xlnx-versal-virt.rst
15
--- a/target/hexagon/cpu.c
20
+++ b/docs/system/arm/xlnx-versal-virt.rst
16
+++ b/target/hexagon/cpu.c
21
@@ -XXX,XX +XXX,XX @@ Implemented devices:
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
22
- DDR memory
18
23
- BBRAM (36 bytes of Battery-backed RAM)
19
set_default_nan_mode(1, &env->fp_status);
24
- eFUSE (3072 bytes of one-time field-programmable bit array)
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
25
+- 2 CANFDs
21
+ /* Default NaN value: sign bit set, all frac bits set */
26
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
27
QEMU does not yet model any other devices, including the PL and the AI Engine.
23
}
28
24
29
@@ -XXX,XX +XXX,XX @@ To use a different index value, N, from default of 1, add:
25
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
30
26
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
Better yet, do not use actual product data when running guest image
32
on this Xilinx Versal Virt board.
33
+
34
+Using CANFDs for Versal Virt
35
+""""""""""""""""""""""""""""
36
+Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
37
+implementation. Bus connection and socketCAN connection for each CAN module
38
+can be set through command lines.
39
+
40
+To connect both CANFD0 and CANFD1 on the same bus:
41
+
42
+.. code-block:: bash
43
+
44
+ -object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
45
+
46
+To connect CANFD0 and CANFD1 to separate buses:
47
+
48
+.. code-block:: bash
49
+
50
+ -object can-bus,id=canbus0 -object can-bus,id=canbus1 \
51
+ -machine canbus0=canbus0 -machine canbus1=canbus1
52
+
53
+The SocketCAN interface can connect to a Physical or a Virtual CAN interfaces on
54
+the host machine. Please check this document to learn about CAN interface on
55
+Linux: docs/system/devices/can.rst
56
+
57
+To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
58
+
59
+.. code-block:: bash
60
+
61
+ -object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
62
+ -object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
63
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
64
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
65
--- a/include/hw/arm/xlnx-versal.h
28
--- a/fpu/softfloat-specialize.c.inc
66
+++ b/include/hw/arm/xlnx-versal.h
29
+++ b/fpu/softfloat-specialize.c.inc
67
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
68
#include "hw/dma/xlnx_csu_dma.h"
31
uint8_t dnan_pattern = status->default_nan_pattern;
69
#include "hw/misc/xlnx-versal-crl.h"
32
70
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
33
if (dnan_pattern == 0) {
71
+#include "hw/net/xlnx-versal-canfd.h"
34
-#if defined(TARGET_HEXAGON)
72
35
- /* Sign bit set, all frac bits set. */
73
#define TYPE_XLNX_VERSAL "xlnx-versal"
36
- dnan_pattern = 0b11111111;
74
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
37
-#else
75
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
38
/*
76
#define XLNX_VERSAL_NR_SDS 2
39
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
77
#define XLNX_VERSAL_NR_XRAM 4
40
* S390, SH4, TriCore, and Xtensa. Our other supported targets
78
#define XLNX_VERSAL_NR_IRQS 192
41
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
79
+#define XLNX_VERSAL_NR_CANFD 2
42
/* sign bit clear, set frac msb */
80
+#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000)
43
dnan_pattern = 0b01000000;
81
44
}
82
struct Versal {
45
-#endif
83
/*< private >*/
84
@@ -XXX,XX +XXX,XX @@ struct Versal {
85
CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
86
XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
87
VersalUsb2 usb;
88
+ CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
89
+ XlnxVersalCANFDState canfd[XLNX_VERSAL_NR_CANFD];
90
} iou;
91
92
/* Real-time Processing Unit. */
93
@@ -XXX,XX +XXX,XX @@ struct Versal {
94
#define VERSAL_CRL_IRQ 10
95
#define VERSAL_UART0_IRQ_0 18
96
#define VERSAL_UART1_IRQ_0 19
97
+#define VERSAL_CANFD0_IRQ_0 20
98
+#define VERSAL_CANFD1_IRQ_0 21
99
#define VERSAL_USB0_IRQ_0 22
100
#define VERSAL_GEM0_IRQ_0 56
101
#define VERSAL_GEM0_WAKE_IRQ_0 57
102
@@ -XXX,XX +XXX,XX @@ struct Versal {
103
#define MM_UART1 0xff010000U
104
#define MM_UART1_SIZE 0x10000
105
106
+#define MM_CANFD0 0xff060000U
107
+#define MM_CANFD0_SIZE 0x10000
108
+#define MM_CANFD1 0xff070000U
109
+#define MM_CANFD1_SIZE 0x10000
110
+
111
#define MM_GEM0 0xff0c0000U
112
#define MM_GEM0_SIZE 0x10000
113
#define MM_GEM1 0xff0d0000U
114
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/hw/arm/xlnx-versal-virt.c
117
+++ b/hw/arm/xlnx-versal-virt.c
118
@@ -XXX,XX +XXX,XX @@ struct VersalVirt {
119
uint32_t clk_25Mhz;
120
uint32_t usb;
121
uint32_t dwc;
122
+ uint32_t canfd[2];
123
} phandle;
124
struct arm_boot_info binfo;
125
126
+ CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
127
struct {
128
bool secure;
129
} cfg;
130
@@ -XXX,XX +XXX,XX @@ static void fdt_add_uart_nodes(VersalVirt *s)
131
}
46
}
132
}
47
assert(dnan_pattern != 0);
133
134
+static void fdt_add_canfd_nodes(VersalVirt *s)
135
+{
136
+ uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
137
+ uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
138
+ unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
139
+ const char clocknames[] = "can_clk\0s_axi_aclk";
140
+ int i;
141
+
142
+ /* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
143
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
144
+ char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
145
+ qemu_fdt_add_subnode(s->fdt, name);
146
+
147
+ qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40);
148
+ qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20);
149
+
150
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
151
+ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
152
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
153
+ clocknames, sizeof(clocknames));
154
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
155
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
156
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
157
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
158
+ 2, addrs[i], 2, size[i]);
159
+ qemu_fdt_setprop_string(s->fdt, name, "compatible",
160
+ "xlnx,canfd-2.0");
161
+
162
+ g_free(name);
163
+ }
164
+}
165
+
166
static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
167
uint32_t phandle)
168
{
169
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
170
TYPE_XLNX_VERSAL);
171
object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
172
&error_abort);
173
+ object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[0]),
174
+ &error_abort);
175
+ object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[1]),
176
+ &error_abort);
177
sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
178
179
fdt_create(s);
180
create_virtio_regions(s);
181
fdt_add_gem_nodes(s);
182
fdt_add_uart_nodes(s);
183
+ fdt_add_canfd_nodes(s);
184
fdt_add_gic_nodes(s);
185
fdt_add_timer_nodes(s);
186
fdt_add_zdma_nodes(s);
187
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
188
189
static void versal_virt_machine_instance_init(Object *obj)
190
{
191
+ VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
192
+
193
+ /*
194
+ * User can set canbus0 and canbus1 properties to can-bus object and connect
195
+ * to socketcan(optional) interface via command line.
196
+ */
197
+ object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
198
+ (Object **)&s->canbus[0],
199
+ object_property_allow_set_link,
200
+ 0);
201
+ object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
202
+ (Object **)&s->canbus[1],
203
+ object_property_allow_set_link,
204
+ 0);
205
}
206
207
static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
208
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/hw/arm/xlnx-versal.c
211
+++ b/hw/arm/xlnx-versal.c
212
@@ -XXX,XX +XXX,XX @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
213
}
214
}
215
216
+static void versal_create_canfds(Versal *s, qemu_irq *pic)
217
+{
218
+ int i;
219
+ uint32_t irqs[] = { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0};
220
+ uint64_t addrs[] = { MM_CANFD0, MM_CANFD1 };
221
+
222
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.canfd); i++) {
223
+ char *name = g_strdup_printf("canfd%d", i);
224
+ SysBusDevice *sbd;
225
+ MemoryRegion *mr;
226
+
227
+ object_initialize_child(OBJECT(s), name, &s->lpd.iou.canfd[i],
228
+ TYPE_XILINX_CANFD);
229
+ sbd = SYS_BUS_DEVICE(&s->lpd.iou.canfd[i]);
230
+
231
+ object_property_set_int(OBJECT(&s->lpd.iou.canfd[i]), "ext_clk_freq",
232
+ XLNX_VERSAL_CANFD_REF_CLK , &error_abort);
233
+
234
+ object_property_set_link(OBJECT(&s->lpd.iou.canfd[i]), "canfdbus",
235
+ OBJECT(s->lpd.iou.canbus[i]),
236
+ &error_abort);
237
+
238
+ sysbus_realize(sbd, &error_fatal);
239
+
240
+ mr = sysbus_mmio_get_region(sbd, 0);
241
+ memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
242
+
243
+ sysbus_connect_irq(sbd, 0, pic[irqs[i]]);
244
+ g_free(name);
245
+ }
246
+}
247
+
248
static void versal_create_usbs(Versal *s, qemu_irq *pic)
249
{
250
DeviceState *dev;
251
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
252
versal_create_apu_gic(s, pic);
253
versal_create_rpu_cpus(s);
254
versal_create_uarts(s, pic);
255
+ versal_create_canfds(s, pic);
256
versal_create_usbs(s, pic);
257
versal_create_gems(s, pic);
258
versal_create_admas(s, pic);
259
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
260
static Property versal_properties[] = {
261
DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
262
MemoryRegion *),
263
+ DEFINE_PROP_LINK("canbus0", Versal, lpd.iou.canbus[0],
264
+ TYPE_CAN_BUS, CanBusState *),
265
+ DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1],
266
+ TYPE_CAN_BUS, CanBusState *),
267
DEFINE_PROP_END_OF_LIST()
268
};
269
48
270
--
49
--
271
2.34.1
50
2.34.1
diff view generated by jsdifflib
1
From: qianfan Zhao <qianfanguijin@163.com>
1
Set the default NaN pattern explicitly for riscv.
2
2
3
Add test case for booting from initrd and sd card.
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(+)
4
9
5
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
6
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
7
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
tests/avocado/boot_linux_console.py | 176 ++++++++++++++++++++++++++++
11
1 file changed, 176 insertions(+)
12
13
diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/avocado/boot_linux_console.py
12
--- a/target/riscv/cpu.c
16
+++ b/tests/avocado/boot_linux_console.py
13
+++ b/target/riscv/cpu.c
17
@@ -XXX,XX +XXX,XX @@ def test_arm_quanta_gsj_initrd(self):
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
18
self.wait_for_console_pattern(
15
cs->exception_index = RISCV_EXCP_NONE;
19
'Give root password for system maintenance')
16
env->load_res = -1;
20
17
set_default_nan_mode(1, &env->fp_status);
21
+ def test_arm_bpim2u(self):
18
+ /* Default NaN value: sign bit clear, frac msb set */
22
+ """
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
23
+ :avocado: tags=arch:arm
20
env->vill = true;
24
+ :avocado: tags=machine:bpim2u
21
25
+ :avocado: tags=accel:tcg
22
#ifndef CONFIG_USER_ONLY
26
+ """
27
+ deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
28
+ 'linux-image-current-sunxi_21.02.2_armhf.deb')
29
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
30
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
31
+ kernel_path = self.extract_from_deb(deb_path,
32
+ '/boot/vmlinuz-5.10.16-sunxi')
33
+ dtb_path = ('/usr/lib/linux-image-current-sunxi/'
34
+ 'sun8i-r40-bananapi-m2-ultra.dtb')
35
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
36
+
37
+ self.vm.set_console()
38
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
39
+ 'console=ttyS0,115200n8 '
40
+ 'earlycon=uart,mmio32,0x1c28000')
41
+ self.vm.add_args('-kernel', kernel_path,
42
+ '-dtb', dtb_path,
43
+ '-append', kernel_command_line)
44
+ self.vm.launch()
45
+ console_pattern = 'Kernel command line: %s' % kernel_command_line
46
+ self.wait_for_console_pattern(console_pattern)
47
+
48
+ def test_arm_bpim2u_initrd(self):
49
+ """
50
+ :avocado: tags=arch:arm
51
+ :avocado: tags=accel:tcg
52
+ :avocado: tags=machine:bpim2u
53
+ """
54
+ deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
55
+ 'linux-image-current-sunxi_21.02.2_armhf.deb')
56
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
57
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
58
+ kernel_path = self.extract_from_deb(deb_path,
59
+ '/boot/vmlinuz-5.10.16-sunxi')
60
+ dtb_path = ('/usr/lib/linux-image-current-sunxi/'
61
+ 'sun8i-r40-bananapi-m2-ultra.dtb')
62
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
63
+ initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
64
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
65
+ 'arm/rootfs-armv7a.cpio.gz')
66
+ initrd_hash = '604b2e45cdf35045846b8bbfbf2129b1891bdc9c'
67
+ initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
68
+ initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
69
+ archive.gzip_uncompress(initrd_path_gz, initrd_path)
70
+
71
+ self.vm.set_console()
72
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
73
+ 'console=ttyS0,115200 '
74
+ 'panic=-1 noreboot')
75
+ self.vm.add_args('-kernel', kernel_path,
76
+ '-dtb', dtb_path,
77
+ '-initrd', initrd_path,
78
+ '-append', kernel_command_line,
79
+ '-no-reboot')
80
+ self.vm.launch()
81
+ self.wait_for_console_pattern('Boot successful.')
82
+
83
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
84
+ 'Allwinner sun8i Family')
85
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
86
+ 'system-control@1c00000')
87
+ exec_command_and_wait_for_pattern(self, 'reboot',
88
+ 'reboot: Restarting system')
89
+ # Wait for VM to shut down gracefully
90
+ self.vm.wait()
91
+
92
+ def test_arm_bpim2u_gmac(self):
93
+ """
94
+ :avocado: tags=arch:arm
95
+ :avocado: tags=accel:tcg
96
+ :avocado: tags=machine:bpim2u
97
+ :avocado: tags=device:sd
98
+ """
99
+ self.require_netdev('user')
100
+
101
+ deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
102
+ 'linux-image-current-sunxi_21.02.2_armhf.deb')
103
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
104
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
105
+ kernel_path = self.extract_from_deb(deb_path,
106
+ '/boot/vmlinuz-5.10.16-sunxi')
107
+ dtb_path = ('/usr/lib/linux-image-current-sunxi/'
108
+ 'sun8i-r40-bananapi-m2-ultra.dtb')
109
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
110
+ rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
111
+ 'buildroot-baseline/20221116.0/armel/rootfs.ext2.xz')
112
+ rootfs_hash = 'fae32f337c7b87547b10f42599acf109da8b6d9a'
113
+ rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
114
+ rootfs_path = os.path.join(self.workdir, 'rootfs.cpio')
115
+ archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
116
+ image_pow2ceil_expand(rootfs_path)
117
+
118
+ self.vm.set_console()
119
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
120
+ 'console=ttyS0,115200 '
121
+ 'root=/dev/mmcblk0 rootwait rw '
122
+ 'panic=-1 noreboot')
123
+ self.vm.add_args('-kernel', kernel_path,
124
+ '-dtb', dtb_path,
125
+ '-drive', 'file=' + rootfs_path + ',if=sd,format=raw',
126
+ '-net', 'nic,model=gmac,netdev=host_gmac',
127
+ '-netdev', 'user,id=host_gmac',
128
+ '-append', kernel_command_line,
129
+ '-no-reboot')
130
+ self.vm.launch()
131
+ shell_ready = "/bin/sh: can't access tty; job control turned off"
132
+ self.wait_for_console_pattern(shell_ready)
133
+
134
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
135
+ 'Allwinner sun8i Family')
136
+ exec_command_and_wait_for_pattern(self, 'cat /proc/partitions',
137
+ 'mmcblk0')
138
+ exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up',
139
+ 'eth0: Link is Up')
140
+ exec_command_and_wait_for_pattern(self, 'udhcpc eth0',
141
+ 'udhcpc: lease of 10.0.2.15 obtained')
142
+ exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2',
143
+ '3 packets transmitted, 3 packets received, 0% packet loss')
144
+ exec_command_and_wait_for_pattern(self, 'reboot',
145
+ 'reboot: Restarting system')
146
+ # Wait for VM to shut down gracefully
147
+ self.vm.wait()
148
+
149
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
150
+ def test_arm_bpim2u_openwrt_22_03_3(self):
151
+ """
152
+ :avocado: tags=arch:arm
153
+ :avocado: tags=machine:bpim2u
154
+ :avocado: tags=device:sd
155
+ """
156
+
157
+ # This test download a 8.9 MiB compressed image and expand it
158
+ # to 127 MiB.
159
+ image_url = ('https://downloads.openwrt.org/releases/22.03.3/targets/'
160
+ 'sunxi/cortexa7/openwrt-22.03.3-sunxi-cortexa7-'
161
+ 'sinovoip_bananapi-m2-ultra-ext4-sdcard.img.gz')
162
+ image_hash = ('5b41b4e11423e562c6011640f9a7cd3b'
163
+ 'dd0a3d42b83430f7caa70a432e6cd82c')
164
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash,
165
+ algorithm='sha256')
166
+ image_path = archive.extract(image_path_gz, self.workdir)
167
+ image_pow2ceil_expand(image_path)
168
+
169
+ self.vm.set_console()
170
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
171
+ '-nic', 'user',
172
+ '-no-reboot')
173
+ self.vm.launch()
174
+
175
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
176
+ 'usbcore.nousb '
177
+ 'noreboot')
178
+
179
+ self.wait_for_console_pattern('U-Boot SPL')
180
+
181
+ interrupt_interactive_console_until_pattern(
182
+ self, 'Hit any key to stop autoboot:', '=>')
183
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
184
+ kernel_command_line + "'", '=>')
185
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...');
186
+
187
+ self.wait_for_console_pattern(
188
+ 'Please press Enter to activate this console.')
189
+
190
+ exec_command_and_wait_for_pattern(self, ' ', 'root@')
191
+
192
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
193
+ 'Allwinner sun8i Family')
194
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
195
+ 'system-control@1c00000')
196
+
197
def test_arm_orangepi(self):
198
"""
199
:avocado: tags=arch:arm
200
--
23
--
201
2.34.1
24
2.34.1
diff view generated by jsdifflib
1
From: qianfan Zhao <qianfanguijin@163.com>
1
Set the default NaN pattern explicitly for tricore.
2
2
3
TWI(i2c) is designed to be used as an interface between CPU host and the
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
serial 2-Wire bus. It can support all standard 2-Wire transfer, can be
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
operated in standard mode(100kbit/s) or fast-mode, supporting data rate
5
Message-id: 20241202131347.498124-54-peter.maydell@linaro.org
6
up to 400kbit/s.
6
---
7
target/tricore/helper.c | 2 ++
8
1 file changed, 2 insertions(+)
7
9
8
Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
9
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/allwinner-r40.h | 3 +++
13
hw/arm/allwinner-r40.c | 11 ++++++++++-
14
2 files changed, 13 insertions(+), 1 deletion(-)
15
16
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/allwinner-r40.h
12
--- a/target/tricore/helper.c
19
+++ b/include/hw/arm/allwinner-r40.h
13
+++ b/target/tricore/helper.c
20
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
21
#include "hw/intc/arm_gic.h"
15
set_flush_to_zero(1, &env->fp_status);
22
#include "hw/sd/allwinner-sdhost.h"
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
23
#include "hw/misc/allwinner-r40-ccu.h"
17
set_default_nan_mode(1, &env->fp_status);
24
+#include "hw/i2c/allwinner-i2c.h"
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
25
#include "target/arm/cpu.h"
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
26
#include "sysemu/block-backend.h"
27
28
@@ -XXX,XX +XXX,XX @@ enum {
29
AW_R40_DEV_UART5,
30
AW_R40_DEV_UART6,
31
AW_R40_DEV_UART7,
32
+ AW_R40_DEV_TWI0,
33
AW_R40_DEV_GIC_DIST,
34
AW_R40_DEV_GIC_CPU,
35
AW_R40_DEV_GIC_HYP,
36
@@ -XXX,XX +XXX,XX @@ struct AwR40State {
37
AwA10PITState timer;
38
AwSdHostState mmc[AW_R40_NUM_MMCS];
39
AwR40ClockCtlState ccu;
40
+ AWI2CState i2c0;
41
GICState gic;
42
MemoryRegion sram_a1;
43
MemoryRegion sram_a2;
44
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/allwinner-r40.c
47
+++ b/hw/arm/allwinner-r40.c
48
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_r40_memmap[] = {
49
[AW_R40_DEV_UART5] = 0x01c29400,
50
[AW_R40_DEV_UART6] = 0x01c29800,
51
[AW_R40_DEV_UART7] = 0x01c29c00,
52
+ [AW_R40_DEV_TWI0] = 0x01c2ac00,
53
[AW_R40_DEV_GIC_DIST] = 0x01c81000,
54
[AW_R40_DEV_GIC_CPU] = 0x01c82000,
55
[AW_R40_DEV_GIC_HYP] = 0x01c84000,
56
@@ -XXX,XX +XXX,XX @@ static struct AwR40Unimplemented r40_unimplemented[] = {
57
{ "uart7", 0x01c29c00, 1 * KiB },
58
{ "ps20", 0x01c2a000, 1 * KiB },
59
{ "ps21", 0x01c2a400, 1 * KiB },
60
- { "twi0", 0x01c2ac00, 1 * KiB },
61
{ "twi1", 0x01c2b000, 1 * KiB },
62
{ "twi2", 0x01c2b400, 1 * KiB },
63
{ "twi3", 0x01c2b800, 1 * KiB },
64
@@ -XXX,XX +XXX,XX @@ enum {
65
AW_R40_GIC_SPI_UART1 = 2,
66
AW_R40_GIC_SPI_UART2 = 3,
67
AW_R40_GIC_SPI_UART3 = 4,
68
+ AW_R40_GIC_SPI_TWI0 = 7,
69
AW_R40_GIC_SPI_UART4 = 17,
70
AW_R40_GIC_SPI_UART5 = 18,
71
AW_R40_GIC_SPI_UART6 = 19,
72
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_init(Object *obj)
73
object_initialize_child(obj, mmc_names[i], &s->mmc[i],
74
TYPE_AW_SDHOST_SUN5I);
75
}
76
+
77
+ object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
78
}
20
}
79
21
80
static void allwinner_r40_realize(DeviceState *dev, Error **errp)
22
uint32_t psw_read(CPUTriCoreState *env)
81
@@ -XXX,XX +XXX,XX @@ static void allwinner_r40_realize(DeviceState *dev, Error **errp)
82
115200, serial_hd(i), DEVICE_NATIVE_ENDIAN);
83
}
84
85
+ /* I2C */
86
+ sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
87
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, s->memmap[AW_R40_DEV_TWI0]);
88
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0,
89
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_TWI0));
90
+
91
/* Unimplemented devices */
92
for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
93
create_unimplemented_device(r40_unimplemented[i].device_name,
94
--
23
--
95
2.34.1
24
2.34.1
diff view generated by jsdifflib
1
From: Vikram Garhwal <vikram.garhwal@amd.com>
1
Now that all our targets have bene converted to explicitly specify
2
their pattern for the default NaN value we can remove the remaining
3
fallback code in parts64_default_nan().
2
4
3
The QTests perform three tests on the Xilinx VERSAL CANFD controller:
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Tests the CANFD controllers in loopback.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Tests the CANFD controllers in normal mode with CAN frame.
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
6
Tests the CANFD controllers in normal mode with CANFD frame.
8
---
9
fpu/softfloat-specialize.c.inc | 14 --------------
10
1 file changed, 14 deletions(-)
7
11
8
Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com>
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
9
Acked-by: Thomas Huth <thuth@redhat.com>
10
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
tests/qtest/xlnx-canfd-test.c | 423 ++++++++++++++++++++++++++++++++++
15
tests/qtest/meson.build | 1 +
16
2 files changed, 424 insertions(+)
17
create mode 100644 tests/qtest/xlnx-canfd-test.c
18
19
diff --git a/tests/qtest/xlnx-canfd-test.c b/tests/qtest/xlnx-canfd-test.c
20
new file mode 100644
21
index XXXXXXX..XXXXXXX
22
--- /dev/null
23
+++ b/tests/qtest/xlnx-canfd-test.c
24
@@ -XXX,XX +XXX,XX @@
25
+/*
26
+ * SPDX-License-Identifier: MIT
27
+ *
28
+ * QTests for the Xilinx Versal CANFD controller.
29
+ *
30
+ * Copyright (c) 2022 AMD Inc.
31
+ *
32
+ * Written-by: Vikram Garhwal<vikram.garhwal@amd.com>
33
+ *
34
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
35
+ * of this software and associated documentation files (the "Software"), to deal
36
+ * in the Software without restriction, including without limitation the rights
37
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38
+ * copies of the Software, and to permit persons to whom the Software is
39
+ * furnished to do so, subject to the following conditions:
40
+ *
41
+ * The above copyright notice and this permission notice shall be included in
42
+ * all copies or substantial portions of the Software.
43
+ *
44
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
47
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
50
+ * THE SOFTWARE.
51
+ */
52
+
53
+#include "qemu/osdep.h"
54
+#include "libqtest.h"
55
+
56
+/* Base address. */
57
+#define CANFD0_BASE_ADDR 0xff060000
58
+#define CANFD1_BASE_ADDR 0xff070000
59
+
60
+/* Register addresses. */
61
+#define R_SRR_OFFSET 0x00
62
+#define R_MSR_OFFSET 0x04
63
+#define R_FILTER_CONTROL_REGISTER 0xe0
64
+#define R_SR_OFFSET 0x18
65
+#define R_ISR_OFFSET 0x1c
66
+#define R_IER_OFFSET 0x20
67
+#define R_ICR_OFFSET 0x24
68
+#define R_TX_READY_REQ_REGISTER 0x90
69
+#define RX_FIFO_STATUS_REGISTER 0xe8
70
+#define R_TXID_OFFSET 0x100
71
+#define R_TXDLC_OFFSET 0x104
72
+#define R_TXDATA1_OFFSET 0x108
73
+#define R_TXDATA2_OFFSET 0x10c
74
+#define R_AFMR_REGISTER0 0xa00
75
+#define R_AFIR_REGISTER0 0xa04
76
+#define R_RX0_ID_OFFSET 0x2100
77
+#define R_RX0_DLC_OFFSET 0x2104
78
+#define R_RX0_DATA1_OFFSET 0x2108
79
+#define R_RX0_DATA2_OFFSET 0x210c
80
+
81
+/* CANFD modes. */
82
+#define SRR_CONFIG_MODE 0x00
83
+#define MSR_NORMAL_MODE 0x00
84
+#define MSR_LOOPBACK_MODE (1 << 1)
85
+#define ENABLE_CANFD (1 << 1)
86
+
87
+/* CANFD status. */
88
+#define STATUS_CONFIG_MODE (1 << 0)
89
+#define STATUS_NORMAL_MODE (1 << 3)
90
+#define STATUS_LOOPBACK_MODE (1 << 1)
91
+#define ISR_TXOK (1 << 1)
92
+#define ISR_RXOK (1 << 4)
93
+
94
+#define ENABLE_ALL_FILTERS 0xffffffff
95
+#define ENABLE_ALL_INTERRUPTS 0xffffffff
96
+
97
+/* We are sending one canfd message. */
98
+#define TX_READY_REG_VAL 0x1
99
+
100
+#define FIRST_RX_STORE_INDEX 0x1
101
+#define STATUS_REG_MASK 0xf
102
+#define DLC_FD_BIT_SHIFT 0x1b
103
+#define DLC_FD_BIT_MASK 0xf8000000
104
+#define FIFO_STATUS_READ_INDEX_MASK 0x3f
105
+#define FIFO_STATUS_FILL_LEVEL_MASK 0x7f00
106
+#define FILL_LEVEL_SHIFT 0x8
107
+
108
+/* CANFD frame size ID, DLC and 16 DATA word. */
109
+#define CANFD_FRAME_SIZE 18
110
+/* CAN frame size ID, DLC and 2 DATA word. */
111
+#define CAN_FRAME_SIZE 4
112
+
113
+/* Set the filters for CANFD controller. */
114
+static void enable_filters(QTestState *qts)
115
+{
116
+ const uint32_t arr_afmr[32] = { 0xb423deaa, 0xa2a40bdc, 0x1b64f486,
117
+ 0x95c0d4ee, 0xe0c44528, 0x4b407904,
118
+ 0xd2673f46, 0x9fc638d6, 0x8844f3d8,
119
+ 0xa607d1e8, 0x67871bf4, 0xc2557dc,
120
+ 0x9ea5b53e, 0x3643c0cc, 0x5a05ea8e,
121
+ 0x83a46d84, 0x4a25c2b8, 0x93a66008,
122
+ 0x2e467470, 0xedc66118, 0x9086f9f2,
123
+ 0xfa23dd36, 0xb6654b90, 0xb221b8ca,
124
+ 0x3467d1e2, 0xa3a55542, 0x5b26a012,
125
+ 0x2281ea7e, 0xcea0ece8, 0xdc61e588,
126
+ 0x2e5676a, 0x16821320 };
127
+
128
+ const uint32_t arr_afir[32] = { 0xa833dfa1, 0x255a477e, 0x3a4bb1c5,
129
+ 0x8f560a6c, 0x27f38903, 0x2fecec4d,
130
+ 0xa014c66d, 0xec289b8, 0x7e52dead,
131
+ 0x82e94f3c, 0xcf3e3c5c, 0x66059871,
132
+ 0x3f213df4, 0x25ac3959, 0xa12e9bef,
133
+ 0xa3ad3af, 0xbafd7fe, 0xb3cb40fd,
134
+ 0x5d9caa81, 0x2ed61902, 0x7cd64a0,
135
+ 0x4b1fa538, 0x9b5ced8c, 0x150de059,
136
+ 0xd2794227, 0x635e820a, 0xbb6b02cf,
137
+ 0xbb58176, 0x570025bb, 0xa78d9658,
138
+ 0x49d735df, 0xe5399d2f };
139
+
140
+ /* Passing the respective array values to all the AFMR and AFIR pairs. */
141
+ for (int i = 0; i < 32; i++) {
142
+ /* For CANFD0. */
143
+ qtest_writel(qts, CANFD0_BASE_ADDR + R_AFMR_REGISTER0 + 8 * i,
144
+ arr_afmr[i]);
145
+ qtest_writel(qts, CANFD0_BASE_ADDR + R_AFIR_REGISTER0 + 8 * i,
146
+ arr_afir[i]);
147
+
148
+ /* For CANFD1. */
149
+ qtest_writel(qts, CANFD1_BASE_ADDR + R_AFMR_REGISTER0 + 8 * i,
150
+ arr_afmr[i]);
151
+ qtest_writel(qts, CANFD1_BASE_ADDR + R_AFIR_REGISTER0 + 8 * i,
152
+ arr_afir[i]);
153
+ }
154
+
155
+ /* Enable all the pairs from AFR register. */
156
+ qtest_writel(qts, CANFD0_BASE_ADDR + R_FILTER_CONTROL_REGISTER,
157
+ ENABLE_ALL_FILTERS);
158
+ qtest_writel(qts, CANFD1_BASE_ADDR + R_FILTER_CONTROL_REGISTER,
159
+ ENABLE_ALL_FILTERS);
160
+}
161
+
162
+static void configure_canfd(QTestState *qts, uint8_t mode)
163
+{
164
+ uint32_t status = 0;
165
+
166
+ /* Put CANFD0 and CANFD1 in config mode. */
167
+ qtest_writel(qts, CANFD0_BASE_ADDR + R_SRR_OFFSET, SRR_CONFIG_MODE);
168
+ qtest_writel(qts, CANFD1_BASE_ADDR + R_SRR_OFFSET, SRR_CONFIG_MODE);
169
+
170
+ /* Write mode of operation in Mode select register. */
171
+ qtest_writel(qts, CANFD0_BASE_ADDR + R_MSR_OFFSET, mode);
172
+ qtest_writel(qts, CANFD1_BASE_ADDR + R_MSR_OFFSET, mode);
173
+
174
+ enable_filters(qts);
175
+
176
+ /* Check here if CANFD0 and CANFD1 are in config mode. */
177
+ status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
178
+ status = status & STATUS_REG_MASK;
179
+ g_assert_cmpint(status, ==, STATUS_CONFIG_MODE);
180
+
181
+ status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
182
+ status = status & STATUS_REG_MASK;
183
+ g_assert_cmpint(status, ==, STATUS_CONFIG_MODE);
184
+
185
+ qtest_writel(qts, CANFD1_BASE_ADDR + R_IER_OFFSET, ENABLE_ALL_INTERRUPTS);
186
+ qtest_writel(qts, CANFD1_BASE_ADDR + R_IER_OFFSET, ENABLE_ALL_INTERRUPTS);
187
+
188
+ qtest_writel(qts, CANFD0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CANFD);
189
+ qtest_writel(qts, CANFD1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CANFD);
190
+}
191
+
192
+static void generate_random_data(uint32_t *buf_tx, bool is_canfd_frame)
193
+{
194
+ /* Generate random TX data for CANFD frame. */
195
+ if (is_canfd_frame) {
196
+ for (int i = 0; i < CANFD_FRAME_SIZE - 2; i++) {
197
+ buf_tx[2 + i] = rand();
198
+ }
199
+ } else {
200
+ /* Generate random TX data for CAN frame. */
201
+ for (int i = 0; i < CAN_FRAME_SIZE - 2; i++) {
202
+ buf_tx[2 + i] = rand();
203
+ }
204
+ }
205
+}
206
+
207
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
208
+{
209
+ uint32_t int_status;
210
+ uint32_t fifo_status_reg_value;
211
+ /* At which RX FIFO the received data is stored. */
212
+ uint8_t store_ind = 0;
213
+ bool is_canfd_frame = false;
214
+
215
+ /* Read the interrupt on CANFD rx. */
216
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
217
+
218
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
219
+
220
+ /* Find the fill level and read index. */
221
+ fifo_status_reg_value = qtest_readl(qts, can_base_addr +
222
+ RX_FIFO_STATUS_REGISTER);
223
+
224
+ store_ind = (fifo_status_reg_value & FIFO_STATUS_READ_INDEX_MASK) +
225
+ ((fifo_status_reg_value & FIFO_STATUS_FILL_LEVEL_MASK) >>
226
+ FILL_LEVEL_SHIFT);
227
+
228
+ g_assert_cmpint(store_ind, ==, FIRST_RX_STORE_INDEX);
229
+
230
+ /* Read the RX register data for CANFD. */
231
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RX0_ID_OFFSET);
232
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RX0_DLC_OFFSET);
233
+
234
+ is_canfd_frame = (buf_rx[1] >> DLC_FD_BIT_SHIFT) & 1;
235
+
236
+ if (is_canfd_frame) {
237
+ for (int i = 0; i < CANFD_FRAME_SIZE - 2; i++) {
238
+ buf_rx[i + 2] = qtest_readl(qts,
239
+ can_base_addr + R_RX0_DATA1_OFFSET + 4 * i);
240
+ }
241
+ } else {
242
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RX0_DATA1_OFFSET);
243
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RX0_DATA2_OFFSET);
244
+ }
245
+
246
+ /* Clear the RX interrupt. */
247
+ qtest_writel(qts, CANFD1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
248
+}
249
+
250
+static void write_data(QTestState *qts, uint64_t can_base_addr,
251
+ const uint32_t *buf_tx, bool is_canfd_frame)
252
+{
253
+ /* Write the TX register data for CANFD. */
254
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
255
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
256
+
257
+ if (is_canfd_frame) {
258
+ for (int i = 0; i < CANFD_FRAME_SIZE - 2; i++) {
259
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET + 4 * i,
260
+ buf_tx[2 + i]);
261
+ }
262
+ } else {
263
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
264
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
265
+ }
266
+}
267
+
268
+static void send_data(QTestState *qts, uint64_t can_base_addr)
269
+{
270
+ uint32_t int_status;
271
+
272
+ qtest_writel(qts, can_base_addr + R_TX_READY_REQ_REGISTER,
273
+ TX_READY_REG_VAL);
274
+
275
+ /* Read the interrupt on CANFD for tx. */
276
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
277
+
278
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
279
+
280
+ /* Clear the interrupt for tx. */
281
+ qtest_writel(qts, CANFD0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
282
+}
283
+
284
+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
285
+ bool is_canfd_frame)
286
+{
287
+ uint16_t size = 0;
288
+ uint8_t len = CAN_FRAME_SIZE;
289
+
290
+ if (is_canfd_frame) {
291
+ len = CANFD_FRAME_SIZE;
292
+ }
293
+
294
+ while (size < len) {
295
+ if (R_RX0_ID_OFFSET + 4 * size == R_RX0_DLC_OFFSET) {
296
+ g_assert_cmpint((buf_rx[size] & DLC_FD_BIT_MASK), ==,
297
+ (buf_tx[size] & DLC_FD_BIT_MASK));
298
+ } else {
299
+ if (!is_canfd_frame && size == 4) {
300
+ break;
301
+ }
302
+
303
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
304
+ }
305
+
306
+ size++;
307
+ }
308
+}
309
+/*
310
+ * Xilinx CANFD supports both CAN and CANFD frames. This test will be
311
+ * transferring CAN frame i.e. 8 bytes of data from CANFD0 and CANFD1 through
312
+ * canbus. CANFD0 initiate the data transfer to can-bus, CANFD1 receives the
313
+ * data. Test compares the can frame data sent from CANFD0 and received on
314
+ * CANFD1.
315
+ */
316
+static void test_can_data_transfer(void)
317
+{
318
+ uint32_t buf_tx[CAN_FRAME_SIZE] = { 0x5a5bb9a4, 0x80000000,
319
+ 0x12345678, 0x87654321 };
320
+ uint32_t buf_rx[CAN_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 };
321
+ uint32_t status = 0;
322
+
323
+ generate_random_data(buf_tx, false);
324
+
325
+ QTestState *qts = qtest_init("-machine xlnx-versal-virt"
326
+ " -object can-bus,id=canbus"
327
+ " -machine canbus0=canbus"
328
+ " -machine canbus1=canbus"
329
+ );
330
+
331
+ configure_canfd(qts, MSR_NORMAL_MODE);
332
+
333
+ /* Check if CANFD0 and CANFD1 are in Normal mode. */
334
+ status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
335
+ status = status & STATUS_REG_MASK;
336
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
337
+
338
+ status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
339
+ status = status & STATUS_REG_MASK;
340
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
341
+
342
+ write_data(qts, CANFD0_BASE_ADDR, buf_tx, false);
343
+
344
+ send_data(qts, CANFD0_BASE_ADDR);
345
+ read_data(qts, CANFD1_BASE_ADDR, buf_rx);
346
+ match_rx_tx_data(buf_tx, buf_rx, false);
347
+
348
+ qtest_quit(qts);
349
+}
350
+
351
+/*
352
+ * This test will be transferring CANFD frame i.e. 64 bytes of data from CANFD0
353
+ * and CANFD1 through canbus. CANFD0 initiate the data transfer to can-bus,
354
+ * CANFD1 receives the data. Test compares the CANFD frame data sent from CANFD0
355
+ * with received on CANFD1.
356
+ */
357
+static void test_canfd_data_transfer(void)
358
+{
359
+ uint32_t buf_tx[CANFD_FRAME_SIZE] = { 0x5a5bb9a4, 0xf8000000 };
360
+ uint32_t buf_rx[CANFD_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 };
361
+ uint32_t status = 0;
362
+
363
+ generate_random_data(buf_tx, true);
364
+
365
+ QTestState *qts = qtest_init("-machine xlnx-versal-virt"
366
+ " -object can-bus,id=canbus"
367
+ " -machine canbus0=canbus"
368
+ " -machine canbus1=canbus"
369
+ );
370
+
371
+ configure_canfd(qts, MSR_NORMAL_MODE);
372
+
373
+ /* Check if CANFD0 and CANFD1 are in Normal mode. */
374
+ status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
375
+ status = status & STATUS_REG_MASK;
376
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
377
+
378
+ status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
379
+ status = status & STATUS_REG_MASK;
380
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
381
+
382
+ write_data(qts, CANFD0_BASE_ADDR, buf_tx, true);
383
+
384
+ send_data(qts, CANFD0_BASE_ADDR);
385
+ read_data(qts, CANFD1_BASE_ADDR, buf_rx);
386
+ match_rx_tx_data(buf_tx, buf_rx, true);
387
+
388
+ qtest_quit(qts);
389
+}
390
+
391
+/*
392
+ * This test is performing loopback mode on CANFD0 and CANFD1. Data sent from
393
+ * TX of each CANFD0 and CANFD1 are compared with RX register data for
394
+ * respective CANFD Controller.
395
+ */
396
+static void test_can_loopback(void)
397
+{
398
+ uint32_t buf_tx[CANFD_FRAME_SIZE] = { 0x5a5bb9a4, 0xf8000000 };
399
+ uint32_t buf_rx[CANFD_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 };
400
+ uint32_t status = 0;
401
+
402
+ generate_random_data(buf_tx, true);
403
+
404
+ QTestState *qts = qtest_init("-machine xlnx-versal-virt"
405
+ " -object can-bus,id=canbus"
406
+ " -machine canbus0=canbus"
407
+ " -machine canbus1=canbus"
408
+ );
409
+
410
+ configure_canfd(qts, MSR_LOOPBACK_MODE);
411
+
412
+ /* Check if CANFD0 and CANFD1 are set in correct loopback mode. */
413
+ status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
414
+ status = status & STATUS_REG_MASK;
415
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
416
+
417
+ status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
418
+ status = status & STATUS_REG_MASK;
419
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
420
+
421
+ write_data(qts, CANFD0_BASE_ADDR, buf_tx, true);
422
+
423
+ send_data(qts, CANFD0_BASE_ADDR);
424
+ read_data(qts, CANFD0_BASE_ADDR, buf_rx);
425
+ match_rx_tx_data(buf_tx, buf_rx, true);
426
+
427
+ generate_random_data(buf_tx, true);
428
+
429
+ write_data(qts, CANFD1_BASE_ADDR, buf_tx, true);
430
+
431
+ send_data(qts, CANFD1_BASE_ADDR);
432
+ read_data(qts, CANFD1_BASE_ADDR, buf_rx);
433
+ match_rx_tx_data(buf_tx, buf_rx, true);
434
+
435
+ qtest_quit(qts);
436
+}
437
+
438
+int main(int argc, char **argv)
439
+{
440
+ g_test_init(&argc, &argv, NULL);
441
+
442
+ qtest_add_func("/net/canfd/can_data_transfer", test_can_data_transfer);
443
+ qtest_add_func("/net/canfd/canfd_data_transfer", test_canfd_data_transfer);
444
+ qtest_add_func("/net/canfd/can_loopback", test_can_loopback);
445
+
446
+ return g_test_run();
447
+}
448
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
449
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
450
--- a/tests/qtest/meson.build
14
--- a/fpu/softfloat-specialize.c.inc
451
+++ b/tests/qtest/meson.build
15
+++ b/fpu/softfloat-specialize.c.inc
452
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
453
(config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? \
17
uint64_t frac;
454
['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \
18
uint8_t dnan_pattern = status->default_nan_pattern;
455
(config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \
19
456
+ (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : []) + \
20
- if (dnan_pattern == 0) {
457
(config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \
21
- /*
458
(config_all.has_key('CONFIG_TCG') and \
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
459
config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
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;
460
--
37
--
461
2.34.1
38
2.34.1
diff view generated by jsdifflib
1
From: Francesco Cagnin <fcagnin@quarkslab.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
These helpers will be also used for HVF. Aside from reformatting a
3
Inline pickNaNMulAdd into its only caller. This makes
4
couple of comments for 'checkpatch.pl' and updating meson to compile
4
one assert redundant with the immediately preceding IF.
5
'hyp_gdbstub.c', this is just code motion.
6
5
7
Signed-off-by: Francesco Cagnin <fcagnin@quarkslab.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
10
Message-id: 20230601153107.81955-2-fcagnin@quarkslab.com
9
[PMM: keep comment from old code in new location]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
target/arm/internals.h | 50 +++++++
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
14
target/arm/hyp_gdbstub.c | 253 +++++++++++++++++++++++++++++++++++
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
15
target/arm/kvm64.c | 276 ---------------------------------------
14
2 files changed, 40 insertions(+), 55 deletions(-)
16
target/arm/meson.build | 3 +-
17
4 files changed, 305 insertions(+), 277 deletions(-)
18
create mode 100644 target/arm/hyp_gdbstub.c
19
15
20
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/internals.h
18
--- a/fpu/softfloat-parts.c.inc
23
+++ b/target/arm/internals.h
19
+++ b/fpu/softfloat-parts.c.inc
24
@@ -XXX,XX +XXX,XX @@ static inline bool arm_fgt_active(CPUARMState *env, int el)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
}
22
23
if (s->default_nan_mode) {
24
+ /*
25
+ * We guarantee not to require the target to tell us how to
26
+ * pick a NaN if we're always returning the default NaN.
27
+ * But if we're not in default-NaN mode then the target must
28
+ * specify.
29
+ */
30
which = 3;
31
+ } else if (infzero) {
32
+ /*
33
+ * Inf * 0 + NaN -- some implementations return the
34
+ * default NaN here, and some return the input NaN.
35
+ */
36
+ switch (s->float_infzeronan_rule) {
37
+ case float_infzeronan_dnan_never:
38
+ which = 2;
39
+ break;
40
+ case float_infzeronan_dnan_always:
41
+ which = 3;
42
+ break;
43
+ case float_infzeronan_dnan_if_qnan:
44
+ which = is_qnan(c->cls) ? 3 : 2;
45
+ break;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
} else {
50
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
51
+ FloatClass cls[3] = { a->cls, b->cls, c->cls };
52
+ Float3NaNPropRule rule = s->float_3nan_prop_rule;
53
+
54
+ assert(rule != float_3nan_prop_none);
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
56
+ /* We have at least one SNaN input and should prefer it */
57
+ do {
58
+ which = rule & R_3NAN_1ST_MASK;
59
+ rule >>= R_3NAN_1ST_LENGTH;
60
+ } while (!is_snan(cls[which]));
61
+ } else {
62
+ do {
63
+ which = rule & R_3NAN_1ST_MASK;
64
+ rule >>= R_3NAN_1ST_LENGTH;
65
+ } while (!is_nan(cls[which]));
66
+ }
67
}
68
69
if (which == 3) {
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
71
index XXXXXXX..XXXXXXX 100644
72
--- a/fpu/softfloat-specialize.c.inc
73
+++ b/fpu/softfloat-specialize.c.inc
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
75
}
25
}
76
}
26
77
27
void assert_hflags_rebuild_correctly(CPUARMState *env);
78
-/*----------------------------------------------------------------------------
28
+
79
-| Select which NaN to propagate for a three-input operation.
29
+/*
80
-| For the moment we assume that no CPU needs the 'larger significand'
30
+ * Although the ARM implementation of hardware assisted debugging
81
-| information.
31
+ * allows for different breakpoints per-core, the current GDB
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
32
+ * interface treats them as a global pool of registers (which seems to
83
-*----------------------------------------------------------------------------*/
33
+ * be the case for x86, ppc and s390). As a result we store one copy
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
+ * of registers which is used for all active cores.
85
- bool infzero, bool have_snan, float_status *status)
35
+ *
36
+ * Write access is serialised by virtue of the GDB protocol which
37
+ * updates things. Read access (i.e. when the values are copied to the
38
+ * vCPU) is also gated by GDB's run control.
39
+ *
40
+ * This is not unreasonable as most of the time debugging kernels you
41
+ * never know which core will eventually execute your function.
42
+ */
43
+
44
+typedef struct {
45
+ uint64_t bcr;
46
+ uint64_t bvr;
47
+} HWBreakpoint;
48
+
49
+/*
50
+ * The watchpoint registers can cover more area than the requested
51
+ * watchpoint so we need to store the additional information
52
+ * somewhere. We also need to supply a CPUWatchpoint to the GDB stub
53
+ * when the watchpoint is hit.
54
+ */
55
+typedef struct {
56
+ uint64_t wcr;
57
+ uint64_t wvr;
58
+ CPUWatchpoint details;
59
+} HWWatchpoint;
60
+
61
+/* Maximum and current break/watch point counts */
62
+extern int max_hw_bps, max_hw_wps;
63
+extern GArray *hw_breakpoints, *hw_watchpoints;
64
+
65
+#define cur_hw_wps (hw_watchpoints->len)
66
+#define cur_hw_bps (hw_breakpoints->len)
67
+#define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i))
68
+#define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i))
69
+
70
+bool find_hw_breakpoint(CPUState *cpu, target_ulong pc);
71
+int insert_hw_breakpoint(target_ulong pc);
72
+int delete_hw_breakpoint(target_ulong pc);
73
+
74
+bool check_watchpoint_in_range(int i, target_ulong addr);
75
+CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr);
76
+int insert_hw_watchpoint(target_ulong addr, target_ulong len, int type);
77
+int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type);
78
#endif
79
diff --git a/target/arm/hyp_gdbstub.c b/target/arm/hyp_gdbstub.c
80
new file mode 100644
81
index XXXXXXX..XXXXXXX
82
--- /dev/null
83
+++ b/target/arm/hyp_gdbstub.c
84
@@ -XXX,XX +XXX,XX @@
85
+/*
86
+ * ARM implementation of KVM and HVF hooks, 64 bit specific code
87
+ *
88
+ * Copyright Mian-M. Hamayun 2013, Virtual Open Systems
89
+ * Copyright Alex Bennée 2014, Linaro
90
+ *
91
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
92
+ * See the COPYING file in the top-level directory.
93
+ *
94
+ */
95
+
96
+#include "qemu/osdep.h"
97
+#include "cpu.h"
98
+#include "internals.h"
99
+#include "exec/gdbstub.h"
100
+
101
+/* Maximum and current break/watch point counts */
102
+int max_hw_bps, max_hw_wps;
103
+GArray *hw_breakpoints, *hw_watchpoints;
104
+
105
+/**
106
+ * insert_hw_breakpoint()
107
+ * @addr: address of breakpoint
108
+ *
109
+ * See ARM ARM D2.9.1 for details but here we are only going to create
110
+ * simple un-linked breakpoints (i.e. we don't chain breakpoints
111
+ * together to match address and context or vmid). The hardware is
112
+ * capable of fancier matching but that will require exposing that
113
+ * fanciness to GDB's interface
114
+ *
115
+ * DBGBCR<n>_EL1, Debug Breakpoint Control Registers
116
+ *
117
+ * 31 24 23 20 19 16 15 14 13 12 9 8 5 4 3 2 1 0
118
+ * +------+------+-------+-----+----+------+-----+------+-----+---+
119
+ * | RES0 | BT | LBN | SSC | HMC| RES0 | BAS | RES0 | PMC | E |
120
+ * +------+------+-------+-----+----+------+-----+------+-----+---+
121
+ *
122
+ * BT: Breakpoint type (0 = unlinked address match)
123
+ * LBN: Linked BP number (0 = unused)
124
+ * SSC/HMC/PMC: Security, Higher and Priv access control (Table D-12)
125
+ * BAS: Byte Address Select (RES1 for AArch64)
126
+ * E: Enable bit
127
+ *
128
+ * DBGBVR<n>_EL1, Debug Breakpoint Value Registers
129
+ *
130
+ * 63 53 52 49 48 2 1 0
131
+ * +------+-----------+----------+-----+
132
+ * | RESS | VA[52:49] | VA[48:2] | 0 0 |
133
+ * +------+-----------+----------+-----+
134
+ *
135
+ * Depending on the addressing mode bits the top bits of the register
136
+ * are a sign extension of the highest applicable VA bit. Some
137
+ * versions of GDB don't do it correctly so we ensure they are correct
138
+ * here so future PC comparisons will work properly.
139
+ */
140
+
141
+int insert_hw_breakpoint(target_ulong addr)
142
+{
143
+ HWBreakpoint brk = {
144
+ .bcr = 0x1, /* BCR E=1, enable */
145
+ .bvr = sextract64(addr, 0, 53)
146
+ };
147
+
148
+ if (cur_hw_bps >= max_hw_bps) {
149
+ return -ENOBUFS;
150
+ }
151
+
152
+ brk.bcr = deposit32(brk.bcr, 1, 2, 0x3); /* PMC = 11 */
153
+ brk.bcr = deposit32(brk.bcr, 5, 4, 0xf); /* BAS = RES1 */
154
+
155
+ g_array_append_val(hw_breakpoints, brk);
156
+
157
+ return 0;
158
+}
159
+
160
+/**
161
+ * delete_hw_breakpoint()
162
+ * @pc: address of breakpoint
163
+ *
164
+ * Delete a breakpoint and shuffle any above down
165
+ */
166
+
167
+int delete_hw_breakpoint(target_ulong pc)
168
+{
169
+ int i;
170
+ for (i = 0; i < hw_breakpoints->len; i++) {
171
+ HWBreakpoint *brk = get_hw_bp(i);
172
+ if (brk->bvr == pc) {
173
+ g_array_remove_index(hw_breakpoints, i);
174
+ return 0;
175
+ }
176
+ }
177
+ return -ENOENT;
178
+}
179
+
180
+/**
181
+ * insert_hw_watchpoint()
182
+ * @addr: address of watch point
183
+ * @len: size of area
184
+ * @type: type of watch point
185
+ *
186
+ * See ARM ARM D2.10. As with the breakpoints we can do some advanced
187
+ * stuff if we want to. The watch points can be linked with the break
188
+ * points above to make them context aware. However for simplicity
189
+ * currently we only deal with simple read/write watch points.
190
+ *
191
+ * D7.3.11 DBGWCR<n>_EL1, Debug Watchpoint Control Registers
192
+ *
193
+ * 31 29 28 24 23 21 20 19 16 15 14 13 12 5 4 3 2 1 0
194
+ * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+
195
+ * | RES0 | MASK | RES0 | WT | LBN | SSC | HMC | BAS | LSC | PAC | E |
196
+ * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+
197
+ *
198
+ * MASK: num bits addr mask (0=none,01/10=res,11=3 bits (8 bytes))
199
+ * WT: 0 - unlinked, 1 - linked (not currently used)
200
+ * LBN: Linked BP number (not currently used)
201
+ * SSC/HMC/PAC: Security, Higher and Priv access control (Table D2-11)
202
+ * BAS: Byte Address Select
203
+ * LSC: Load/Store control (01: load, 10: store, 11: both)
204
+ * E: Enable
205
+ *
206
+ * The bottom 2 bits of the value register are masked. Therefore to
207
+ * break on any sizes smaller than an unaligned word you need to set
208
+ * MASK=0, BAS=bit per byte in question. For larger regions (^2) you
209
+ * need to ensure you mask the address as required and set BAS=0xff
210
+ */
211
+
212
+int insert_hw_watchpoint(target_ulong addr, target_ulong len, int type)
213
+{
214
+ HWWatchpoint wp = {
215
+ .wcr = R_DBGWCR_E_MASK, /* E=1, enable */
216
+ .wvr = addr & (~0x7ULL),
217
+ .details = { .vaddr = addr, .len = len }
218
+ };
219
+
220
+ if (cur_hw_wps >= max_hw_wps) {
221
+ return -ENOBUFS;
222
+ }
223
+
224
+ /*
225
+ * HMC=0 SSC=0 PAC=3 will hit EL0 or EL1, any security state,
226
+ * valid whether EL3 is implemented or not
227
+ */
228
+ wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, PAC, 3);
229
+
230
+ switch (type) {
231
+ case GDB_WATCHPOINT_READ:
232
+ wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 1);
233
+ wp.details.flags = BP_MEM_READ;
234
+ break;
235
+ case GDB_WATCHPOINT_WRITE:
236
+ wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 2);
237
+ wp.details.flags = BP_MEM_WRITE;
238
+ break;
239
+ case GDB_WATCHPOINT_ACCESS:
240
+ wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 3);
241
+ wp.details.flags = BP_MEM_ACCESS;
242
+ break;
243
+ default:
244
+ g_assert_not_reached();
245
+ break;
246
+ }
247
+ if (len <= 8) {
248
+ /* we align the address and set the bits in BAS */
249
+ int off = addr & 0x7;
250
+ int bas = (1 << len) - 1;
251
+
252
+ wp.wcr = deposit32(wp.wcr, 5 + off, 8 - off, bas);
253
+ } else {
254
+ /* For ranges above 8 bytes we need to be a power of 2 */
255
+ if (is_power_of_2(len)) {
256
+ int bits = ctz64(len);
257
+
258
+ wp.wvr &= ~((1 << bits) - 1);
259
+ wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, MASK, bits);
260
+ wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, BAS, 0xff);
261
+ } else {
262
+ return -ENOBUFS;
263
+ }
264
+ }
265
+
266
+ g_array_append_val(hw_watchpoints, wp);
267
+ return 0;
268
+}
269
+
270
+bool check_watchpoint_in_range(int i, target_ulong addr)
271
+{
272
+ HWWatchpoint *wp = get_hw_wp(i);
273
+ uint64_t addr_top, addr_bottom = wp->wvr;
274
+ int bas = extract32(wp->wcr, 5, 8);
275
+ int mask = extract32(wp->wcr, 24, 4);
276
+
277
+ if (mask) {
278
+ addr_top = addr_bottom + (1 << mask);
279
+ } else {
280
+ /*
281
+ * BAS must be contiguous but can offset against the base
282
+ * address in DBGWVR
283
+ */
284
+ addr_bottom = addr_bottom + ctz32(bas);
285
+ addr_top = addr_bottom + clo32(bas);
286
+ }
287
+
288
+ if (addr >= addr_bottom && addr <= addr_top) {
289
+ return true;
290
+ }
291
+
292
+ return false;
293
+}
294
+
295
+/**
296
+ * delete_hw_watchpoint()
297
+ * @addr: address of breakpoint
298
+ *
299
+ * Delete a breakpoint and shuffle any above down
300
+ */
301
+
302
+int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type)
303
+{
304
+ int i;
305
+ for (i = 0; i < cur_hw_wps; i++) {
306
+ if (check_watchpoint_in_range(i, addr)) {
307
+ g_array_remove_index(hw_watchpoints, i);
308
+ return 0;
309
+ }
310
+ }
311
+ return -ENOENT;
312
+}
313
+
314
+bool find_hw_breakpoint(CPUState *cpu, target_ulong pc)
315
+{
316
+ int i;
317
+
318
+ for (i = 0; i < cur_hw_bps; i++) {
319
+ HWBreakpoint *bp = get_hw_bp(i);
320
+ if (bp->bvr == pc) {
321
+ return true;
322
+ }
323
+ }
324
+ return false;
325
+}
326
+
327
+CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr)
328
+{
329
+ int i;
330
+
331
+ for (i = 0; i < cur_hw_wps; i++) {
332
+ if (check_watchpoint_in_range(i, addr)) {
333
+ return &get_hw_wp(i)->details;
334
+ }
335
+ }
336
+ return NULL;
337
+}
338
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
339
index XXXXXXX..XXXXXXX 100644
340
--- a/target/arm/kvm64.c
341
+++ b/target/arm/kvm64.c
342
@@ -XXX,XX +XXX,XX @@
343
344
static bool have_guest_debug;
345
346
-/*
347
- * Although the ARM implementation of hardware assisted debugging
348
- * allows for different breakpoints per-core, the current GDB
349
- * interface treats them as a global pool of registers (which seems to
350
- * be the case for x86, ppc and s390). As a result we store one copy
351
- * of registers which is used for all active cores.
352
- *
353
- * Write access is serialised by virtue of the GDB protocol which
354
- * updates things. Read access (i.e. when the values are copied to the
355
- * vCPU) is also gated by GDB's run control.
356
- *
357
- * This is not unreasonable as most of the time debugging kernels you
358
- * never know which core will eventually execute your function.
359
- */
360
-
361
-typedef struct {
362
- uint64_t bcr;
363
- uint64_t bvr;
364
-} HWBreakpoint;
365
-
366
-/* The watchpoint registers can cover more area than the requested
367
- * watchpoint so we need to store the additional information
368
- * somewhere. We also need to supply a CPUWatchpoint to the GDB stub
369
- * when the watchpoint is hit.
370
- */
371
-typedef struct {
372
- uint64_t wcr;
373
- uint64_t wvr;
374
- CPUWatchpoint details;
375
-} HWWatchpoint;
376
-
377
-/* Maximum and current break/watch point counts */
378
-int max_hw_bps, max_hw_wps;
379
-GArray *hw_breakpoints, *hw_watchpoints;
380
-
381
-#define cur_hw_wps (hw_watchpoints->len)
382
-#define cur_hw_bps (hw_breakpoints->len)
383
-#define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i))
384
-#define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i))
385
-
386
void kvm_arm_init_debug(KVMState *s)
387
{
388
have_guest_debug = kvm_check_extension(s,
389
@@ -XXX,XX +XXX,XX @@ void kvm_arm_init_debug(KVMState *s)
390
return;
391
}
392
393
-/**
394
- * insert_hw_breakpoint()
395
- * @addr: address of breakpoint
396
- *
397
- * See ARM ARM D2.9.1 for details but here we are only going to create
398
- * simple un-linked breakpoints (i.e. we don't chain breakpoints
399
- * together to match address and context or vmid). The hardware is
400
- * capable of fancier matching but that will require exposing that
401
- * fanciness to GDB's interface
402
- *
403
- * DBGBCR<n>_EL1, Debug Breakpoint Control Registers
404
- *
405
- * 31 24 23 20 19 16 15 14 13 12 9 8 5 4 3 2 1 0
406
- * +------+------+-------+-----+----+------+-----+------+-----+---+
407
- * | RES0 | BT | LBN | SSC | HMC| RES0 | BAS | RES0 | PMC | E |
408
- * +------+------+-------+-----+----+------+-----+------+-----+---+
409
- *
410
- * BT: Breakpoint type (0 = unlinked address match)
411
- * LBN: Linked BP number (0 = unused)
412
- * SSC/HMC/PMC: Security, Higher and Priv access control (Table D-12)
413
- * BAS: Byte Address Select (RES1 for AArch64)
414
- * E: Enable bit
415
- *
416
- * DBGBVR<n>_EL1, Debug Breakpoint Value Registers
417
- *
418
- * 63 53 52 49 48 2 1 0
419
- * +------+-----------+----------+-----+
420
- * | RESS | VA[52:49] | VA[48:2] | 0 0 |
421
- * +------+-----------+----------+-----+
422
- *
423
- * Depending on the addressing mode bits the top bits of the register
424
- * are a sign extension of the highest applicable VA bit. Some
425
- * versions of GDB don't do it correctly so we ensure they are correct
426
- * here so future PC comparisons will work properly.
427
- */
428
-
429
-static int insert_hw_breakpoint(target_ulong addr)
430
-{
86
-{
431
- HWBreakpoint brk = {
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
432
- .bcr = 0x1, /* BCR E=1, enable */
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
433
- .bvr = sextract64(addr, 0, 53)
89
- int which;
434
- };
435
-
436
- if (cur_hw_bps >= max_hw_bps) {
437
- return -ENOBUFS;
438
- }
439
-
440
- brk.bcr = deposit32(brk.bcr, 1, 2, 0x3); /* PMC = 11 */
441
- brk.bcr = deposit32(brk.bcr, 5, 4, 0xf); /* BAS = RES1 */
442
-
443
- g_array_append_val(hw_breakpoints, brk);
444
-
445
- return 0;
446
-}
447
-
448
-/**
449
- * delete_hw_breakpoint()
450
- * @pc: address of breakpoint
451
- *
452
- * Delete a breakpoint and shuffle any above down
453
- */
454
-
455
-static int delete_hw_breakpoint(target_ulong pc)
456
-{
457
- int i;
458
- for (i = 0; i < hw_breakpoints->len; i++) {
459
- HWBreakpoint *brk = get_hw_bp(i);
460
- if (brk->bvr == pc) {
461
- g_array_remove_index(hw_breakpoints, i);
462
- return 0;
463
- }
464
- }
465
- return -ENOENT;
466
-}
467
-
468
-/**
469
- * insert_hw_watchpoint()
470
- * @addr: address of watch point
471
- * @len: size of area
472
- * @type: type of watch point
473
- *
474
- * See ARM ARM D2.10. As with the breakpoints we can do some advanced
475
- * stuff if we want to. The watch points can be linked with the break
476
- * points above to make them context aware. However for simplicity
477
- * currently we only deal with simple read/write watch points.
478
- *
479
- * D7.3.11 DBGWCR<n>_EL1, Debug Watchpoint Control Registers
480
- *
481
- * 31 29 28 24 23 21 20 19 16 15 14 13 12 5 4 3 2 1 0
482
- * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+
483
- * | RES0 | MASK | RES0 | WT | LBN | SSC | HMC | BAS | LSC | PAC | E |
484
- * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+
485
- *
486
- * MASK: num bits addr mask (0=none,01/10=res,11=3 bits (8 bytes))
487
- * WT: 0 - unlinked, 1 - linked (not currently used)
488
- * LBN: Linked BP number (not currently used)
489
- * SSC/HMC/PAC: Security, Higher and Priv access control (Table D2-11)
490
- * BAS: Byte Address Select
491
- * LSC: Load/Store control (01: load, 10: store, 11: both)
492
- * E: Enable
493
- *
494
- * The bottom 2 bits of the value register are masked. Therefore to
495
- * break on any sizes smaller than an unaligned word you need to set
496
- * MASK=0, BAS=bit per byte in question. For larger regions (^2) you
497
- * need to ensure you mask the address as required and set BAS=0xff
498
- */
499
-
500
-static int insert_hw_watchpoint(target_ulong addr,
501
- target_ulong len, int type)
502
-{
503
- HWWatchpoint wp = {
504
- .wcr = R_DBGWCR_E_MASK, /* E=1, enable */
505
- .wvr = addr & (~0x7ULL),
506
- .details = { .vaddr = addr, .len = len }
507
- };
508
-
509
- if (cur_hw_wps >= max_hw_wps) {
510
- return -ENOBUFS;
511
- }
512
-
90
-
513
- /*
91
- /*
514
- * HMC=0 SSC=0 PAC=3 will hit EL0 or EL1, any security state,
92
- * We guarantee not to require the target to tell us how to
515
- * valid whether EL3 is implemented or not
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.
516
- */
96
- */
517
- wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, PAC, 3);
97
- assert(!status->default_nan_mode);
518
-
98
-
519
- switch (type) {
99
- if (infzero) {
520
- case GDB_WATCHPOINT_READ:
100
- /*
521
- wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 1);
101
- * Inf * 0 + NaN -- some implementations return the default NaN here,
522
- wp.details.flags = BP_MEM_READ;
102
- * and some return the input NaN.
523
- break;
103
- */
524
- case GDB_WATCHPOINT_WRITE:
104
- switch (status->float_infzeronan_rule) {
525
- wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 2);
105
- case float_infzeronan_dnan_never:
526
- wp.details.flags = BP_MEM_WRITE;
106
- return 2;
527
- break;
107
- case float_infzeronan_dnan_always:
528
- case GDB_WATCHPOINT_ACCESS:
108
- return 3;
529
- wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 3);
109
- case float_infzeronan_dnan_if_qnan:
530
- wp.details.flags = BP_MEM_ACCESS;
110
- return is_qnan(c_cls) ? 3 : 2;
531
- break;
111
- default:
532
- default:
112
- g_assert_not_reached();
533
- g_assert_not_reached();
534
- break;
535
- }
536
- if (len <= 8) {
537
- /* we align the address and set the bits in BAS */
538
- int off = addr & 0x7;
539
- int bas = (1 << len) - 1;
540
-
541
- wp.wcr = deposit32(wp.wcr, 5 + off, 8 - off, bas);
542
- } else {
543
- /* For ranges above 8 bytes we need to be a power of 2 */
544
- if (is_power_of_2(len)) {
545
- int bits = ctz64(len);
546
-
547
- wp.wvr &= ~((1 << bits) - 1);
548
- wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, MASK, bits);
549
- wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, BAS, 0xff);
550
- } else {
551
- return -ENOBUFS;
552
- }
113
- }
553
- }
114
- }
554
-
115
-
555
- g_array_append_val(hw_watchpoints, wp);
116
- assert(rule != float_3nan_prop_none);
556
- return 0;
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;
557
-}
130
-}
558
-
131
-
559
-
132
/*----------------------------------------------------------------------------
560
-static bool check_watchpoint_in_range(int i, target_ulong addr)
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
561
-{
134
| NaN; otherwise returns 0.
562
- HWWatchpoint *wp = get_hw_wp(i);
563
- uint64_t addr_top, addr_bottom = wp->wvr;
564
- int bas = extract32(wp->wcr, 5, 8);
565
- int mask = extract32(wp->wcr, 24, 4);
566
-
567
- if (mask) {
568
- addr_top = addr_bottom + (1 << mask);
569
- } else {
570
- /* BAS must be contiguous but can offset against the base
571
- * address in DBGWVR */
572
- addr_bottom = addr_bottom + ctz32(bas);
573
- addr_top = addr_bottom + clo32(bas);
574
- }
575
-
576
- if (addr >= addr_bottom && addr <= addr_top) {
577
- return true;
578
- }
579
-
580
- return false;
581
-}
582
-
583
-/**
584
- * delete_hw_watchpoint()
585
- * @addr: address of breakpoint
586
- *
587
- * Delete a breakpoint and shuffle any above down
588
- */
589
-
590
-static int delete_hw_watchpoint(target_ulong addr,
591
- target_ulong len, int type)
592
-{
593
- int i;
594
- for (i = 0; i < cur_hw_wps; i++) {
595
- if (check_watchpoint_in_range(i, addr)) {
596
- g_array_remove_index(hw_watchpoints, i);
597
- return 0;
598
- }
599
- }
600
- return -ENOENT;
601
-}
602
-
603
-
604
int kvm_arch_insert_hw_breakpoint(target_ulong addr,
605
target_ulong len, int type)
606
{
607
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_hw_debug_active(CPUState *cs)
608
return ((cur_hw_wps > 0) || (cur_hw_bps > 0));
609
}
610
611
-static bool find_hw_breakpoint(CPUState *cpu, target_ulong pc)
612
-{
613
- int i;
614
-
615
- for (i = 0; i < cur_hw_bps; i++) {
616
- HWBreakpoint *bp = get_hw_bp(i);
617
- if (bp->bvr == pc) {
618
- return true;
619
- }
620
- }
621
- return false;
622
-}
623
-
624
-static CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr)
625
-{
626
- int i;
627
-
628
- for (i = 0; i < cur_hw_wps; i++) {
629
- if (check_watchpoint_in_range(i, addr)) {
630
- return &get_hw_wp(i)->details;
631
- }
632
- }
633
- return NULL;
634
-}
635
-
636
static bool kvm_arm_set_device_attr(CPUState *cs, struct kvm_device_attr *attr,
637
const char *name)
638
{
639
diff --git a/target/arm/meson.build b/target/arm/meson.build
640
index XXXXXXX..XXXXXXX 100644
641
--- a/target/arm/meson.build
642
+++ b/target/arm/meson.build
643
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
644
))
645
arm_ss.add(zlib)
646
647
-arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
648
+arm_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
649
+arm_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
650
651
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
652
'cpu64.c',
653
--
135
--
654
2.34.1
136
2.34.1
655
137
656
138
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Pass the individual memop to gen_mte_checkN.
3
Remove "3" as a special case for which and simply
4
For the moment, do nothing with it.
4
branch to return the desired value.
5
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230530191438.411344-14-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-4-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
---
10
---
11
target/arm/tcg/translate-a64.h | 2 +-
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
12
target/arm/tcg/translate-a64.c | 31 +++++++++++++++++++------------
12
1 file changed, 10 insertions(+), 10 deletions(-)
13
target/arm/tcg/translate-sve.c | 4 ++--
14
3 files changed, 22 insertions(+), 15 deletions(-)
15
13
16
diff --git a/target/arm/tcg/translate-a64.h b/target/arm/tcg/translate-a64.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/target/arm/tcg/translate-a64.h
16
--- a/fpu/softfloat-parts.c.inc
19
+++ b/target/arm/tcg/translate-a64.h
17
+++ b/fpu/softfloat-parts.c.inc
20
@@ -XXX,XX +XXX,XX @@ TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
19
* But if we're not in default-NaN mode then the target must
22
bool tag_checked, MemOp memop);
20
* specify.
23
TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
21
*/
24
- bool tag_checked, int size);
22
- which = 3;
25
+ bool tag_checked, int total_size, MemOp memop);
23
+ goto default_nan;
26
24
} else if (infzero) {
27
/* We should have at some point before trying to access an FP register
25
/*
28
* done the necessary access check, so assert that
26
* Inf * 0 + NaN -- some implementations return the
29
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
index XXXXXXX..XXXXXXX 100644
28
*/
31
--- a/target/arm/tcg/translate-a64.c
29
switch (s->float_infzeronan_rule) {
32
+++ b/target/arm/tcg/translate-a64.c
30
case float_infzeronan_dnan_never:
33
@@ -XXX,XX +XXX,XX @@ TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
31
- which = 2;
34
* For MTE, check multiple logical sequential accesses.
32
break;
35
*/
33
case float_infzeronan_dnan_always:
36
TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
34
- which = 3;
37
- bool tag_checked, int size)
35
- break;
38
+ bool tag_checked, int total_size, MemOp single_mop)
36
+ goto default_nan;
39
{
37
case float_infzeronan_dnan_if_qnan:
40
if (tag_checked && s->mte_active[0]) {
38
- which = is_qnan(c->cls) ? 3 : 2;
41
TCGv_i64 ret;
39
+ if (is_qnan(c->cls)) {
42
@@ -XXX,XX +XXX,XX @@ TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
40
+ goto default_nan;
43
desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
41
+ }
44
desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
42
break;
45
desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
43
default:
46
- desc = FIELD_DP32(desc, MTEDESC, SIZEM1, size - 1);
44
g_assert_not_reached();
47
+ desc = FIELD_DP32(desc, MTEDESC, SIZEM1, total_size - 1);
45
}
48
46
+ which = 2;
49
ret = tcg_temp_new_i64();
47
} else {
50
gen_helper_mte_check(ret, cpu_env, tcg_constant_i32(desc), addr);
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
51
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
52
bool is_vector = extract32(insn, 26, 1);
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
53
bool is_load = extract32(insn, 22, 1);
54
int opc = extract32(insn, 30, 2);
55
-
56
bool is_signed = false;
57
bool postindex = false;
58
bool wback = false;
59
bool set_tag = false;
60
-
61
TCGv_i64 clean_addr, dirty_addr;
62
-
63
+ MemOp mop;
64
int size;
65
66
if (opc == 3) {
67
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
68
}
51
}
69
}
52
}
70
53
71
+ if (is_vector) {
54
- if (which == 3) {
72
+ mop = finalize_memop_asimd(s, size);
55
- parts_default_nan(a, s);
73
+ } else {
56
- return a;
74
+ mop = finalize_memop(s, size);
57
- }
75
+ }
76
clean_addr = gen_mte_checkN(s, dirty_addr, !is_load,
77
- (wback || rn != 31) && !set_tag, 2 << size);
78
+ (wback || rn != 31) && !set_tag,
79
+ 2 << size, mop);
80
81
if (is_vector) {
82
- MemOp mop = finalize_memop_asimd(s, size);
83
-
58
-
84
+ /* LSE2 does not merge FP pairs; leave these as separate operations. */
59
switch (which) {
85
if (is_load) {
60
case 0:
86
do_fp_ld(s, rt, clean_addr, mop);
61
break;
87
} else {
62
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
88
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
63
parts_silence_nan(a, s);
89
} else {
64
}
90
TCGv_i64 tcg_rt = cpu_reg(s, rt);
65
return a;
91
TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
92
- MemOp mop = size + 1;
93
94
/*
95
+ * We built mop above for the single logical access -- rebuild it
96
+ * now for the paired operation.
97
+ *
98
* With LSE2, non-sign-extending pairs are treated atomically if
99
* aligned, and if unaligned one of the pair will be completely
100
* within a 16-byte block and that element will be atomic.
101
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
102
* This treats sign-extending loads like zero-extending loads,
103
* since that reuses the most code below.
104
*/
105
+ mop = size + 1;
106
if (s->align_mem) {
107
mop |= (size == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
108
}
109
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
110
* promote consecutive little-endian elements below.
111
*/
112
clean_addr = gen_mte_checkN(s, tcg_rn, is_store, is_postidx || rn != 31,
113
- total);
114
+ total, finalize_memop(s, size));
115
116
/*
117
* Consecutive little-endian elements from a single register
118
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
119
total = selem << scale;
120
tcg_rn = cpu_reg_sp(s, rn);
121
122
- clean_addr = gen_mte_checkN(s, tcg_rn, !is_load, is_postidx || rn != 31,
123
- total);
124
mop = finalize_memop(s, scale);
125
126
+ clean_addr = gen_mte_checkN(s, tcg_rn, !is_load, is_postidx || rn != 31,
127
+ total, mop);
128
+
66
+
129
tcg_ebytes = tcg_constant_i64(1 << scale);
67
+ default_nan:
130
for (xs = 0; xs < selem; xs++) {
68
+ parts_default_nan(a, s);
131
if (replicate) {
69
+ return a;
132
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
70
}
133
index XXXXXXX..XXXXXXX 100644
71
134
--- a/target/arm/tcg/translate-sve.c
72
/*
135
+++ b/target/arm/tcg/translate-sve.c
136
@@ -XXX,XX +XXX,XX @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
137
138
dirty_addr = tcg_temp_new_i64();
139
tcg_gen_addi_i64(dirty_addr, cpu_reg_sp(s, rn), imm);
140
- clean_addr = gen_mte_checkN(s, dirty_addr, false, rn != 31, len);
141
+ clean_addr = gen_mte_checkN(s, dirty_addr, false, rn != 31, len, MO_8);
142
143
/*
144
* Note that unpredicated load/store of vector/predicate registers
145
@@ -XXX,XX +XXX,XX @@ void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
146
147
dirty_addr = tcg_temp_new_i64();
148
tcg_gen_addi_i64(dirty_addr, cpu_reg_sp(s, rn), imm);
149
- clean_addr = gen_mte_checkN(s, dirty_addr, false, rn != 31, len);
150
+ clean_addr = gen_mte_checkN(s, dirty_addr, false, rn != 31, len, MO_8);
151
152
/* Note that unpredicated load/store of vector/predicate registers
153
* are defined as a stream of bytes, which equates to little-endian
154
--
73
--
155
2.34.1
74
2.34.1
75
76
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This fixes a bug in that these two insns should have been using atomic
3
Assign the pointer return value to 'a' directly,
4
16-byte stores, since MTE is ARMv8.5 and LSE2 is mandatory from ARMv8.4.
4
rather than going through an intermediary index.
5
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230530191438.411344-7-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-5-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
---
10
---
11
target/arm/tcg/translate-a64.c | 17 ++++++++++-------
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
12
1 file changed, 10 insertions(+), 7 deletions(-)
12
1 file changed, 10 insertions(+), 22 deletions(-)
13
13
14
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/tcg/translate-a64.c
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/tcg/translate-a64.c
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
19
FloatPartsN *c, float_status *s,
20
if (is_zero) {
20
int ab_mask, int abc_mask)
21
TCGv_i64 clean_addr = clean_data_tbi(s, addr);
21
{
22
- TCGv_i64 tcg_zero = tcg_constant_i64(0);
22
- int which;
23
+ TCGv_i64 zero64 = tcg_constant_i64(0);
23
bool infzero = (ab_mask == float_cmask_infzero);
24
+ TCGv_i128 zero128 = tcg_temp_new_i128();
24
bool have_snan = (abc_mask & float_cmask_snan);
25
int mem_index = get_mem_index(s);
25
+ FloatPartsN *ret;
26
- int i, n = (1 + is_pair) << LOG2_TAG_GRANULE;
26
27
+ MemOp mop = finalize_memop(s, MO_128 | MO_ALIGN);
27
if (unlikely(have_snan)) {
28
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
29
- tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index,
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
- MO_UQ | MO_ALIGN_16);
30
default:
31
- for (i = 8; i < n; i += 8) {
31
g_assert_not_reached();
32
- tcg_gen_addi_i64(clean_addr, clean_addr, 8);
32
}
33
- tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index, MO_UQ);
33
- which = 2;
34
+ tcg_gen_concat_i64_i128(zero128, zero64, zero64);
34
+ ret = c;
35
+
35
} else {
36
+ /* This is 1 or 2 atomic 16-byte operations. */
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
37
+ tcg_gen_qemu_st_i128(zero128, clean_addr, mem_index, mop);
37
+ FloatPartsN *val[3] = { a, b, c };
38
+ if (is_pair) {
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
+ tcg_gen_addi_i64(clean_addr, clean_addr, 16);
39
40
+ tcg_gen_qemu_st_i128(zero128, clean_addr, mem_index, mop);
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));
41
}
56
}
42
}
57
}
43
58
59
- switch (which) {
60
- case 0:
61
- break;
62
- case 1:
63
- a = b;
64
- break;
65
- case 2:
66
- a = c;
67
- break;
68
- default:
69
- g_assert_not_reached();
70
+ if (is_snan(ret->cls)) {
71
+ parts_silence_nan(ret, s);
72
}
73
- if (is_snan(a->cls)) {
74
- parts_silence_nan(a, s);
75
- }
76
- return a;
77
+ return ret;
78
79
default_nan:
80
parts_default_nan(a, s);
44
--
81
--
45
2.34.1
82
2.34.1
83
84
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We are going to need the complete memop beforehand,
3
While all indices into val[] should be in [0-2], the mask
4
so let's not compute it twice.
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.
5
7
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
9
Message-id: 20230530191438.411344-12-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/tcg/translate-a64.c | 43 ++++++++++++++++++----------------
13
fpu/softfloat-parts.c.inc | 2 +-
13
1 file changed, 23 insertions(+), 20 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
15
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/tcg/translate-a64.c
18
--- a/fpu/softfloat-parts.c.inc
18
+++ b/target/arm/tcg/translate-a64.c
19
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@ static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
20
/*
21
}
21
* Store from FP register to memory
22
ret = c;
22
*/
23
-static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
24
+static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, MemOp mop)
25
{
26
/* This writes the bottom N bits of a 128 bit wide vector to memory */
27
TCGv_i64 tmplo = tcg_temp_new_i64();
28
- MemOp mop = finalize_memop_asimd(s, size);
29
30
tcg_gen_ld_i64(tmplo, cpu_env, fp_reg_offset(s, srcidx, MO_64));
31
32
- if (size < MO_128) {
33
+ if ((mop & MO_SIZE) < MO_128) {
34
tcg_gen_qemu_st_i64(tmplo, tcg_addr, get_mem_index(s), mop);
35
} else {
23
} else {
36
TCGv_i64 tmphi = tcg_temp_new_i64();
24
- FloatPartsN *val[3] = { a, b, c };
37
@@ -XXX,XX +XXX,XX @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
38
/*
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
* Load from memory to FP register
27
40
*/
28
assert(rule != float_3nan_prop_none);
41
-static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
42
+static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, MemOp mop)
43
{
44
/* This always zero-extends and writes to a full 128 bit wide vector */
45
TCGv_i64 tmplo = tcg_temp_new_i64();
46
TCGv_i64 tmphi = NULL;
47
- MemOp mop = finalize_memop_asimd(s, size);
48
49
- if (size < MO_128) {
50
+ if ((mop & MO_SIZE) < MO_128) {
51
tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), mop);
52
} else {
53
TCGv_i128 t16 = tcg_temp_new_i128();
54
@@ -XXX,XX +XXX,XX @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
55
bool is_signed = false;
56
int size = 2;
57
TCGv_i64 tcg_rt, clean_addr;
58
+ MemOp memop;
59
60
if (is_vector) {
61
if (opc == 3) {
62
@@ -XXX,XX +XXX,XX @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
63
if (!fp_access_check(s)) {
64
return;
65
}
66
+ memop = finalize_memop_asimd(s, size);
67
} else {
68
if (opc == 3) {
69
/* PRFM (literal) : prefetch */
70
@@ -XXX,XX +XXX,XX @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
71
}
72
size = 2 + extract32(opc, 0, 1);
73
is_signed = extract32(opc, 1, 1);
74
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
75
}
76
77
tcg_rt = cpu_reg(s, rt);
78
79
clean_addr = tcg_temp_new_i64();
80
gen_pc_plus_diff(s, clean_addr, imm);
81
+
82
if (is_vector) {
83
- do_fp_ld(s, rt, clean_addr, size);
84
+ do_fp_ld(s, rt, clean_addr, memop);
85
} else {
86
/* Only unsigned 32bit loads target 32bit registers. */
87
bool iss_sf = opc != 0;
88
- MemOp memop = finalize_memop(s, size + is_signed * MO_SIGN);
89
-
90
do_gpr_ld(s, tcg_rt, clean_addr, memop, false, true, rt, iss_sf, false);
91
}
92
}
93
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
94
(wback || rn != 31) && !set_tag, 2 << size);
95
96
if (is_vector) {
97
+ MemOp mop = finalize_memop_asimd(s, size);
98
+
99
if (is_load) {
100
- do_fp_ld(s, rt, clean_addr, size);
101
+ do_fp_ld(s, rt, clean_addr, mop);
102
} else {
103
- do_fp_st(s, rt, clean_addr, size);
104
+ do_fp_st(s, rt, clean_addr, mop);
105
}
106
tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
107
if (is_load) {
108
- do_fp_ld(s, rt2, clean_addr, size);
109
+ do_fp_ld(s, rt2, clean_addr, mop);
110
} else {
111
- do_fp_st(s, rt2, clean_addr, size);
112
+ do_fp_st(s, rt2, clean_addr, mop);
113
}
114
} else {
115
TCGv_i64 tcg_rt = cpu_reg(s, rt);
116
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
117
if (!fp_access_check(s)) {
118
return;
119
}
120
+ memop = finalize_memop_asimd(s, size);
121
} else {
122
if (size == 3 && opc == 2) {
123
/* PRFM - prefetch */
124
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
125
is_store = (opc == 0);
126
is_signed = !is_store && extract32(opc, 1, 1);
127
is_extended = (size < 3) && extract32(opc, 0, 1);
128
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
129
}
130
131
switch (idx) {
132
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
133
}
134
135
memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
136
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
137
138
clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
139
writeback || rn != 31,
140
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
141
142
if (is_vector) {
143
if (is_store) {
144
- do_fp_st(s, rt, clean_addr, size);
145
+ do_fp_st(s, rt, clean_addr, memop);
146
} else {
147
- do_fp_ld(s, rt, clean_addr, size);
148
+ do_fp_ld(s, rt, clean_addr, memop);
149
}
150
} else {
151
TCGv_i64 tcg_rt = cpu_reg(s, rt);
152
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
153
154
if (is_vector) {
155
if (is_store) {
156
- do_fp_st(s, rt, clean_addr, size);
157
+ do_fp_st(s, rt, clean_addr, memop);
158
} else {
159
- do_fp_ld(s, rt, clean_addr, size);
160
+ do_fp_ld(s, rt, clean_addr, memop);
161
}
162
} else {
163
TCGv_i64 tcg_rt = cpu_reg(s, rt);
164
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
165
166
if (is_vector) {
167
if (is_store) {
168
- do_fp_st(s, rt, clean_addr, size);
169
+ do_fp_st(s, rt, clean_addr, memop);
170
} else {
171
- do_fp_ld(s, rt, clean_addr, size);
172
+ do_fp_ld(s, rt, clean_addr, memop);
173
}
174
} else {
175
TCGv_i64 tcg_rt = cpu_reg(s, rt);
176
--
29
--
177
2.34.1
30
2.34.1
178
31
179
32
diff view generated by jsdifflib
1
From: Vikram Garhwal <vikram.garhwal@amd.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN bus
3
This function is part of the public interface and
4
implementation. Bus connection and socketCAN connection for each CAN module
4
is not "specialized" to any target in any way.
5
can be set through command lines.
6
5
7
Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-7-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
---
10
---
11
include/hw/net/xlnx-versal-canfd.h | 87 ++
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
12
hw/net/can/xlnx-versal-canfd.c | 2107 ++++++++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
13
hw/net/can/meson.build | 1 +
13
2 files changed, 52 insertions(+), 52 deletions(-)
14
hw/net/can/trace-events | 7 +
15
4 files changed, 2202 insertions(+)
16
create mode 100644 include/hw/net/xlnx-versal-canfd.h
17
create mode 100644 hw/net/can/xlnx-versal-canfd.c
18
14
19
diff --git a/include/hw/net/xlnx-versal-canfd.h b/include/hw/net/xlnx-versal-canfd.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
20
new file mode 100644
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX
17
--- a/fpu/softfloat.c
22
--- /dev/null
18
+++ b/fpu/softfloat.c
23
+++ b/include/hw/net/xlnx-versal-canfd.h
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
24
@@ -XXX,XX +XXX,XX @@
20
*zExpPtr = 1 - shiftCount;
25
+/*
21
}
26
+ * QEMU model of the Xilinx Versal CANFD Controller.
22
27
+ *
23
+/*----------------------------------------------------------------------------
28
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
24
+| Takes two extended double-precision floating-point values `a' and `b', one
29
+ *
25
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
30
+ * Written-by: Vikram Garhwal<vikram.garhwal@amd.com>
26
+| `b' is a signaling NaN, the invalid exception is raised.
31
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
27
+*----------------------------------------------------------------------------*/
32
+ * Pavel Pisa.
33
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
34
+ * of this software and associated documentation files (the "Software"), to deal
35
+ * in the Software without restriction, including without limitation the rights
36
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37
+ * copies of the Software, and to permit persons to whom the Software is
38
+ * furnished to do so, subject to the following conditions:
39
+ *
40
+ * The above copyright notice and this permission notice shall be included in
41
+ * all copies or substantial portions of the Software.
42
+ *
43
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
46
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
49
+ * THE SOFTWARE.
50
+ */
51
+
28
+
52
+#ifndef HW_CANFD_XILINX_H
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
53
+#define HW_CANFD_XILINX_H
30
+{
31
+ bool aIsLargerSignificand;
32
+ FloatClass a_cls, b_cls;
54
+
33
+
55
+#include "hw/register.h"
34
+ /* This is not complete, but is good enough for pickNaN. */
56
+#include "hw/ptimer.h"
35
+ a_cls = (!floatx80_is_any_nan(a)
57
+#include "net/can_emu.h"
36
+ ? float_class_normal
58
+#include "hw/qdev-clock.h"
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);
59
+
45
+
60
+#define TYPE_XILINX_CANFD "xlnx.versal-canfd"
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
61
+
47
+ float_raise(float_flag_invalid, status);
62
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCANFDState, XILINX_CANFD)
63
+
64
+#define NUM_REGS_PER_MSG_SPACE 18 /* 1 ID + 1 DLC + 16 Data(DW0 - DW15) regs. */
65
+#define MAX_NUM_RX 64
66
+#define OFFSET_RX1_DW15 (0x4144 / 4)
67
+#define CANFD_TIMER_MAX 0xFFFFUL
68
+#define CANFD_DEFAULT_CLOCK (25 * 1000 * 1000)
69
+
70
+#define XLNX_VERSAL_CANFD_R_MAX (OFFSET_RX1_DW15 + \
71
+ ((MAX_NUM_RX - 1) * NUM_REGS_PER_MSG_SPACE) + 1)
72
+
73
+typedef struct XlnxVersalCANFDState {
74
+ SysBusDevice parent_obj;
75
+ MemoryRegion iomem;
76
+
77
+ qemu_irq irq_canfd_int;
78
+ qemu_irq irq_addr_err;
79
+
80
+ RegisterInfo reg_info[XLNX_VERSAL_CANFD_R_MAX];
81
+ RegisterAccessInfo *tx_regs;
82
+ RegisterAccessInfo *rx0_regs;
83
+ RegisterAccessInfo *rx1_regs;
84
+ RegisterAccessInfo *af_regs;
85
+ RegisterAccessInfo *txe_regs;
86
+ RegisterAccessInfo *rx_mailbox_regs;
87
+ RegisterAccessInfo *af_mask_regs_mailbox;
88
+
89
+ uint32_t regs[XLNX_VERSAL_CANFD_R_MAX];
90
+
91
+ ptimer_state *canfd_timer;
92
+
93
+ CanBusClientState bus_client;
94
+ CanBusState *canfdbus;
95
+
96
+ struct {
97
+ uint8_t rx0_fifo;
98
+ uint8_t rx1_fifo;
99
+ uint8_t tx_fifo;
100
+ bool enable_rx_fifo1;
101
+ uint32_t ext_clk_freq;
102
+ } cfg;
103
+
104
+} XlnxVersalCANFDState;
105
+
106
+typedef struct tx_ready_reg_info {
107
+ uint32_t can_id;
108
+ uint32_t reg_num;
109
+} tx_ready_reg_info;
110
+
111
+#endif
112
diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
113
new file mode 100644
114
index XXXXXXX..XXXXXXX
115
--- /dev/null
116
+++ b/hw/net/can/xlnx-versal-canfd.c
117
@@ -XXX,XX +XXX,XX @@
118
+/*
119
+ * QEMU model of the Xilinx Versal CANFD device.
120
+ *
121
+ * This implementation is based on the following datasheet:
122
+ * https://docs.xilinx.com/v/u/2.0-English/pg223-canfd
123
+ *
124
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
125
+ *
126
+ * Written-by: Vikram Garhwal <vikram.garhwal@amd.com>
127
+ *
128
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
129
+ * Pavel Pisa
130
+ *
131
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
132
+ * of this software and associated documentation files (the "Software"), to deal
133
+ * in the Software without restriction, including without limitation the rights
134
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
135
+ * copies of the Software, and to permit persons to whom the Software is
136
+ * furnished to do so, subject to the following conditions:
137
+ *
138
+ * The above copyright notice and this permission notice shall be included in
139
+ * all copies or substantial portions of the Software.
140
+ *
141
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
142
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
143
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
144
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
145
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
146
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
147
+ * THE SOFTWARE.
148
+ */
149
+
150
+#include "qemu/osdep.h"
151
+#include "hw/sysbus.h"
152
+#include "hw/irq.h"
153
+#include "hw/register.h"
154
+#include "qapi/error.h"
155
+#include "qemu/bitops.h"
156
+#include "qemu/log.h"
157
+#include "qemu/cutils.h"
158
+#include "qemu/event_notifier.h"
159
+#include "hw/qdev-properties.h"
160
+#include "qom/object_interfaces.h"
161
+#include "migration/vmstate.h"
162
+#include "hw/net/xlnx-versal-canfd.h"
163
+#include "trace.h"
164
+
165
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
166
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
167
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
168
+REG32(MODE_SELECT_REGISTER, 0x4)
169
+ FIELD(MODE_SELECT_REGISTER, ITO, 8, 8)
170
+ FIELD(MODE_SELECT_REGISTER, ABR, 7, 1)
171
+ FIELD(MODE_SELECT_REGISTER, SBR, 6, 1)
172
+ FIELD(MODE_SELECT_REGISTER, DPEE, 5, 1)
173
+ FIELD(MODE_SELECT_REGISTER, DAR, 4, 1)
174
+ FIELD(MODE_SELECT_REGISTER, BRSD, 3, 1)
175
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
176
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
177
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
178
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
179
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
180
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
181
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 16, 7)
182
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 8, 7)
183
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 8)
184
+REG32(ERROR_COUNTER_REGISTER, 0x10)
185
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
186
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
187
+REG32(ERROR_STATUS_REGISTER, 0x14)
188
+ FIELD(ERROR_STATUS_REGISTER, F_BERR, 11, 1)
189
+ FIELD(ERROR_STATUS_REGISTER, F_STER, 10, 1)
190
+ FIELD(ERROR_STATUS_REGISTER, F_FMER, 9, 1)
191
+ FIELD(ERROR_STATUS_REGISTER, F_CRCER, 8, 1)
192
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
193
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
194
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
195
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
196
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
197
+REG32(STATUS_REGISTER, 0x18)
198
+ FIELD(STATUS_REGISTER, TDCV, 16, 7)
199
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
200
+ FIELD(STATUS_REGISTER, BSFR_CONFIG, 10, 1)
201
+ FIELD(STATUS_REGISTER, PEE_CONFIG, 9, 1)
202
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
203
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
204
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
205
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
206
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
207
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
208
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
209
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
210
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
211
+ FIELD(INTERRUPT_STATUS_REGISTER, TXEWMFLL, 31, 1)
212
+ FIELD(INTERRUPT_STATUS_REGISTER, TXEOFLW, 30, 1)
213
+ FIELD(INTERRUPT_STATUS_REGISTER, RXBOFLW_BI, 24, 6)
214
+ FIELD(INTERRUPT_STATUS_REGISTER, RXLRM_BI, 18, 6)
215
+ FIELD(INTERRUPT_STATUS_REGISTER, RXMNF, 17, 1)
216
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL_1, 16, 1)
217
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 15, 1)
218
+ FIELD(INTERRUPT_STATUS_REGISTER, TXCRS, 14, 1)
219
+ FIELD(INTERRUPT_STATUS_REGISTER, TXRRS, 13, 1)
220
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
221
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
222
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
223
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
224
+ /*
225
+ * In the original HW description below bit is named as ERROR but an ERROR
226
+ * field name collides with a macro in Windows build. To avoid Windows build
227
+ * failures, the bit is renamed to ERROR_BIT.
228
+ */
229
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR_BIT, 8, 1)
230
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFOFLW, 6, 1)
231
+ FIELD(INTERRUPT_STATUS_REGISTER, TSCNT_OFLW, 5, 1)
232
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
233
+ FIELD(INTERRUPT_STATUS_REGISTER, BSFRD, 3, 1)
234
+ FIELD(INTERRUPT_STATUS_REGISTER, PEE, 2, 1)
235
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
236
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
237
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
238
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXEWMFLL, 31, 1)
239
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXEOFLW, 30, 1)
240
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXMNF, 17, 1)
241
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL_1, 16, 1)
242
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFOFLW_1, 15, 1)
243
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXCRS, 14, 1)
244
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXRRS, 13, 1)
245
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
246
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
247
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
248
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
249
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
250
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERFXOFLW, 6, 1)
251
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETSCNT_OFLW, 5, 1)
252
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
253
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSFRD, 3, 1)
254
+ FIELD(INTERRUPT_ENABLE_REGISTER, EPEE, 2, 1)
255
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
256
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLOST, 0, 1)
257
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
258
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXEWMFLL, 31, 1)
259
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXEOFLW, 30, 1)
260
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXMNF, 17, 1)
261
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL_1, 16, 1)
262
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFOFLW_1, 15, 1)
263
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXCRS, 14, 1)
264
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXRRS, 13, 1)
265
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
266
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
267
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
268
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
269
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
270
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRFXOFLW, 6, 1)
271
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTSCNT_OFLW, 5, 1)
272
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSFRD, 3, 1)
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CPEE, 2, 1)
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLOST, 0, 1)
277
+REG32(TIMESTAMP_REGISTER, 0x28)
278
+ FIELD(TIMESTAMP_REGISTER, TIMESTAMP_CNT, 16, 16)
279
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
280
+REG32(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x88)
281
+ FIELD(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, TDC, 16, 1)
282
+ FIELD(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, TDCOFF, 8, 6)
283
+ FIELD(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, DP_BRP, 0, 8)
284
+REG32(DATA_PHASE_BIT_TIMING_REGISTER, 0x8c)
285
+ FIELD(DATA_PHASE_BIT_TIMING_REGISTER, DP_SJW, 16, 4)
286
+ FIELD(DATA_PHASE_BIT_TIMING_REGISTER, DP_TS2, 8, 4)
287
+ FIELD(DATA_PHASE_BIT_TIMING_REGISTER, DP_TS1, 0, 5)
288
+REG32(TX_BUFFER_READY_REQUEST_REGISTER, 0x90)
289
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR31, 31, 1)
290
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR30, 30, 1)
291
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR29, 29, 1)
292
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR28, 28, 1)
293
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR27, 27, 1)
294
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR26, 26, 1)
295
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR25, 25, 1)
296
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR24, 24, 1)
297
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR23, 23, 1)
298
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR22, 22, 1)
299
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR21, 21, 1)
300
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR20, 20, 1)
301
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR19, 19, 1)
302
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR18, 18, 1)
303
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR17, 17, 1)
304
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR16, 16, 1)
305
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR15, 15, 1)
306
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR14, 14, 1)
307
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR13, 13, 1)
308
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR12, 12, 1)
309
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR11, 11, 1)
310
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR10, 10, 1)
311
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR9, 9, 1)
312
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR8, 8, 1)
313
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR7, 7, 1)
314
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR6, 6, 1)
315
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR5, 5, 1)
316
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR4, 4, 1)
317
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR3, 3, 1)
318
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR2, 2, 1)
319
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR1, 1, 1)
320
+ FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR0, 0, 1)
321
+REG32(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, 0x94)
322
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS31, 31, 1)
323
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS30, 30, 1)
324
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS29, 29, 1)
325
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS28, 28, 1)
326
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS27, 27, 1)
327
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS26, 26, 1)
328
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS25, 25, 1)
329
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS24, 24, 1)
330
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS23, 23, 1)
331
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS22, 22, 1)
332
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS21, 21, 1)
333
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS20, 20, 1)
334
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS19, 19, 1)
335
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS18, 18, 1)
336
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS17, 17, 1)
337
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS16, 16, 1)
338
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS15, 15, 1)
339
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS14, 14, 1)
340
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS13, 13, 1)
341
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS12, 12, 1)
342
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS11, 11, 1)
343
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS10, 10, 1)
344
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS9, 9, 1)
345
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS8, 8, 1)
346
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS7, 7, 1)
347
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS6, 6, 1)
348
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS5, 5, 1)
349
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS4, 4, 1)
350
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS3, 3, 1)
351
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS2, 2, 1)
352
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS1, 1, 1)
353
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS0, 0, 1)
354
+REG32(TX_BUFFER_CANCEL_REQUEST_REGISTER, 0x98)
355
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR31, 31, 1)
356
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR30, 30, 1)
357
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR29, 29, 1)
358
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR28, 28, 1)
359
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR27, 27, 1)
360
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR26, 26, 1)
361
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR25, 25, 1)
362
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR24, 24, 1)
363
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR23, 23, 1)
364
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR22, 22, 1)
365
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR21, 21, 1)
366
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR20, 20, 1)
367
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR19, 19, 1)
368
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR18, 18, 1)
369
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR17, 17, 1)
370
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR16, 16, 1)
371
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR15, 15, 1)
372
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR14, 14, 1)
373
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR13, 13, 1)
374
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR12, 12, 1)
375
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR11, 11, 1)
376
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR10, 10, 1)
377
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR9, 9, 1)
378
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR8, 8, 1)
379
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR7, 7, 1)
380
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR6, 6, 1)
381
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR5, 5, 1)
382
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR4, 4, 1)
383
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR3, 3, 1)
384
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR2, 2, 1)
385
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR1, 1, 1)
386
+ FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR0, 0, 1)
387
+REG32(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, 0x9c)
388
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS31, 31,
389
+ 1)
390
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS30, 30,
391
+ 1)
392
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS29, 29,
393
+ 1)
394
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS28, 28,
395
+ 1)
396
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS27, 27,
397
+ 1)
398
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS26, 26,
399
+ 1)
400
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS25, 25,
401
+ 1)
402
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS24, 24,
403
+ 1)
404
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS23, 23,
405
+ 1)
406
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS22, 22,
407
+ 1)
408
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS21, 21,
409
+ 1)
410
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS20, 20,
411
+ 1)
412
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS19, 19,
413
+ 1)
414
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS18, 18,
415
+ 1)
416
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS17, 17,
417
+ 1)
418
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS16, 16,
419
+ 1)
420
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS15, 15,
421
+ 1)
422
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS14, 14,
423
+ 1)
424
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS13, 13,
425
+ 1)
426
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS12, 12,
427
+ 1)
428
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS11, 11,
429
+ 1)
430
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS10, 10,
431
+ 1)
432
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS9, 9, 1)
433
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS8, 8, 1)
434
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS7, 7, 1)
435
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS6, 6, 1)
436
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS5, 5, 1)
437
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS4, 4, 1)
438
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS3, 3, 1)
439
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS2, 2, 1)
440
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS1, 1, 1)
441
+ FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS0, 0, 1)
442
+REG32(TX_EVENT_FIFO_STATUS_REGISTER, 0xa0)
443
+ FIELD(TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL, 8, 6)
444
+ FIELD(TX_EVENT_FIFO_STATUS_REGISTER, TXE_IRI, 7, 1)
445
+ FIELD(TX_EVENT_FIFO_STATUS_REGISTER, TXE_RI, 0, 5)
446
+REG32(TX_EVENT_FIFO_WATERMARK_REGISTER, 0xa4)
447
+ FIELD(TX_EVENT_FIFO_WATERMARK_REGISTER, TXE_FWM, 0, 5)
448
+REG32(ACCEPTANCE_FILTER_CONTROL_REGISTER, 0xe0)
449
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF31, 31, 1)
450
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF30, 30, 1)
451
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF29, 29, 1)
452
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF28, 28, 1)
453
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF27, 27, 1)
454
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF26, 26, 1)
455
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF25, 25, 1)
456
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF24, 24, 1)
457
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF23, 23, 1)
458
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF22, 22, 1)
459
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF21, 21, 1)
460
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF20, 20, 1)
461
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF19, 19, 1)
462
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF18, 18, 1)
463
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF17, 17, 1)
464
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF16, 16, 1)
465
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF15, 15, 1)
466
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF14, 14, 1)
467
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF13, 13, 1)
468
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF12, 12, 1)
469
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF11, 11, 1)
470
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF10, 10, 1)
471
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF9, 9, 1)
472
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF8, 8, 1)
473
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF7, 7, 1)
474
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF6, 6, 1)
475
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF5, 5, 1)
476
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF4, 4, 1)
477
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF3, 3, 1)
478
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF2, 2, 1)
479
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF1, 1, 1)
480
+ FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF0, 0, 1)
481
+REG32(RX_FIFO_STATUS_REGISTER, 0xe8)
482
+ FIELD(RX_FIFO_STATUS_REGISTER, FL_1, 24, 7)
483
+ FIELD(RX_FIFO_STATUS_REGISTER, IRI_1, 23, 1)
484
+ FIELD(RX_FIFO_STATUS_REGISTER, RI_1, 16, 6)
485
+ FIELD(RX_FIFO_STATUS_REGISTER, FL, 8, 7)
486
+ FIELD(RX_FIFO_STATUS_REGISTER, IRI, 7, 1)
487
+ FIELD(RX_FIFO_STATUS_REGISTER, RI, 0, 6)
488
+REG32(RX_FIFO_WATERMARK_REGISTER, 0xec)
489
+ FIELD(RX_FIFO_WATERMARK_REGISTER, RXFP, 16, 5)
490
+ FIELD(RX_FIFO_WATERMARK_REGISTER, RXFWM_1, 8, 6)
491
+ FIELD(RX_FIFO_WATERMARK_REGISTER, RXFWM, 0, 6)
492
+REG32(TB_ID_REGISTER, 0x100)
493
+ FIELD(TB_ID_REGISTER, ID, 21, 11)
494
+ FIELD(TB_ID_REGISTER, SRR_RTR_RRS, 20, 1)
495
+ FIELD(TB_ID_REGISTER, IDE, 19, 1)
496
+ FIELD(TB_ID_REGISTER, ID_EXT, 1, 18)
497
+ FIELD(TB_ID_REGISTER, RTR_RRS, 0, 1)
498
+REG32(TB0_DLC_REGISTER, 0x104)
499
+ FIELD(TB0_DLC_REGISTER, DLC, 28, 4)
500
+ FIELD(TB0_DLC_REGISTER, FDF, 27, 1)
501
+ FIELD(TB0_DLC_REGISTER, BRS, 26, 1)
502
+ FIELD(TB0_DLC_REGISTER, RSVD2, 25, 1)
503
+ FIELD(TB0_DLC_REGISTER, EFC, 24, 1)
504
+ FIELD(TB0_DLC_REGISTER, MM, 16, 8)
505
+ FIELD(TB0_DLC_REGISTER, RSVD1, 0, 16)
506
+REG32(TB_DW0_REGISTER, 0x108)
507
+ FIELD(TB_DW0_REGISTER, DATA_BYTES0, 24, 8)
508
+ FIELD(TB_DW0_REGISTER, DATA_BYTES1, 16, 8)
509
+ FIELD(TB_DW0_REGISTER, DATA_BYTES2, 8, 8)
510
+ FIELD(TB_DW0_REGISTER, DATA_BYTES3, 0, 8)
511
+REG32(TB_DW1_REGISTER, 0x10c)
512
+ FIELD(TB_DW1_REGISTER, DATA_BYTES4, 24, 8)
513
+ FIELD(TB_DW1_REGISTER, DATA_BYTES5, 16, 8)
514
+ FIELD(TB_DW1_REGISTER, DATA_BYTES6, 8, 8)
515
+ FIELD(TB_DW1_REGISTER, DATA_BYTES7, 0, 8)
516
+REG32(TB_DW2_REGISTER, 0x110)
517
+ FIELD(TB_DW2_REGISTER, DATA_BYTES8, 24, 8)
518
+ FIELD(TB_DW2_REGISTER, DATA_BYTES9, 16, 8)
519
+ FIELD(TB_DW2_REGISTER, DATA_BYTES10, 8, 8)
520
+ FIELD(TB_DW2_REGISTER, DATA_BYTES11, 0, 8)
521
+REG32(TB_DW3_REGISTER, 0x114)
522
+ FIELD(TB_DW3_REGISTER, DATA_BYTES12, 24, 8)
523
+ FIELD(TB_DW3_REGISTER, DATA_BYTES13, 16, 8)
524
+ FIELD(TB_DW3_REGISTER, DATA_BYTES14, 8, 8)
525
+ FIELD(TB_DW3_REGISTER, DATA_BYTES15, 0, 8)
526
+REG32(TB_DW4_REGISTER, 0x118)
527
+ FIELD(TB_DW4_REGISTER, DATA_BYTES16, 24, 8)
528
+ FIELD(TB_DW4_REGISTER, DATA_BYTES17, 16, 8)
529
+ FIELD(TB_DW4_REGISTER, DATA_BYTES18, 8, 8)
530
+ FIELD(TB_DW4_REGISTER, DATA_BYTES19, 0, 8)
531
+REG32(TB_DW5_REGISTER, 0x11c)
532
+ FIELD(TB_DW5_REGISTER, DATA_BYTES20, 24, 8)
533
+ FIELD(TB_DW5_REGISTER, DATA_BYTES21, 16, 8)
534
+ FIELD(TB_DW5_REGISTER, DATA_BYTES22, 8, 8)
535
+ FIELD(TB_DW5_REGISTER, DATA_BYTES23, 0, 8)
536
+REG32(TB_DW6_REGISTER, 0x120)
537
+ FIELD(TB_DW6_REGISTER, DATA_BYTES24, 24, 8)
538
+ FIELD(TB_DW6_REGISTER, DATA_BYTES25, 16, 8)
539
+ FIELD(TB_DW6_REGISTER, DATA_BYTES26, 8, 8)
540
+ FIELD(TB_DW6_REGISTER, DATA_BYTES27, 0, 8)
541
+REG32(TB_DW7_REGISTER, 0x124)
542
+ FIELD(TB_DW7_REGISTER, DATA_BYTES28, 24, 8)
543
+ FIELD(TB_DW7_REGISTER, DATA_BYTES29, 16, 8)
544
+ FIELD(TB_DW7_REGISTER, DATA_BYTES30, 8, 8)
545
+ FIELD(TB_DW7_REGISTER, DATA_BYTES31, 0, 8)
546
+REG32(TB_DW8_REGISTER, 0x128)
547
+ FIELD(TB_DW8_REGISTER, DATA_BYTES32, 24, 8)
548
+ FIELD(TB_DW8_REGISTER, DATA_BYTES33, 16, 8)
549
+ FIELD(TB_DW8_REGISTER, DATA_BYTES34, 8, 8)
550
+ FIELD(TB_DW8_REGISTER, DATA_BYTES35, 0, 8)
551
+REG32(TB_DW9_REGISTER, 0x12c)
552
+ FIELD(TB_DW9_REGISTER, DATA_BYTES36, 24, 8)
553
+ FIELD(TB_DW9_REGISTER, DATA_BYTES37, 16, 8)
554
+ FIELD(TB_DW9_REGISTER, DATA_BYTES38, 8, 8)
555
+ FIELD(TB_DW9_REGISTER, DATA_BYTES39, 0, 8)
556
+REG32(TB_DW10_REGISTER, 0x130)
557
+ FIELD(TB_DW10_REGISTER, DATA_BYTES40, 24, 8)
558
+ FIELD(TB_DW10_REGISTER, DATA_BYTES41, 16, 8)
559
+ FIELD(TB_DW10_REGISTER, DATA_BYTES42, 8, 8)
560
+ FIELD(TB_DW10_REGISTER, DATA_BYTES43, 0, 8)
561
+REG32(TB_DW11_REGISTER, 0x134)
562
+ FIELD(TB_DW11_REGISTER, DATA_BYTES44, 24, 8)
563
+ FIELD(TB_DW11_REGISTER, DATA_BYTES45, 16, 8)
564
+ FIELD(TB_DW11_REGISTER, DATA_BYTES46, 8, 8)
565
+ FIELD(TB_DW11_REGISTER, DATA_BYTES47, 0, 8)
566
+REG32(TB_DW12_REGISTER, 0x138)
567
+ FIELD(TB_DW12_REGISTER, DATA_BYTES48, 24, 8)
568
+ FIELD(TB_DW12_REGISTER, DATA_BYTES49, 16, 8)
569
+ FIELD(TB_DW12_REGISTER, DATA_BYTES50, 8, 8)
570
+ FIELD(TB_DW12_REGISTER, DATA_BYTES51, 0, 8)
571
+REG32(TB_DW13_REGISTER, 0x13c)
572
+ FIELD(TB_DW13_REGISTER, DATA_BYTES52, 24, 8)
573
+ FIELD(TB_DW13_REGISTER, DATA_BYTES53, 16, 8)
574
+ FIELD(TB_DW13_REGISTER, DATA_BYTES54, 8, 8)
575
+ FIELD(TB_DW13_REGISTER, DATA_BYTES55, 0, 8)
576
+REG32(TB_DW14_REGISTER, 0x140)
577
+ FIELD(TB_DW14_REGISTER, DATA_BYTES56, 24, 8)
578
+ FIELD(TB_DW14_REGISTER, DATA_BYTES57, 16, 8)
579
+ FIELD(TB_DW14_REGISTER, DATA_BYTES58, 8, 8)
580
+ FIELD(TB_DW14_REGISTER, DATA_BYTES59, 0, 8)
581
+REG32(TB_DW15_REGISTER, 0x144)
582
+ FIELD(TB_DW15_REGISTER, DATA_BYTES60, 24, 8)
583
+ FIELD(TB_DW15_REGISTER, DATA_BYTES61, 16, 8)
584
+ FIELD(TB_DW15_REGISTER, DATA_BYTES62, 8, 8)
585
+ FIELD(TB_DW15_REGISTER, DATA_BYTES63, 0, 8)
586
+REG32(AFMR_REGISTER, 0xa00)
587
+ FIELD(AFMR_REGISTER, AMID, 21, 11)
588
+ FIELD(AFMR_REGISTER, AMSRR, 20, 1)
589
+ FIELD(AFMR_REGISTER, AMIDE, 19, 1)
590
+ FIELD(AFMR_REGISTER, AMID_EXT, 1, 18)
591
+ FIELD(AFMR_REGISTER, AMRTR, 0, 1)
592
+REG32(AFIR_REGISTER, 0xa04)
593
+ FIELD(AFIR_REGISTER, AIID, 21, 11)
594
+ FIELD(AFIR_REGISTER, AISRR, 20, 1)
595
+ FIELD(AFIR_REGISTER, AIIDE, 19, 1)
596
+ FIELD(AFIR_REGISTER, AIID_EXT, 1, 18)
597
+ FIELD(AFIR_REGISTER, AIRTR, 0, 1)
598
+REG32(TXE_FIFO_TB_ID_REGISTER, 0x2000)
599
+ FIELD(TXE_FIFO_TB_ID_REGISTER, ID, 21, 11)
600
+ FIELD(TXE_FIFO_TB_ID_REGISTER, SRR_RTR_RRS, 20, 1)
601
+ FIELD(TXE_FIFO_TB_ID_REGISTER, IDE, 19, 1)
602
+ FIELD(TXE_FIFO_TB_ID_REGISTER, ID_EXT, 1, 18)
603
+ FIELD(TXE_FIFO_TB_ID_REGISTER, RTR_RRS, 0, 1)
604
+REG32(TXE_FIFO_TB_DLC_REGISTER, 0x2004)
605
+ FIELD(TXE_FIFO_TB_DLC_REGISTER, DLC, 28, 4)
606
+ FIELD(TXE_FIFO_TB_DLC_REGISTER, FDF, 27, 1)
607
+ FIELD(TXE_FIFO_TB_DLC_REGISTER, BRS, 26, 1)
608
+ FIELD(TXE_FIFO_TB_DLC_REGISTER, ET, 24, 2)
609
+ FIELD(TXE_FIFO_TB_DLC_REGISTER, MM, 16, 8)
610
+ FIELD(TXE_FIFO_TB_DLC_REGISTER, TIMESTAMP, 0, 16)
611
+REG32(RB_ID_REGISTER, 0x2100)
612
+ FIELD(RB_ID_REGISTER, ID, 21, 11)
613
+ FIELD(RB_ID_REGISTER, SRR_RTR_RRS, 20, 1)
614
+ FIELD(RB_ID_REGISTER, IDE, 19, 1)
615
+ FIELD(RB_ID_REGISTER, ID_EXT, 1, 18)
616
+ FIELD(RB_ID_REGISTER, RTR_RRS, 0, 1)
617
+REG32(RB_DLC_REGISTER, 0x2104)
618
+ FIELD(RB_DLC_REGISTER, DLC, 28, 4)
619
+ FIELD(RB_DLC_REGISTER, FDF, 27, 1)
620
+ FIELD(RB_DLC_REGISTER, BRS, 26, 1)
621
+ FIELD(RB_DLC_REGISTER, ESI, 25, 1)
622
+ FIELD(RB_DLC_REGISTER, MATCHED_FILTER_INDEX, 16, 5)
623
+ FIELD(RB_DLC_REGISTER, TIMESTAMP, 0, 16)
624
+REG32(RB_DW0_REGISTER, 0x2108)
625
+ FIELD(RB_DW0_REGISTER, DATA_BYTES0, 24, 8)
626
+ FIELD(RB_DW0_REGISTER, DATA_BYTES1, 16, 8)
627
+ FIELD(RB_DW0_REGISTER, DATA_BYTES2, 8, 8)
628
+ FIELD(RB_DW0_REGISTER, DATA_BYTES3, 0, 8)
629
+REG32(RB_DW1_REGISTER, 0x210c)
630
+ FIELD(RB_DW1_REGISTER, DATA_BYTES4, 24, 8)
631
+ FIELD(RB_DW1_REGISTER, DATA_BYTES5, 16, 8)
632
+ FIELD(RB_DW1_REGISTER, DATA_BYTES6, 8, 8)
633
+ FIELD(RB_DW1_REGISTER, DATA_BYTES7, 0, 8)
634
+REG32(RB_DW2_REGISTER, 0x2110)
635
+ FIELD(RB_DW2_REGISTER, DATA_BYTES8, 24, 8)
636
+ FIELD(RB_DW2_REGISTER, DATA_BYTES9, 16, 8)
637
+ FIELD(RB_DW2_REGISTER, DATA_BYTES10, 8, 8)
638
+ FIELD(RB_DW2_REGISTER, DATA_BYTES11, 0, 8)
639
+REG32(RB_DW3_REGISTER, 0x2114)
640
+ FIELD(RB_DW3_REGISTER, DATA_BYTES12, 24, 8)
641
+ FIELD(RB_DW3_REGISTER, DATA_BYTES13, 16, 8)
642
+ FIELD(RB_DW3_REGISTER, DATA_BYTES14, 8, 8)
643
+ FIELD(RB_DW3_REGISTER, DATA_BYTES15, 0, 8)
644
+REG32(RB_DW4_REGISTER, 0x2118)
645
+ FIELD(RB_DW4_REGISTER, DATA_BYTES16, 24, 8)
646
+ FIELD(RB_DW4_REGISTER, DATA_BYTES17, 16, 8)
647
+ FIELD(RB_DW4_REGISTER, DATA_BYTES18, 8, 8)
648
+ FIELD(RB_DW4_REGISTER, DATA_BYTES19, 0, 8)
649
+REG32(RB_DW5_REGISTER, 0x211c)
650
+ FIELD(RB_DW5_REGISTER, DATA_BYTES20, 24, 8)
651
+ FIELD(RB_DW5_REGISTER, DATA_BYTES21, 16, 8)
652
+ FIELD(RB_DW5_REGISTER, DATA_BYTES22, 8, 8)
653
+ FIELD(RB_DW5_REGISTER, DATA_BYTES23, 0, 8)
654
+REG32(RB_DW6_REGISTER, 0x2120)
655
+ FIELD(RB_DW6_REGISTER, DATA_BYTES24, 24, 8)
656
+ FIELD(RB_DW6_REGISTER, DATA_BYTES25, 16, 8)
657
+ FIELD(RB_DW6_REGISTER, DATA_BYTES26, 8, 8)
658
+ FIELD(RB_DW6_REGISTER, DATA_BYTES27, 0, 8)
659
+REG32(RB_DW7_REGISTER, 0x2124)
660
+ FIELD(RB_DW7_REGISTER, DATA_BYTES28, 24, 8)
661
+ FIELD(RB_DW7_REGISTER, DATA_BYTES29, 16, 8)
662
+ FIELD(RB_DW7_REGISTER, DATA_BYTES30, 8, 8)
663
+ FIELD(RB_DW7_REGISTER, DATA_BYTES31, 0, 8)
664
+REG32(RB_DW8_REGISTER, 0x2128)
665
+ FIELD(RB_DW8_REGISTER, DATA_BYTES32, 24, 8)
666
+ FIELD(RB_DW8_REGISTER, DATA_BYTES33, 16, 8)
667
+ FIELD(RB_DW8_REGISTER, DATA_BYTES34, 8, 8)
668
+ FIELD(RB_DW8_REGISTER, DATA_BYTES35, 0, 8)
669
+REG32(RB_DW9_REGISTER, 0x212c)
670
+ FIELD(RB_DW9_REGISTER, DATA_BYTES36, 24, 8)
671
+ FIELD(RB_DW9_REGISTER, DATA_BYTES37, 16, 8)
672
+ FIELD(RB_DW9_REGISTER, DATA_BYTES38, 8, 8)
673
+ FIELD(RB_DW9_REGISTER, DATA_BYTES39, 0, 8)
674
+REG32(RB_DW10_REGISTER, 0x2130)
675
+ FIELD(RB_DW10_REGISTER, DATA_BYTES40, 24, 8)
676
+ FIELD(RB_DW10_REGISTER, DATA_BYTES41, 16, 8)
677
+ FIELD(RB_DW10_REGISTER, DATA_BYTES42, 8, 8)
678
+ FIELD(RB_DW10_REGISTER, DATA_BYTES43, 0, 8)
679
+REG32(RB_DW11_REGISTER, 0x2134)
680
+ FIELD(RB_DW11_REGISTER, DATA_BYTES44, 24, 8)
681
+ FIELD(RB_DW11_REGISTER, DATA_BYTES45, 16, 8)
682
+ FIELD(RB_DW11_REGISTER, DATA_BYTES46, 8, 8)
683
+ FIELD(RB_DW11_REGISTER, DATA_BYTES47, 0, 8)
684
+REG32(RB_DW12_REGISTER, 0x2138)
685
+ FIELD(RB_DW12_REGISTER, DATA_BYTES48, 24, 8)
686
+ FIELD(RB_DW12_REGISTER, DATA_BYTES49, 16, 8)
687
+ FIELD(RB_DW12_REGISTER, DATA_BYTES50, 8, 8)
688
+ FIELD(RB_DW12_REGISTER, DATA_BYTES51, 0, 8)
689
+REG32(RB_DW13_REGISTER, 0x213c)
690
+ FIELD(RB_DW13_REGISTER, DATA_BYTES52, 24, 8)
691
+ FIELD(RB_DW13_REGISTER, DATA_BYTES53, 16, 8)
692
+ FIELD(RB_DW13_REGISTER, DATA_BYTES54, 8, 8)
693
+ FIELD(RB_DW13_REGISTER, DATA_BYTES55, 0, 8)
694
+REG32(RB_DW14_REGISTER, 0x2140)
695
+ FIELD(RB_DW14_REGISTER, DATA_BYTES56, 24, 8)
696
+ FIELD(RB_DW14_REGISTER, DATA_BYTES57, 16, 8)
697
+ FIELD(RB_DW14_REGISTER, DATA_BYTES58, 8, 8)
698
+ FIELD(RB_DW14_REGISTER, DATA_BYTES59, 0, 8)
699
+REG32(RB_DW15_REGISTER, 0x2144)
700
+ FIELD(RB_DW15_REGISTER, DATA_BYTES60, 24, 8)
701
+ FIELD(RB_DW15_REGISTER, DATA_BYTES61, 16, 8)
702
+ FIELD(RB_DW15_REGISTER, DATA_BYTES62, 8, 8)
703
+ FIELD(RB_DW15_REGISTER, DATA_BYTES63, 0, 8)
704
+REG32(RB_ID_REGISTER_1, 0x4100)
705
+ FIELD(RB_ID_REGISTER_1, ID, 21, 11)
706
+ FIELD(RB_ID_REGISTER_1, SRR_RTR_RRS, 20, 1)
707
+ FIELD(RB_ID_REGISTER_1, IDE, 19, 1)
708
+ FIELD(RB_ID_REGISTER_1, ID_EXT, 1, 18)
709
+ FIELD(RB_ID_REGISTER_1, RTR_RRS, 0, 1)
710
+REG32(RB_DLC_REGISTER_1, 0x4104)
711
+ FIELD(RB_DLC_REGISTER_1, DLC, 28, 4)
712
+ FIELD(RB_DLC_REGISTER_1, FDF, 27, 1)
713
+ FIELD(RB_DLC_REGISTER_1, BRS, 26, 1)
714
+ FIELD(RB_DLC_REGISTER_1, ESI, 25, 1)
715
+ FIELD(RB_DLC_REGISTER_1, MATCHED_FILTER_INDEX, 16, 5)
716
+ FIELD(RB_DLC_REGISTER_1, TIMESTAMP, 0, 16)
717
+REG32(RB0_DW0_REGISTER_1, 0x4108)
718
+ FIELD(RB0_DW0_REGISTER_1, DATA_BYTES0, 24, 8)
719
+ FIELD(RB0_DW0_REGISTER_1, DATA_BYTES1, 16, 8)
720
+ FIELD(RB0_DW0_REGISTER_1, DATA_BYTES2, 8, 8)
721
+ FIELD(RB0_DW0_REGISTER_1, DATA_BYTES3, 0, 8)
722
+REG32(RB_DW1_REGISTER_1, 0x410c)
723
+ FIELD(RB_DW1_REGISTER_1, DATA_BYTES4, 24, 8)
724
+ FIELD(RB_DW1_REGISTER_1, DATA_BYTES5, 16, 8)
725
+ FIELD(RB_DW1_REGISTER_1, DATA_BYTES6, 8, 8)
726
+ FIELD(RB_DW1_REGISTER_1, DATA_BYTES7, 0, 8)
727
+REG32(RB_DW2_REGISTER_1, 0x4110)
728
+ FIELD(RB_DW2_REGISTER_1, DATA_BYTES8, 24, 8)
729
+ FIELD(RB_DW2_REGISTER_1, DATA_BYTES9, 16, 8)
730
+ FIELD(RB_DW2_REGISTER_1, DATA_BYTES10, 8, 8)
731
+ FIELD(RB_DW2_REGISTER_1, DATA_BYTES11, 0, 8)
732
+REG32(RB_DW3_REGISTER_1, 0x4114)
733
+ FIELD(RB_DW3_REGISTER_1, DATA_BYTES12, 24, 8)
734
+ FIELD(RB_DW3_REGISTER_1, DATA_BYTES13, 16, 8)
735
+ FIELD(RB_DW3_REGISTER_1, DATA_BYTES14, 8, 8)
736
+ FIELD(RB_DW3_REGISTER_1, DATA_BYTES15, 0, 8)
737
+REG32(RB_DW4_REGISTER_1, 0x4118)
738
+ FIELD(RB_DW4_REGISTER_1, DATA_BYTES16, 24, 8)
739
+ FIELD(RB_DW4_REGISTER_1, DATA_BYTES17, 16, 8)
740
+ FIELD(RB_DW4_REGISTER_1, DATA_BYTES18, 8, 8)
741
+ FIELD(RB_DW4_REGISTER_1, DATA_BYTES19, 0, 8)
742
+REG32(RB_DW5_REGISTER_1, 0x411c)
743
+ FIELD(RB_DW5_REGISTER_1, DATA_BYTES20, 24, 8)
744
+ FIELD(RB_DW5_REGISTER_1, DATA_BYTES21, 16, 8)
745
+ FIELD(RB_DW5_REGISTER_1, DATA_BYTES22, 8, 8)
746
+ FIELD(RB_DW5_REGISTER_1, DATA_BYTES23, 0, 8)
747
+REG32(RB_DW6_REGISTER_1, 0x4120)
748
+ FIELD(RB_DW6_REGISTER_1, DATA_BYTES24, 24, 8)
749
+ FIELD(RB_DW6_REGISTER_1, DATA_BYTES25, 16, 8)
750
+ FIELD(RB_DW6_REGISTER_1, DATA_BYTES26, 8, 8)
751
+ FIELD(RB_DW6_REGISTER_1, DATA_BYTES27, 0, 8)
752
+REG32(RB_DW7_REGISTER_1, 0x4124)
753
+ FIELD(RB_DW7_REGISTER_1, DATA_BYTES28, 24, 8)
754
+ FIELD(RB_DW7_REGISTER_1, DATA_BYTES29, 16, 8)
755
+ FIELD(RB_DW7_REGISTER_1, DATA_BYTES30, 8, 8)
756
+ FIELD(RB_DW7_REGISTER_1, DATA_BYTES31, 0, 8)
757
+REG32(RB_DW8_REGISTER_1, 0x4128)
758
+ FIELD(RB_DW8_REGISTER_1, DATA_BYTES32, 24, 8)
759
+ FIELD(RB_DW8_REGISTER_1, DATA_BYTES33, 16, 8)
760
+ FIELD(RB_DW8_REGISTER_1, DATA_BYTES34, 8, 8)
761
+ FIELD(RB_DW8_REGISTER_1, DATA_BYTES35, 0, 8)
762
+REG32(RB_DW9_REGISTER_1, 0x412c)
763
+ FIELD(RB_DW9_REGISTER_1, DATA_BYTES36, 24, 8)
764
+ FIELD(RB_DW9_REGISTER_1, DATA_BYTES37, 16, 8)
765
+ FIELD(RB_DW9_REGISTER_1, DATA_BYTES38, 8, 8)
766
+ FIELD(RB_DW9_REGISTER_1, DATA_BYTES39, 0, 8)
767
+REG32(RB_DW10_REGISTER_1, 0x4130)
768
+ FIELD(RB_DW10_REGISTER_1, DATA_BYTES40, 24, 8)
769
+ FIELD(RB_DW10_REGISTER_1, DATA_BYTES41, 16, 8)
770
+ FIELD(RB_DW10_REGISTER_1, DATA_BYTES42, 8, 8)
771
+ FIELD(RB_DW10_REGISTER_1, DATA_BYTES43, 0, 8)
772
+REG32(RB_DW11_REGISTER_1, 0x4134)
773
+ FIELD(RB_DW11_REGISTER_1, DATA_BYTES44, 24, 8)
774
+ FIELD(RB_DW11_REGISTER_1, DATA_BYTES45, 16, 8)
775
+ FIELD(RB_DW11_REGISTER_1, DATA_BYTES46, 8, 8)
776
+ FIELD(RB_DW11_REGISTER_1, DATA_BYTES47, 0, 8)
777
+REG32(RB_DW12_REGISTER_1, 0x4138)
778
+ FIELD(RB_DW12_REGISTER_1, DATA_BYTES48, 24, 8)
779
+ FIELD(RB_DW12_REGISTER_1, DATA_BYTES49, 16, 8)
780
+ FIELD(RB_DW12_REGISTER_1, DATA_BYTES50, 8, 8)
781
+ FIELD(RB_DW12_REGISTER_1, DATA_BYTES51, 0, 8)
782
+REG32(RB_DW13_REGISTER_1, 0x413c)
783
+ FIELD(RB_DW13_REGISTER_1, DATA_BYTES52, 24, 8)
784
+ FIELD(RB_DW13_REGISTER_1, DATA_BYTES53, 16, 8)
785
+ FIELD(RB_DW13_REGISTER_1, DATA_BYTES54, 8, 8)
786
+ FIELD(RB_DW13_REGISTER_1, DATA_BYTES55, 0, 8)
787
+REG32(RB_DW14_REGISTER_1, 0x4140)
788
+ FIELD(RB_DW14_REGISTER_1, DATA_BYTES56, 24, 8)
789
+ FIELD(RB_DW14_REGISTER_1, DATA_BYTES57, 16, 8)
790
+ FIELD(RB_DW14_REGISTER_1, DATA_BYTES58, 8, 8)
791
+ FIELD(RB_DW14_REGISTER_1, DATA_BYTES59, 0, 8)
792
+REG32(RB_DW15_REGISTER_1, 0x4144)
793
+ FIELD(RB_DW15_REGISTER_1, DATA_BYTES60, 24, 8)
794
+ FIELD(RB_DW15_REGISTER_1, DATA_BYTES61, 16, 8)
795
+ FIELD(RB_DW15_REGISTER_1, DATA_BYTES62, 8, 8)
796
+ FIELD(RB_DW15_REGISTER_1, DATA_BYTES63, 0, 8)
797
+
798
+static uint8_t canfd_dlc_array[8] = {8, 12, 16, 20, 24, 32, 48, 64};
799
+
800
+static void canfd_update_irq(XlnxVersalCANFDState *s)
801
+{
802
+ unsigned int irq = s->regs[R_INTERRUPT_STATUS_REGISTER] &
803
+ s->regs[R_INTERRUPT_ENABLE_REGISTER];
804
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
805
+
806
+ /* RX watermark interrupts. */
807
+ if (ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, FL) >
808
+ ARRAY_FIELD_EX32(s->regs, RX_FIFO_WATERMARK_REGISTER, RXFWM)) {
809
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
810
+ }
48
+ }
811
+
49
+
812
+ if (ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1) >
50
+ if (status->default_nan_mode) {
813
+ ARRAY_FIELD_EX32(s->regs, RX_FIFO_WATERMARK_REGISTER, RXFWM_1)) {
51
+ return floatx80_default_nan(status);
814
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL_1, 1);
815
+ }
52
+ }
816
+
53
+
817
+ /* TX watermark interrupt. */
54
+ if (a.low < b.low) {
818
+ if (ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL) >
55
+ aIsLargerSignificand = 0;
819
+ ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_WATERMARK_REGISTER, TXE_FWM)) {
56
+ } else if (b.low < a.low) {
820
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXEWMFLL, 1);
57
+ aIsLargerSignificand = 1;
58
+ } else {
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
821
+ }
60
+ }
822
+
61
+
823
+ trace_xlnx_canfd_update_irq(path, s->regs[R_INTERRUPT_STATUS_REGISTER],
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
824
+ s->regs[R_INTERRUPT_ENABLE_REGISTER], irq);
63
+ if (is_snan(b_cls)) {
825
+
64
+ return floatx80_silence_nan(b, status);
826
+ qemu_set_irq(s->irq_canfd_int, irq);
65
+ }
827
+}
66
+ return b;
828
+
829
+static void canfd_ier_post_write(RegisterInfo *reg, uint64_t val64)
830
+{
831
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
832
+
833
+ canfd_update_irq(s);
834
+}
835
+
836
+static uint64_t canfd_icr_pre_write(RegisterInfo *reg, uint64_t val64)
837
+{
838
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
839
+ uint32_t val = val64;
840
+
841
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
842
+
843
+ /*
844
+ * RXBOFLW_BI field is automatically cleared to default if RXBOFLW bit is
845
+ * cleared in ISR.
846
+ */
847
+ if (ARRAY_FIELD_EX32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL_1)) {
848
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXBOFLW_BI, 0);
849
+ }
850
+
851
+ canfd_update_irq(s);
852
+
853
+ return 0;
854
+}
855
+
856
+static void canfd_config_reset(XlnxVersalCANFDState *s)
857
+{
858
+
859
+ unsigned int i;
860
+
861
+ /* Reset all the configuration registers. */
862
+ for (i = 0; i < R_RX_FIFO_WATERMARK_REGISTER; ++i) {
863
+ register_reset(&s->reg_info[i]);
864
+ }
865
+
866
+ canfd_update_irq(s);
867
+}
868
+
869
+static void canfd_config_mode(XlnxVersalCANFDState *s)
870
+{
871
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
872
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
873
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
874
+
875
+ /* Put XlnxVersalCANFDState in configuration mode. */
876
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
877
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
878
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
879
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
880
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR_BIT, 0);
881
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW, 0);
882
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 0);
883
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
884
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
885
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
886
+
887
+ /* Clear the time stamp. */
888
+ ptimer_transaction_begin(s->canfd_timer);
889
+ ptimer_set_count(s->canfd_timer, 0);
890
+ ptimer_transaction_commit(s->canfd_timer);
891
+
892
+ canfd_update_irq(s);
893
+}
894
+
895
+static void update_status_register_mode_bits(XlnxVersalCANFDState *s)
896
+{
897
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
898
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
899
+ /* Wake up interrupt bit. */
900
+ bool wakeup_irq_val = !sleep_mode && sleep_status;
901
+ /* Sleep interrupt bit. */
902
+ bool sleep_irq_val = sleep_mode && !sleep_status;
903
+
904
+ /* Clear previous core mode status bits. */
905
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
906
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
907
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
908
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
909
+
910
+ /* set current mode bit and generate irqs accordingly. */
911
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
912
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
913
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
914
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
915
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
916
+ sleep_irq_val);
917
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
918
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
919
+ } else {
67
+ } else {
920
+ /* If all bits are zero, XlnxVersalCANFDState is set in normal mode. */
68
+ if (is_snan(a_cls)) {
921
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
69
+ return floatx80_silence_nan(a, status);
922
+ /* Set wakeup interrupt bit. */
923
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
924
+ wakeup_irq_val);
925
+ }
926
+
927
+ /* Put the CANFD in error active state. */
928
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ESTAT, 1);
929
+
930
+ canfd_update_irq(s);
931
+}
932
+
933
+static uint64_t canfd_msr_pre_write(RegisterInfo *reg, uint64_t val64)
934
+{
935
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
936
+ uint32_t val = val64;
937
+ uint8_t multi_mode = 0;
938
+
939
+ /*
940
+ * Multiple mode set check. This is done to make sure user doesn't set
941
+ * multiple modes.
942
+ */
943
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
944
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
945
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
946
+
947
+ if (multi_mode > 1) {
948
+ qemu_log_mask(LOG_GUEST_ERROR, "Attempting to configure several modes"
949
+ " simultaneously. One mode will be selected according to"
950
+ " their priority: LBACK > SLEEP > SNOOP.\n");
951
+ }
952
+
953
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
954
+ /* In configuration mode, any mode can be selected. */
955
+ s->regs[R_MODE_SELECT_REGISTER] = val;
956
+ } else {
957
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
958
+
959
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
960
+
961
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
962
+ qemu_log_mask(LOG_GUEST_ERROR, "Attempting to set LBACK mode"
963
+ " without setting CEN bit as 0\n");
964
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
965
+ qemu_log_mask(LOG_GUEST_ERROR, "Attempting to set SNOOP mode"
966
+ " without setting CEN bit as 0\n");
967
+ }
70
+ }
968
+
71
+ return a;
969
+ update_status_register_mode_bits(s);
970
+ }
971
+
972
+ return s->regs[R_MODE_SELECT_REGISTER];
973
+}
974
+
975
+static void canfd_exit_sleep_mode(XlnxVersalCANFDState *s)
976
+{
977
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
978
+ update_status_register_mode_bits(s);
979
+}
980
+
981
+static void regs2frame(XlnxVersalCANFDState *s, qemu_can_frame *frame,
982
+ uint32_t reg_num)
983
+{
984
+ uint32_t i = 0;
985
+ uint32_t j = 0;
986
+ uint32_t val = 0;
987
+ uint32_t dlc_reg_val = 0;
988
+ uint32_t dlc_value = 0;
989
+
990
+ /* Check that reg_num should be within TX register space. */
991
+ assert(reg_num <= R_TB_ID_REGISTER + (NUM_REGS_PER_MSG_SPACE *
992
+ s->cfg.tx_fifo));
993
+
994
+ dlc_reg_val = s->regs[reg_num + 1];
995
+ dlc_value = FIELD_EX32(dlc_reg_val, TB0_DLC_REGISTER, DLC);
996
+
997
+ frame->can_id = s->regs[reg_num];
998
+
999
+ if (FIELD_EX32(dlc_reg_val, TB0_DLC_REGISTER, FDF)) {
1000
+ /*
1001
+ * CANFD frame.
1002
+ * Converting dlc(0 to 15) 4 Byte data to plain length(i.e. 0 to 64)
1003
+ * 1 Byte data. This is done to make it work with SocketCAN.
1004
+ * On actual CANFD frame, this value can't be more than 0xF.
1005
+ * Conversion table for DLC to plain length:
1006
+ *
1007
+ * DLC Plain Length
1008
+ * 0 - 8 0 - 8
1009
+ * 9 9 - 12
1010
+ * 10 13 - 16
1011
+ * 11 17 - 20
1012
+ * 12 21 - 24
1013
+ * 13 25 - 32
1014
+ * 14 33 - 48
1015
+ * 15 49 - 64
1016
+ */
1017
+
1018
+ frame->flags = QEMU_CAN_FRMF_TYPE_FD;
1019
+
1020
+ if (dlc_value < 8) {
1021
+ frame->can_dlc = dlc_value;
1022
+ } else {
1023
+ assert((dlc_value - 8) < ARRAY_SIZE(canfd_dlc_array));
1024
+ frame->can_dlc = canfd_dlc_array[dlc_value - 8];
1025
+ }
1026
+ } else {
1027
+ /*
1028
+ * FD Format bit not set that means it is a CAN Frame.
1029
+ * Conversion table for classic CAN:
1030
+ *
1031
+ * DLC Plain Length
1032
+ * 0 - 7 0 - 7
1033
+ * 8 - 15 8
1034
+ */
1035
+
1036
+ if (dlc_value > 8) {
1037
+ frame->can_dlc = 8;
1038
+ qemu_log_mask(LOG_GUEST_ERROR, "Maximum DLC value for Classic CAN"
1039
+ " frame is 8. Only 8 byte data will be sent.\n");
1040
+ } else {
1041
+ frame->can_dlc = dlc_value;
1042
+ }
1043
+ }
1044
+
1045
+ for (j = 0; j < frame->can_dlc; j++) {
1046
+ val = 8 * i;
1047
+
1048
+ frame->data[j] = extract32(s->regs[reg_num + 2 + (j / 4)], val, 8);
1049
+ i++;
1050
+
1051
+ if (i % 4 == 0) {
1052
+ i = 0;
1053
+ }
1054
+ }
72
+ }
1055
+}
73
+}
1056
+
74
+
1057
+static void process_cancellation_requests(XlnxVersalCANFDState *s)
75
/*----------------------------------------------------------------------------
1058
+{
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
1059
+ uint32_t clear_mask = s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER] &
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
1060
+ s->regs[R_TX_BUFFER_CANCEL_REQUEST_REGISTER];
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
1061
+
1062
+ s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER] &= ~clear_mask;
1063
+ s->regs[R_TX_BUFFER_CANCEL_REQUEST_REGISTER] &= ~clear_mask;
1064
+
1065
+ canfd_update_irq(s);
1066
+}
1067
+
1068
+static void store_rx_sequential(XlnxVersalCANFDState *s,
1069
+ const qemu_can_frame *frame,
1070
+ uint32_t fill_level, uint32_t read_index,
1071
+ uint32_t store_location, uint8_t rx_fifo,
1072
+ bool rx_fifo_id, uint8_t filter_index)
1073
+{
1074
+ int i;
1075
+ bool is_canfd_frame;
1076
+ uint8_t dlc = frame->can_dlc;
1077
+ uint8_t rx_reg_num = 0;
1078
+ uint32_t dlc_reg_val = 0;
1079
+ uint32_t data_reg_val = 0;
1080
+
1081
+ /* Getting RX0/1 fill level */
1082
+ if ((fill_level) > rx_fifo - 1) {
1083
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1084
+
1085
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: RX%d Buffer is full. Discarding the"
1086
+ " message\n", path, rx_fifo_id);
1087
+
1088
+ /* Set the corresponding RF buffer overflow interrupt. */
1089
+ if (rx_fifo_id == 0) {
1090
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW, 1);
1091
+ } else {
1092
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 1);
1093
+ }
1094
+ } else {
1095
+ uint16_t rx_timestamp = CANFD_TIMER_MAX -
1096
+ ptimer_get_count(s->canfd_timer);
1097
+
1098
+ if (rx_timestamp == 0xFFFF) {
1099
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TSCNT_OFLW, 1);
1100
+ } else {
1101
+ ARRAY_FIELD_DP32(s->regs, TIMESTAMP_REGISTER, TIMESTAMP_CNT,
1102
+ rx_timestamp);
1103
+ }
1104
+
1105
+ if (rx_fifo_id == 0) {
1106
+ ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL,
1107
+ fill_level + 1);
1108
+ assert(store_location <=
1109
+ R_RB_ID_REGISTER + (s->cfg.rx0_fifo *
1110
+ NUM_REGS_PER_MSG_SPACE));
1111
+ } else {
1112
+ ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1,
1113
+ fill_level + 1);
1114
+ assert(store_location <=
1115
+ R_RB_ID_REGISTER_1 + (s->cfg.rx1_fifo *
1116
+ NUM_REGS_PER_MSG_SPACE));
1117
+ }
1118
+
1119
+ s->regs[store_location] = frame->can_id;
1120
+
1121
+ dlc = frame->can_dlc;
1122
+
1123
+ if (frame->flags == QEMU_CAN_FRMF_TYPE_FD) {
1124
+ is_canfd_frame = true;
1125
+
1126
+ /* Store dlc value in Xilinx specific format. */
1127
+ for (i = 0; i < ARRAY_SIZE(canfd_dlc_array); i++) {
1128
+ if (canfd_dlc_array[i] == frame->can_dlc) {
1129
+ dlc_reg_val = FIELD_DP32(0, RB_DLC_REGISTER, DLC, 8 + i);
1130
+ }
1131
+ }
1132
+ } else {
1133
+ is_canfd_frame = false;
1134
+
1135
+ if (frame->can_dlc > 8) {
1136
+ dlc = 8;
1137
+ }
1138
+
1139
+ dlc_reg_val = FIELD_DP32(0, RB_DLC_REGISTER, DLC, dlc);
1140
+ }
1141
+
1142
+ dlc_reg_val |= FIELD_DP32(0, RB_DLC_REGISTER, FDF, is_canfd_frame);
1143
+ dlc_reg_val |= FIELD_DP32(0, RB_DLC_REGISTER, TIMESTAMP, rx_timestamp);
1144
+ dlc_reg_val |= FIELD_DP32(0, RB_DLC_REGISTER, MATCHED_FILTER_INDEX,
1145
+ filter_index);
1146
+ s->regs[store_location + 1] = dlc_reg_val;
1147
+
1148
+ for (i = 0; i < dlc; i++) {
1149
+ /* Register size is 4 byte but frame->data each is 1 byte. */
1150
+ switch (i % 4) {
1151
+ case 0:
1152
+ rx_reg_num = i / 4;
1153
+
1154
+ data_reg_val = FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES3,
1155
+ frame->data[i]);
1156
+ break;
1157
+ case 1:
1158
+ data_reg_val |= FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES2,
1159
+ frame->data[i]);
1160
+ break;
1161
+ case 2:
1162
+ data_reg_val |= FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES1,
1163
+ frame->data[i]);
1164
+ break;
1165
+ case 3:
1166
+ data_reg_val |= FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES0,
1167
+ frame->data[i]);
1168
+ /*
1169
+ * Last Bytes data which means we have all 4 bytes ready to
1170
+ * store in one rx regs.
1171
+ */
1172
+ s->regs[store_location + rx_reg_num + 2] = data_reg_val;
1173
+ break;
1174
+ }
1175
+ }
1176
+
1177
+ if (i % 4) {
1178
+ /*
1179
+ * In case DLC is not multiplier of 4, data is not saved to RX FIFO
1180
+ * in above switch case. Store the remaining bytes here.
1181
+ */
1182
+ s->regs[store_location + rx_reg_num + 2] = data_reg_val;
1183
+ }
1184
+
1185
+ /* set the interrupt as RXOK. */
1186
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
1187
+ }
1188
+}
1189
+
1190
+static void update_rx_sequential(XlnxVersalCANFDState *s,
1191
+ const qemu_can_frame *frame)
1192
+{
1193
+ bool filter_pass = false;
1194
+ uint8_t filter_index = 0;
1195
+ int i;
1196
+ int filter_partition = ARRAY_FIELD_EX32(s->regs,
1197
+ RX_FIFO_WATERMARK_REGISTER, RXFP);
1198
+ uint32_t store_location;
1199
+ uint32_t fill_level;
1200
+ uint32_t read_index;
1201
+ uint8_t store_index = 0;
1202
+ g_autofree char *path = NULL;
1203
+ /*
1204
+ * If all UAF bits are set to 0, then received messages are not stored
1205
+ * in the RX buffers.
1206
+ */
1207
+ if (s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER]) {
1208
+ uint32_t acceptance_filter_status =
1209
+ s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER];
1210
+
1211
+ for (i = 0; i < 32; i++) {
1212
+ if (acceptance_filter_status & 0x1) {
1213
+ uint32_t msg_id_masked = s->regs[R_AFMR_REGISTER + 2 * i] &
1214
+ frame->can_id;
1215
+ uint32_t afir_id_masked = s->regs[R_AFIR_REGISTER + 2 * i] &
1216
+ s->regs[R_AFMR_REGISTER + 2 * i];
1217
+ uint16_t std_msg_id_masked = FIELD_EX32(msg_id_masked,
1218
+ AFIR_REGISTER, AIID);
1219
+ uint16_t std_afir_id_masked = FIELD_EX32(afir_id_masked,
1220
+ AFIR_REGISTER, AIID);
1221
+ uint32_t ext_msg_id_masked = FIELD_EX32(msg_id_masked,
1222
+ AFIR_REGISTER,
1223
+ AIID_EXT);
1224
+ uint32_t ext_afir_id_masked = FIELD_EX32(afir_id_masked,
1225
+ AFIR_REGISTER,
1226
+ AIID_EXT);
1227
+ bool ext_ide = FIELD_EX32(s->regs[R_AFMR_REGISTER + 2 * i],
1228
+ AFMR_REGISTER, AMIDE);
1229
+
1230
+ if (std_msg_id_masked == std_afir_id_masked) {
1231
+ if (ext_ide) {
1232
+ /* Extended message ID message. */
1233
+ if (ext_msg_id_masked == ext_afir_id_masked) {
1234
+ filter_pass = true;
1235
+ filter_index = i;
1236
+
1237
+ break;
1238
+ }
1239
+ } else {
1240
+ /* Standard message ID. */
1241
+ filter_pass = true;
1242
+ filter_index = i;
1243
+
1244
+ break;
1245
+ }
1246
+ }
1247
+ }
1248
+ acceptance_filter_status >>= 1;
1249
+ }
1250
+ }
1251
+
1252
+ if (!filter_pass) {
1253
+ path = object_get_canonical_path(OBJECT(s));
1254
+
1255
+ trace_xlnx_canfd_rx_fifo_filter_reject(path, frame->can_id,
1256
+ frame->can_dlc);
1257
+ } else {
1258
+ if (filter_index <= filter_partition) {
1259
+ fill_level = ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, FL);
1260
+ read_index = ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, RI);
1261
+ store_index = read_index + fill_level;
1262
+
1263
+ if (read_index == s->cfg.rx0_fifo - 1) {
1264
+ /*
1265
+ * When ri is s->cfg.rx0_fifo - 1 i.e. max, it goes cyclic that
1266
+ * means we reset the ri to 0x0.
1267
+ */
1268
+ read_index = 0;
1269
+ ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI,
1270
+ read_index);
1271
+ }
1272
+
1273
+ if (store_index > s->cfg.rx0_fifo - 1) {
1274
+ store_index -= s->cfg.rx0_fifo - 1;
1275
+ }
1276
+
1277
+ store_location = R_RB_ID_REGISTER +
1278
+ (store_index * NUM_REGS_PER_MSG_SPACE);
1279
+
1280
+ store_rx_sequential(s, frame, fill_level, read_index,
1281
+ store_location, s->cfg.rx0_fifo, 0,
1282
+ filter_index);
1283
+ } else {
1284
+ /* RX 1 fill level message */
1285
+ fill_level = ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER,
1286
+ FL_1);
1287
+ read_index = ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER,
1288
+ RI_1);
1289
+ store_index = read_index + fill_level;
1290
+
1291
+ if (read_index == s->cfg.rx1_fifo - 1) {
1292
+ /*
1293
+ * When ri is s->cfg.rx1_fifo - 1 i.e. max, it goes cyclic that
1294
+ * means we reset the ri to 0x0.
1295
+ */
1296
+ read_index = 0;
1297
+ ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI_1,
1298
+ read_index);
1299
+ }
1300
+
1301
+ if (store_index > s->cfg.rx1_fifo - 1) {
1302
+ store_index -= s->cfg.rx1_fifo - 1;
1303
+ }
1304
+
1305
+ store_location = R_RB_ID_REGISTER_1 +
1306
+ (store_index * NUM_REGS_PER_MSG_SPACE);
1307
+
1308
+ store_rx_sequential(s, frame, fill_level, read_index,
1309
+ store_location, s->cfg.rx1_fifo, 1,
1310
+ filter_index);
1311
+ }
1312
+
1313
+ path = object_get_canonical_path(OBJECT(s));
1314
+
1315
+ trace_xlnx_canfd_rx_data(path, frame->can_id, frame->can_dlc,
1316
+ frame->flags);
1317
+ canfd_update_irq(s);
1318
+ }
1319
+}
1320
+
1321
+static bool tx_ready_check(XlnxVersalCANFDState *s)
1322
+{
1323
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1324
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1325
+
1326
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
1327
+ " XlnxVersalCANFDState is in reset mode\n", path);
1328
+
1329
+ return false;
1330
+ }
1331
+
1332
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
1333
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1334
+
1335
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
1336
+ " XlnxVersalCANFDState is in configuration mode."
1337
+ " Reset the core so operations can start fresh\n",
1338
+ path);
1339
+ return false;
1340
+ }
1341
+
1342
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
1343
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1344
+
1345
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
1346
+ " XlnxVersalCANFDState is in SNOOP MODE\n",
1347
+ path);
1348
+ return false;
1349
+ }
1350
+
1351
+ return true;
1352
+}
1353
+
1354
+static void tx_fifo_stamp(XlnxVersalCANFDState *s, uint32_t tb0_regid)
1355
+{
1356
+ /*
1357
+ * If EFC bit in DLC message is set, this means we will store the
1358
+ * event of this transmitted message with time stamp.
1359
+ */
1360
+ uint32_t dlc_reg_val = 0;
1361
+
1362
+ if (FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER, EFC)) {
1363
+ uint8_t dlc_val = FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER,
1364
+ DLC);
1365
+ bool fdf_val = FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER,
1366
+ FDF);
1367
+ bool brs_val = FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER,
1368
+ BRS);
1369
+ uint8_t mm_val = FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER,
1370
+ MM);
1371
+ uint8_t fill_level = ARRAY_FIELD_EX32(s->regs,
1372
+ TX_EVENT_FIFO_STATUS_REGISTER,
1373
+ TXE_FL);
1374
+ uint8_t read_index = ARRAY_FIELD_EX32(s->regs,
1375
+ TX_EVENT_FIFO_STATUS_REGISTER,
1376
+ TXE_RI);
1377
+ uint8_t store_index = fill_level + read_index;
1378
+
1379
+ if ((fill_level) > s->cfg.tx_fifo - 1) {
1380
+ qemu_log_mask(LOG_GUEST_ERROR, "TX Event Buffer is full."
1381
+ " Discarding the message\n");
1382
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXEOFLW, 1);
1383
+ } else {
1384
+ if (read_index == s->cfg.tx_fifo - 1) {
1385
+ /*
1386
+ * When ri is s->cfg.tx_fifo - 1 i.e. max, it goes cyclic that
1387
+ * means we reset the ri to 0x0.
1388
+ */
1389
+ read_index = 0;
1390
+ ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_RI,
1391
+ read_index);
1392
+ }
1393
+
1394
+ if (store_index > s->cfg.tx_fifo - 1) {
1395
+ store_index -= s->cfg.tx_fifo - 1;
1396
+ }
1397
+
1398
+ assert(store_index < s->cfg.tx_fifo);
1399
+
1400
+ uint32_t tx_event_reg0_id = R_TXE_FIFO_TB_ID_REGISTER +
1401
+ (store_index * 2);
1402
+
1403
+ /* Store message ID in TX event register. */
1404
+ s->regs[tx_event_reg0_id] = s->regs[tb0_regid];
1405
+
1406
+ uint16_t tx_timestamp = CANFD_TIMER_MAX -
1407
+ ptimer_get_count(s->canfd_timer);
1408
+
1409
+ /* Store DLC with time stamp in DLC regs. */
1410
+ dlc_reg_val = FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, DLC, dlc_val);
1411
+ dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, FDF,
1412
+ fdf_val);
1413
+ dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, BRS,
1414
+ brs_val);
1415
+ dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, ET, 0x3);
1416
+ dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, MM, mm_val);
1417
+ dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, TIMESTAMP,
1418
+ tx_timestamp);
1419
+ s->regs[tx_event_reg0_id + 1] = dlc_reg_val;
1420
+
1421
+ ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL,
1422
+ fill_level + 1);
1423
+ }
1424
+ }
1425
+}
1426
+
1427
+static gint g_cmp_ids(gconstpointer data1, gconstpointer data2)
1428
+{
1429
+ tx_ready_reg_info *tx_reg_1 = (tx_ready_reg_info *) data1;
1430
+ tx_ready_reg_info *tx_reg_2 = (tx_ready_reg_info *) data2;
1431
+
1432
+ return tx_reg_1->can_id - tx_reg_2->can_id;
1433
+}
1434
+
1435
+static void free_list(GSList *list)
1436
+{
1437
+ GSList *iterator = NULL;
1438
+
1439
+ for (iterator = list; iterator != NULL; iterator = iterator->next) {
1440
+ g_free((tx_ready_reg_info *)iterator->data);
1441
+ }
1442
+
1443
+ g_slist_free(list);
1444
+
1445
+ return;
1446
+}
1447
+
1448
+static GSList *prepare_tx_data(XlnxVersalCANFDState *s)
1449
+{
1450
+ uint8_t i = 0;
1451
+ GSList *list = NULL;
1452
+ uint32_t reg_num = 0;
1453
+ uint32_t reg_ready = s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER];
1454
+
1455
+ /* First find the messages which are ready for transmission. */
1456
+ for (i = 0; i < s->cfg.tx_fifo; i++) {
1457
+ if (reg_ready & 1) {
1458
+ reg_num = R_TB_ID_REGISTER + (NUM_REGS_PER_MSG_SPACE * i);
1459
+ tx_ready_reg_info *temp = g_new(tx_ready_reg_info, 1);
1460
+
1461
+ temp->can_id = s->regs[reg_num];
1462
+ temp->reg_num = reg_num;
1463
+ list = g_slist_prepend(list, temp);
1464
+ list = g_slist_sort(list, g_cmp_ids);
1465
+ }
1466
+
1467
+ reg_ready >>= 1;
1468
+ }
1469
+
1470
+ s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER] = 0;
1471
+ s->regs[R_TX_BUFFER_CANCEL_REQUEST_REGISTER] = 0;
1472
+
1473
+ return list;
1474
+}
1475
+
1476
+static void transfer_data(XlnxVersalCANFDState *s)
1477
+{
1478
+ bool canfd_tx = tx_ready_check(s);
1479
+ GSList *list, *iterator = NULL;
1480
+ qemu_can_frame frame;
1481
+
1482
+ if (!canfd_tx) {
1483
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1484
+
1485
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller not enabled for data"
1486
+ " transfer\n", path);
1487
+ return;
1488
+ }
1489
+
1490
+ list = prepare_tx_data(s);
1491
+ if (list == NULL) {
1492
+ return;
1493
+ }
1494
+
1495
+ for (iterator = list; iterator != NULL; iterator = iterator->next) {
1496
+ regs2frame(s, &frame,
1497
+ ((tx_ready_reg_info *)iterator->data)->reg_num);
1498
+
1499
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
1500
+ update_rx_sequential(s, &frame);
1501
+ tx_fifo_stamp(s, ((tx_ready_reg_info *)iterator->data)->reg_num);
1502
+
1503
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
1504
+ } else {
1505
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1506
+
1507
+ trace_xlnx_canfd_tx_data(path, frame.can_id, frame.can_dlc,
1508
+ frame.flags);
1509
+ can_bus_client_send(&s->bus_client, &frame, 1);
1510
+ tx_fifo_stamp(s,
1511
+ ((tx_ready_reg_info *)iterator->data)->reg_num);
1512
+
1513
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXRRS, 1);
1514
+
1515
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
1516
+ canfd_exit_sleep_mode(s);
1517
+ }
1518
+ }
1519
+ }
1520
+
1521
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
1522
+ free_list(list);
1523
+
1524
+ canfd_update_irq(s);
1525
+}
1526
+
1527
+static uint64_t canfd_srr_pre_write(RegisterInfo *reg, uint64_t val64)
1528
+{
1529
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1530
+ uint32_t val = val64;
1531
+
1532
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
1533
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
1534
+
1535
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
1536
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1537
+
1538
+ trace_xlnx_canfd_reset(path, val64);
1539
+
1540
+ /* First, core will do software reset then will enter in config mode. */
1541
+ canfd_config_reset(s);
1542
+ } else if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
1543
+ canfd_config_mode(s);
1544
+ } else {
1545
+ /*
1546
+ * Leave config mode. Now XlnxVersalCANFD core will enter Normal, Sleep,
1547
+ * snoop or Loopback mode depending upon LBACK, SLEEP, SNOOP register
1548
+ * states.
1549
+ */
1550
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
1551
+
1552
+ ptimer_transaction_begin(s->canfd_timer);
1553
+ ptimer_set_count(s->canfd_timer, 0);
1554
+ ptimer_transaction_commit(s->canfd_timer);
1555
+ update_status_register_mode_bits(s);
1556
+ transfer_data(s);
1557
+ }
1558
+
1559
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
1560
+}
1561
+
1562
+static uint64_t filter_mask(RegisterInfo *reg, uint64_t val64)
1563
+{
1564
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1565
+ uint32_t reg_idx = (reg->access->addr) / 4;
1566
+ uint32_t val = val64;
1567
+ uint32_t filter_offset = (reg_idx - R_AFMR_REGISTER) / 2;
1568
+
1569
+ if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
1570
+ (1 << filter_offset))) {
1571
+ s->regs[reg_idx] = val;
1572
+ } else {
1573
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1574
+
1575
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabled\n",
1576
+ path, filter_offset + 1);
1577
+ }
1578
+
1579
+ return s->regs[reg_idx];
1580
+}
1581
+
1582
+static uint64_t filter_id(RegisterInfo *reg, uint64_t val64)
1583
+{
1584
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1585
+ hwaddr reg_idx = (reg->access->addr) / 4;
1586
+ uint32_t val = val64;
1587
+ uint32_t filter_offset = (reg_idx - R_AFIR_REGISTER) / 2;
1588
+
1589
+ if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
1590
+ (1 << filter_offset))) {
1591
+ s->regs[reg_idx] = val;
1592
+ } else {
1593
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1594
+
1595
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabled\n",
1596
+ path, filter_offset + 1);
1597
+ }
1598
+
1599
+ return s->regs[reg_idx];
1600
+}
1601
+
1602
+static uint64_t canfd_tx_fifo_status_prew(RegisterInfo *reg, uint64_t val64)
1603
+{
1604
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1605
+ uint32_t val = val64;
1606
+ uint8_t read_ind = 0;
1607
+ uint8_t fill_ind = ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER,
1608
+ TXE_FL);
1609
+
1610
+ if (FIELD_EX32(val, TX_EVENT_FIFO_STATUS_REGISTER, TXE_IRI) && fill_ind) {
1611
+ read_ind = ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER,
1612
+ TXE_RI) + 1;
1613
+
1614
+ if (read_ind > s->cfg.tx_fifo - 1) {
1615
+ read_ind = 0;
1616
+ }
1617
+
1618
+ /*
1619
+ * Increase the read index by 1 and decrease the fill level by 1.
1620
+ */
1621
+ ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_RI,
1622
+ read_ind);
1623
+ ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL,
1624
+ fill_ind - 1);
1625
+ }
1626
+
1627
+ return s->regs[R_TX_EVENT_FIFO_STATUS_REGISTER];
1628
+}
1629
+
1630
+static uint64_t canfd_rx_fifo_status_prew(RegisterInfo *reg, uint64_t val64)
1631
+{
1632
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1633
+ uint32_t val = val64;
1634
+ uint8_t read_ind = 0;
1635
+ uint8_t fill_ind = 0;
1636
+
1637
+ if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, IRI)) {
1638
+ /* FL index is zero, setting IRI bit has no effect. */
1639
+ if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL) != 0) {
1640
+ read_ind = FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, RI) + 1;
1641
+
1642
+ if (read_ind > s->cfg.rx0_fifo - 1) {
1643
+ read_ind = 0;
1644
+ }
1645
+
1646
+ fill_ind = FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL) - 1;
1647
+
1648
+ ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI, read_ind);
1649
+ ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL, fill_ind);
1650
+ }
1651
+ }
1652
+
1653
+ if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, IRI_1)) {
1654
+ /* FL_1 index is zero, setting IRI_1 bit has no effect. */
1655
+ if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL_1) != 0) {
1656
+ read_ind = FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, RI_1) + 1;
1657
+
1658
+ if (read_ind > s->cfg.rx1_fifo - 1) {
1659
+ read_ind = 0;
1660
+ }
1661
+
1662
+ fill_ind = FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL_1) - 1;
1663
+
1664
+ ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI_1, read_ind);
1665
+ ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1, fill_ind);
1666
+ }
1667
+ }
1668
+
1669
+ return s->regs[R_RX_FIFO_STATUS_REGISTER];
1670
+}
1671
+
1672
+static uint64_t canfd_tsr_pre_write(RegisterInfo *reg, uint64_t val64)
1673
+{
1674
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1675
+ uint32_t val = val64;
1676
+
1677
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
1678
+ ARRAY_FIELD_DP32(s->regs, TIMESTAMP_REGISTER, TIMESTAMP_CNT, 0);
1679
+ ptimer_transaction_begin(s->canfd_timer);
1680
+ ptimer_set_count(s->canfd_timer, 0);
1681
+ ptimer_transaction_commit(s->canfd_timer);
1682
+ }
1683
+
1684
+ return 0;
1685
+}
1686
+
1687
+static uint64_t canfd_trr_reg_prew(RegisterInfo *reg, uint64_t val64)
1688
+{
1689
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1690
+
1691
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
1692
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1693
+
1694
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in SNOOP mode."
1695
+ " tx_ready_register will stay in reset mode\n", path);
1696
+ return 0;
1697
+ } else {
1698
+ return val64;
1699
+ }
1700
+}
1701
+
1702
+static void canfd_trr_reg_postw(RegisterInfo *reg, uint64_t val64)
1703
+{
1704
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1705
+
1706
+ transfer_data(s);
1707
+}
1708
+
1709
+static void canfd_cancel_reg_postw(RegisterInfo *reg, uint64_t val64)
1710
+{
1711
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1712
+
1713
+ process_cancellation_requests(s);
1714
+}
1715
+
1716
+static uint64_t canfd_write_check_prew(RegisterInfo *reg, uint64_t val64)
1717
+{
1718
+ XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
1719
+ uint32_t val = val64;
1720
+
1721
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
1722
+ return val;
1723
+ }
1724
+ return 0;
1725
+}
1726
+
1727
+static const RegisterAccessInfo canfd_tx_regs[] = {
1728
+ { .name = "TB_ID_REGISTER", .addr = A_TB_ID_REGISTER,
1729
+ },{ .name = "TB0_DLC_REGISTER", .addr = A_TB0_DLC_REGISTER,
1730
+ },{ .name = "TB_DW0_REGISTER", .addr = A_TB_DW0_REGISTER,
1731
+ },{ .name = "TB_DW1_REGISTER", .addr = A_TB_DW1_REGISTER,
1732
+ },{ .name = "TB_DW2_REGISTER", .addr = A_TB_DW2_REGISTER,
1733
+ },{ .name = "TB_DW3_REGISTER", .addr = A_TB_DW3_REGISTER,
1734
+ },{ .name = "TB_DW4_REGISTER", .addr = A_TB_DW4_REGISTER,
1735
+ },{ .name = "TB_DW5_REGISTER", .addr = A_TB_DW5_REGISTER,
1736
+ },{ .name = "TB_DW6_REGISTER", .addr = A_TB_DW6_REGISTER,
1737
+ },{ .name = "TB_DW7_REGISTER", .addr = A_TB_DW7_REGISTER,
1738
+ },{ .name = "TB_DW8_REGISTER", .addr = A_TB_DW8_REGISTER,
1739
+ },{ .name = "TB_DW9_REGISTER", .addr = A_TB_DW9_REGISTER,
1740
+ },{ .name = "TB_DW10_REGISTER", .addr = A_TB_DW10_REGISTER,
1741
+ },{ .name = "TB_DW11_REGISTER", .addr = A_TB_DW11_REGISTER,
1742
+ },{ .name = "TB_DW12_REGISTER", .addr = A_TB_DW12_REGISTER,
1743
+ },{ .name = "TB_DW13_REGISTER", .addr = A_TB_DW13_REGISTER,
1744
+ },{ .name = "TB_DW14_REGISTER", .addr = A_TB_DW14_REGISTER,
1745
+ },{ .name = "TB_DW15_REGISTER", .addr = A_TB_DW15_REGISTER,
1746
+ }
1747
+};
1748
+
1749
+static const RegisterAccessInfo canfd_rx0_regs[] = {
1750
+ { .name = "RB_ID_REGISTER", .addr = A_RB_ID_REGISTER,
1751
+ .ro = 0xffffffff,
1752
+ },{ .name = "RB_DLC_REGISTER", .addr = A_RB_DLC_REGISTER,
1753
+ .ro = 0xfe1fffff,
1754
+ },{ .name = "RB_DW0_REGISTER", .addr = A_RB_DW0_REGISTER,
1755
+ .ro = 0xffffffff,
1756
+ },{ .name = "RB_DW1_REGISTER", .addr = A_RB_DW1_REGISTER,
1757
+ .ro = 0xffffffff,
1758
+ },{ .name = "RB_DW2_REGISTER", .addr = A_RB_DW2_REGISTER,
1759
+ .ro = 0xffffffff,
1760
+ },{ .name = "RB_DW3_REGISTER", .addr = A_RB_DW3_REGISTER,
1761
+ .ro = 0xffffffff,
1762
+ },{ .name = "RB_DW4_REGISTER", .addr = A_RB_DW4_REGISTER,
1763
+ .ro = 0xffffffff,
1764
+ },{ .name = "RB_DW5_REGISTER", .addr = A_RB_DW5_REGISTER,
1765
+ .ro = 0xffffffff,
1766
+ },{ .name = "RB_DW6_REGISTER", .addr = A_RB_DW6_REGISTER,
1767
+ .ro = 0xffffffff,
1768
+ },{ .name = "RB_DW7_REGISTER", .addr = A_RB_DW7_REGISTER,
1769
+ .ro = 0xffffffff,
1770
+ },{ .name = "RB_DW8_REGISTER", .addr = A_RB_DW8_REGISTER,
1771
+ .ro = 0xffffffff,
1772
+ },{ .name = "RB_DW9_REGISTER", .addr = A_RB_DW9_REGISTER,
1773
+ .ro = 0xffffffff,
1774
+ },{ .name = "RB_DW10_REGISTER", .addr = A_RB_DW10_REGISTER,
1775
+ .ro = 0xffffffff,
1776
+ },{ .name = "RB_DW11_REGISTER", .addr = A_RB_DW11_REGISTER,
1777
+ .ro = 0xffffffff,
1778
+ },{ .name = "RB_DW12_REGISTER", .addr = A_RB_DW12_REGISTER,
1779
+ .ro = 0xffffffff,
1780
+ },{ .name = "RB_DW13_REGISTER", .addr = A_RB_DW13_REGISTER,
1781
+ .ro = 0xffffffff,
1782
+ },{ .name = "RB_DW14_REGISTER", .addr = A_RB_DW14_REGISTER,
1783
+ .ro = 0xffffffff,
1784
+ },{ .name = "RB_DW15_REGISTER", .addr = A_RB_DW15_REGISTER,
1785
+ .ro = 0xffffffff,
1786
+ }
1787
+};
1788
+
1789
+static const RegisterAccessInfo canfd_rx1_regs[] = {
1790
+ { .name = "RB_ID_REGISTER_1", .addr = A_RB_ID_REGISTER_1,
1791
+ .ro = 0xffffffff,
1792
+ },{ .name = "RB_DLC_REGISTER_1", .addr = A_RB_DLC_REGISTER_1,
1793
+ .ro = 0xfe1fffff,
1794
+ },{ .name = "RB0_DW0_REGISTER_1", .addr = A_RB0_DW0_REGISTER_1,
1795
+ .ro = 0xffffffff,
1796
+ },{ .name = "RB_DW1_REGISTER_1", .addr = A_RB_DW1_REGISTER_1,
1797
+ .ro = 0xffffffff,
1798
+ },{ .name = "RB_DW2_REGISTER_1", .addr = A_RB_DW2_REGISTER_1,
1799
+ .ro = 0xffffffff,
1800
+ },{ .name = "RB_DW3_REGISTER_1", .addr = A_RB_DW3_REGISTER_1,
1801
+ .ro = 0xffffffff,
1802
+ },{ .name = "RB_DW4_REGISTER_1", .addr = A_RB_DW4_REGISTER_1,
1803
+ .ro = 0xffffffff,
1804
+ },{ .name = "RB_DW5_REGISTER_1", .addr = A_RB_DW5_REGISTER_1,
1805
+ .ro = 0xffffffff,
1806
+ },{ .name = "RB_DW6_REGISTER_1", .addr = A_RB_DW6_REGISTER_1,
1807
+ .ro = 0xffffffff,
1808
+ },{ .name = "RB_DW7_REGISTER_1", .addr = A_RB_DW7_REGISTER_1,
1809
+ .ro = 0xffffffff,
1810
+ },{ .name = "RB_DW8_REGISTER_1", .addr = A_RB_DW8_REGISTER_1,
1811
+ .ro = 0xffffffff,
1812
+ },{ .name = "RB_DW9_REGISTER_1", .addr = A_RB_DW9_REGISTER_1,
1813
+ .ro = 0xffffffff,
1814
+ },{ .name = "RB_DW10_REGISTER_1", .addr = A_RB_DW10_REGISTER_1,
1815
+ .ro = 0xffffffff,
1816
+ },{ .name = "RB_DW11_REGISTER_1", .addr = A_RB_DW11_REGISTER_1,
1817
+ .ro = 0xffffffff,
1818
+ },{ .name = "RB_DW12_REGISTER_1", .addr = A_RB_DW12_REGISTER_1,
1819
+ .ro = 0xffffffff,
1820
+ },{ .name = "RB_DW13_REGISTER_1", .addr = A_RB_DW13_REGISTER_1,
1821
+ .ro = 0xffffffff,
1822
+ },{ .name = "RB_DW14_REGISTER_1", .addr = A_RB_DW14_REGISTER_1,
1823
+ .ro = 0xffffffff,
1824
+ },{ .name = "RB_DW15_REGISTER_1", .addr = A_RB_DW15_REGISTER_1,
1825
+ .ro = 0xffffffff,
1826
+ }
1827
+};
1828
+
1829
+/* Acceptance filter registers. */
1830
+static const RegisterAccessInfo canfd_af_regs[] = {
1831
+ { .name = "AFMR_REGISTER", .addr = A_AFMR_REGISTER,
1832
+ .pre_write = filter_mask,
1833
+ },{ .name = "AFIR_REGISTER", .addr = A_AFIR_REGISTER,
1834
+ .pre_write = filter_id,
1835
+ }
1836
+};
1837
+
1838
+static const RegisterAccessInfo canfd_txe_regs[] = {
1839
+ { .name = "TXE_FIFO_TB_ID_REGISTER", .addr = A_TXE_FIFO_TB_ID_REGISTER,
1840
+ .ro = 0xffffffff,
1841
+ },{ .name = "TXE_FIFO_TB_DLC_REGISTER", .addr = A_TXE_FIFO_TB_DLC_REGISTER,
1842
+ .ro = 0xffffffff,
1843
+ }
1844
+};
1845
+
1846
+static const RegisterAccessInfo canfd_regs_info[] = {
1847
+ { .name = "SOFTWARE_RESET_REGISTER", .addr = A_SOFTWARE_RESET_REGISTER,
1848
+ .pre_write = canfd_srr_pre_write,
1849
+ },{ .name = "MODE_SELECT_REGISTER", .addr = A_MODE_SELECT_REGISTER,
1850
+ .pre_write = canfd_msr_pre_write,
1851
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
1852
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
1853
+ .pre_write = canfd_write_check_prew,
1854
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
1855
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
1856
+ .pre_write = canfd_write_check_prew,
1857
+ },{ .name = "ERROR_COUNTER_REGISTER", .addr = A_ERROR_COUNTER_REGISTER,
1858
+ .ro = 0xffff,
1859
+ },{ .name = "ERROR_STATUS_REGISTER", .addr = A_ERROR_STATUS_REGISTER,
1860
+ .w1c = 0xf1f,
1861
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
1862
+ .reset = 0x1,
1863
+ .ro = 0x7f17ff,
1864
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
1865
+ .addr = A_INTERRUPT_STATUS_REGISTER,
1866
+ .ro = 0xffffff7f,
1867
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1868
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1869
+ .post_write = canfd_ier_post_write,
1870
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1871
+ .addr = A_INTERRUPT_CLEAR_REGISTER, .pre_write = canfd_icr_pre_write,
1872
+ },{ .name = "TIMESTAMP_REGISTER", .addr = A_TIMESTAMP_REGISTER,
1873
+ .ro = 0xffff0000,
1874
+ .pre_write = canfd_tsr_pre_write,
1875
+ },{ .name = "DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER",
1876
+ .addr = A_DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER,
1877
+ .pre_write = canfd_write_check_prew,
1878
+ },{ .name = "DATA_PHASE_BIT_TIMING_REGISTER",
1879
+ .addr = A_DATA_PHASE_BIT_TIMING_REGISTER,
1880
+ .pre_write = canfd_write_check_prew,
1881
+ },{ .name = "TX_BUFFER_READY_REQUEST_REGISTER",
1882
+ .addr = A_TX_BUFFER_READY_REQUEST_REGISTER,
1883
+ .pre_write = canfd_trr_reg_prew,
1884
+ .post_write = canfd_trr_reg_postw,
1885
+ },{ .name = "INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER",
1886
+ .addr = A_INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER,
1887
+ },{ .name = "TX_BUFFER_CANCEL_REQUEST_REGISTER",
1888
+ .addr = A_TX_BUFFER_CANCEL_REQUEST_REGISTER,
1889
+ .post_write = canfd_cancel_reg_postw,
1890
+ },{ .name = "INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER",
1891
+ .addr = A_INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER,
1892
+ },{ .name = "TX_EVENT_FIFO_STATUS_REGISTER",
1893
+ .addr = A_TX_EVENT_FIFO_STATUS_REGISTER,
1894
+ .ro = 0x3f1f, .pre_write = canfd_tx_fifo_status_prew,
1895
+ },{ .name = "TX_EVENT_FIFO_WATERMARK_REGISTER",
1896
+ .addr = A_TX_EVENT_FIFO_WATERMARK_REGISTER,
1897
+ .reset = 0xf,
1898
+ .pre_write = canfd_write_check_prew,
1899
+ },{ .name = "ACCEPTANCE_FILTER_CONTROL_REGISTER",
1900
+ .addr = A_ACCEPTANCE_FILTER_CONTROL_REGISTER,
1901
+ },{ .name = "RX_FIFO_STATUS_REGISTER", .addr = A_RX_FIFO_STATUS_REGISTER,
1902
+ .ro = 0x7f3f7f3f, .pre_write = canfd_rx_fifo_status_prew,
1903
+ },{ .name = "RX_FIFO_WATERMARK_REGISTER",
1904
+ .addr = A_RX_FIFO_WATERMARK_REGISTER,
1905
+ .reset = 0x1f0f0f,
1906
+ .pre_write = canfd_write_check_prew,
1907
+ }
1908
+};
1909
+
1910
+static void xlnx_versal_canfd_ptimer_cb(void *opaque)
1911
+{
1912
+ /* No action required on the timer rollover. */
1913
+}
1914
+
1915
+static const MemoryRegionOps canfd_ops = {
1916
+ .read = register_read_memory,
1917
+ .write = register_write_memory,
1918
+ .endianness = DEVICE_LITTLE_ENDIAN,
1919
+ .valid = {
1920
+ .min_access_size = 4,
1921
+ .max_access_size = 4,
1922
+ },
1923
+};
1924
+
1925
+static void canfd_reset(DeviceState *dev)
1926
+{
1927
+ XlnxVersalCANFDState *s = XILINX_CANFD(dev);
1928
+ unsigned int i;
1929
+
1930
+ for (i = 0; i < ARRAY_SIZE(s->reg_info); ++i) {
1931
+ register_reset(&s->reg_info[i]);
1932
+ }
1933
+
1934
+ ptimer_transaction_begin(s->canfd_timer);
1935
+ ptimer_set_count(s->canfd_timer, 0);
1936
+ ptimer_transaction_commit(s->canfd_timer);
1937
+}
1938
+
1939
+static bool can_xilinx_canfd_receive(CanBusClientState *client)
1940
+{
1941
+ XlnxVersalCANFDState *s = container_of(client, XlnxVersalCANFDState,
1942
+ bus_client);
1943
+
1944
+ bool reset_state = ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST);
1945
+ bool can_enabled = ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN);
1946
+
1947
+ return !reset_state && can_enabled;
1948
+}
1949
+
1950
+static ssize_t canfd_xilinx_receive(CanBusClientState *client,
1951
+ const qemu_can_frame *buf,
1952
+ size_t buf_size)
1953
+{
1954
+ XlnxVersalCANFDState *s = container_of(client, XlnxVersalCANFDState,
1955
+ bus_client);
1956
+ const qemu_can_frame *frame = buf;
1957
+
1958
+ assert(buf_size > 0);
1959
+
1960
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
1961
+ /*
1962
+ * XlnxVersalCANFDState will not participate in normal bus communication
1963
+ * and does not receive any messages transmitted by other CAN nodes.
1964
+ */
1965
+ return 1;
1966
+ }
1967
+
1968
+ /* Update the status register that we are receiving message. */
1969
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, BBSY, 1);
1970
+
1971
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1972
+ /* Snoop Mode: Just keep the data. no response back. */
1973
+ update_rx_sequential(s, frame);
1974
+ } else {
1975
+ if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1976
+ /*
1977
+ * XlnxVersalCANFDState is in sleep mode. Any data on bus will bring
1978
+ * it to the wake up state.
1979
+ */
1980
+ canfd_exit_sleep_mode(s);
1981
+ }
1982
+
1983
+ update_rx_sequential(s, frame);
1984
+ }
1985
+
1986
+ /* Message processing done. Update the status back to !busy */
1987
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, BBSY, 0);
1988
+ return 1;
1989
+}
1990
+
1991
+static CanBusClientInfo canfd_xilinx_bus_client_info = {
1992
+ .can_receive = can_xilinx_canfd_receive,
1993
+ .receive = canfd_xilinx_receive,
1994
+};
1995
+
1996
+static int xlnx_canfd_connect_to_bus(XlnxVersalCANFDState *s,
1997
+ CanBusState *bus)
1998
+{
1999
+ s->bus_client.info = &canfd_xilinx_bus_client_info;
2000
+
2001
+ return can_bus_insert_client(bus, &s->bus_client);
2002
+}
2003
+
2004
+#define NUM_REG_PER_AF ARRAY_SIZE(canfd_af_regs)
2005
+#define NUM_AF 32
2006
+#define NUM_REG_PER_TXE ARRAY_SIZE(canfd_txe_regs)
2007
+#define NUM_TXE 32
2008
+
2009
+static int canfd_populate_regarray(XlnxVersalCANFDState *s,
2010
+ RegisterInfoArray *r_array, int pos,
2011
+ const RegisterAccessInfo *rae,
2012
+ int num_rae)
2013
+{
2014
+ int i;
2015
+
2016
+ for (i = 0; i < num_rae; i++) {
2017
+ int index = rae[i].addr / 4;
2018
+ RegisterInfo *r = &s->reg_info[index];
2019
+
2020
+ object_initialize(r, sizeof(*r), TYPE_REGISTER);
2021
+
2022
+ *r = (RegisterInfo) {
2023
+ .data = &s->regs[index],
2024
+ .data_size = sizeof(uint32_t),
2025
+ .access = &rae[i],
2026
+ .opaque = OBJECT(s),
2027
+ };
2028
+
2029
+ r_array->r[i + pos] = r;
2030
+ }
2031
+ return i + pos;
2032
+}
2033
+
2034
+static void canfd_create_rai(RegisterAccessInfo *rai_array,
2035
+ const RegisterAccessInfo *canfd_regs,
2036
+ int template_rai_array_sz,
2037
+ int num_template_to_copy)
2038
+{
2039
+ int i;
2040
+ int reg_num;
2041
+
2042
+ for (reg_num = 0; reg_num < num_template_to_copy; reg_num++) {
2043
+ int pos = reg_num * template_rai_array_sz;
2044
+
2045
+ memcpy(rai_array + pos, canfd_regs,
2046
+ template_rai_array_sz * sizeof(RegisterAccessInfo));
2047
+
2048
+ for (i = 0; i < template_rai_array_sz; i++) {
2049
+ const char *name = canfd_regs[i].name;
2050
+ uint64_t addr = canfd_regs[i].addr;
2051
+ rai_array[i + pos].name = g_strdup_printf("%s%d", name, reg_num);
2052
+ rai_array[i + pos].addr = addr + pos * 4;
2053
+ }
2054
+ }
2055
+}
2056
+
2057
+static RegisterInfoArray *canfd_create_regarray(XlnxVersalCANFDState *s)
2058
+{
2059
+ const char *device_prefix = object_get_typename(OBJECT(s));
2060
+ uint64_t memory_size = XLNX_VERSAL_CANFD_R_MAX * 4;
2061
+ int num_regs;
2062
+ int pos = 0;
2063
+ RegisterInfoArray *r_array;
2064
+
2065
+ num_regs = ARRAY_SIZE(canfd_regs_info) +
2066
+ s->cfg.tx_fifo * NUM_REGS_PER_MSG_SPACE +
2067
+ s->cfg.rx0_fifo * NUM_REGS_PER_MSG_SPACE +
2068
+ NUM_AF * NUM_REG_PER_AF +
2069
+ NUM_TXE * NUM_REG_PER_TXE;
2070
+
2071
+ s->tx_regs = g_new0(RegisterAccessInfo,
2072
+ s->cfg.tx_fifo * ARRAY_SIZE(canfd_tx_regs));
2073
+
2074
+ canfd_create_rai(s->tx_regs, canfd_tx_regs,
2075
+ ARRAY_SIZE(canfd_tx_regs), s->cfg.tx_fifo);
2076
+
2077
+ s->rx0_regs = g_new0(RegisterAccessInfo,
2078
+ s->cfg.rx0_fifo * ARRAY_SIZE(canfd_rx0_regs));
2079
+
2080
+ canfd_create_rai(s->rx0_regs, canfd_rx0_regs,
2081
+ ARRAY_SIZE(canfd_rx0_regs), s->cfg.rx0_fifo);
2082
+
2083
+ s->af_regs = g_new0(RegisterAccessInfo,
2084
+ NUM_AF * ARRAY_SIZE(canfd_af_regs));
2085
+
2086
+ canfd_create_rai(s->af_regs, canfd_af_regs,
2087
+ ARRAY_SIZE(canfd_af_regs), NUM_AF);
2088
+
2089
+ s->txe_regs = g_new0(RegisterAccessInfo,
2090
+ NUM_TXE * ARRAY_SIZE(canfd_txe_regs));
2091
+
2092
+ canfd_create_rai(s->txe_regs, canfd_txe_regs,
2093
+ ARRAY_SIZE(canfd_txe_regs), NUM_TXE);
2094
+
2095
+ if (s->cfg.enable_rx_fifo1) {
2096
+ num_regs += s->cfg.rx1_fifo * NUM_REGS_PER_MSG_SPACE;
2097
+
2098
+ s->rx1_regs = g_new0(RegisterAccessInfo,
2099
+ s->cfg.rx1_fifo * ARRAY_SIZE(canfd_rx1_regs));
2100
+
2101
+ canfd_create_rai(s->rx1_regs, canfd_rx1_regs,
2102
+ ARRAY_SIZE(canfd_rx1_regs), s->cfg.rx1_fifo);
2103
+ }
2104
+
2105
+ r_array = g_new0(RegisterInfoArray, 1);
2106
+ r_array->r = g_new0(RegisterInfo * , num_regs);
2107
+ r_array->num_elements = num_regs;
2108
+ r_array->prefix = device_prefix;
2109
+
2110
+ pos = canfd_populate_regarray(s, r_array, pos,
2111
+ canfd_regs_info,
2112
+ ARRAY_SIZE(canfd_regs_info));
2113
+ pos = canfd_populate_regarray(s, r_array, pos,
2114
+ s->tx_regs, s->cfg.tx_fifo *
2115
+ NUM_REGS_PER_MSG_SPACE);
2116
+ pos = canfd_populate_regarray(s, r_array, pos,
2117
+ s->rx0_regs, s->cfg.rx0_fifo *
2118
+ NUM_REGS_PER_MSG_SPACE);
2119
+ if (s->cfg.enable_rx_fifo1) {
2120
+ pos = canfd_populate_regarray(s, r_array, pos,
2121
+ s->rx1_regs, s->cfg.rx1_fifo *
2122
+ NUM_REGS_PER_MSG_SPACE);
2123
+ }
2124
+ pos = canfd_populate_regarray(s, r_array, pos,
2125
+ s->af_regs, NUM_AF * NUM_REG_PER_AF);
2126
+ pos = canfd_populate_regarray(s, r_array, pos,
2127
+ s->txe_regs, NUM_TXE * NUM_REG_PER_TXE);
2128
+
2129
+ memory_region_init_io(&r_array->mem, OBJECT(s), &canfd_ops, r_array,
2130
+ device_prefix, memory_size);
2131
+ return r_array;
2132
+}
2133
+
2134
+static void canfd_realize(DeviceState *dev, Error **errp)
2135
+{
2136
+ XlnxVersalCANFDState *s = XILINX_CANFD(dev);
2137
+ RegisterInfoArray *reg_array;
2138
+
2139
+ reg_array = canfd_create_regarray(s);
2140
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
2141
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
2142
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_canfd_int);
2143
+
2144
+ if (s->canfdbus) {
2145
+ if (xlnx_canfd_connect_to_bus(s, s->canfdbus) < 0) {
2146
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
2147
+
2148
+ error_setg(errp, "%s: xlnx_canfd_connect_to_bus failed", path);
2149
+ return;
2150
+ }
2151
+
2152
+ }
2153
+
2154
+ /* Allocate a new timer. */
2155
+ s->canfd_timer = ptimer_init(xlnx_versal_canfd_ptimer_cb, s,
2156
+ PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
2157
+ PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
2158
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD);
2159
+
2160
+ ptimer_transaction_begin(s->canfd_timer);
2161
+
2162
+ ptimer_set_freq(s->canfd_timer, s->cfg.ext_clk_freq);
2163
+ ptimer_set_limit(s->canfd_timer, CANFD_TIMER_MAX, 1);
2164
+ ptimer_run(s->canfd_timer, 0);
2165
+ ptimer_transaction_commit(s->canfd_timer);
2166
+}
2167
+
2168
+static void canfd_init(Object *obj)
2169
+{
2170
+ XlnxVersalCANFDState *s = XILINX_CANFD(obj);
2171
+
2172
+ memory_region_init(&s->iomem, obj, TYPE_XILINX_CANFD,
2173
+ XLNX_VERSAL_CANFD_R_MAX * 4);
2174
+}
2175
+
2176
+static const VMStateDescription vmstate_canfd = {
2177
+ .name = TYPE_XILINX_CANFD,
2178
+ .version_id = 1,
2179
+ .minimum_version_id = 1,
2180
+ .fields = (VMStateField[]) {
2181
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCANFDState,
2182
+ XLNX_VERSAL_CANFD_R_MAX),
2183
+ VMSTATE_PTIMER(canfd_timer, XlnxVersalCANFDState),
2184
+ VMSTATE_END_OF_LIST(),
2185
+ }
2186
+};
2187
+
2188
+static Property canfd_core_properties[] = {
2189
+ DEFINE_PROP_UINT8("rx-fifo0", XlnxVersalCANFDState, cfg.rx0_fifo, 0x40),
2190
+ DEFINE_PROP_UINT8("rx-fifo1", XlnxVersalCANFDState, cfg.rx1_fifo, 0x40),
2191
+ DEFINE_PROP_UINT8("tx-fifo", XlnxVersalCANFDState, cfg.tx_fifo, 0x20),
2192
+ DEFINE_PROP_BOOL("enable-rx-fifo1", XlnxVersalCANFDState,
2193
+ cfg.enable_rx_fifo1, true),
2194
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxVersalCANFDState, cfg.ext_clk_freq,
2195
+ CANFD_DEFAULT_CLOCK),
2196
+ DEFINE_PROP_LINK("canfdbus", XlnxVersalCANFDState, canfdbus, TYPE_CAN_BUS,
2197
+ CanBusState *),
2198
+ DEFINE_PROP_END_OF_LIST(),
2199
+};
2200
+
2201
+static void canfd_class_init(ObjectClass *klass, void *data)
2202
+{
2203
+ DeviceClass *dc = DEVICE_CLASS(klass);
2204
+
2205
+ dc->reset = canfd_reset;
2206
+ dc->realize = canfd_realize;
2207
+ device_class_set_props(dc, canfd_core_properties);
2208
+ dc->vmsd = &vmstate_canfd;
2209
+}
2210
+
2211
+static const TypeInfo canfd_info = {
2212
+ .name = TYPE_XILINX_CANFD,
2213
+ .parent = TYPE_SYS_BUS_DEVICE,
2214
+ .instance_size = sizeof(XlnxVersalCANFDState),
2215
+ .class_init = canfd_class_init,
2216
+ .instance_init = canfd_init,
2217
+};
2218
+
2219
+static void canfd_register_types(void)
2220
+{
2221
+ type_register_static(&canfd_info);
2222
+}
2223
+
2224
+type_init(canfd_register_types)
2225
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
2226
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
2227
--- a/hw/net/can/meson.build
80
--- a/fpu/softfloat-specialize.c.inc
2228
+++ b/hw/net/can/meson.build
81
+++ b/fpu/softfloat-specialize.c.inc
2229
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
2230
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
83
return a;
2231
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
84
}
2232
softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
85
2233
+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-canfd.c'))
86
-/*----------------------------------------------------------------------------
2234
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
87
-| Takes two extended double-precision floating-point values `a' and `b', one
2235
index XXXXXXX..XXXXXXX 100644
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
2236
--- a/hw/net/can/trace-events
89
-| `b' is a signaling NaN, the invalid exception is raised.
2237
+++ b/hw/net/can/trace-events
90
-*----------------------------------------------------------------------------*/
2238
@@ -XXX,XX +XXX,XX @@ xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter%d MAS
91
-
2239
xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
2240
xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
93
-{
2241
xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus communication. Status Register: 0x%08x"
94
- bool aIsLargerSignificand;
2242
+
95
- FloatClass a_cls, b_cls;
2243
+# xlnx-versal-canfd.c
96
-
2244
+xlnx_canfd_update_irq(char *path, uint32_t isr, uint32_t ier, uint32_t irq) "%s: ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
97
- /* This is not complete, but is good enough for pickNaN. */
2245
+xlnx_canfd_rx_fifo_filter_reject(char *path, uint32_t id, uint8_t dlc) "%s: Frame: ID: 0x%08x DLC: 0x%02x"
98
- a_cls = (!floatx80_is_any_nan(a)
2246
+xlnx_canfd_rx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flags) "%s: Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
99
- ? float_class_normal
2247
+xlnx_canfd_tx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flgas) "%s: Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
100
- : floatx80_is_signaling_nan(a, status)
2248
+xlnx_canfd_reset(char *path, uint32_t val) "%s: Resetting controller with value = 0x%08x"
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.
2249
--
141
--
2250
2.34.1
142
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Unpacking and repacking the parts may be slightly more work
4
than we did before, but we get to reuse more code. For a
5
code path handling exceptional values, this is an improvement.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20230530191438.411344-16-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/cpu.h | 3 ++-
12
fpu/softfloat.c | 43 +++++--------------------------------------
9
target/arm/tcg/translate.h | 2 ++
13
1 file changed, 5 insertions(+), 38 deletions(-)
10
target/arm/tcg/hflags.c | 6 ++++++
11
target/arm/tcg/translate-a64.c | 1 +
12
4 files changed, 11 insertions(+), 1 deletion(-)
13
14
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
--- a/fpu/softfloat.c
17
+++ b/target/arm/cpu.h
18
+++ b/fpu/softfloat.c
18
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
19
#define SCTLR_D (1U << 5) /* up to v5; RAO in v6 */
20
20
#define SCTLR_CP15BEN (1U << 5) /* v7 onward */
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
21
#define SCTLR_L (1U << 6) /* up to v5; RAO in v6 and v7; RAZ in v8 */
22
{
22
-#define SCTLR_nAA (1U << 6) /* when v8.4-LSE is implemented */
23
- bool aIsLargerSignificand;
23
+#define SCTLR_nAA (1U << 6) /* when FEAT_LSE2 is implemented */
24
- FloatClass a_cls, b_cls;
24
#define SCTLR_B (1U << 7) /* up to v6; RAZ in v7 */
25
+ FloatParts128 pa, pb, *pr;
25
#define SCTLR_ITD (1U << 7) /* v8 onward */
26
26
#define SCTLR_S (1U << 8) /* up to v6; RAZ in v7 */
27
- /* This is not complete, but is good enough for pickNaN. */
27
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, SVL, 24, 4)
28
- a_cls = (!floatx80_is_any_nan(a)
28
/* Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not. */
29
- ? float_class_normal
29
FIELD(TBFLAG_A64, SME_TRAP_NONSTREAMING, 28, 1)
30
- : floatx80_is_signaling_nan(a, status)
30
FIELD(TBFLAG_A64, FGT_ERET, 29, 1)
31
- ? float_class_snan
31
+FIELD(TBFLAG_A64, NAA, 30, 1)
32
- : float_class_qnan);
32
33
- b_cls = (!floatx80_is_any_nan(b)
33
/*
34
- ? float_class_normal
34
* Helpers for using the above.
35
- : floatx80_is_signaling_nan(b, status)
35
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
36
- ? float_class_snan
36
index XXXXXXX..XXXXXXX 100644
37
- : float_class_qnan);
37
--- a/target/arm/tcg/translate.h
38
-
38
+++ b/target/arm/tcg/translate.h
39
- if (is_snan(a_cls) || is_snan(b_cls)) {
39
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
40
- float_raise(float_flag_invalid, status);
40
bool fgt_eret;
41
- }
41
/* True if fine-grained trap on SVC is enabled */
42
-
42
bool fgt_svc;
43
- if (status->default_nan_mode) {
43
+ /* True if FEAT_LSE2 SCTLR_ELx.nAA is set */
44
+ if (!floatx80_unpack_canonical(&pa, a, status) ||
44
+ bool naa;
45
+ !floatx80_unpack_canonical(&pb, b, status)) {
45
/*
46
return floatx80_default_nan(status);
46
* >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
47
* < 0, set by the current instruction.
48
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/tcg/hflags.c
51
+++ b/target/arm/tcg/hflags.c
52
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
53
}
54
}
47
}
55
48
56
+ if (cpu_isar_feature(aa64_lse2, env_archcpu(env))) {
49
- if (a.low < b.low) {
57
+ if (sctlr & SCTLR_nAA) {
50
- aIsLargerSignificand = 0;
58
+ DP_TBFLAG_A64(flags, NAA, 1);
51
- } else if (b.low < a.low) {
59
+ }
52
- aIsLargerSignificand = 1;
60
+ }
53
- } else {
61
+
54
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
62
/* Compute the condition for using AccType_UNPRIV for LDTR et al. */
55
- }
63
if (!(env->pstate & PSTATE_UAO)) {
56
-
64
switch (mmu_idx) {
57
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
65
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
58
- if (is_snan(b_cls)) {
66
index XXXXXXX..XXXXXXX 100644
59
- return floatx80_silence_nan(b, status);
67
--- a/target/arm/tcg/translate-a64.c
60
- }
68
+++ b/target/arm/tcg/translate-a64.c
61
- return b;
69
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
62
- } else {
70
dc->pstate_sm = EX_TBFLAG_A64(tb_flags, PSTATE_SM);
63
- if (is_snan(a_cls)) {
71
dc->pstate_za = EX_TBFLAG_A64(tb_flags, PSTATE_ZA);
64
- return floatx80_silence_nan(a, status);
72
dc->sme_trap_nonstreaming = EX_TBFLAG_A64(tb_flags, SME_TRAP_NONSTREAMING);
65
- }
73
+ dc->naa = EX_TBFLAG_A64(tb_flags, NAA);
66
- return a;
74
dc->vec_len = 0;
67
- }
75
dc->vec_stride = 0;
68
+ pr = parts_pick_nan(&pa, &pb, status);
76
dc->cp_regs = arm_cpu->cp_regs;
69
+ return floatx80_round_pack_canonical(pr, status);
70
}
71
72
/*----------------------------------------------------------------------------
77
--
73
--
78
2.34.1
74
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We are going to need the complete memop beforehand,
3
Inline pickNaN into its only caller. This makes one assert
4
so let's not compute it twice.
4
redundant with the immediately preceding IF.
5
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230530191438.411344-11-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-9-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
---
10
---
11
target/arm/tcg/translate-a64.c | 61 +++++++++++++++++++---------------
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
12
1 file changed, 35 insertions(+), 26 deletions(-)
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
13
13
2 files changed, 73 insertions(+), 105 deletions(-)
14
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
14
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/tcg/translate-a64.c
17
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/tcg/translate-a64.c
18
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
19
unsigned int iss_srt,
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
20
bool iss_sf, bool iss_ar)
21
float_status *s)
21
{
22
{
22
- memop = finalize_memop(s, memop);
23
+ int cmp, which;
23
tcg_gen_qemu_st_i64(source, tcg_addr, memidx, memop);
24
+
24
25
if (is_snan(a->cls) || is_snan(b->cls)) {
25
if (iss_valid) {
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
26
@@ -XXX,XX +XXX,XX @@ static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
27
}
27
bool iss_valid, unsigned int iss_srt,
28
28
bool iss_sf, bool iss_ar)
29
if (s->default_nan_mode) {
29
{
30
parts_default_nan(a, s);
30
- memop = finalize_memop(s, memop);
31
- } else {
31
tcg_gen_qemu_ld_i64(dest, tcg_addr, memidx, memop);
32
- int cmp = frac_cmp(a, b);
32
33
- if (cmp == 0) {
33
if (extend && (memop & MO_SIGN)) {
34
- cmp = a->sign < b->sign;
34
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
35
- }
35
int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
36
+ return a;
36
int size = extract32(insn, 30, 2);
37
+ }
37
TCGv_i64 clean_addr;
38
38
+ MemOp memop;
39
- if (pickNaN(a->cls, b->cls, cmp > 0, s)) {
39
40
- a = b;
40
switch (o2_L_o1_o0) {
41
- }
41
case 0x0: /* STXR */
42
+ cmp = frac_cmp(a, b);
42
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
43
+ if (cmp == 0) {
43
gen_check_sp_alignment(s);
44
+ cmp = a->sign < b->sign;
45
+ }
46
+
47
+ switch (s->float_2nan_prop_rule) {
48
+ case float_2nan_prop_s_ab:
49
if (is_snan(a->cls)) {
50
- parts_silence_nan(a, s);
51
+ which = 0;
52
+ } else if (is_snan(b->cls)) {
53
+ which = 1;
54
+ } else if (is_qnan(a->cls)) {
55
+ which = 0;
56
+ } else {
57
+ which = 1;
44
}
58
}
45
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
59
+ break;
46
+ /* TODO: ARMv8.4-LSE SCTLR.nAA */
60
+ case float_2nan_prop_s_ba:
47
+ memop = finalize_memop(s, size | MO_ALIGN);
61
+ if (is_snan(b->cls)) {
48
clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
62
+ which = 1;
49
true, rn != 31, size);
63
+ } else if (is_snan(a->cls)) {
50
- /* TODO: ARMv8.4-LSE SCTLR.nAA */
64
+ which = 0;
51
- do_gpr_st(s, cpu_reg(s, rt), clean_addr, size | MO_ALIGN, true, rt,
65
+ } else if (is_qnan(b->cls)) {
52
+ do_gpr_st(s, cpu_reg(s, rt), clean_addr, memop, true, rt,
66
+ which = 1;
53
disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
67
+ } else {
54
return;
68
+ which = 0;
55
69
+ }
56
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
70
+ break;
57
if (rn == 31) {
71
+ case float_2nan_prop_ab:
58
gen_check_sp_alignment(s);
72
+ which = is_nan(a->cls) ? 0 : 1;
59
}
73
+ break;
60
+ /* TODO: ARMv8.4-LSE SCTLR.nAA */
74
+ case float_2nan_prop_ba:
61
+ memop = finalize_memop(s, size | MO_ALIGN);
75
+ which = is_nan(b->cls) ? 1 : 0;
62
clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
76
+ break;
63
false, rn != 31, size);
77
+ case float_2nan_prop_x87:
64
- /* TODO: ARMv8.4-LSE SCTLR.nAA */
78
+ /*
65
- do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size | MO_ALIGN, false, true,
79
+ * This implements x87 NaN propagation rules:
66
+ do_gpr_ld(s, cpu_reg(s, rt), clean_addr, memop, false, true,
80
+ * SNaN + QNaN => return the QNaN
67
rt, disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
81
+ * two SNaNs => return the one with the larger significand, silenced
68
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
82
+ * two QNaNs => return the one with the larger significand
69
return;
83
+ * SNaN and a non-NaN => return the SNaN, silenced
70
@@ -XXX,XX +XXX,XX @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
84
+ * QNaN and a non-NaN => return the QNaN
71
} else {
85
+ *
72
/* Only unsigned 32bit loads target 32bit registers. */
86
+ * If we get down to comparing significands and they are the same,
73
bool iss_sf = opc != 0;
87
+ * return the NaN with the positive sign bit (if any).
74
+ MemOp memop = finalize_memop(s, size + is_signed * MO_SIGN);
88
+ */
75
89
+ if (is_snan(a->cls)) {
76
- do_gpr_ld(s, tcg_rt, clean_addr, size + is_signed * MO_SIGN,
90
+ if (is_snan(b->cls)) {
77
- false, true, rt, iss_sf, false);
91
+ which = cmp > 0 ? 0 : 1;
78
+ do_gpr_ld(s, tcg_rt, clean_addr, memop, false, true, rt, iss_sf, false);
92
+ } else {
93
+ which = is_qnan(b->cls) ? 1 : 0;
94
+ }
95
+ } else if (is_qnan(a->cls)) {
96
+ if (is_snan(b->cls) || !is_qnan(b->cls)) {
97
+ which = 0;
98
+ } else {
99
+ which = cmp > 0 ? 0 : 1;
100
+ }
101
+ } else {
102
+ which = 1;
103
+ }
104
+ break;
105
+ default:
106
+ g_assert_not_reached();
107
+ }
108
+
109
+ if (which) {
110
+ a = b;
111
+ }
112
+ if (is_snan(a->cls)) {
113
+ parts_silence_nan(a, s);
114
}
115
return a;
116
}
117
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
118
index XXXXXXX..XXXXXXX 100644
119
--- a/fpu/softfloat-specialize.c.inc
120
+++ b/fpu/softfloat-specialize.c.inc
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
79
}
122
}
80
}
123
}
81
124
82
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
125
-/*----------------------------------------------------------------------------
83
bool post_index;
126
-| Select which NaN to propagate for a two-input operation.
84
bool writeback;
127
-| IEEE754 doesn't specify all the details of this, so the
85
int memidx;
128
-| algorithm is target-specific.
129
-| The routine is passed various bits of information about the
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
131
-| Note that signalling NaNs are always squashed to quiet NaNs
132
-| by the caller, by calling floatXX_silence_nan() before
133
-| returning them.
134
-|
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
136
-| of some kind, and is true if a has the larger significand,
137
-| or if both a and b have the same significand but a is
138
-| positive but b is negative. It is only needed for the x87
139
-| tie-break rule.
140
-*----------------------------------------------------------------------------*/
86
-
141
-
87
+ MemOp memop;
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
88
TCGv_i64 clean_addr, dirty_addr;
143
- bool aIsLargerSignificand, float_status *status)
89
144
-{
90
if (is_vector) {
145
- /*
91
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
146
- * We guarantee not to require the target to tell us how to
92
return;
147
- * pick a NaN if we're always returning the default NaN.
93
}
148
- * But if we're not in default-NaN mode then the target must
94
is_store = (opc == 0);
149
- * specify via set_float_2nan_prop_rule().
95
- is_signed = extract32(opc, 1, 1);
150
- */
96
+ is_signed = !is_store && extract32(opc, 1, 1);
151
- assert(!status->default_nan_mode);
97
is_extended = (size < 3) && extract32(opc, 0, 1);
98
}
99
100
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
101
}
102
103
memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
104
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
105
+
106
clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
107
writeback || rn != 31,
108
size, is_unpriv, memidx);
109
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
110
bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
111
112
if (is_store) {
113
- do_gpr_st_memidx(s, tcg_rt, clean_addr, size, memidx,
114
+ do_gpr_st_memidx(s, tcg_rt, clean_addr, memop, memidx,
115
iss_valid, rt, iss_sf, false);
116
} else {
117
- do_gpr_ld_memidx(s, tcg_rt, clean_addr, size + is_signed * MO_SIGN,
118
+ do_gpr_ld_memidx(s, tcg_rt, clean_addr, memop,
119
is_extended, memidx,
120
iss_valid, rt, iss_sf, false);
121
}
122
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
123
bool is_signed = false;
124
bool is_store = false;
125
bool is_extended = false;
126
-
152
-
127
TCGv_i64 tcg_rm, clean_addr, dirty_addr;
153
- switch (status->float_2nan_prop_rule) {
128
+ MemOp memop;
154
- case float_2nan_prop_s_ab:
129
155
- if (is_snan(a_cls)) {
130
if (extract32(opt, 1, 1) == 0) {
156
- return 0;
131
unallocated_encoding(s);
157
- } else if (is_snan(b_cls)) {
132
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
158
- return 1;
133
return;
159
- } else if (is_qnan(a_cls)) {
134
}
160
- return 0;
135
is_store = (opc == 0);
161
- } else {
136
- is_signed = extract32(opc, 1, 1);
162
- return 1;
137
+ is_signed = !is_store && extract32(opc, 1, 1);
163
- }
138
is_extended = (size < 3) && extract32(opc, 0, 1);
164
- break;
139
}
165
- case float_2nan_prop_s_ba:
140
166
- if (is_snan(b_cls)) {
141
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
167
- return 1;
142
ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
168
- } else if (is_snan(a_cls)) {
143
169
- return 0;
144
tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
170
- } else if (is_qnan(b_cls)) {
145
+
171
- return 1;
146
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
172
- } else {
147
clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, size);
173
- return 0;
148
174
- }
149
if (is_vector) {
175
- break;
150
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
176
- case float_2nan_prop_ab:
151
} else {
177
- if (is_nan(a_cls)) {
152
TCGv_i64 tcg_rt = cpu_reg(s, rt);
178
- return 0;
153
bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
179
- } else {
154
+
180
- return 1;
155
if (is_store) {
181
- }
156
- do_gpr_st(s, tcg_rt, clean_addr, size,
182
- break;
157
+ do_gpr_st(s, tcg_rt, clean_addr, memop,
183
- case float_2nan_prop_ba:
158
true, rt, iss_sf, false);
184
- if (is_nan(b_cls)) {
159
} else {
185
- return 1;
160
- do_gpr_ld(s, tcg_rt, clean_addr, size + is_signed * MO_SIGN,
186
- } else {
161
+ do_gpr_ld(s, tcg_rt, clean_addr, memop,
187
- return 0;
162
is_extended, true, rt, iss_sf, false);
188
- }
163
}
189
- break;
164
}
190
- case float_2nan_prop_x87:
165
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
191
- /*
166
int rn = extract32(insn, 5, 5);
192
- * This implements x87 NaN propagation rules:
167
unsigned int imm12 = extract32(insn, 10, 12);
193
- * SNaN + QNaN => return the QNaN
168
unsigned int offset;
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
-}
169
-
220
-
170
TCGv_i64 clean_addr, dirty_addr;
221
/*----------------------------------------------------------------------------
171
-
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
172
bool is_store;
223
| NaN; otherwise returns 0.
173
bool is_signed = false;
174
bool is_extended = false;
175
+ MemOp memop;
176
177
if (is_vector) {
178
size |= (opc & 2) << 1;
179
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
180
return;
181
}
182
is_store = (opc == 0);
183
- is_signed = extract32(opc, 1, 1);
184
+ is_signed = !is_store && extract32(opc, 1, 1);
185
is_extended = (size < 3) && extract32(opc, 0, 1);
186
}
187
188
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
189
dirty_addr = read_cpu_reg_sp(s, rn, 1);
190
offset = imm12 << size;
191
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
192
+
193
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
194
clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, size);
195
196
if (is_vector) {
197
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
198
TCGv_i64 tcg_rt = cpu_reg(s, rt);
199
bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
200
if (is_store) {
201
- do_gpr_st(s, tcg_rt, clean_addr, size,
202
- true, rt, iss_sf, false);
203
+ do_gpr_st(s, tcg_rt, clean_addr, memop, true, rt, iss_sf, false);
204
} else {
205
- do_gpr_ld(s, tcg_rt, clean_addr, size + is_signed * MO_SIGN,
206
+ do_gpr_ld(s, tcg_rt, clean_addr, memop,
207
is_extended, true, rt, iss_sf, false);
208
}
209
}
210
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
211
bool a = extract32(insn, 23, 1);
212
TCGv_i64 tcg_rs, tcg_rt, clean_addr;
213
AtomicThreeOpFn *fn = NULL;
214
- MemOp mop = s->be_data | size | MO_ALIGN;
215
+ MemOp mop = finalize_memop(s, size | MO_ALIGN);
216
217
if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
218
unallocated_encoding(s);
219
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
220
* full load-acquire (we only need "load-acquire processor consistent"),
221
* but we choose to implement them as full LDAQ.
222
*/
223
- do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false,
224
+ do_gpr_ld(s, cpu_reg(s, rt), clean_addr, mop, false,
225
true, rt, disas_ldst_compute_iss_sf(size, false, 0), true);
226
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
227
return;
228
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn,
229
bool use_key_a = !extract32(insn, 23, 1);
230
int offset;
231
TCGv_i64 clean_addr, dirty_addr, tcg_rt;
232
+ MemOp memop;
233
234
if (size != 3 || is_vector || !dc_isar_feature(aa64_pauth, s)) {
235
unallocated_encoding(s);
236
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn,
237
offset = sextract32(offset << size, 0, 10 + size);
238
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
239
240
+ memop = finalize_memop(s, size);
241
+
242
/* Note that "clean" and "dirty" here refer to TBI not PAC. */
243
clean_addr = gen_mte_check1(s, dirty_addr, false,
244
is_wback || rn != 31, size);
245
246
tcg_rt = cpu_reg(s, rt);
247
- do_gpr_ld(s, tcg_rt, clean_addr, size,
248
+ do_gpr_ld(s, tcg_rt, clean_addr, memop,
249
/* extend */ false, /* iss_valid */ !is_wback,
250
/* iss_srt */ rt, /* iss_sf */ true, /* iss_ar */ false);
251
252
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
253
}
254
255
/* TODO: ARMv8.4-LSE SCTLR.nAA */
256
- mop = size | MO_ALIGN;
257
+ mop = finalize_memop(s, size | MO_ALIGN);
258
259
switch (opc) {
260
case 0: /* STLURB */
261
--
224
--
262
2.34.1
225
2.34.1
226
227
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
FEAT_LSE2 only requires that atomic operations not cross a
3
Remember if there was an SNaN, and use that to simplify
4
16-byte boundary. Ordered operations may be completely
4
float_2nan_prop_s_{ab,ba} to only the snan component.
5
unaligned if SCTLR.nAA is set.
5
Then, fall through to the corresponding
6
6
float_2nan_prop_{ab,ba} case to handle any remaining
7
Because this alignment check is so special, do it by hand.
7
nans, which must be quiet.
8
Make sure not to keep TCG temps live across the branch.
9
8
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20230530191438.411344-17-richard.henderson@linaro.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
13
---
15
target/arm/tcg/helper-a64.h | 3 +
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
16
target/arm/tcg/helper-a64.c | 7 ++
15
1 file changed, 12 insertions(+), 20 deletions(-)
17
target/arm/tcg/translate-a64.c | 120 ++++++++++++++++++++++++++-------
18
3 files changed, 104 insertions(+), 26 deletions(-)
19
16
20
diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/tcg/helper-a64.h
19
--- a/fpu/softfloat-parts.c.inc
23
+++ b/target/arm/tcg/helper-a64.h
20
+++ b/fpu/softfloat-parts.c.inc
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(st2g_stub, TCG_CALL_NO_WG, void, env, i64)
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
25
DEF_HELPER_FLAGS_2(ldgm, TCG_CALL_NO_WG, i64, env, i64)
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
26
DEF_HELPER_FLAGS_3(stgm, TCG_CALL_NO_WG, void, env, i64, i64)
23
float_status *s)
27
DEF_HELPER_FLAGS_3(stzgm_tags, TCG_CALL_NO_WG, void, env, i64, i64)
28
+
29
+DEF_HELPER_FLAGS_4(unaligned_access, TCG_CALL_NO_WG,
30
+ noreturn, env, i64, i32, i32)
31
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/tcg/helper-a64.c
34
+++ b/target/arm/tcg/helper-a64.c
35
@@ -XXX,XX +XXX,XX @@ void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
36
37
memset(mem, 0, blocklen);
38
}
39
+
40
+void HELPER(unaligned_access)(CPUARMState *env, uint64_t addr,
41
+ uint32_t access_type, uint32_t mmu_idx)
42
+{
43
+ arm_cpu_do_unaligned_access(env_cpu(env), addr, access_type,
44
+ mmu_idx, GETPC());
45
+}
46
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/tcg/translate-a64.c
49
+++ b/target/arm/tcg/translate-a64.c
50
@@ -XXX,XX +XXX,XX @@ TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
51
return clean_data_tbi(s, addr);
52
}
53
54
+/*
55
+ * Generate the special alignment check that applies to AccType_ATOMIC
56
+ * and AccType_ORDERED insns under FEAT_LSE2: the access need not be
57
+ * naturally aligned, but it must not cross a 16-byte boundary.
58
+ * See AArch64.CheckAlignment().
59
+ */
60
+static void check_lse2_align(DisasContext *s, int rn, int imm,
61
+ bool is_write, MemOp mop)
62
+{
63
+ TCGv_i32 tmp;
64
+ TCGv_i64 addr;
65
+ TCGLabel *over_label;
66
+ MMUAccessType type;
67
+ int mmu_idx;
68
+
69
+ tmp = tcg_temp_new_i32();
70
+ tcg_gen_extrl_i64_i32(tmp, cpu_reg_sp(s, rn));
71
+ tcg_gen_addi_i32(tmp, tmp, imm & 15);
72
+ tcg_gen_andi_i32(tmp, tmp, 15);
73
+ tcg_gen_addi_i32(tmp, tmp, memop_size(mop));
74
+
75
+ over_label = gen_new_label();
76
+ tcg_gen_brcondi_i32(TCG_COND_LEU, tmp, 16, over_label);
77
+
78
+ addr = tcg_temp_new_i64();
79
+ tcg_gen_addi_i64(addr, cpu_reg_sp(s, rn), imm);
80
+
81
+ type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD,
82
+ mmu_idx = get_mem_index(s);
83
+ gen_helper_unaligned_access(cpu_env, addr, tcg_constant_i32(type),
84
+ tcg_constant_i32(mmu_idx));
85
+
86
+ gen_set_label(over_label);
87
+
88
+}
89
+
90
+/* Handle the alignment check for AccType_ATOMIC instructions. */
91
+static MemOp check_atomic_align(DisasContext *s, int rn, MemOp mop)
92
+{
93
+ MemOp size = mop & MO_SIZE;
94
+
95
+ if (size == MO_8) {
96
+ return mop;
97
+ }
98
+
99
+ /*
100
+ * If size == MO_128, this is a LDXP, and the operation is single-copy
101
+ * atomic for each doubleword, not the entire quadword; it still must
102
+ * be quadword aligned.
103
+ */
104
+ if (size == MO_128) {
105
+ return finalize_memop_atom(s, MO_128 | MO_ALIGN,
106
+ MO_ATOM_IFALIGN_PAIR);
107
+ }
108
+ if (dc_isar_feature(aa64_lse2, s)) {
109
+ check_lse2_align(s, rn, 0, true, mop);
110
+ } else {
111
+ mop |= MO_ALIGN;
112
+ }
113
+ return finalize_memop(s, mop);
114
+}
115
+
116
+/* Handle the alignment check for AccType_ORDERED instructions. */
117
+static MemOp check_ordered_align(DisasContext *s, int rn, int imm,
118
+ bool is_write, MemOp mop)
119
+{
120
+ MemOp size = mop & MO_SIZE;
121
+
122
+ if (size == MO_8) {
123
+ return mop;
124
+ }
125
+ if (size == MO_128) {
126
+ return finalize_memop_atom(s, MO_128 | MO_ALIGN,
127
+ MO_ATOM_IFALIGN_PAIR);
128
+ }
129
+ if (!dc_isar_feature(aa64_lse2, s)) {
130
+ mop |= MO_ALIGN;
131
+ } else if (!s->naa) {
132
+ check_lse2_align(s, rn, imm, is_write, mop);
133
+ }
134
+ return finalize_memop(s, mop);
135
+}
136
+
137
typedef struct DisasCompare64 {
138
TCGCond cond;
139
TCGv_i64 value;
140
@@ -XXX,XX +XXX,XX @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2, int rn,
141
{
24
{
142
int idx = get_mem_index(s);
25
+ bool have_snan = false;
143
TCGv_i64 dirty_addr, clean_addr;
26
int cmp, which;
144
- MemOp memop;
27
145
-
28
if (is_snan(a->cls) || is_snan(b->cls)) {
146
- /*
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
147
- * For pairs:
30
+ have_snan = true;
148
- * if size == 2, the operation is single-copy atomic for the doubleword.
149
- * if size == 3, the operation is single-copy atomic for *each* doubleword,
150
- * not the entire quadword, however it must be quadword aligned.
151
- */
152
- memop = size + is_pair;
153
- if (memop == MO_128) {
154
- memop = finalize_memop_atom(s, MO_128 | MO_ALIGN,
155
- MO_ATOM_IFALIGN_PAIR);
156
- } else {
157
- memop = finalize_memop(s, memop | MO_ALIGN);
158
- }
159
+ MemOp memop = check_atomic_align(s, rn, size + is_pair);
160
161
s->is_ldex = true;
162
dirty_addr = cpu_reg_sp(s, rn);
163
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap(DisasContext *s, int rs, int rt,
164
if (rn == 31) {
165
gen_check_sp_alignment(s);
166
}
31
}
167
- memop = finalize_memop(s, size | MO_ALIGN);
32
168
+ memop = check_atomic_align(s, rn, size);
33
if (s->default_nan_mode) {
169
clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, memop);
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
170
tcg_gen_atomic_cmpxchg_i64(tcg_rs, clean_addr, tcg_rs, tcg_rt,
35
171
memidx, memop);
36
switch (s->float_2nan_prop_rule) {
172
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
37
case float_2nan_prop_s_ab:
173
}
38
- if (is_snan(a->cls)) {
174
39
- which = 0;
175
/* This is a single atomic access, despite the "pair". */
40
- } else if (is_snan(b->cls)) {
176
- memop = finalize_memop(s, (size + 1) | MO_ALIGN);
41
- which = 1;
177
+ memop = check_atomic_align(s, rn, size + 1);
42
- } else if (is_qnan(a->cls)) {
178
clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, memop);
43
- which = 0;
179
44
- } else {
180
if (size == 2) {
45
- which = 1;
181
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
46
+ if (have_snan) {
182
gen_check_sp_alignment(s);
47
+ which = is_snan(a->cls) ? 0 : 1;
48
+ break;
183
}
49
}
184
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
50
- break;
185
- /* TODO: ARMv8.4-LSE SCTLR.nAA */
51
- case float_2nan_prop_s_ba:
186
- memop = finalize_memop(s, size | MO_ALIGN);
52
- if (is_snan(b->cls)) {
187
+ memop = check_ordered_align(s, rn, 0, true, size);
53
- which = 1;
188
clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
54
- } else if (is_snan(a->cls)) {
189
true, rn != 31, memop);
55
- which = 0;
190
do_gpr_st(s, cpu_reg(s, rt), clean_addr, memop, true, rt,
56
- } else if (is_qnan(b->cls)) {
191
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
57
- which = 1;
192
if (rn == 31) {
58
- } else {
193
gen_check_sp_alignment(s);
59
- which = 0;
194
}
60
- }
195
- /* TODO: ARMv8.4-LSE SCTLR.nAA */
61
- break;
196
- memop = finalize_memop(s, size | MO_ALIGN);
62
+ /* fall through */
197
+ memop = check_ordered_align(s, rn, 0, false, size);
63
case float_2nan_prop_ab:
198
clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
64
which = is_nan(a->cls) ? 0 : 1;
199
false, rn != 31, memop);
65
break;
200
do_gpr_ld(s, cpu_reg(s, rt), clean_addr, memop, false, true,
66
+ case float_2nan_prop_s_ba:
201
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
67
+ if (have_snan) {
202
bool a = extract32(insn, 23, 1);
68
+ which = is_snan(b->cls) ? 1 : 0;
203
TCGv_i64 tcg_rs, tcg_rt, clean_addr;
69
+ break;
204
AtomicThreeOpFn *fn = NULL;
70
+ }
205
- MemOp mop = finalize_memop(s, size | MO_ALIGN);
71
+ /* fall through */
206
+ MemOp mop = size;
72
case float_2nan_prop_ba:
207
73
which = is_nan(b->cls) ? 1 : 0;
208
if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
74
break;
209
unallocated_encoding(s);
210
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
211
if (rn == 31) {
212
gen_check_sp_alignment(s);
213
}
214
+
215
+ mop = check_atomic_align(s, rn, mop);
216
clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), false, rn != 31, mop);
217
218
if (o3_opc == 014) {
219
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
220
bool is_store = false;
221
bool extend = false;
222
bool iss_sf;
223
- MemOp mop;
224
+ MemOp mop = size;
225
226
if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
227
unallocated_encoding(s);
228
return;
229
}
230
231
- /* TODO: ARMv8.4-LSE SCTLR.nAA */
232
- mop = finalize_memop(s, size | MO_ALIGN);
233
-
234
switch (opc) {
235
case 0: /* STLURB */
236
is_store = true;
237
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
238
gen_check_sp_alignment(s);
239
}
240
241
+ mop = check_ordered_align(s, rn, offset, is_store, mop);
242
+
243
dirty_addr = read_cpu_reg_sp(s, rn, 1);
244
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
245
clean_addr = clean_data_tbi(s, dirty_addr);
246
--
75
--
247
2.34.1
76
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
While we don't require 16-byte atomicity here, using a single larger
3
Move the fractional comparison to the end of the
4
load simplifies the code, and makes it a closer match to STXP.
4
float_2nan_prop_x87 case. This is not required for
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.
5
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
8
Message-id: 20230530191438.411344-5-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
target/arm/tcg/translate-a64.c | 31 ++++++++++++++++++++-----------
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
12
1 file changed, 20 insertions(+), 11 deletions(-)
15
1 file changed, 9 insertions(+), 10 deletions(-)
13
16
14
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/tcg/translate-a64.c
19
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/tcg/translate-a64.c
20
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
19
TCGv_i64 addr, int size, bool is_pair)
22
return a;
20
{
23
}
21
int idx = get_mem_index(s);
24
22
- MemOp memop = s->be_data;
25
- cmp = frac_cmp(a, b);
23
+ MemOp memop;
26
- if (cmp == 0) {
24
27
- cmp = a->sign < b->sign;
25
g_assert(size <= 3);
28
- }
26
if (is_pair) {
29
-
27
g_assert(size >= 2);
30
switch (s->float_2nan_prop_rule) {
28
if (size == 2) {
31
case float_2nan_prop_s_ab:
29
/* The pair must be single-copy atomic for the doubleword. */
32
if (have_snan) {
30
- memop |= MO_64 | MO_ALIGN;
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
31
+ memop = finalize_memop(s, MO_64 | MO_ALIGN);
34
* return the NaN with the positive sign bit (if any).
32
tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
35
*/
33
if (s->be_data == MO_LE) {
36
if (is_snan(a->cls)) {
34
tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
37
- if (is_snan(b->cls)) {
35
@@ -XXX,XX +XXX,XX @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
38
- which = cmp > 0 ? 0 : 1;
36
tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 0, 32);
39
- } else {
40
+ if (!is_snan(b->cls)) {
41
which = is_qnan(b->cls) ? 1 : 0;
42
+ break;
43
}
44
} else if (is_qnan(a->cls)) {
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
46
which = 0;
47
- } else {
48
- which = cmp > 0 ? 0 : 1;
49
+ break;
37
}
50
}
38
} else {
51
} else {
39
- /* The pair must be single-copy atomic for *each* doubleword, not
52
which = 1;
40
- the entire quadword, however it must be quadword aligned. */
53
+ break;
41
- memop |= MO_64;
42
- tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx,
43
- memop | MO_ALIGN_16);
44
+ /*
45
+ * The pair must be single-copy atomic for *each* doubleword, not
46
+ * the entire quadword, however it must be quadword aligned.
47
+ * Expose the complete load to tcg, for ease of tlb lookup,
48
+ * but indicate that only 8-byte atomicity is required.
49
+ */
50
+ TCGv_i128 t16 = tcg_temp_new_i128();
51
52
- TCGv_i64 addr2 = tcg_temp_new_i64();
53
- tcg_gen_addi_i64(addr2, addr, 8);
54
- tcg_gen_qemu_ld_i64(cpu_exclusive_high, addr2, idx, memop);
55
+ memop = finalize_memop_atom(s, MO_128 | MO_ALIGN_16,
56
+ MO_ATOM_IFALIGN_PAIR);
57
+ tcg_gen_qemu_ld_i128(t16, addr, idx, memop);
58
59
+ if (s->be_data == MO_LE) {
60
+ tcg_gen_extr_i128_i64(cpu_exclusive_val,
61
+ cpu_exclusive_high, t16);
62
+ } else {
63
+ tcg_gen_extr_i128_i64(cpu_exclusive_high,
64
+ cpu_exclusive_val, t16);
65
+ }
66
tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
67
tcg_gen_mov_i64(cpu_reg(s, rt2), cpu_exclusive_high);
68
}
54
}
69
} else {
55
+ cmp = frac_cmp(a, b);
70
- memop |= size | MO_ALIGN;
56
+ if (cmp == 0) {
71
+ memop = finalize_memop(s, size | MO_ALIGN);
57
+ cmp = a->sign < b->sign;
72
tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
58
+ }
73
tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
59
+ which = cmp > 0 ? 0 : 1;
74
}
60
break;
61
default:
62
g_assert_not_reached();
75
--
63
--
76
2.34.1
64
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
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>
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230530191438.411344-3-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
target/arm/cpu.h | 5 +++++
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
10
1 file changed, 5 insertions(+)
12
1 file changed, 13 insertions(+), 15 deletions(-)
11
13
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.h
16
--- a/fpu/softfloat-parts.c.inc
15
+++ b/target/arm/cpu.h
17
+++ b/fpu/softfloat-parts.c.inc
16
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
17
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
19
float_status *s)
20
{
21
bool have_snan = false;
22
- int cmp, which;
23
+ FloatPartsN *ret;
24
+ int cmp;
25
26
if (is_snan(a->cls) || is_snan(b->cls)) {
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
29
switch (s->float_2nan_prop_rule) {
30
case float_2nan_prop_s_ab:
31
if (have_snan) {
32
- which = is_snan(a->cls) ? 0 : 1;
33
+ ret = is_snan(a->cls) ? a : b;
34
break;
35
}
36
/* fall through */
37
case float_2nan_prop_ab:
38
- which = is_nan(a->cls) ? 0 : 1;
39
+ ret = is_nan(a->cls) ? a : b;
40
break;
41
case float_2nan_prop_s_ba:
42
if (have_snan) {
43
- which = is_snan(b->cls) ? 1 : 0;
44
+ ret = is_snan(b->cls) ? b : a;
45
break;
46
}
47
/* fall through */
48
case float_2nan_prop_ba:
49
- which = is_nan(b->cls) ? 1 : 0;
50
+ ret = is_nan(b->cls) ? b : a;
51
break;
52
case float_2nan_prop_x87:
53
/*
54
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
55
*/
56
if (is_snan(a->cls)) {
57
if (!is_snan(b->cls)) {
58
- which = is_qnan(b->cls) ? 1 : 0;
59
+ ret = is_qnan(b->cls) ? b : a;
60
break;
61
}
62
} else if (is_qnan(a->cls)) {
63
if (is_snan(b->cls) || !is_qnan(b->cls)) {
64
- which = 0;
65
+ ret = a;
66
break;
67
}
68
} else {
69
- which = 1;
70
+ ret = b;
71
break;
72
}
73
cmp = frac_cmp(a, b);
74
if (cmp == 0) {
75
cmp = a->sign < b->sign;
76
}
77
- which = cmp > 0 ? 0 : 1;
78
+ ret = cmp > 0 ? a : b;
79
break;
80
default:
81
g_assert_not_reached();
82
}
83
84
- if (which) {
85
- a = b;
86
+ if (is_snan(ret->cls)) {
87
+ parts_silence_nan(ret, s);
88
}
89
- if (is_snan(a->cls)) {
90
- parts_silence_nan(a, s);
91
- }
92
- return a;
93
+ return ret;
18
}
94
}
19
95
20
+static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id)
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
+{
22
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, AT) != 0;
23
+}
24
+
25
static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id)
26
{
27
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, FWB) != 0;
28
--
97
--
29
2.34.1
98
2.34.1
30
99
31
100
diff view generated by jsdifflib
1
From: Francesco Cagnin <fcagnin@quarkslab.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Required for guest debugging.
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
update my email address, and update the mailmap to match.
4
5
5
Signed-off-by: Francesco Cagnin <fcagnin@quarkslab.com>
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
6
Message-id: 20230601153107.81955-3-fcagnin@quarkslab.com
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
target/arm/hvf/hvf.c | 213 +++++++++++++++++++++++++++++++++++++++++++
14
MAINTAINERS | 2 +-
11
1 file changed, 213 insertions(+)
15
.mailmap | 5 +++--
16
2 files changed, 4 insertions(+), 3 deletions(-)
12
17
13
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
18
diff --git a/MAINTAINERS b/MAINTAINERS
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/hvf/hvf.c
20
--- a/MAINTAINERS
16
+++ b/target/arm/hvf/hvf.c
21
+++ b/MAINTAINERS
17
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
18
#define SYSREG_ICC_SGI1R_EL1 SYSREG(3, 0, 12, 11, 5)
23
SBSA-REF
19
#define SYSREG_ICC_SRE_EL1 SYSREG(3, 0, 12, 12, 5)
24
M: Radoslaw Biernacki <rad@semihalf.com>
20
25
M: Peter Maydell <peter.maydell@linaro.org>
21
+#define SYSREG_MDSCR_EL1 SYSREG(2, 0, 0, 2, 2)
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
22
+#define SYSREG_DBGBVR0_EL1 SYSREG(2, 0, 0, 0, 4)
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
23
+#define SYSREG_DBGBCR0_EL1 SYSREG(2, 0, 0, 0, 5)
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
24
+#define SYSREG_DBGWVR0_EL1 SYSREG(2, 0, 0, 0, 6)
29
L: qemu-arm@nongnu.org
25
+#define SYSREG_DBGWCR0_EL1 SYSREG(2, 0, 0, 0, 7)
30
S: Maintained
26
+#define SYSREG_DBGBVR1_EL1 SYSREG(2, 0, 0, 1, 4)
31
diff --git a/.mailmap b/.mailmap
27
+#define SYSREG_DBGBCR1_EL1 SYSREG(2, 0, 0, 1, 5)
32
index XXXXXXX..XXXXXXX 100644
28
+#define SYSREG_DBGWVR1_EL1 SYSREG(2, 0, 0, 1, 6)
33
--- a/.mailmap
29
+#define SYSREG_DBGWCR1_EL1 SYSREG(2, 0, 0, 1, 7)
34
+++ b/.mailmap
30
+#define SYSREG_DBGBVR2_EL1 SYSREG(2, 0, 0, 2, 4)
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
31
+#define SYSREG_DBGBCR2_EL1 SYSREG(2, 0, 0, 2, 5)
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
32
+#define SYSREG_DBGWVR2_EL1 SYSREG(2, 0, 0, 2, 6)
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
33
+#define SYSREG_DBGWCR2_EL1 SYSREG(2, 0, 0, 2, 7)
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
34
+#define SYSREG_DBGBVR3_EL1 SYSREG(2, 0, 0, 3, 4)
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
35
+#define SYSREG_DBGBCR3_EL1 SYSREG(2, 0, 0, 3, 5)
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
36
+#define SYSREG_DBGWVR3_EL1 SYSREG(2, 0, 0, 3, 6)
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
37
+#define SYSREG_DBGWCR3_EL1 SYSREG(2, 0, 0, 3, 7)
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
38
+#define SYSREG_DBGBVR4_EL1 SYSREG(2, 0, 0, 4, 4)
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
39
+#define SYSREG_DBGBCR4_EL1 SYSREG(2, 0, 0, 4, 5)
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
40
+#define SYSREG_DBGWVR4_EL1 SYSREG(2, 0, 0, 4, 6)
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
41
+#define SYSREG_DBGWCR4_EL1 SYSREG(2, 0, 0, 4, 7)
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
42
+#define SYSREG_DBGBVR5_EL1 SYSREG(2, 0, 0, 5, 4)
43
+#define SYSREG_DBGBCR5_EL1 SYSREG(2, 0, 0, 5, 5)
44
+#define SYSREG_DBGWVR5_EL1 SYSREG(2, 0, 0, 5, 6)
45
+#define SYSREG_DBGWCR5_EL1 SYSREG(2, 0, 0, 5, 7)
46
+#define SYSREG_DBGBVR6_EL1 SYSREG(2, 0, 0, 6, 4)
47
+#define SYSREG_DBGBCR6_EL1 SYSREG(2, 0, 0, 6, 5)
48
+#define SYSREG_DBGWVR6_EL1 SYSREG(2, 0, 0, 6, 6)
49
+#define SYSREG_DBGWCR6_EL1 SYSREG(2, 0, 0, 6, 7)
50
+#define SYSREG_DBGBVR7_EL1 SYSREG(2, 0, 0, 7, 4)
51
+#define SYSREG_DBGBCR7_EL1 SYSREG(2, 0, 0, 7, 5)
52
+#define SYSREG_DBGWVR7_EL1 SYSREG(2, 0, 0, 7, 6)
53
+#define SYSREG_DBGWCR7_EL1 SYSREG(2, 0, 0, 7, 7)
54
+#define SYSREG_DBGBVR8_EL1 SYSREG(2, 0, 0, 8, 4)
55
+#define SYSREG_DBGBCR8_EL1 SYSREG(2, 0, 0, 8, 5)
56
+#define SYSREG_DBGWVR8_EL1 SYSREG(2, 0, 0, 8, 6)
57
+#define SYSREG_DBGWCR8_EL1 SYSREG(2, 0, 0, 8, 7)
58
+#define SYSREG_DBGBVR9_EL1 SYSREG(2, 0, 0, 9, 4)
59
+#define SYSREG_DBGBCR9_EL1 SYSREG(2, 0, 0, 9, 5)
60
+#define SYSREG_DBGWVR9_EL1 SYSREG(2, 0, 0, 9, 6)
61
+#define SYSREG_DBGWCR9_EL1 SYSREG(2, 0, 0, 9, 7)
62
+#define SYSREG_DBGBVR10_EL1 SYSREG(2, 0, 0, 10, 4)
63
+#define SYSREG_DBGBCR10_EL1 SYSREG(2, 0, 0, 10, 5)
64
+#define SYSREG_DBGWVR10_EL1 SYSREG(2, 0, 0, 10, 6)
65
+#define SYSREG_DBGWCR10_EL1 SYSREG(2, 0, 0, 10, 7)
66
+#define SYSREG_DBGBVR11_EL1 SYSREG(2, 0, 0, 11, 4)
67
+#define SYSREG_DBGBCR11_EL1 SYSREG(2, 0, 0, 11, 5)
68
+#define SYSREG_DBGWVR11_EL1 SYSREG(2, 0, 0, 11, 6)
69
+#define SYSREG_DBGWCR11_EL1 SYSREG(2, 0, 0, 11, 7)
70
+#define SYSREG_DBGBVR12_EL1 SYSREG(2, 0, 0, 12, 4)
71
+#define SYSREG_DBGBCR12_EL1 SYSREG(2, 0, 0, 12, 5)
72
+#define SYSREG_DBGWVR12_EL1 SYSREG(2, 0, 0, 12, 6)
73
+#define SYSREG_DBGWCR12_EL1 SYSREG(2, 0, 0, 12, 7)
74
+#define SYSREG_DBGBVR13_EL1 SYSREG(2, 0, 0, 13, 4)
75
+#define SYSREG_DBGBCR13_EL1 SYSREG(2, 0, 0, 13, 5)
76
+#define SYSREG_DBGWVR13_EL1 SYSREG(2, 0, 0, 13, 6)
77
+#define SYSREG_DBGWCR13_EL1 SYSREG(2, 0, 0, 13, 7)
78
+#define SYSREG_DBGBVR14_EL1 SYSREG(2, 0, 0, 14, 4)
79
+#define SYSREG_DBGBCR14_EL1 SYSREG(2, 0, 0, 14, 5)
80
+#define SYSREG_DBGWVR14_EL1 SYSREG(2, 0, 0, 14, 6)
81
+#define SYSREG_DBGWCR14_EL1 SYSREG(2, 0, 0, 14, 7)
82
+#define SYSREG_DBGBVR15_EL1 SYSREG(2, 0, 0, 15, 4)
83
+#define SYSREG_DBGBCR15_EL1 SYSREG(2, 0, 0, 15, 5)
84
+#define SYSREG_DBGWVR15_EL1 SYSREG(2, 0, 0, 15, 6)
85
+#define SYSREG_DBGWCR15_EL1 SYSREG(2, 0, 0, 15, 7)
86
+
87
#define WFX_IS_WFE (1 << 0)
88
89
#define TMR_CTL_ENABLE (1 << 0)
90
@@ -XXX,XX +XXX,XX @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
91
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
92
}
93
break;
94
+ case SYSREG_DBGBVR0_EL1:
95
+ case SYSREG_DBGBVR1_EL1:
96
+ case SYSREG_DBGBVR2_EL1:
97
+ case SYSREG_DBGBVR3_EL1:
98
+ case SYSREG_DBGBVR4_EL1:
99
+ case SYSREG_DBGBVR5_EL1:
100
+ case SYSREG_DBGBVR6_EL1:
101
+ case SYSREG_DBGBVR7_EL1:
102
+ case SYSREG_DBGBVR8_EL1:
103
+ case SYSREG_DBGBVR9_EL1:
104
+ case SYSREG_DBGBVR10_EL1:
105
+ case SYSREG_DBGBVR11_EL1:
106
+ case SYSREG_DBGBVR12_EL1:
107
+ case SYSREG_DBGBVR13_EL1:
108
+ case SYSREG_DBGBVR14_EL1:
109
+ case SYSREG_DBGBVR15_EL1:
110
+ val = env->cp15.dbgbvr[SYSREG_CRM(reg)];
111
+ break;
112
+ case SYSREG_DBGBCR0_EL1:
113
+ case SYSREG_DBGBCR1_EL1:
114
+ case SYSREG_DBGBCR2_EL1:
115
+ case SYSREG_DBGBCR3_EL1:
116
+ case SYSREG_DBGBCR4_EL1:
117
+ case SYSREG_DBGBCR5_EL1:
118
+ case SYSREG_DBGBCR6_EL1:
119
+ case SYSREG_DBGBCR7_EL1:
120
+ case SYSREG_DBGBCR8_EL1:
121
+ case SYSREG_DBGBCR9_EL1:
122
+ case SYSREG_DBGBCR10_EL1:
123
+ case SYSREG_DBGBCR11_EL1:
124
+ case SYSREG_DBGBCR12_EL1:
125
+ case SYSREG_DBGBCR13_EL1:
126
+ case SYSREG_DBGBCR14_EL1:
127
+ case SYSREG_DBGBCR15_EL1:
128
+ val = env->cp15.dbgbcr[SYSREG_CRM(reg)];
129
+ break;
130
+ case SYSREG_DBGWVR0_EL1:
131
+ case SYSREG_DBGWVR1_EL1:
132
+ case SYSREG_DBGWVR2_EL1:
133
+ case SYSREG_DBGWVR3_EL1:
134
+ case SYSREG_DBGWVR4_EL1:
135
+ case SYSREG_DBGWVR5_EL1:
136
+ case SYSREG_DBGWVR6_EL1:
137
+ case SYSREG_DBGWVR7_EL1:
138
+ case SYSREG_DBGWVR8_EL1:
139
+ case SYSREG_DBGWVR9_EL1:
140
+ case SYSREG_DBGWVR10_EL1:
141
+ case SYSREG_DBGWVR11_EL1:
142
+ case SYSREG_DBGWVR12_EL1:
143
+ case SYSREG_DBGWVR13_EL1:
144
+ case SYSREG_DBGWVR14_EL1:
145
+ case SYSREG_DBGWVR15_EL1:
146
+ val = env->cp15.dbgwvr[SYSREG_CRM(reg)];
147
+ break;
148
+ case SYSREG_DBGWCR0_EL1:
149
+ case SYSREG_DBGWCR1_EL1:
150
+ case SYSREG_DBGWCR2_EL1:
151
+ case SYSREG_DBGWCR3_EL1:
152
+ case SYSREG_DBGWCR4_EL1:
153
+ case SYSREG_DBGWCR5_EL1:
154
+ case SYSREG_DBGWCR6_EL1:
155
+ case SYSREG_DBGWCR7_EL1:
156
+ case SYSREG_DBGWCR8_EL1:
157
+ case SYSREG_DBGWCR9_EL1:
158
+ case SYSREG_DBGWCR10_EL1:
159
+ case SYSREG_DBGWCR11_EL1:
160
+ case SYSREG_DBGWCR12_EL1:
161
+ case SYSREG_DBGWCR13_EL1:
162
+ case SYSREG_DBGWCR14_EL1:
163
+ case SYSREG_DBGWCR15_EL1:
164
+ val = env->cp15.dbgwcr[SYSREG_CRM(reg)];
165
+ break;
166
default:
167
if (is_id_sysreg(reg)) {
168
/* ID system registers read as RES0 */
169
@@ -XXX,XX +XXX,XX @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
170
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
171
}
172
break;
173
+ case SYSREG_MDSCR_EL1:
174
+ env->cp15.mdscr_el1 = val;
175
+ break;
176
+ case SYSREG_DBGBVR0_EL1:
177
+ case SYSREG_DBGBVR1_EL1:
178
+ case SYSREG_DBGBVR2_EL1:
179
+ case SYSREG_DBGBVR3_EL1:
180
+ case SYSREG_DBGBVR4_EL1:
181
+ case SYSREG_DBGBVR5_EL1:
182
+ case SYSREG_DBGBVR6_EL1:
183
+ case SYSREG_DBGBVR7_EL1:
184
+ case SYSREG_DBGBVR8_EL1:
185
+ case SYSREG_DBGBVR9_EL1:
186
+ case SYSREG_DBGBVR10_EL1:
187
+ case SYSREG_DBGBVR11_EL1:
188
+ case SYSREG_DBGBVR12_EL1:
189
+ case SYSREG_DBGBVR13_EL1:
190
+ case SYSREG_DBGBVR14_EL1:
191
+ case SYSREG_DBGBVR15_EL1:
192
+ env->cp15.dbgbvr[SYSREG_CRM(reg)] = val;
193
+ break;
194
+ case SYSREG_DBGBCR0_EL1:
195
+ case SYSREG_DBGBCR1_EL1:
196
+ case SYSREG_DBGBCR2_EL1:
197
+ case SYSREG_DBGBCR3_EL1:
198
+ case SYSREG_DBGBCR4_EL1:
199
+ case SYSREG_DBGBCR5_EL1:
200
+ case SYSREG_DBGBCR6_EL1:
201
+ case SYSREG_DBGBCR7_EL1:
202
+ case SYSREG_DBGBCR8_EL1:
203
+ case SYSREG_DBGBCR9_EL1:
204
+ case SYSREG_DBGBCR10_EL1:
205
+ case SYSREG_DBGBCR11_EL1:
206
+ case SYSREG_DBGBCR12_EL1:
207
+ case SYSREG_DBGBCR13_EL1:
208
+ case SYSREG_DBGBCR14_EL1:
209
+ case SYSREG_DBGBCR15_EL1:
210
+ env->cp15.dbgbcr[SYSREG_CRM(reg)] = val;
211
+ break;
212
+ case SYSREG_DBGWVR0_EL1:
213
+ case SYSREG_DBGWVR1_EL1:
214
+ case SYSREG_DBGWVR2_EL1:
215
+ case SYSREG_DBGWVR3_EL1:
216
+ case SYSREG_DBGWVR4_EL1:
217
+ case SYSREG_DBGWVR5_EL1:
218
+ case SYSREG_DBGWVR6_EL1:
219
+ case SYSREG_DBGWVR7_EL1:
220
+ case SYSREG_DBGWVR8_EL1:
221
+ case SYSREG_DBGWVR9_EL1:
222
+ case SYSREG_DBGWVR10_EL1:
223
+ case SYSREG_DBGWVR11_EL1:
224
+ case SYSREG_DBGWVR12_EL1:
225
+ case SYSREG_DBGWVR13_EL1:
226
+ case SYSREG_DBGWVR14_EL1:
227
+ case SYSREG_DBGWVR15_EL1:
228
+ env->cp15.dbgwvr[SYSREG_CRM(reg)] = val;
229
+ break;
230
+ case SYSREG_DBGWCR0_EL1:
231
+ case SYSREG_DBGWCR1_EL1:
232
+ case SYSREG_DBGWCR2_EL1:
233
+ case SYSREG_DBGWCR3_EL1:
234
+ case SYSREG_DBGWCR4_EL1:
235
+ case SYSREG_DBGWCR5_EL1:
236
+ case SYSREG_DBGWCR6_EL1:
237
+ case SYSREG_DBGWCR7_EL1:
238
+ case SYSREG_DBGWCR8_EL1:
239
+ case SYSREG_DBGWCR9_EL1:
240
+ case SYSREG_DBGWCR10_EL1:
241
+ case SYSREG_DBGWCR11_EL1:
242
+ case SYSREG_DBGWCR12_EL1:
243
+ case SYSREG_DBGWCR13_EL1:
244
+ case SYSREG_DBGWCR14_EL1:
245
+ case SYSREG_DBGWCR15_EL1:
246
+ env->cp15.dbgwcr[SYSREG_CRM(reg)] = val;
247
+ break;
248
default:
249
cpu_synchronize_state(cpu);
250
trace_hvf_unhandled_sysreg_write(env->pc, reg,
251
--
47
--
252
2.34.1
48
2.34.1
49
50
diff view generated by jsdifflib
1
From: Vikram Garhwal <vikram.garhwal@amd.com>
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
2
3
Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com>
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
5
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
MAINTAINERS | 2 +-
11
MAINTAINERS | 2 ++
9
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 2 insertions(+)
10
13
11
diff --git a/MAINTAINERS b/MAINTAINERS
14
diff --git a/MAINTAINERS b/MAINTAINERS
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/MAINTAINERS
16
--- a/MAINTAINERS
14
+++ b/MAINTAINERS
17
+++ b/MAINTAINERS
15
@@ -XXX,XX +XXX,XX @@ M: Francisco Iglesias <francisco.iglesias@amd.com>
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
19
20
Xilinx CAN
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
16
S: Maintained
23
S: Maintained
17
F: hw/net/can/xlnx-*
24
F: hw/net/can/xlnx-*
18
F: include/hw/net/xlnx-*
25
F: include/hw/net/xlnx-*
19
-F: tests/qtest/xlnx-can-test*
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
20
+F: tests/qtest/xlnx-can*-test*
27
CAN bus subsystem and hardware
21
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
22
EDU
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
23
M: Jiri Slaby <jslaby@suse.cz>
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
31
S: Maintained
32
W: https://canbus.pages.fel.cvut.cz/
33
F: net/can/*
24
--
34
--
25
2.34.1
35
2.34.1
diff view generated by jsdifflib