1
target-arm queue: the big things in here are SVE in system
1
First arm pullreq of the 5.1 cycle; mostly bugfixes and some
2
emulation mode, and v8M stack limit checking; there are
2
cleanup patches. The new clock modelling framework is the big
3
also a handful of smaller fixes.
3
thing here.
4
4
5
thanks
6
-- PMM
5
-- PMM
7
6
8
The following changes since commit 079911cb6e26898e16f5bb56ef4f9d33cf92d32d:
7
The following changes since commit 648db19685b7030aa558a4ddbd3a8e53d8c9a062:
9
8
10
Merge remote-tracking branch 'remotes/rth/tags/pull-fpu-20181005' into staging (2018-10-08 12:44:35 +0100)
9
Merge remote-tracking branch 'remotes/armbru/tags/pull-misc-2020-04-29' into staging (2020-04-29 15:07:33 +0100)
11
10
12
are available in the Git repository at:
11
are available in the Git repository at:
13
12
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20181008
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200430
15
14
16
for you to fetch changes up to 74e2e59b8d0a68be0956310fc349179c89fd7be0:
15
for you to fetch changes up to 1267437e593e85498f9105b3bdab796630d2e83f:
17
16
18
hw/display/bcm2835_fb: Silence Coverity warning about multiply overflow (2018-10-08 14:55:05 +0100)
17
hw/arm: xlnx-zcu102: Disable unsupported FDT firmware nodes (2020-04-30 11:52:29 +0100)
19
18
20
----------------------------------------------------------------
19
----------------------------------------------------------------
21
target-arm queue:
20
target-arm queue:
22
* target/arm: fix error in a code comment
21
* xlnx-zdma: Fix endianness handling of descriptor loading
23
* virt: Suppress external aborts on virt-2.10 and earlier
22
* nrf51: Fix last GPIO CNF address
24
* target/arm: Correct condition for v8M callee stack push
23
* gicv3: Use gicr_typer in arm_gicv3_icc_reset
25
* target/arm: Don't read r4 from v8M exception stackframe twice
24
* msf2: Add EMAC block to SmartFusion2 SoC
26
* target/arm: Support SVE in system emulation mode
25
* New clock modelling framework
27
* target/arm: Implement v8M hardware stack limit checking
26
* hw/arm: versal: Setup the ADMA with 128bit bus-width
28
* hw/display/bcm2835_fb: Silence Coverity warning about multiply overflow
27
* Cadence: gem: fix wraparound in 64bit descriptors
28
* cadence_gem: clear RX control descriptor
29
* target/arm: Vectorize integer comparison vs zero
30
* hw/arm/virt: dt: add kaslr-seed property
31
* hw/arm: xlnx-zcu102: Disable unsupported FDT firmware nodes
29
32
30
----------------------------------------------------------------
33
----------------------------------------------------------------
31
Dongjiu Geng (1):
34
Cameron Esfahani (1):
32
target/arm: fix code comments error
35
nrf51: Fix last GPIO CNF address
33
36
34
Peter Maydell (17):
37
Damien Hedde (7):
35
virt: Suppress external aborts on virt-2.10 and earlier
38
hw/core/clock-vmstate: define a vmstate entry for clock state
36
target/arm: Correct condition for v8M callee stack push
39
qdev: add clock input&output support to devices.
37
target/arm: Don't read r4 from v8M exception stackframe twice
40
qdev-clock: introduce an init array to ease the device construction
38
target/arm: Define new TBFLAG for v8M stack checking
41
hw/misc/zynq_slcr: add clock generation for uarts
39
target/arm: Define new EXCP type for v8M stack overflows
42
hw/char/cadence_uart: add clock support
40
target/arm: Move v7m_using_psp() to internals.h
43
hw/arm/xilinx_zynq: connect uart clocks to slcr
41
target/arm: Add v8M stack checks on ADD/SUB/MOV of SP
44
qdev-monitor: print the device's clock with info qtree
42
target/arm: Add some comments in Thumb decode
43
target/arm: Add v8M stack checks on exception entry
44
target/arm: Add v8M stack limit checks on NS function calls
45
target/arm: Add v8M stack checks for LDRD/STRD (imm)
46
target/arm: Add v8M stack checks for Thumb2 LDM/STM
47
target/arm: Add v8M stack checks for T32 load/store single
48
target/arm: Add v8M stack checks for Thumb push/pop
49
target/arm: Add v8M stack checks for VLDM/VSTM
50
target/arm: Add v8M stack checks for MSR to SP_NS
51
hw/display/bcm2835_fb: Silence Coverity warning about multiply overflow
52
45
53
Richard Henderson (15):
46
Edgar E. Iglesias (7):
54
target/arm: Define ID_AA64ZFR0_EL1
47
dma/xlnx-zdma: Fix descriptor loading (MEM) wrt endianness
55
target/arm: Adjust sve_exception_el
48
dma/xlnx-zdma: Fix descriptor loading (REG) wrt endianness
56
target/arm: Pass in current_el to fp and sve_exception_el
49
hw/arm: versal: Setup the ADMA with 128bit bus-width
57
target/arm: Handle SVE vector length changes in system mode
50
device_tree: Allow name wildcards in qemu_fdt_node_path()
58
target/arm: Adjust aarch64_cpu_dump_state for system mode SVE
51
device_tree: Constify compat in qemu_fdt_node_path()
59
target/arm: Clear unused predicate bits for LD1RQ
52
hw/arm: xlnx-zcu102: Move arm_boot_info into XlnxZCU102
60
target/arm: Rewrite helper_sve_ld1*_r using pages
53
hw/arm: xlnx-zcu102: Disable unsupported FDT firmware nodes
61
target/arm: Rewrite helper_sve_ld[234]*_r
62
target/arm: Rewrite helper_sve_st[1234]*_r
63
target/arm: Split contiguous loads for endianness
64
target/arm: Split contiguous stores for endianness
65
target/arm: Rewrite vector gather loads
66
target/arm: Rewrite vector gather stores
67
target/arm: Rewrite vector gather first-fault loads
68
target/arm: Pass TCGMemOpIdx to sve memory helpers
69
54
70
target/arm/cpu.h | 17 +
55
Jerome Forissier (2):
71
target/arm/helper-sve.h | 385 ++++++---
56
hw/arm/virt: dt: move creation of /secure-chosen to create_fdt()
72
target/arm/helper.h | 2 +
57
hw/arm/virt: dt: add kaslr-seed property
73
target/arm/internals.h | 44 +
74
target/arm/kvm_arm.h | 4 +-
75
target/arm/translate.h | 1 +
76
hw/arm/virt.c | 2 +
77
hw/display/bcm2835_fb.c | 2 +-
78
target/arm/cpu64.c | 42 -
79
target/arm/helper.c | 345 +++++---
80
target/arm/kvm.c | 2 +-
81
target/arm/op_helper.c | 24 +-
82
target/arm/sve_helper.c | 1961 ++++++++++++++++++++++++++++++--------------
83
target/arm/translate-a64.c | 8 +-
84
target/arm/translate-sve.c | 670 ++++++++++-----
85
target/arm/translate.c | 198 ++++-
86
16 files changed, 2611 insertions(+), 1096 deletions(-)
87
58
59
Keqian Zhu (2):
60
bugfix: Use gicr_typer in arm_gicv3_icc_reset
61
Typo: Correct the name of CPU hotplug memory region
62
63
Peter Maydell (2):
64
hw/core/clock: introduce clock object
65
docs/clocks: add device's clock documentation
66
67
Philippe Mathieu-Daudé (3):
68
target/arm: Restrict the Address Translate write operation to TCG accel
69
target/arm/cpu: Use ARRAY_SIZE() to iterate over ARMCPUInfo[]
70
target/arm/cpu: Update coding style to make checkpatch.pl happy
71
72
Ramon Fried (2):
73
Cadence: gem: fix wraparound in 64bit descriptors
74
net: cadence_gem: clear RX control descriptor
75
76
Richard Henderson (1):
77
target/arm: Vectorize integer comparison vs zero
78
79
Subbaraya Sundeep (3):
80
hw/net: Add Smartfusion2 emac block
81
msf2: Add EMAC block to SmartFusion2 SoC
82
tests/boot_linux_console: Add ethernet test to SmartFusion2
83
84
Thomas Huth (1):
85
target/arm: Make cpu_register() available for other files
86
87
hw/core/Makefile.objs | 2 +
88
hw/net/Makefile.objs | 1 +
89
tests/Makefile.include | 1 +
90
include/hw/arm/msf2-soc.h | 2 +
91
include/hw/char/cadence_uart.h | 1 +
92
include/hw/clock.h | 225 +++++++++++++
93
include/hw/gpio/nrf51_gpio.h | 2 +-
94
include/hw/net/msf2-emac.h | 53 +++
95
include/hw/qdev-clock.h | 159 +++++++++
96
include/hw/qdev-core.h | 12 +
97
include/sysemu/device_tree.h | 5 +-
98
target/arm/cpu-qom.h | 9 +-
99
target/arm/helper.h | 27 +-
100
target/arm/translate.h | 5 +
101
device_tree.c | 4 +-
102
hw/acpi/cpu.c | 2 +-
103
hw/arm/msf2-soc.c | 26 +-
104
hw/arm/virt.c | 20 +-
105
hw/arm/xilinx_zynq.c | 57 +++-
106
hw/arm/xlnx-versal.c | 2 +
107
hw/arm/xlnx-zcu102.c | 39 ++-
108
hw/char/cadence_uart.c | 73 +++-
109
hw/core/clock-vmstate.c | 25 ++
110
hw/core/clock.c | 130 ++++++++
111
hw/core/qdev-clock.c | 185 +++++++++++
112
hw/core/qdev.c | 12 +
113
hw/dma/xlnx-zdma.c | 25 +-
114
hw/intc/arm_gicv3_kvm.c | 4 +-
115
hw/misc/zynq_slcr.c | 172 +++++++++-
116
hw/net/cadence_gem.c | 16 +-
117
hw/net/msf2-emac.c | 589 +++++++++++++++++++++++++++++++++
118
qdev-monitor.c | 9 +
119
target/arm/cpu.c | 25 +-
120
target/arm/cpu64.c | 16 +-
121
target/arm/helper.c | 17 +
122
target/arm/neon_helper.c | 24 --
123
target/arm/translate-a64.c | 64 +---
124
target/arm/translate.c | 256 ++++++++++++--
125
target/arm/vec_helper.c | 25 ++
126
MAINTAINERS | 2 +
127
docs/devel/clocks.rst | 391 ++++++++++++++++++++++
128
docs/devel/index.rst | 1 +
129
hw/char/trace-events | 3 +
130
hw/core/trace-events | 7 +
131
tests/acceptance/boot_linux_console.py | 15 +-
132
45 files changed, 2538 insertions(+), 202 deletions(-)
133
create mode 100644 include/hw/clock.h
134
create mode 100644 include/hw/net/msf2-emac.h
135
create mode 100644 include/hw/qdev-clock.h
136
create mode 100644 hw/core/clock-vmstate.c
137
create mode 100644 hw/core/clock.c
138
create mode 100644 hw/core/qdev-clock.c
139
create mode 100644 hw/net/msf2-emac.c
140
create mode 100644 docs/devel/clocks.rst
141
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
This fixes the endianness problem for softmmu, and moves
3
Fix descriptor loading from memory wrt host endianness.
4
the main loop out of a macro and into an inlined function.
5
4
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reported-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20181005175350.30752-14-richard.henderson@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20200404122718.25111-2-edgar.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/helper-sve.h | 52 ++++++++++----
12
hw/dma/xlnx-zdma.c | 11 +++++++----
13
target/arm/sve_helper.c | 139 ++++++++++++++++++++++++-------------
13
1 file changed, 7 insertions(+), 4 deletions(-)
14
target/arm/translate-sve.c | 74 +++++++++++++-------
15
3 files changed, 177 insertions(+), 88 deletions(-)
16
14
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/hw/dma/xlnx-zdma.c b/hw/dma/xlnx-zdma.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-sve.h
17
--- a/hw/dma/xlnx-zdma.c
20
+++ b/target/arm/helper-sve.h
18
+++ b/hw/dma/xlnx-zdma.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve_ldffsds_zd, TCG_CALL_NO_WG,
19
@@ -XXX,XX +XXX,XX @@ static void zdma_put_regaddr64(XlnxZDMA *s, unsigned int basereg, uint64_t addr)
22
20
s->regs[basereg + 1] = addr >> 32;
23
DEF_HELPER_FLAGS_6(sve_stbs_zsu, TCG_CALL_NO_WG,
24
void, env, ptr, ptr, ptr, tl, i32)
25
-DEF_HELPER_FLAGS_6(sve_sths_zsu, TCG_CALL_NO_WG,
26
+DEF_HELPER_FLAGS_6(sve_sths_le_zsu, TCG_CALL_NO_WG,
27
void, env, ptr, ptr, ptr, tl, i32)
28
-DEF_HELPER_FLAGS_6(sve_stss_zsu, TCG_CALL_NO_WG,
29
+DEF_HELPER_FLAGS_6(sve_sths_be_zsu, TCG_CALL_NO_WG,
30
+ void, env, ptr, ptr, ptr, tl, i32)
31
+DEF_HELPER_FLAGS_6(sve_stss_le_zsu, TCG_CALL_NO_WG,
32
+ void, env, ptr, ptr, ptr, tl, i32)
33
+DEF_HELPER_FLAGS_6(sve_stss_be_zsu, TCG_CALL_NO_WG,
34
void, env, ptr, ptr, ptr, tl, i32)
35
36
DEF_HELPER_FLAGS_6(sve_stbs_zss, TCG_CALL_NO_WG,
37
void, env, ptr, ptr, ptr, tl, i32)
38
-DEF_HELPER_FLAGS_6(sve_sths_zss, TCG_CALL_NO_WG,
39
+DEF_HELPER_FLAGS_6(sve_sths_le_zss, TCG_CALL_NO_WG,
40
void, env, ptr, ptr, ptr, tl, i32)
41
-DEF_HELPER_FLAGS_6(sve_stss_zss, TCG_CALL_NO_WG,
42
+DEF_HELPER_FLAGS_6(sve_sths_be_zss, TCG_CALL_NO_WG,
43
+ void, env, ptr, ptr, ptr, tl, i32)
44
+DEF_HELPER_FLAGS_6(sve_stss_le_zss, TCG_CALL_NO_WG,
45
+ void, env, ptr, ptr, ptr, tl, i32)
46
+DEF_HELPER_FLAGS_6(sve_stss_be_zss, TCG_CALL_NO_WG,
47
void, env, ptr, ptr, ptr, tl, i32)
48
49
DEF_HELPER_FLAGS_6(sve_stbd_zsu, TCG_CALL_NO_WG,
50
void, env, ptr, ptr, ptr, tl, i32)
51
-DEF_HELPER_FLAGS_6(sve_sthd_zsu, TCG_CALL_NO_WG,
52
+DEF_HELPER_FLAGS_6(sve_sthd_le_zsu, TCG_CALL_NO_WG,
53
void, env, ptr, ptr, ptr, tl, i32)
54
-DEF_HELPER_FLAGS_6(sve_stsd_zsu, TCG_CALL_NO_WG,
55
+DEF_HELPER_FLAGS_6(sve_sthd_be_zsu, TCG_CALL_NO_WG,
56
void, env, ptr, ptr, ptr, tl, i32)
57
-DEF_HELPER_FLAGS_6(sve_stdd_zsu, TCG_CALL_NO_WG,
58
+DEF_HELPER_FLAGS_6(sve_stsd_le_zsu, TCG_CALL_NO_WG,
59
+ void, env, ptr, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_6(sve_stsd_be_zsu, TCG_CALL_NO_WG,
61
+ void, env, ptr, ptr, ptr, tl, i32)
62
+DEF_HELPER_FLAGS_6(sve_stdd_le_zsu, TCG_CALL_NO_WG,
63
+ void, env, ptr, ptr, ptr, tl, i32)
64
+DEF_HELPER_FLAGS_6(sve_stdd_be_zsu, TCG_CALL_NO_WG,
65
void, env, ptr, ptr, ptr, tl, i32)
66
67
DEF_HELPER_FLAGS_6(sve_stbd_zss, TCG_CALL_NO_WG,
68
void, env, ptr, ptr, ptr, tl, i32)
69
-DEF_HELPER_FLAGS_6(sve_sthd_zss, TCG_CALL_NO_WG,
70
+DEF_HELPER_FLAGS_6(sve_sthd_le_zss, TCG_CALL_NO_WG,
71
void, env, ptr, ptr, ptr, tl, i32)
72
-DEF_HELPER_FLAGS_6(sve_stsd_zss, TCG_CALL_NO_WG,
73
+DEF_HELPER_FLAGS_6(sve_sthd_be_zss, TCG_CALL_NO_WG,
74
void, env, ptr, ptr, ptr, tl, i32)
75
-DEF_HELPER_FLAGS_6(sve_stdd_zss, TCG_CALL_NO_WG,
76
+DEF_HELPER_FLAGS_6(sve_stsd_le_zss, TCG_CALL_NO_WG,
77
+ void, env, ptr, ptr, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_6(sve_stsd_be_zss, TCG_CALL_NO_WG,
79
+ void, env, ptr, ptr, ptr, tl, i32)
80
+DEF_HELPER_FLAGS_6(sve_stdd_le_zss, TCG_CALL_NO_WG,
81
+ void, env, ptr, ptr, ptr, tl, i32)
82
+DEF_HELPER_FLAGS_6(sve_stdd_be_zss, TCG_CALL_NO_WG,
83
void, env, ptr, ptr, ptr, tl, i32)
84
85
DEF_HELPER_FLAGS_6(sve_stbd_zd, TCG_CALL_NO_WG,
86
void, env, ptr, ptr, ptr, tl, i32)
87
-DEF_HELPER_FLAGS_6(sve_sthd_zd, TCG_CALL_NO_WG,
88
+DEF_HELPER_FLAGS_6(sve_sthd_le_zd, TCG_CALL_NO_WG,
89
void, env, ptr, ptr, ptr, tl, i32)
90
-DEF_HELPER_FLAGS_6(sve_stsd_zd, TCG_CALL_NO_WG,
91
+DEF_HELPER_FLAGS_6(sve_sthd_be_zd, TCG_CALL_NO_WG,
92
void, env, ptr, ptr, ptr, tl, i32)
93
-DEF_HELPER_FLAGS_6(sve_stdd_zd, TCG_CALL_NO_WG,
94
+DEF_HELPER_FLAGS_6(sve_stsd_le_zd, TCG_CALL_NO_WG,
95
+ void, env, ptr, ptr, ptr, tl, i32)
96
+DEF_HELPER_FLAGS_6(sve_stsd_be_zd, TCG_CALL_NO_WG,
97
+ void, env, ptr, ptr, ptr, tl, i32)
98
+DEF_HELPER_FLAGS_6(sve_stdd_le_zd, TCG_CALL_NO_WG,
99
+ void, env, ptr, ptr, ptr, tl, i32)
100
+DEF_HELPER_FLAGS_6(sve_stdd_be_zd, TCG_CALL_NO_WG,
101
void, env, ptr, ptr, ptr, tl, i32)
102
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/sve_helper.c
105
+++ b/target/arm/sve_helper.c
106
@@ -XXX,XX +XXX,XX @@ DO_LDFF1_ZPZ_D(sve_ldffsds_zd, uint64_t, int32_t, cpu_ldl_data_ra)
107
108
/* Stores with a vector index. */
109
110
-#define DO_ST1_ZPZ_S(NAME, TYPEI, FN) \
111
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
112
- target_ulong base, uint32_t desc) \
113
-{ \
114
- intptr_t i, oprsz = simd_oprsz(desc); \
115
- unsigned scale = simd_data(desc); \
116
- uintptr_t ra = GETPC(); \
117
- for (i = 0; i < oprsz; ) { \
118
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
119
- do { \
120
- if (likely(pg & 1)) { \
121
- target_ulong off = *(TYPEI *)(vm + H1_4(i)); \
122
- uint32_t d = *(uint32_t *)(vd + H1_4(i)); \
123
- FN(env, base + (off << scale), d, ra); \
124
- } \
125
- i += sizeof(uint32_t), pg >>= sizeof(uint32_t); \
126
- } while (i & 15); \
127
- } \
128
+static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
129
+ target_ulong base, uint32_t desc, uintptr_t ra,
130
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
131
+{
132
+ const int mmu_idx = cpu_mmu_index(env, false);
133
+ intptr_t i, oprsz = simd_oprsz(desc);
134
+ unsigned scale = simd_data(desc);
135
+
136
+ set_helper_retaddr(ra);
137
+ for (i = 0; i < oprsz; ) {
138
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
139
+ do {
140
+ if (likely(pg & 1)) {
141
+ target_ulong off = off_fn(vm, i);
142
+ tlb_fn(env, vd, i, base + (off << scale), mmu_idx, ra);
143
+ }
144
+ i += 4, pg >>= 4;
145
+ } while (i & 15);
146
+ }
147
+ set_helper_retaddr(0);
148
}
21
}
149
22
150
-#define DO_ST1_ZPZ_D(NAME, TYPEI, FN) \
23
-static bool zdma_load_descriptor(XlnxZDMA *s, uint64_t addr, void *buf)
151
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
24
+static bool zdma_load_descriptor(XlnxZDMA *s, uint64_t addr,
152
- target_ulong base, uint32_t desc) \
25
+ XlnxZDMADescr *descr)
153
-{ \
26
{
154
- intptr_t i, oprsz = simd_oprsz(desc) / 8; \
27
/* ZDMA descriptors must be aligned to their own size. */
155
- unsigned scale = simd_data(desc); \
28
if (addr % sizeof(XlnxZDMADescr)) {
156
- uintptr_t ra = GETPC(); \
29
qemu_log_mask(LOG_GUEST_ERROR,
157
- uint64_t *d = vd, *m = vm; uint8_t *pg = vg; \
30
"zdma: unaligned descriptor at %" PRIx64,
158
- for (i = 0; i < oprsz; i++) { \
31
addr);
159
- if (likely(pg[H1(i)] & 1)) { \
32
- memset(buf, 0x0, sizeof(XlnxZDMADescr));
160
- target_ulong off = (target_ulong)(TYPEI)m[i] << scale; \
33
+ memset(descr, 0x0, sizeof(XlnxZDMADescr));
161
- FN(env, base + off, d[i], ra); \
34
s->error = true;
162
- } \
35
return false;
163
- } \
36
}
164
+static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
37
165
+ target_ulong base, uint32_t desc, uintptr_t ra,
38
- address_space_read(s->dma_as, addr, s->attr, buf, sizeof(XlnxZDMADescr));
166
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
39
+ descr->addr = address_space_ldq_le(s->dma_as, addr, s->attr, NULL);
167
+{
40
+ descr->size = address_space_ldl_le(s->dma_as, addr + 8, s->attr, NULL);
168
+ const int mmu_idx = cpu_mmu_index(env, false);
41
+ descr->attr = address_space_ldl_le(s->dma_as, addr + 12, s->attr, NULL);
169
+ intptr_t i, oprsz = simd_oprsz(desc) / 8;
170
+ unsigned scale = simd_data(desc);
171
+
172
+ set_helper_retaddr(ra);
173
+ for (i = 0; i < oprsz; i++) {
174
+ uint8_t pg = *(uint8_t *)(vg + H1(i));
175
+ if (likely(pg & 1)) {
176
+ target_ulong off = off_fn(vm, i * 8);
177
+ tlb_fn(env, vd, i * 8, base + (off << scale), mmu_idx, ra);
178
+ }
179
+ }
180
+ set_helper_retaddr(0);
181
}
182
183
-DO_ST1_ZPZ_S(sve_stbs_zsu, uint32_t, cpu_stb_data_ra)
184
-DO_ST1_ZPZ_S(sve_sths_zsu, uint32_t, cpu_stw_data_ra)
185
-DO_ST1_ZPZ_S(sve_stss_zsu, uint32_t, cpu_stl_data_ra)
186
+#define DO_ST1_ZPZ_S(MEM, OFS) \
187
+void __attribute__((flatten)) HELPER(sve_st##MEM##_##OFS) \
188
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
189
+ target_ulong base, uint32_t desc) \
190
+{ \
191
+ sve_st1_zs(env, vd, vg, vm, base, desc, GETPC(), \
192
+ off_##OFS##_s, sve_st1##MEM##_tlb); \
193
+}
194
195
-DO_ST1_ZPZ_S(sve_stbs_zss, int32_t, cpu_stb_data_ra)
196
-DO_ST1_ZPZ_S(sve_sths_zss, int32_t, cpu_stw_data_ra)
197
-DO_ST1_ZPZ_S(sve_stss_zss, int32_t, cpu_stl_data_ra)
198
+#define DO_ST1_ZPZ_D(MEM, OFS) \
199
+void __attribute__((flatten)) HELPER(sve_st##MEM##_##OFS) \
200
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
201
+ target_ulong base, uint32_t desc) \
202
+{ \
203
+ sve_st1_zd(env, vd, vg, vm, base, desc, GETPC(), \
204
+ off_##OFS##_d, sve_st1##MEM##_tlb); \
205
+}
206
207
-DO_ST1_ZPZ_D(sve_stbd_zsu, uint32_t, cpu_stb_data_ra)
208
-DO_ST1_ZPZ_D(sve_sthd_zsu, uint32_t, cpu_stw_data_ra)
209
-DO_ST1_ZPZ_D(sve_stsd_zsu, uint32_t, cpu_stl_data_ra)
210
-DO_ST1_ZPZ_D(sve_stdd_zsu, uint32_t, cpu_stq_data_ra)
211
+DO_ST1_ZPZ_S(bs, zsu)
212
+DO_ST1_ZPZ_S(hs_le, zsu)
213
+DO_ST1_ZPZ_S(hs_be, zsu)
214
+DO_ST1_ZPZ_S(ss_le, zsu)
215
+DO_ST1_ZPZ_S(ss_be, zsu)
216
217
-DO_ST1_ZPZ_D(sve_stbd_zss, int32_t, cpu_stb_data_ra)
218
-DO_ST1_ZPZ_D(sve_sthd_zss, int32_t, cpu_stw_data_ra)
219
-DO_ST1_ZPZ_D(sve_stsd_zss, int32_t, cpu_stl_data_ra)
220
-DO_ST1_ZPZ_D(sve_stdd_zss, int32_t, cpu_stq_data_ra)
221
+DO_ST1_ZPZ_S(bs, zss)
222
+DO_ST1_ZPZ_S(hs_le, zss)
223
+DO_ST1_ZPZ_S(hs_be, zss)
224
+DO_ST1_ZPZ_S(ss_le, zss)
225
+DO_ST1_ZPZ_S(ss_be, zss)
226
227
-DO_ST1_ZPZ_D(sve_stbd_zd, uint64_t, cpu_stb_data_ra)
228
-DO_ST1_ZPZ_D(sve_sthd_zd, uint64_t, cpu_stw_data_ra)
229
-DO_ST1_ZPZ_D(sve_stsd_zd, uint64_t, cpu_stl_data_ra)
230
-DO_ST1_ZPZ_D(sve_stdd_zd, uint64_t, cpu_stq_data_ra)
231
+DO_ST1_ZPZ_D(bd, zsu)
232
+DO_ST1_ZPZ_D(hd_le, zsu)
233
+DO_ST1_ZPZ_D(hd_be, zsu)
234
+DO_ST1_ZPZ_D(sd_le, zsu)
235
+DO_ST1_ZPZ_D(sd_be, zsu)
236
+DO_ST1_ZPZ_D(dd_le, zsu)
237
+DO_ST1_ZPZ_D(dd_be, zsu)
238
+
239
+DO_ST1_ZPZ_D(bd, zss)
240
+DO_ST1_ZPZ_D(hd_le, zss)
241
+DO_ST1_ZPZ_D(hd_be, zss)
242
+DO_ST1_ZPZ_D(sd_le, zss)
243
+DO_ST1_ZPZ_D(sd_be, zss)
244
+DO_ST1_ZPZ_D(dd_le, zss)
245
+DO_ST1_ZPZ_D(dd_be, zss)
246
+
247
+DO_ST1_ZPZ_D(bd, zd)
248
+DO_ST1_ZPZ_D(hd_le, zd)
249
+DO_ST1_ZPZ_D(hd_be, zd)
250
+DO_ST1_ZPZ_D(sd_le, zd)
251
+DO_ST1_ZPZ_D(sd_be, zd)
252
+DO_ST1_ZPZ_D(dd_le, zd)
253
+DO_ST1_ZPZ_D(dd_be, zd)
254
+
255
+#undef DO_ST1_ZPZ_S
256
+#undef DO_ST1_ZPZ_D
257
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
258
index XXXXXXX..XXXXXXX 100644
259
--- a/target/arm/translate-sve.c
260
+++ b/target/arm/translate-sve.c
261
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
262
return true;
42
return true;
263
}
43
}
264
44
265
-/* Indexed by [xs][msz]. */
45
@@ -XXX,XX +XXX,XX @@ static void zdma_update_descr_addr(XlnxZDMA *s, bool type,
266
-static gen_helper_gvec_mem_scatter * const scatter_store_fn32[2][3] = {
46
} else {
267
- { gen_helper_sve_stbs_zsu,
47
addr = zdma_get_regaddr64(s, basereg);
268
- gen_helper_sve_sths_zsu,
48
addr += sizeof(s->dsc_dst);
269
- gen_helper_sve_stss_zsu, },
49
- address_space_read(s->dma_as, addr, s->attr, (void *) &next, 8);
270
- { gen_helper_sve_stbs_zss,
50
+ next = address_space_ldq_le(s->dma_as, addr, s->attr, NULL);
271
- gen_helper_sve_sths_zss,
272
- gen_helper_sve_stss_zss, },
273
+/* Indexed by [be][xs][msz]. */
274
+static gen_helper_gvec_mem_scatter * const scatter_store_fn32[2][2][3] = {
275
+ /* Little-endian */
276
+ { { gen_helper_sve_stbs_zsu,
277
+ gen_helper_sve_sths_le_zsu,
278
+ gen_helper_sve_stss_le_zsu, },
279
+ { gen_helper_sve_stbs_zss,
280
+ gen_helper_sve_sths_le_zss,
281
+ gen_helper_sve_stss_le_zss, } },
282
+ /* Big-endian */
283
+ { { gen_helper_sve_stbs_zsu,
284
+ gen_helper_sve_sths_be_zsu,
285
+ gen_helper_sve_stss_be_zsu, },
286
+ { gen_helper_sve_stbs_zss,
287
+ gen_helper_sve_sths_be_zss,
288
+ gen_helper_sve_stss_be_zss, } },
289
};
290
291
/* Note that we overload xs=2 to indicate 64-bit offset. */
292
-static gen_helper_gvec_mem_scatter * const scatter_store_fn64[3][4] = {
293
- { gen_helper_sve_stbd_zsu,
294
- gen_helper_sve_sthd_zsu,
295
- gen_helper_sve_stsd_zsu,
296
- gen_helper_sve_stdd_zsu, },
297
- { gen_helper_sve_stbd_zss,
298
- gen_helper_sve_sthd_zss,
299
- gen_helper_sve_stsd_zss,
300
- gen_helper_sve_stdd_zss, },
301
- { gen_helper_sve_stbd_zd,
302
- gen_helper_sve_sthd_zd,
303
- gen_helper_sve_stsd_zd,
304
- gen_helper_sve_stdd_zd, },
305
+static gen_helper_gvec_mem_scatter * const scatter_store_fn64[2][3][4] = {
306
+ /* Little-endian */
307
+ { { gen_helper_sve_stbd_zsu,
308
+ gen_helper_sve_sthd_le_zsu,
309
+ gen_helper_sve_stsd_le_zsu,
310
+ gen_helper_sve_stdd_le_zsu, },
311
+ { gen_helper_sve_stbd_zss,
312
+ gen_helper_sve_sthd_le_zss,
313
+ gen_helper_sve_stsd_le_zss,
314
+ gen_helper_sve_stdd_le_zss, },
315
+ { gen_helper_sve_stbd_zd,
316
+ gen_helper_sve_sthd_le_zd,
317
+ gen_helper_sve_stsd_le_zd,
318
+ gen_helper_sve_stdd_le_zd, } },
319
+ /* Big-endian */
320
+ { { gen_helper_sve_stbd_zsu,
321
+ gen_helper_sve_sthd_be_zsu,
322
+ gen_helper_sve_stsd_be_zsu,
323
+ gen_helper_sve_stdd_be_zsu, },
324
+ { gen_helper_sve_stbd_zss,
325
+ gen_helper_sve_sthd_be_zss,
326
+ gen_helper_sve_stsd_be_zss,
327
+ gen_helper_sve_stdd_be_zss, },
328
+ { gen_helper_sve_stbd_zd,
329
+ gen_helper_sve_sthd_be_zd,
330
+ gen_helper_sve_stsd_be_zd,
331
+ gen_helper_sve_stdd_be_zd, } },
332
};
333
334
static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
335
{
336
gen_helper_gvec_mem_scatter *fn;
337
+ int be = s->be_data == MO_BE;
338
339
if (a->esz < a->msz || (a->msz == 0 && a->scale)) {
340
return false;
341
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
342
}
51
}
343
switch (a->esz) {
52
344
case MO_32:
53
zdma_put_regaddr64(s, basereg, next);
345
- fn = scatter_store_fn32[a->xs][a->msz];
346
+ fn = scatter_store_fn32[be][a->xs][a->msz];
347
break;
348
case MO_64:
349
- fn = scatter_store_fn64[a->xs][a->msz];
350
+ fn = scatter_store_fn64[be][a->xs][a->msz];
351
break;
352
default:
353
g_assert_not_reached();
354
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
355
static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn)
356
{
357
gen_helper_gvec_mem_scatter *fn = NULL;
358
+ int be = s->be_data == MO_BE;
359
TCGv_i64 imm;
360
361
if (a->esz < a->msz) {
362
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn)
363
364
switch (a->esz) {
365
case MO_32:
366
- fn = scatter_store_fn32[0][a->msz];
367
+ fn = scatter_store_fn32[be][0][a->msz];
368
break;
369
case MO_64:
370
- fn = scatter_store_fn64[2][a->msz];
371
+ fn = scatter_store_fn64[be][2][a->msz];
372
break;
373
}
374
assert(fn != NULL);
375
--
54
--
376
2.19.0
55
2.20.1
377
56
378
57
diff view generated by jsdifflib
1
Check the v8M stack limits when pushing the frame for a
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
non-secure function call via BLXNS.
3
2
4
In order to be able to generate the exception we need to
3
Fix descriptor loading from registers wrt host endianness.
5
promote raise_exception() from being local to op_helper.c
6
so we can call it from helper.c.
7
4
5
Reported-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
8
Message-id: 20200404122718.25111-3-edgar.iglesias@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20181002163556.10279-8-peter.maydell@linaro.org
12
---
10
---
13
target/arm/internals.h | 9 +++++++++
11
hw/dma/xlnx-zdma.c | 14 ++++++++++----
14
target/arm/helper.c | 4 ++++
12
1 file changed, 10 insertions(+), 4 deletions(-)
15
target/arm/op_helper.c | 4 ++--
16
3 files changed, 15 insertions(+), 2 deletions(-)
17
13
18
diff --git a/target/arm/internals.h b/target/arm/internals.h
14
diff --git a/hw/dma/xlnx-zdma.c b/hw/dma/xlnx-zdma.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/internals.h
16
--- a/hw/dma/xlnx-zdma.c
21
+++ b/target/arm/internals.h
17
+++ b/hw/dma/xlnx-zdma.c
22
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_EXCRET, RES1, 7, 25) /* including the must-be-1 prefix */
18
@@ -XXX,XX +XXX,XX @@ static void zdma_put_regaddr64(XlnxZDMA *s, unsigned int basereg, uint64_t addr)
23
#define M_FAKE_FSR_NSC_EXEC 0xf /* NS executing in S&NSC memory */
19
s->regs[basereg + 1] = addr >> 32;
24
#define M_FAKE_FSR_SFAULT 0xe /* SecureFault INVTRAN, INVEP or AUVIOL */
20
}
25
21
26
+/**
22
+static void zdma_load_descriptor_reg(XlnxZDMA *s, unsigned int reg,
27
+ * raise_exception: Raise the specified exception.
23
+ XlnxZDMADescr *descr)
28
+ * Raise a guest exception with the specified value, syndrome register
24
+{
29
+ * and target exception level. This should be called from helper functions,
25
+ descr->addr = zdma_get_regaddr64(s, reg);
30
+ * and never returns because we will longjump back up to the CPU main loop.
26
+ descr->size = s->regs[reg + 2];
31
+ */
27
+ descr->attr = s->regs[reg + 3];
32
+void QEMU_NORETURN raise_exception(CPUARMState *env, uint32_t excp,
28
+}
33
+ uint32_t syndrome, uint32_t target_el);
34
+
29
+
35
/*
30
static bool zdma_load_descriptor(XlnxZDMA *s, uint64_t addr,
36
* For AArch64, map a given EL to an index in the banked_spsr array.
31
XlnxZDMADescr *descr)
37
* Note that this mapping and the AArch32 mapping defined in bank_number()
32
{
38
diff --git a/target/arm/helper.c b/target/arm/helper.c
33
@@ -XXX,XX +XXX,XX @@ static void zdma_load_src_descriptor(XlnxZDMA *s)
39
index XXXXXXX..XXXXXXX 100644
34
unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE);
40
--- a/target/arm/helper.c
35
41
+++ b/target/arm/helper.c
36
if (ptype == PT_REG) {
42
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
37
- memcpy(&s->dsc_src, &s->regs[R_ZDMA_CH_SRC_DSCR_WORD0],
43
"BLXNS with misaligned SP is UNPREDICTABLE\n");
38
- sizeof(s->dsc_src));
39
+ zdma_load_descriptor_reg(s, R_ZDMA_CH_SRC_DSCR_WORD0, &s->dsc_src);
40
return;
44
}
41
}
45
42
46
+ if (sp < v7m_sp_limit(env)) {
43
@@ -XXX,XX +XXX,XX @@ static void zdma_load_dst_descriptor(XlnxZDMA *s)
47
+ raise_exception(env, EXCP_STKOF, 0, 1);
44
bool dst_type;
48
+ }
45
49
+
46
if (ptype == PT_REG) {
50
saved_psr = env->v7m.exception;
47
- memcpy(&s->dsc_dst, &s->regs[R_ZDMA_CH_DST_DSCR_WORD0],
51
if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK) {
48
- sizeof(s->dsc_dst));
52
saved_psr |= XPSR_SFPA;
49
+ zdma_load_descriptor_reg(s, R_ZDMA_CH_DST_DSCR_WORD0, &s->dsc_dst);
53
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
50
return;
54
index XXXXXXX..XXXXXXX 100644
51
}
55
--- a/target/arm/op_helper.c
56
+++ b/target/arm/op_helper.c
57
@@ -XXX,XX +XXX,XX @@
58
#define SIGNBIT (uint32_t)0x80000000
59
#define SIGNBIT64 ((uint64_t)1 << 63)
60
61
-static void raise_exception(CPUARMState *env, uint32_t excp,
62
- uint32_t syndrome, uint32_t target_el)
63
+void raise_exception(CPUARMState *env, uint32_t excp,
64
+ uint32_t syndrome, uint32_t target_el)
65
{
66
CPUState *cs = CPU(arm_env_get_cpu(env));
67
52
68
--
53
--
69
2.19.0
54
2.20.1
70
55
71
56
diff view generated by jsdifflib
1
Coverity complains (CID 1395628) that the multiply in the calculation
1
From: Cameron Esfahani <dirty@apple.com>
2
of the framebuffer base is performed as 32x32 but then used in a
3
context that takes a 64-bit hwaddr. This can't actually ever
4
overflow the 32-bit result, because of the constraints placed on
5
the s->config values in bcm2835_fb_validate_config(). But we
6
can placate Coverity anyway, by explicitly casting one of the
7
inputs to a hwaddr, so the whole expression is calculated with
8
64-bit arithmetic.
9
2
3
NRF51_GPIO_REG_CNF_END doesn't actually refer to the start of the last
4
valid CNF register: it's referring to the last byte of the last valid
5
CNF register.
6
7
This hasn't been a problem up to now, as current implementation in
8
memory.c turns an unaligned 4-byte read from 0x77f to a single byte read
9
and the qtest only looks at the least-significant byte of the register.
10
11
But when running with patches which fix unaligned accesses in memory.c,
12
the qtest breaks.
13
14
Considering NRF51 doesn't support unaligned accesses, the simplest fix
15
is to actually set NRF51_GPIO_REG_CNF_END to the start of the last valid
16
CNF register: 0x77c.
17
18
Now, qtests work with or without the unaligned access patches.
19
20
Reviewed-by: Cédric Le Goater <clg@kaod.org>
21
Tested-by: Cédric Le Goater <clg@kaod.org>
22
Reviewed-by: Joel Stanley <joel@jms.id.au>
23
Signed-off-by: Cameron Esfahani <dirty@apple.com>
24
Message-id: 51b427f06838622da783d38ba56e3630d6d85c60.1586925392.git.dirty@apple.com
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
12
Message-id: 20181005133012.26490-1-peter.maydell@linaro.org
13
---
27
---
14
hw/display/bcm2835_fb.c | 2 +-
28
include/hw/gpio/nrf51_gpio.h | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
29
1 file changed, 1 insertion(+), 1 deletion(-)
16
30
17
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
31
diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h
18
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/display/bcm2835_fb.c
33
--- a/include/hw/gpio/nrf51_gpio.h
20
+++ b/hw/display/bcm2835_fb.c
34
+++ b/include/hw/gpio/nrf51_gpio.h
21
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
35
@@ -XXX,XX +XXX,XX @@
22
}
36
#define NRF51_GPIO_REG_DIRSET 0x518
23
37
#define NRF51_GPIO_REG_DIRCLR 0x51C
24
if (s->invalidate) {
38
#define NRF51_GPIO_REG_CNF_START 0x700
25
- hwaddr base = s->config.base + xoff + yoff * src_width;
39
-#define NRF51_GPIO_REG_CNF_END 0x77F
26
+ hwaddr base = s->config.base + xoff + (hwaddr)yoff * src_width;
40
+#define NRF51_GPIO_REG_CNF_END 0x77C
27
framebuffer_update_memory_section(&s->fbsection, s->dma_mr,
41
28
base,
42
#define NRF51_GPIO_PULLDOWN 1
29
s->config.yres, src_width);
43
#define NRF51_GPIO_PULLUP 3
30
--
44
--
31
2.19.0
45
2.20.1
32
46
33
47
diff view generated by jsdifflib
1
Updating the NS stack pointer via MSR to SP_NS should include
1
From: Keqian Zhu <zhukeqian1@huawei.com>
2
a check whether the new SP value is below the stack limit.
3
No other kinds of update to the various stack pointer and
4
limit registers via MSR should perform a check.
5
2
3
The KVM_VGIC_ATTR macro expect the second parameter as gicr_typer,
4
of which high 32bit is constructed by mp_affinity. For most case,
5
the high 32bit of mp_affinity is zero, so it will always access the
6
ICC_CTLR_EL1 of CPU0.
7
8
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
9
Message-id: 20200413091552.62748-2-zhukeqian1@huawei.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181002163556.10279-14-peter.maydell@linaro.org
10
---
12
---
11
target/arm/helper.c | 14 +++++++++++++-
13
hw/intc/arm_gicv3_kvm.c | 4 +---
12
1 file changed, 13 insertions(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 3 deletions(-)
13
15
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
18
--- a/hw/intc/arm_gicv3_kvm.c
17
+++ b/target/arm/helper.c
19
+++ b/hw/intc/arm_gicv3_kvm.c
18
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
20
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_get(GICv3State *s)
19
* currently in handler mode or not, using the NS CONTROL.SPSEL.
21
20
*/
22
static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
21
bool spsel = env->v7m.control[M_REG_NS] & R_V7M_CONTROL_SPSEL_MASK;
23
{
22
+ bool is_psp = !arm_v7m_is_handler_mode(env) && spsel;
24
- ARMCPU *cpu;
23
+ uint32_t limit;
25
GICv3State *s;
24
26
GICv3CPUState *c;
25
if (!env->v7m.secure) {
27
26
return;
28
c = (GICv3CPUState *)env->gicv3state;
27
}
29
s = c->gic;
28
- if (!arm_v7m_is_handler_mode(env) && spsel) {
30
- cpu = ARM_CPU(c->cpu);
29
+
31
30
+ limit = is_psp ? env->v7m.psplim[false] : env->v7m.msplim[false];
32
c->icc_pmr_el1 = 0;
31
+
33
c->icc_bpr[GICV3_G0] = GIC_MIN_BPR;
32
+ if (val < limit) {
34
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
33
+ CPUState *cs = CPU(arm_env_get_cpu(env));
35
34
+
36
/* Initialize to actual HW supported configuration */
35
+ cpu_restore_state(cs, GETPC(), true);
37
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
36
+ raise_exception(env, EXCP_STKOF, 0, 1);
38
- KVM_VGIC_ATTR(ICC_CTLR_EL1, cpu->mp_affinity),
37
+ }
39
+ KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer),
38
+
40
&c->icc_ctlr_el1[GICV3_NS], false, &error_abort);
39
+ if (is_psp) {
41
40
env->v7m.other_ss_psp = val;
42
c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
41
} else {
42
env->v7m.other_ss_msp = val;
43
--
43
--
44
2.19.0
44
2.20.1
45
45
46
46
diff view generated by jsdifflib
1
In v7m_exception_taken() we were incorrectly using a
1
From: Keqian Zhu <zhukeqian1@huawei.com>
2
"LR bit EXCRET.ES is 1" check when it should be 0
3
(compare the pseudocode ExceptionTaken() function).
4
This meant we didn't stack the callee-saved registers
5
when tailchaining from a NonSecure to a Secure exception.
6
2
7
Cc: qemu-stable@nongnu.org
3
Replace "acpi-mem-hotplug" with "acpi-cpu-hotplug"
4
5
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
6
Message-id: 20200413091552.62748-4-zhukeqian1@huawei.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20181002145940.30931-1-peter.maydell@linaro.org
11
---
9
---
12
target/arm/helper.c | 2 +-
10
hw/acpi/cpu.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
14
12
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
15
--- a/hw/acpi/cpu.c
18
+++ b/target/arm/helper.c
16
+++ b/hw/acpi/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
17
@@ -XXX,XX +XXX,XX @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
20
* not already saved.
18
state->devs[i].arch_id = id_list->cpus[i].arch_id;
21
*/
19
}
22
if (lr & R_V7M_EXCRET_DCRS_MASK &&
20
memory_region_init_io(&state->ctrl_reg, owner, &cpu_hotplug_ops, state,
23
- !(dotailchain && (lr & R_V7M_EXCRET_ES_MASK))) {
21
- "acpi-mem-hotplug", ACPI_CPU_HOTPLUG_REG_LEN);
24
+ !(dotailchain && !(lr & R_V7M_EXCRET_ES_MASK))) {
22
+ "acpi-cpu-hotplug", ACPI_CPU_HOTPLUG_REG_LEN);
25
push_failed = v7m_push_callee_stack(cpu, lr, dotailchain,
23
memory_region_add_subregion(as, base_addr, &state->ctrl_reg);
26
ignore_stackfaults);
24
}
27
}
25
28
--
26
--
29
2.19.0
27
2.20.1
30
28
31
29
diff view generated by jsdifflib
1
Add v8M stack checks for the instructions in the T32
1
From: Subbaraya Sundeep <sundeep.lkml@gmail.com>
2
"load/store single" encoding class: these are the
3
"immediate pre-indexed" and "immediate, post-indexed"
4
LDR and STR instructions.
5
2
3
Modelled Ethernet MAC of Smartfusion2 SoC.
4
Micrel KSZ8051 PHY is present on Emcraft's
5
SOM kit hence same PHY is emulated.
6
7
Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 1587048891-30493-2-git-send-email-sundeep.lkml@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181002163556.10279-11-peter.maydell@linaro.org
10
---
12
---
11
target/arm/translate.c | 23 ++++++++++++++++++++++-
13
hw/net/Makefile.objs | 1 +
12
1 file changed, 22 insertions(+), 1 deletion(-)
14
include/hw/net/msf2-emac.h | 53 ++++
15
hw/net/msf2-emac.c | 589 +++++++++++++++++++++++++++++++++++++
16
MAINTAINERS | 2 +
17
4 files changed, 645 insertions(+)
18
create mode 100644 include/hw/net/msf2-emac.h
19
create mode 100644 hw/net/msf2-emac.c
13
20
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
21
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
23
--- a/hw/net/Makefile.objs
17
+++ b/target/arm/translate.c
24
+++ b/hw/net/Makefile.objs
18
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
25
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_ROCKER) += rocker/rocker.o rocker/rocker_fp.o \
19
imm = -imm;
26
obj-$(call lnot,$(CONFIG_ROCKER)) += rocker/qmp-norocker.o
20
/* Fall through. */
27
21
case 0xf: /* Pre-increment. */
28
common-obj-$(CONFIG_CAN_BUS) += can/
22
- tcg_gen_addi_i32(addr, addr, imm);
29
+common-obj-$(CONFIG_MSF2) += msf2-emac.o
23
writeback = 1;
30
diff --git a/include/hw/net/msf2-emac.h b/include/hw/net/msf2-emac.h
24
break;
31
new file mode 100644
25
default:
32
index XXXXXXX..XXXXXXX
26
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
33
--- /dev/null
27
34
+++ b/include/hw/net/msf2-emac.h
28
issinfo = writeback ? ISSInvalid : rs;
35
@@ -XXX,XX +XXX,XX @@
29
36
+/*
30
+ if (s->v8m_stackcheck && rn == 13 && writeback) {
37
+ * QEMU model of the Smartfusion2 Ethernet MAC.
31
+ /*
38
+ *
32
+ * Stackcheck. Here we know 'addr' is the current SP;
39
+ * Copyright (c) 2020 Subbaraya Sundeep <sundeep.lkml@gmail.com>.
33
+ * if imm is +ve we're moving SP up, else down. It is
40
+ *
34
+ * UNKNOWN whether the limit check triggers when SP starts
41
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
35
+ * below the limit and ends up above it; we chose to do so.
42
+ * of this software and associated documentation files (the "Software"), to deal
36
+ */
43
+ * in the Software without restriction, including without limitation the rights
37
+ if ((int32_t)imm < 0) {
44
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38
+ TCGv_i32 newsp = tcg_temp_new_i32();
45
+ * copies of the Software, and to permit persons to whom the Software is
39
+
46
+ * furnished to do so, subject to the following conditions:
40
+ tcg_gen_addi_i32(newsp, addr, imm);
47
+ *
41
+ gen_helper_v8m_stackcheck(cpu_env, newsp);
48
+ * The above copyright notice and this permission notice shall be included in
42
+ tcg_temp_free_i32(newsp);
49
+ * all copies or substantial portions of the Software.
43
+ } else {
50
+ *
44
+ gen_helper_v8m_stackcheck(cpu_env, addr);
51
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
54
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
+ * THE SOFTWARE.
58
+ */
59
+
60
+#include "hw/sysbus.h"
61
+#include "exec/memory.h"
62
+#include "net/net.h"
63
+#include "net/eth.h"
64
+
65
+#define TYPE_MSS_EMAC "msf2-emac"
66
+#define MSS_EMAC(obj) \
67
+ OBJECT_CHECK(MSF2EmacState, (obj), TYPE_MSS_EMAC)
68
+
69
+#define R_MAX (0x1a0 / 4)
70
+#define PHY_MAX_REGS 32
71
+
72
+typedef struct MSF2EmacState {
73
+ SysBusDevice parent;
74
+
75
+ MemoryRegion mmio;
76
+ MemoryRegion *dma_mr;
77
+ AddressSpace dma_as;
78
+
79
+ qemu_irq irq;
80
+ NICState *nic;
81
+ NICConf conf;
82
+
83
+ uint8_t mac_addr[ETH_ALEN];
84
+ uint32_t rx_desc;
85
+ uint16_t phy_regs[PHY_MAX_REGS];
86
+
87
+ uint32_t regs[R_MAX];
88
+} MSF2EmacState;
89
diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c
90
new file mode 100644
91
index XXXXXXX..XXXXXXX
92
--- /dev/null
93
+++ b/hw/net/msf2-emac.c
94
@@ -XXX,XX +XXX,XX @@
95
+/*
96
+ * QEMU model of the Smartfusion2 Ethernet MAC.
97
+ *
98
+ * Copyright (c) 2020 Subbaraya Sundeep <sundeep.lkml@gmail.com>.
99
+ *
100
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
101
+ * of this software and associated documentation files (the "Software"), to deal
102
+ * in the Software without restriction, including without limitation the rights
103
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
104
+ * copies of the Software, and to permit persons to whom the Software is
105
+ * furnished to do so, subject to the following conditions:
106
+ *
107
+ * The above copyright notice and this permission notice shall be included in
108
+ * all copies or substantial portions of the Software.
109
+ *
110
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
111
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
112
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
113
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
114
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
115
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
116
+ * THE SOFTWARE.
117
+ *
118
+ * Refer to section Ethernet MAC in the document:
119
+ * UG0331: SmartFusion2 Microcontroller Subsystem User Guide
120
+ * Datasheet URL:
121
+ * https://www.microsemi.com/document-portal/cat_view/56661-internal-documents/
122
+ * 56758-soc?lang=en&limit=20&limitstart=220
123
+ */
124
+
125
+#include "qemu/osdep.h"
126
+#include "qemu-common.h"
127
+#include "qemu/log.h"
128
+#include "qapi/error.h"
129
+#include "exec/address-spaces.h"
130
+#include "hw/registerfields.h"
131
+#include "hw/net/msf2-emac.h"
132
+#include "hw/net/mii.h"
133
+#include "hw/irq.h"
134
+#include "hw/qdev-properties.h"
135
+#include "migration/vmstate.h"
136
+
137
+REG32(CFG1, 0x0)
138
+ FIELD(CFG1, RESET, 31, 1)
139
+ FIELD(CFG1, RX_EN, 2, 1)
140
+ FIELD(CFG1, TX_EN, 0, 1)
141
+ FIELD(CFG1, LB_EN, 8, 1)
142
+REG32(CFG2, 0x4)
143
+REG32(IFG, 0x8)
144
+REG32(HALF_DUPLEX, 0xc)
145
+REG32(MAX_FRAME_LENGTH, 0x10)
146
+REG32(MII_CMD, 0x24)
147
+ FIELD(MII_CMD, READ, 0, 1)
148
+REG32(MII_ADDR, 0x28)
149
+ FIELD(MII_ADDR, REGADDR, 0, 5)
150
+ FIELD(MII_ADDR, PHYADDR, 8, 5)
151
+REG32(MII_CTL, 0x2c)
152
+REG32(MII_STS, 0x30)
153
+REG32(STA1, 0x40)
154
+REG32(STA2, 0x44)
155
+REG32(FIFO_CFG0, 0x48)
156
+REG32(FIFO_CFG4, 0x58)
157
+ FIELD(FIFO_CFG4, BCAST, 9, 1)
158
+ FIELD(FIFO_CFG4, MCAST, 8, 1)
159
+REG32(FIFO_CFG5, 0x5C)
160
+ FIELD(FIFO_CFG5, BCAST, 9, 1)
161
+ FIELD(FIFO_CFG5, MCAST, 8, 1)
162
+REG32(DMA_TX_CTL, 0x180)
163
+ FIELD(DMA_TX_CTL, EN, 0, 1)
164
+REG32(DMA_TX_DESC, 0x184)
165
+REG32(DMA_TX_STATUS, 0x188)
166
+ FIELD(DMA_TX_STATUS, PKTCNT, 16, 8)
167
+ FIELD(DMA_TX_STATUS, UNDERRUN, 1, 1)
168
+ FIELD(DMA_TX_STATUS, PKT_SENT, 0, 1)
169
+REG32(DMA_RX_CTL, 0x18c)
170
+ FIELD(DMA_RX_CTL, EN, 0, 1)
171
+REG32(DMA_RX_DESC, 0x190)
172
+REG32(DMA_RX_STATUS, 0x194)
173
+ FIELD(DMA_RX_STATUS, PKTCNT, 16, 8)
174
+ FIELD(DMA_RX_STATUS, OVERFLOW, 2, 1)
175
+ FIELD(DMA_RX_STATUS, PKT_RCVD, 0, 1)
176
+REG32(DMA_IRQ_MASK, 0x198)
177
+REG32(DMA_IRQ, 0x19c)
178
+
179
+#define EMPTY_MASK (1 << 31)
180
+#define PKT_SIZE 0x7FF
181
+#define PHYADDR 0x1
182
+#define MAX_PKT_SIZE 2048
183
+
184
+typedef struct {
185
+ uint32_t pktaddr;
186
+ uint32_t pktsize;
187
+ uint32_t next;
188
+} EmacDesc;
189
+
190
+static uint32_t emac_get_isr(MSF2EmacState *s)
191
+{
192
+ uint32_t ier = s->regs[R_DMA_IRQ_MASK];
193
+ uint32_t tx = s->regs[R_DMA_TX_STATUS] & 0xF;
194
+ uint32_t rx = s->regs[R_DMA_RX_STATUS] & 0xF;
195
+ uint32_t isr = (rx << 4) | tx;
196
+
197
+ s->regs[R_DMA_IRQ] = ier & isr;
198
+ return s->regs[R_DMA_IRQ];
199
+}
200
+
201
+static void emac_update_irq(MSF2EmacState *s)
202
+{
203
+ bool intr = emac_get_isr(s);
204
+
205
+ qemu_set_irq(s->irq, intr);
206
+}
207
+
208
+static void emac_load_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc)
209
+{
210
+ address_space_read(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, d, sizeof *d);
211
+ /* Convert from LE into host endianness. */
212
+ d->pktaddr = le32_to_cpu(d->pktaddr);
213
+ d->pktsize = le32_to_cpu(d->pktsize);
214
+ d->next = le32_to_cpu(d->next);
215
+}
216
+
217
+static void emac_store_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc)
218
+{
219
+ /* Convert from host endianness into LE. */
220
+ d->pktaddr = cpu_to_le32(d->pktaddr);
221
+ d->pktsize = cpu_to_le32(d->pktsize);
222
+ d->next = cpu_to_le32(d->next);
223
+
224
+ address_space_write(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, d, sizeof *d);
225
+}
226
+
227
+static void msf2_dma_tx(MSF2EmacState *s)
228
+{
229
+ NetClientState *nc = qemu_get_queue(s->nic);
230
+ hwaddr desc = s->regs[R_DMA_TX_DESC];
231
+ uint8_t buf[MAX_PKT_SIZE];
232
+ EmacDesc d;
233
+ int size;
234
+ uint8_t pktcnt;
235
+ uint32_t status;
236
+
237
+ if (!(s->regs[R_CFG1] & R_CFG1_TX_EN_MASK)) {
238
+ return;
239
+ }
240
+
241
+ while (1) {
242
+ emac_load_desc(s, &d, desc);
243
+ if (d.pktsize & EMPTY_MASK) {
244
+ break;
245
+ }
246
+ size = d.pktsize & PKT_SIZE;
247
+ address_space_read(&s->dma_as, d.pktaddr, MEMTXATTRS_UNSPECIFIED,
248
+ buf, size);
249
+ /*
250
+ * This is very basic way to send packets. Ideally there should be
251
+ * a FIFO and packets should be sent out from FIFO only when
252
+ * R_CFG1 bit 0 is set.
253
+ */
254
+ if (s->regs[R_CFG1] & R_CFG1_LB_EN_MASK) {
255
+ nc->info->receive(nc, buf, size);
256
+ } else {
257
+ qemu_send_packet(nc, buf, size);
258
+ }
259
+ d.pktsize |= EMPTY_MASK;
260
+ emac_store_desc(s, &d, desc);
261
+ /* update sent packets count */
262
+ status = s->regs[R_DMA_TX_STATUS];
263
+ pktcnt = FIELD_EX32(status, DMA_TX_STATUS, PKTCNT);
264
+ pktcnt++;
265
+ s->regs[R_DMA_TX_STATUS] = FIELD_DP32(status, DMA_TX_STATUS,
266
+ PKTCNT, pktcnt);
267
+ s->regs[R_DMA_TX_STATUS] |= R_DMA_TX_STATUS_PKT_SENT_MASK;
268
+ desc = d.next;
269
+ }
270
+ s->regs[R_DMA_TX_STATUS] |= R_DMA_TX_STATUS_UNDERRUN_MASK;
271
+ s->regs[R_DMA_TX_CTL] &= ~R_DMA_TX_CTL_EN_MASK;
272
+}
273
+
274
+static void msf2_phy_update_link(MSF2EmacState *s)
275
+{
276
+ /* Autonegotiation status mirrors link status. */
277
+ if (qemu_get_queue(s->nic)->link_down) {
278
+ s->phy_regs[MII_BMSR] &= ~(MII_BMSR_AN_COMP |
279
+ MII_BMSR_LINK_ST);
280
+ } else {
281
+ s->phy_regs[MII_BMSR] |= (MII_BMSR_AN_COMP |
282
+ MII_BMSR_LINK_ST);
283
+ }
284
+}
285
+
286
+static void msf2_phy_reset(MSF2EmacState *s)
287
+{
288
+ memset(&s->phy_regs[0], 0, sizeof(s->phy_regs));
289
+ s->phy_regs[MII_BMCR] = 0x1140;
290
+ s->phy_regs[MII_BMSR] = 0x7968;
291
+ s->phy_regs[MII_PHYID1] = 0x0022;
292
+ s->phy_regs[MII_PHYID2] = 0x1550;
293
+ s->phy_regs[MII_ANAR] = 0x01E1;
294
+ s->phy_regs[MII_ANLPAR] = 0xCDE1;
295
+
296
+ msf2_phy_update_link(s);
297
+}
298
+
299
+static void write_to_phy(MSF2EmacState *s)
300
+{
301
+ uint8_t reg_addr = s->regs[R_MII_ADDR] & R_MII_ADDR_REGADDR_MASK;
302
+ uint8_t phy_addr = (s->regs[R_MII_ADDR] >> R_MII_ADDR_PHYADDR_SHIFT) &
303
+ R_MII_ADDR_REGADDR_MASK;
304
+ uint16_t data = s->regs[R_MII_CTL] & 0xFFFF;
305
+
306
+ if (phy_addr != PHYADDR) {
307
+ return;
308
+ }
309
+
310
+ switch (reg_addr) {
311
+ case MII_BMCR:
312
+ if (data & MII_BMCR_RESET) {
313
+ /* Phy reset */
314
+ msf2_phy_reset(s);
315
+ data &= ~MII_BMCR_RESET;
316
+ }
317
+ if (data & MII_BMCR_AUTOEN) {
318
+ /* Complete autonegotiation immediately */
319
+ data &= ~MII_BMCR_AUTOEN;
320
+ s->phy_regs[MII_BMSR] |= MII_BMSR_AN_COMP;
321
+ }
322
+ break;
323
+ }
324
+
325
+ s->phy_regs[reg_addr] = data;
326
+}
327
+
328
+static uint16_t read_from_phy(MSF2EmacState *s)
329
+{
330
+ uint8_t reg_addr = s->regs[R_MII_ADDR] & R_MII_ADDR_REGADDR_MASK;
331
+ uint8_t phy_addr = (s->regs[R_MII_ADDR] >> R_MII_ADDR_PHYADDR_SHIFT) &
332
+ R_MII_ADDR_REGADDR_MASK;
333
+
334
+ if (phy_addr == PHYADDR) {
335
+ return s->phy_regs[reg_addr];
336
+ } else {
337
+ return 0xFFFF;
338
+ }
339
+}
340
+
341
+static void msf2_emac_do_reset(MSF2EmacState *s)
342
+{
343
+ memset(&s->regs[0], 0, sizeof(s->regs));
344
+ s->regs[R_CFG1] = 0x80000000;
345
+ s->regs[R_CFG2] = 0x00007000;
346
+ s->regs[R_IFG] = 0x40605060;
347
+ s->regs[R_HALF_DUPLEX] = 0x00A1F037;
348
+ s->regs[R_MAX_FRAME_LENGTH] = 0x00000600;
349
+ s->regs[R_FIFO_CFG5] = 0X3FFFF;
350
+
351
+ msf2_phy_reset(s);
352
+}
353
+
354
+static uint64_t emac_read(void *opaque, hwaddr addr, unsigned int size)
355
+{
356
+ MSF2EmacState *s = opaque;
357
+ uint32_t r = 0;
358
+
359
+ addr >>= 2;
360
+
361
+ switch (addr) {
362
+ case R_DMA_IRQ:
363
+ r = emac_get_isr(s);
364
+ break;
365
+ default:
366
+ if (addr >= ARRAY_SIZE(s->regs)) {
367
+ qemu_log_mask(LOG_GUEST_ERROR,
368
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
369
+ addr * 4);
370
+ return r;
371
+ }
372
+ r = s->regs[addr];
373
+ break;
374
+ }
375
+ return r;
376
+}
377
+
378
+static void emac_write(void *opaque, hwaddr addr, uint64_t val64,
379
+ unsigned int size)
380
+{
381
+ MSF2EmacState *s = opaque;
382
+ uint32_t value = val64;
383
+ uint32_t enreqbits;
384
+ uint8_t pktcnt;
385
+
386
+ addr >>= 2;
387
+ switch (addr) {
388
+ case R_DMA_TX_CTL:
389
+ s->regs[addr] = value;
390
+ if (value & R_DMA_TX_CTL_EN_MASK) {
391
+ msf2_dma_tx(s);
392
+ }
393
+ break;
394
+ case R_DMA_RX_CTL:
395
+ s->regs[addr] = value;
396
+ if (value & R_DMA_RX_CTL_EN_MASK) {
397
+ s->rx_desc = s->regs[R_DMA_RX_DESC];
398
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
399
+ }
400
+ break;
401
+ case R_CFG1:
402
+ s->regs[addr] = value;
403
+ if (value & R_CFG1_RESET_MASK) {
404
+ msf2_emac_do_reset(s);
405
+ }
406
+ break;
407
+ case R_FIFO_CFG0:
408
+ /*
409
+ * For our implementation, turning on modules is instantaneous,
410
+ * so the states requested via the *ENREQ bits appear in the
411
+ * *ENRPLY bits immediately. Also the reset bits to reset PE-MCXMAC
412
+ * module are not emulated here since it deals with start of frames,
413
+ * inter-packet gap and control frames.
414
+ */
415
+ enreqbits = extract32(value, 8, 5);
416
+ s->regs[addr] = deposit32(value, 16, 5, enreqbits);
417
+ break;
418
+ case R_DMA_TX_DESC:
419
+ if (value & 0x3) {
420
+ qemu_log_mask(LOG_GUEST_ERROR, "Tx Descriptor address should be"
421
+ " 32 bit aligned\n");
422
+ }
423
+ /* Ignore [1:0] bits */
424
+ s->regs[addr] = value & ~3;
425
+ break;
426
+ case R_DMA_RX_DESC:
427
+ if (value & 0x3) {
428
+ qemu_log_mask(LOG_GUEST_ERROR, "Rx Descriptor address should be"
429
+ " 32 bit aligned\n");
430
+ }
431
+ /* Ignore [1:0] bits */
432
+ s->regs[addr] = value & ~3;
433
+ break;
434
+ case R_DMA_TX_STATUS:
435
+ if (value & R_DMA_TX_STATUS_UNDERRUN_MASK) {
436
+ s->regs[addr] &= ~R_DMA_TX_STATUS_UNDERRUN_MASK;
437
+ }
438
+ if (value & R_DMA_TX_STATUS_PKT_SENT_MASK) {
439
+ pktcnt = FIELD_EX32(s->regs[addr], DMA_TX_STATUS, PKTCNT);
440
+ pktcnt--;
441
+ s->regs[addr] = FIELD_DP32(s->regs[addr], DMA_TX_STATUS,
442
+ PKTCNT, pktcnt);
443
+ if (pktcnt == 0) {
444
+ s->regs[addr] &= ~R_DMA_TX_STATUS_PKT_SENT_MASK;
45
+ }
445
+ }
46
+ }
446
+ }
47
+
447
+ break;
48
+ if (writeback && !postinc) {
448
+ case R_DMA_RX_STATUS:
49
+ tcg_gen_addi_i32(addr, addr, imm);
449
+ if (value & R_DMA_RX_STATUS_OVERFLOW_MASK) {
50
+ }
450
+ s->regs[addr] &= ~R_DMA_RX_STATUS_OVERFLOW_MASK;
51
+
451
+ }
52
if (insn & (1 << 20)) {
452
+ if (value & R_DMA_RX_STATUS_PKT_RCVD_MASK) {
53
/* Load. */
453
+ pktcnt = FIELD_EX32(s->regs[addr], DMA_RX_STATUS, PKTCNT);
54
tmp = tcg_temp_new_i32();
454
+ pktcnt--;
455
+ s->regs[addr] = FIELD_DP32(s->regs[addr], DMA_RX_STATUS,
456
+ PKTCNT, pktcnt);
457
+ if (pktcnt == 0) {
458
+ s->regs[addr] &= ~R_DMA_RX_STATUS_PKT_RCVD_MASK;
459
+ }
460
+ }
461
+ break;
462
+ case R_DMA_IRQ:
463
+ break;
464
+ case R_MII_CMD:
465
+ if (value & R_MII_CMD_READ_MASK) {
466
+ s->regs[R_MII_STS] = read_from_phy(s);
467
+ }
468
+ break;
469
+ case R_MII_CTL:
470
+ s->regs[addr] = value;
471
+ write_to_phy(s);
472
+ break;
473
+ case R_STA1:
474
+ s->regs[addr] = value;
475
+ /*
476
+ * R_STA1 [31:24] : octet 1 of mac address
477
+ * R_STA1 [23:16] : octet 2 of mac address
478
+ * R_STA1 [15:8] : octet 3 of mac address
479
+ * R_STA1 [7:0] : octet 4 of mac address
480
+ */
481
+ stl_be_p(s->mac_addr, value);
482
+ break;
483
+ case R_STA2:
484
+ s->regs[addr] = value;
485
+ /*
486
+ * R_STA2 [31:24] : octet 5 of mac address
487
+ * R_STA2 [23:16] : octet 6 of mac address
488
+ */
489
+ stw_be_p(s->mac_addr + 4, value >> 16);
490
+ break;
491
+ default:
492
+ if (addr >= ARRAY_SIZE(s->regs)) {
493
+ qemu_log_mask(LOG_GUEST_ERROR,
494
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
495
+ addr * 4);
496
+ return;
497
+ }
498
+ s->regs[addr] = value;
499
+ break;
500
+ }
501
+ emac_update_irq(s);
502
+}
503
+
504
+static const MemoryRegionOps emac_ops = {
505
+ .read = emac_read,
506
+ .write = emac_write,
507
+ .endianness = DEVICE_NATIVE_ENDIAN,
508
+ .impl = {
509
+ .min_access_size = 4,
510
+ .max_access_size = 4
511
+ }
512
+};
513
+
514
+static bool emac_can_rx(NetClientState *nc)
515
+{
516
+ MSF2EmacState *s = qemu_get_nic_opaque(nc);
517
+
518
+ return (s->regs[R_CFG1] & R_CFG1_RX_EN_MASK) &&
519
+ (s->regs[R_DMA_RX_CTL] & R_DMA_RX_CTL_EN_MASK);
520
+}
521
+
522
+static bool addr_filter_ok(MSF2EmacState *s, const uint8_t *buf)
523
+{
524
+ /* The broadcast MAC address: FF:FF:FF:FF:FF:FF */
525
+ const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF,
526
+ 0xFF, 0xFF };
527
+ bool bcast_en = true;
528
+ bool mcast_en = true;
529
+
530
+ if (s->regs[R_FIFO_CFG5] & R_FIFO_CFG5_BCAST_MASK) {
531
+ bcast_en = true; /* Broadcast dont care for drop circuitry */
532
+ } else if (s->regs[R_FIFO_CFG4] & R_FIFO_CFG4_BCAST_MASK) {
533
+ bcast_en = false;
534
+ }
535
+
536
+ if (s->regs[R_FIFO_CFG5] & R_FIFO_CFG5_MCAST_MASK) {
537
+ mcast_en = true; /* Multicast dont care for drop circuitry */
538
+ } else if (s->regs[R_FIFO_CFG4] & R_FIFO_CFG4_MCAST_MASK) {
539
+ mcast_en = false;
540
+ }
541
+
542
+ if (!memcmp(buf, broadcast_addr, sizeof(broadcast_addr))) {
543
+ return bcast_en;
544
+ }
545
+
546
+ if (buf[0] & 1) {
547
+ return mcast_en;
548
+ }
549
+
550
+ return !memcmp(buf, s->mac_addr, sizeof(s->mac_addr));
551
+}
552
+
553
+static ssize_t emac_rx(NetClientState *nc, const uint8_t *buf, size_t size)
554
+{
555
+ MSF2EmacState *s = qemu_get_nic_opaque(nc);
556
+ EmacDesc d;
557
+ uint8_t pktcnt;
558
+ uint32_t status;
559
+
560
+ if (size > (s->regs[R_MAX_FRAME_LENGTH] & 0xFFFF)) {
561
+ return size;
562
+ }
563
+ if (!addr_filter_ok(s, buf)) {
564
+ return size;
565
+ }
566
+
567
+ emac_load_desc(s, &d, s->rx_desc);
568
+
569
+ if (d.pktsize & EMPTY_MASK) {
570
+ address_space_write(&s->dma_as, d.pktaddr, MEMTXATTRS_UNSPECIFIED,
571
+ buf, size & PKT_SIZE);
572
+ d.pktsize = size & PKT_SIZE;
573
+ emac_store_desc(s, &d, s->rx_desc);
574
+ /* update received packets count */
575
+ status = s->regs[R_DMA_RX_STATUS];
576
+ pktcnt = FIELD_EX32(status, DMA_RX_STATUS, PKTCNT);
577
+ pktcnt++;
578
+ s->regs[R_DMA_RX_STATUS] = FIELD_DP32(status, DMA_RX_STATUS,
579
+ PKTCNT, pktcnt);
580
+ s->regs[R_DMA_RX_STATUS] |= R_DMA_RX_STATUS_PKT_RCVD_MASK;
581
+ s->rx_desc = d.next;
582
+ } else {
583
+ s->regs[R_DMA_RX_CTL] &= ~R_DMA_RX_CTL_EN_MASK;
584
+ s->regs[R_DMA_RX_STATUS] |= R_DMA_RX_STATUS_OVERFLOW_MASK;
585
+ }
586
+ emac_update_irq(s);
587
+ return size;
588
+}
589
+
590
+static void msf2_emac_reset(DeviceState *dev)
591
+{
592
+ MSF2EmacState *s = MSS_EMAC(dev);
593
+
594
+ msf2_emac_do_reset(s);
595
+}
596
+
597
+static void emac_set_link(NetClientState *nc)
598
+{
599
+ MSF2EmacState *s = qemu_get_nic_opaque(nc);
600
+
601
+ msf2_phy_update_link(s);
602
+}
603
+
604
+static NetClientInfo net_msf2_emac_info = {
605
+ .type = NET_CLIENT_DRIVER_NIC,
606
+ .size = sizeof(NICState),
607
+ .can_receive = emac_can_rx,
608
+ .receive = emac_rx,
609
+ .link_status_changed = emac_set_link,
610
+};
611
+
612
+static void msf2_emac_realize(DeviceState *dev, Error **errp)
613
+{
614
+ MSF2EmacState *s = MSS_EMAC(dev);
615
+
616
+ if (!s->dma_mr) {
617
+ error_setg(errp, "MSS_EMAC 'ahb-bus' link not set");
618
+ return;
619
+ }
620
+
621
+ address_space_init(&s->dma_as, s->dma_mr, "emac-ahb");
622
+
623
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
624
+ s->nic = qemu_new_nic(&net_msf2_emac_info, &s->conf,
625
+ object_get_typename(OBJECT(dev)), dev->id, s);
626
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
627
+}
628
+
629
+static void msf2_emac_init(Object *obj)
630
+{
631
+ MSF2EmacState *s = MSS_EMAC(obj);
632
+
633
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
634
+
635
+ memory_region_init_io(&s->mmio, obj, &emac_ops, s,
636
+ "msf2-emac", R_MAX * 4);
637
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
638
+}
639
+
640
+static Property msf2_emac_properties[] = {
641
+ DEFINE_PROP_LINK("ahb-bus", MSF2EmacState, dma_mr,
642
+ TYPE_MEMORY_REGION, MemoryRegion *),
643
+ DEFINE_NIC_PROPERTIES(MSF2EmacState, conf),
644
+ DEFINE_PROP_END_OF_LIST(),
645
+};
646
+
647
+static const VMStateDescription vmstate_msf2_emac = {
648
+ .name = TYPE_MSS_EMAC,
649
+ .version_id = 1,
650
+ .minimum_version_id = 1,
651
+ .fields = (VMStateField[]) {
652
+ VMSTATE_UINT8_ARRAY(mac_addr, MSF2EmacState, ETH_ALEN),
653
+ VMSTATE_UINT32(rx_desc, MSF2EmacState),
654
+ VMSTATE_UINT16_ARRAY(phy_regs, MSF2EmacState, PHY_MAX_REGS),
655
+ VMSTATE_UINT32_ARRAY(regs, MSF2EmacState, R_MAX),
656
+ VMSTATE_END_OF_LIST()
657
+ }
658
+};
659
+
660
+static void msf2_emac_class_init(ObjectClass *klass, void *data)
661
+{
662
+ DeviceClass *dc = DEVICE_CLASS(klass);
663
+
664
+ dc->realize = msf2_emac_realize;
665
+ dc->reset = msf2_emac_reset;
666
+ dc->vmsd = &vmstate_msf2_emac;
667
+ device_class_set_props(dc, msf2_emac_properties);
668
+}
669
+
670
+static const TypeInfo msf2_emac_info = {
671
+ .name = TYPE_MSS_EMAC,
672
+ .parent = TYPE_SYS_BUS_DEVICE,
673
+ .instance_size = sizeof(MSF2EmacState),
674
+ .instance_init = msf2_emac_init,
675
+ .class_init = msf2_emac_class_init,
676
+};
677
+
678
+static void msf2_emac_register_types(void)
679
+{
680
+ type_register_static(&msf2_emac_info);
681
+}
682
+
683
+type_init(msf2_emac_register_types)
684
diff --git a/MAINTAINERS b/MAINTAINERS
685
index XXXXXXX..XXXXXXX 100644
686
--- a/MAINTAINERS
687
+++ b/MAINTAINERS
688
@@ -XXX,XX +XXX,XX @@ F: include/hw/arm/msf2-soc.h
689
F: include/hw/misc/msf2-sysreg.h
690
F: include/hw/timer/mss-timer.h
691
F: include/hw/ssi/mss-spi.h
692
+F: hw/net/msf2-emac.c
693
+F: include/hw/net/msf2-emac.h
694
695
Emcraft M2S-FG484
696
M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
55
--
697
--
56
2.19.0
698
2.20.1
57
699
58
700
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Subbaraya Sundeep <sundeep.lkml@gmail.com>
2
2
3
This fixes the endianness problem for softmmu, and moves
3
With SmartFusion2 Ethernet MAC model in
4
the main loop out of a macro and into an inlined function.
4
place this patch adds the same to SoC.
5
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20181005175350.30752-13-richard.henderson@linaro.org
9
Message-id: 1587048891-30493-3-git-send-email-sundeep.lkml@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/helper-sve.h | 84 +++++++++----
12
include/hw/arm/msf2-soc.h | 2 ++
13
target/arm/sve_helper.c | 225 ++++++++++++++++++++++++----------
13
hw/arm/msf2-soc.c | 26 ++++++++++++++++++++++++--
14
target/arm/translate-sve.c | 244 +++++++++++++++++++++++++------------
14
2 files changed, 26 insertions(+), 2 deletions(-)
15
3 files changed, 386 insertions(+), 167 deletions(-)
16
15
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
16
diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-sve.h
18
--- a/include/hw/arm/msf2-soc.h
20
+++ b/target/arm/helper-sve.h
19
+++ b/include/hw/arm/msf2-soc.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_st1sd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
20
@@ -XXX,XX +XXX,XX @@
22
21
#include "hw/timer/mss-timer.h"
23
DEF_HELPER_FLAGS_6(sve_ldbsu_zsu, TCG_CALL_NO_WG,
22
#include "hw/misc/msf2-sysreg.h"
24
void, env, ptr, ptr, ptr, tl, i32)
23
#include "hw/ssi/mss-spi.h"
25
-DEF_HELPER_FLAGS_6(sve_ldhsu_zsu, TCG_CALL_NO_WG,
24
+#include "hw/net/msf2-emac.h"
26
+DEF_HELPER_FLAGS_6(sve_ldhsu_le_zsu, TCG_CALL_NO_WG,
25
27
void, env, ptr, ptr, ptr, tl, i32)
26
#define TYPE_MSF2_SOC "msf2-soc"
28
-DEF_HELPER_FLAGS_6(sve_ldssu_zsu, TCG_CALL_NO_WG,
27
#define MSF2_SOC(obj) OBJECT_CHECK(MSF2State, (obj), TYPE_MSF2_SOC)
29
+DEF_HELPER_FLAGS_6(sve_ldhsu_be_zsu, TCG_CALL_NO_WG,
28
@@ -XXX,XX +XXX,XX @@ typedef struct MSF2State {
30
+ void, env, ptr, ptr, ptr, tl, i32)
29
MSF2SysregState sysreg;
31
+DEF_HELPER_FLAGS_6(sve_ldss_le_zsu, TCG_CALL_NO_WG,
30
MSSTimerState timer;
32
+ void, env, ptr, ptr, ptr, tl, i32)
31
MSSSpiState spi[MSF2_NUM_SPIS];
33
+DEF_HELPER_FLAGS_6(sve_ldss_be_zsu, TCG_CALL_NO_WG,
32
+ MSF2EmacState emac;
34
void, env, ptr, ptr, ptr, tl, i32)
33
} MSF2State;
35
DEF_HELPER_FLAGS_6(sve_ldbss_zsu, TCG_CALL_NO_WG,
34
36
void, env, ptr, ptr, ptr, tl, i32)
35
#endif
37
-DEF_HELPER_FLAGS_6(sve_ldhss_zsu, TCG_CALL_NO_WG,
36
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
38
+DEF_HELPER_FLAGS_6(sve_ldhss_le_zsu, TCG_CALL_NO_WG,
39
+ void, env, ptr, ptr, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_6(sve_ldhss_be_zsu, TCG_CALL_NO_WG,
41
void, env, ptr, ptr, ptr, tl, i32)
42
43
DEF_HELPER_FLAGS_6(sve_ldbsu_zss, TCG_CALL_NO_WG,
44
void, env, ptr, ptr, ptr, tl, i32)
45
-DEF_HELPER_FLAGS_6(sve_ldhsu_zss, TCG_CALL_NO_WG,
46
+DEF_HELPER_FLAGS_6(sve_ldhsu_le_zss, TCG_CALL_NO_WG,
47
void, env, ptr, ptr, ptr, tl, i32)
48
-DEF_HELPER_FLAGS_6(sve_ldssu_zss, TCG_CALL_NO_WG,
49
+DEF_HELPER_FLAGS_6(sve_ldhsu_be_zss, TCG_CALL_NO_WG,
50
+ void, env, ptr, ptr, ptr, tl, i32)
51
+DEF_HELPER_FLAGS_6(sve_ldss_le_zss, TCG_CALL_NO_WG,
52
+ void, env, ptr, ptr, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_6(sve_ldss_be_zss, TCG_CALL_NO_WG,
54
void, env, ptr, ptr, ptr, tl, i32)
55
DEF_HELPER_FLAGS_6(sve_ldbss_zss, TCG_CALL_NO_WG,
56
void, env, ptr, ptr, ptr, tl, i32)
57
-DEF_HELPER_FLAGS_6(sve_ldhss_zss, TCG_CALL_NO_WG,
58
+DEF_HELPER_FLAGS_6(sve_ldhss_le_zss, TCG_CALL_NO_WG,
59
+ void, env, ptr, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_6(sve_ldhss_be_zss, TCG_CALL_NO_WG,
61
void, env, ptr, ptr, ptr, tl, i32)
62
63
DEF_HELPER_FLAGS_6(sve_ldbdu_zsu, TCG_CALL_NO_WG,
64
void, env, ptr, ptr, ptr, tl, i32)
65
-DEF_HELPER_FLAGS_6(sve_ldhdu_zsu, TCG_CALL_NO_WG,
66
+DEF_HELPER_FLAGS_6(sve_ldhdu_le_zsu, TCG_CALL_NO_WG,
67
void, env, ptr, ptr, ptr, tl, i32)
68
-DEF_HELPER_FLAGS_6(sve_ldsdu_zsu, TCG_CALL_NO_WG,
69
+DEF_HELPER_FLAGS_6(sve_ldhdu_be_zsu, TCG_CALL_NO_WG,
70
void, env, ptr, ptr, ptr, tl, i32)
71
-DEF_HELPER_FLAGS_6(sve_ldddu_zsu, TCG_CALL_NO_WG,
72
+DEF_HELPER_FLAGS_6(sve_ldsdu_le_zsu, TCG_CALL_NO_WG,
73
+ void, env, ptr, ptr, ptr, tl, i32)
74
+DEF_HELPER_FLAGS_6(sve_ldsdu_be_zsu, TCG_CALL_NO_WG,
75
+ void, env, ptr, ptr, ptr, tl, i32)
76
+DEF_HELPER_FLAGS_6(sve_lddd_le_zsu, TCG_CALL_NO_WG,
77
+ void, env, ptr, ptr, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_6(sve_lddd_be_zsu, TCG_CALL_NO_WG,
79
void, env, ptr, ptr, ptr, tl, i32)
80
DEF_HELPER_FLAGS_6(sve_ldbds_zsu, TCG_CALL_NO_WG,
81
void, env, ptr, ptr, ptr, tl, i32)
82
-DEF_HELPER_FLAGS_6(sve_ldhds_zsu, TCG_CALL_NO_WG,
83
+DEF_HELPER_FLAGS_6(sve_ldhds_le_zsu, TCG_CALL_NO_WG,
84
void, env, ptr, ptr, ptr, tl, i32)
85
-DEF_HELPER_FLAGS_6(sve_ldsds_zsu, TCG_CALL_NO_WG,
86
+DEF_HELPER_FLAGS_6(sve_ldhds_be_zsu, TCG_CALL_NO_WG,
87
+ void, env, ptr, ptr, ptr, tl, i32)
88
+DEF_HELPER_FLAGS_6(sve_ldsds_le_zsu, TCG_CALL_NO_WG,
89
+ void, env, ptr, ptr, ptr, tl, i32)
90
+DEF_HELPER_FLAGS_6(sve_ldsds_be_zsu, TCG_CALL_NO_WG,
91
void, env, ptr, ptr, ptr, tl, i32)
92
93
DEF_HELPER_FLAGS_6(sve_ldbdu_zss, TCG_CALL_NO_WG,
94
void, env, ptr, ptr, ptr, tl, i32)
95
-DEF_HELPER_FLAGS_6(sve_ldhdu_zss, TCG_CALL_NO_WG,
96
+DEF_HELPER_FLAGS_6(sve_ldhdu_le_zss, TCG_CALL_NO_WG,
97
void, env, ptr, ptr, ptr, tl, i32)
98
-DEF_HELPER_FLAGS_6(sve_ldsdu_zss, TCG_CALL_NO_WG,
99
+DEF_HELPER_FLAGS_6(sve_ldhdu_be_zss, TCG_CALL_NO_WG,
100
void, env, ptr, ptr, ptr, tl, i32)
101
-DEF_HELPER_FLAGS_6(sve_ldddu_zss, TCG_CALL_NO_WG,
102
+DEF_HELPER_FLAGS_6(sve_ldsdu_le_zss, TCG_CALL_NO_WG,
103
+ void, env, ptr, ptr, ptr, tl, i32)
104
+DEF_HELPER_FLAGS_6(sve_ldsdu_be_zss, TCG_CALL_NO_WG,
105
+ void, env, ptr, ptr, ptr, tl, i32)
106
+DEF_HELPER_FLAGS_6(sve_lddd_le_zss, TCG_CALL_NO_WG,
107
+ void, env, ptr, ptr, ptr, tl, i32)
108
+DEF_HELPER_FLAGS_6(sve_lddd_be_zss, TCG_CALL_NO_WG,
109
void, env, ptr, ptr, ptr, tl, i32)
110
DEF_HELPER_FLAGS_6(sve_ldbds_zss, TCG_CALL_NO_WG,
111
void, env, ptr, ptr, ptr, tl, i32)
112
-DEF_HELPER_FLAGS_6(sve_ldhds_zss, TCG_CALL_NO_WG,
113
+DEF_HELPER_FLAGS_6(sve_ldhds_le_zss, TCG_CALL_NO_WG,
114
void, env, ptr, ptr, ptr, tl, i32)
115
-DEF_HELPER_FLAGS_6(sve_ldsds_zss, TCG_CALL_NO_WG,
116
+DEF_HELPER_FLAGS_6(sve_ldhds_be_zss, TCG_CALL_NO_WG,
117
+ void, env, ptr, ptr, ptr, tl, i32)
118
+DEF_HELPER_FLAGS_6(sve_ldsds_le_zss, TCG_CALL_NO_WG,
119
+ void, env, ptr, ptr, ptr, tl, i32)
120
+DEF_HELPER_FLAGS_6(sve_ldsds_be_zss, TCG_CALL_NO_WG,
121
void, env, ptr, ptr, ptr, tl, i32)
122
123
DEF_HELPER_FLAGS_6(sve_ldbdu_zd, TCG_CALL_NO_WG,
124
void, env, ptr, ptr, ptr, tl, i32)
125
-DEF_HELPER_FLAGS_6(sve_ldhdu_zd, TCG_CALL_NO_WG,
126
+DEF_HELPER_FLAGS_6(sve_ldhdu_le_zd, TCG_CALL_NO_WG,
127
void, env, ptr, ptr, ptr, tl, i32)
128
-DEF_HELPER_FLAGS_6(sve_ldsdu_zd, TCG_CALL_NO_WG,
129
+DEF_HELPER_FLAGS_6(sve_ldhdu_be_zd, TCG_CALL_NO_WG,
130
void, env, ptr, ptr, ptr, tl, i32)
131
-DEF_HELPER_FLAGS_6(sve_ldddu_zd, TCG_CALL_NO_WG,
132
+DEF_HELPER_FLAGS_6(sve_ldsdu_le_zd, TCG_CALL_NO_WG,
133
+ void, env, ptr, ptr, ptr, tl, i32)
134
+DEF_HELPER_FLAGS_6(sve_ldsdu_be_zd, TCG_CALL_NO_WG,
135
+ void, env, ptr, ptr, ptr, tl, i32)
136
+DEF_HELPER_FLAGS_6(sve_lddd_le_zd, TCG_CALL_NO_WG,
137
+ void, env, ptr, ptr, ptr, tl, i32)
138
+DEF_HELPER_FLAGS_6(sve_lddd_be_zd, TCG_CALL_NO_WG,
139
void, env, ptr, ptr, ptr, tl, i32)
140
DEF_HELPER_FLAGS_6(sve_ldbds_zd, TCG_CALL_NO_WG,
141
void, env, ptr, ptr, ptr, tl, i32)
142
-DEF_HELPER_FLAGS_6(sve_ldhds_zd, TCG_CALL_NO_WG,
143
+DEF_HELPER_FLAGS_6(sve_ldhds_le_zd, TCG_CALL_NO_WG,
144
void, env, ptr, ptr, ptr, tl, i32)
145
-DEF_HELPER_FLAGS_6(sve_ldsds_zd, TCG_CALL_NO_WG,
146
+DEF_HELPER_FLAGS_6(sve_ldhds_be_zd, TCG_CALL_NO_WG,
147
+ void, env, ptr, ptr, ptr, tl, i32)
148
+DEF_HELPER_FLAGS_6(sve_ldsds_le_zd, TCG_CALL_NO_WG,
149
+ void, env, ptr, ptr, ptr, tl, i32)
150
+DEF_HELPER_FLAGS_6(sve_ldsds_be_zd, TCG_CALL_NO_WG,
151
void, env, ptr, ptr, ptr, tl, i32)
152
153
DEF_HELPER_FLAGS_6(sve_ldffbsu_zsu, TCG_CALL_NO_WG,
154
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
155
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
156
--- a/target/arm/sve_helper.c
38
--- a/hw/arm/msf2-soc.c
157
+++ b/target/arm/sve_helper.c
39
+++ b/hw/arm/msf2-soc.c
158
@@ -XXX,XX +XXX,XX @@ DO_STN_2(4, dd, 8, 8)
40
@@ -XXX,XX +XXX,XX @@
159
#undef DO_STN_1
41
/*
160
#undef DO_STN_2
42
* SmartFusion2 SoC emulation.
161
43
*
162
-/* Loads with a vector index. */
44
- * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
163
+/*
45
+ * Copyright (c) 2017-2020 Subbaraya Sundeep <sundeep.lkml@gmail.com>
164
+ * Loads with a vector index.
46
*
165
+ */
47
* Permission is hereby granted, free of charge, to any person obtaining a copy
166
48
* of this software and associated documentation files (the "Software"), to deal
167
-#define DO_LD1_ZPZ_S(NAME, TYPEI, TYPEM, FN) \
49
@@ -XXX,XX +XXX,XX @@
168
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
50
169
- target_ulong base, uint32_t desc) \
51
#define MSF2_TIMER_BASE 0x40004000
170
-{ \
52
#define MSF2_SYSREG_BASE 0x40038000
171
- intptr_t i, oprsz = simd_oprsz(desc); \
53
+#define MSF2_EMAC_BASE 0x40041000
172
- unsigned scale = simd_data(desc); \
54
173
- uintptr_t ra = GETPC(); \
55
#define ENVM_BASE_ADDRESS 0x60000000
174
- for (i = 0; i < oprsz; ) { \
56
175
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
57
#define SRAM_BASE_ADDRESS 0x20000000
176
- do { \
58
177
- TYPEM m = 0; \
59
+#define MSF2_EMAC_IRQ 12
178
- if (pg & 1) { \
179
- target_ulong off = *(TYPEI *)(vm + H1_4(i)); \
180
- m = FN(env, base + (off << scale), ra); \
181
- } \
182
- *(uint32_t *)(vd + H1_4(i)) = m; \
183
- i += 4, pg >>= 4; \
184
- } while (i & 15); \
185
- } \
186
+/*
187
+ * Load the element at @reg + @reg_ofs, sign or zero-extend as needed.
188
+ */
189
+typedef target_ulong zreg_off_fn(void *reg, intptr_t reg_ofs);
190
+
60
+
191
+static target_ulong off_zsu_s(void *reg, intptr_t reg_ofs)
61
#define MSF2_ENVM_MAX_SIZE (512 * KiB)
192
+{
62
193
+ return *(uint32_t *)(reg + H1_4(reg_ofs));
63
/*
64
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_initfn(Object *obj)
65
sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
66
TYPE_MSS_SPI);
67
}
68
+
69
+ sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac),
70
+ TYPE_MSS_EMAC);
71
+ if (nd_table[0].used) {
72
+ qemu_check_nic_model(&nd_table[0], TYPE_MSS_EMAC);
73
+ qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]);
74
+ }
194
}
75
}
195
76
196
-#define DO_LD1_ZPZ_D(NAME, TYPEI, TYPEM, FN) \
77
static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
197
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
78
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
198
- target_ulong base, uint32_t desc) \
79
g_free(bus_name);
199
-{ \
80
}
200
- intptr_t i, oprsz = simd_oprsz(desc) / 8; \
81
201
- unsigned scale = simd_data(desc); \
82
+ dev = DEVICE(&s->emac);
202
- uintptr_t ra = GETPC(); \
83
+ object_property_set_link(OBJECT(&s->emac), OBJECT(get_system_memory()),
203
- uint64_t *d = vd, *m = vm; uint8_t *pg = vg; \
84
+ "ahb-bus", &error_abort);
204
- for (i = 0; i < oprsz; i++) { \
85
+ object_property_set_bool(OBJECT(&s->emac), true, "realized", &err);
205
- TYPEM mm = 0; \
86
+ if (err != NULL) {
206
- if (pg[H1(i)] & 1) { \
87
+ error_propagate(errp, err);
207
- target_ulong off = (TYPEI)m[i]; \
88
+ return;
208
- mm = FN(env, base + (off << scale), ra); \
89
+ }
209
- } \
90
+ busdev = SYS_BUS_DEVICE(dev);
210
- d[i] = mm; \
91
+ sysbus_mmio_map(busdev, 0, MSF2_EMAC_BASE);
211
- } \
92
+ sysbus_connect_irq(busdev, 0,
212
+static target_ulong off_zss_s(void *reg, intptr_t reg_ofs)
93
+ qdev_get_gpio_in(armv7m, MSF2_EMAC_IRQ));
213
+{
94
+
214
+ return *(int32_t *)(reg + H1_4(reg_ofs));
95
/* Below devices are not modelled yet. */
96
create_unimplemented_device("i2c_0", 0x40002000, 0x1000);
97
create_unimplemented_device("dma", 0x40003000, 0x1000);
98
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
99
create_unimplemented_device("can", 0x40015000, 0x1000);
100
create_unimplemented_device("rtc", 0x40017000, 0x1000);
101
create_unimplemented_device("apb_config", 0x40020000, 0x10000);
102
- create_unimplemented_device("emac", 0x40041000, 0x1000);
103
create_unimplemented_device("usb", 0x40043000, 0x1000);
215
}
104
}
216
105
217
-DO_LD1_ZPZ_S(sve_ldbsu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
218
-DO_LD1_ZPZ_S(sve_ldhsu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
219
-DO_LD1_ZPZ_S(sve_ldssu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
220
-DO_LD1_ZPZ_S(sve_ldbss_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
221
-DO_LD1_ZPZ_S(sve_ldhss_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
222
+static target_ulong off_zsu_d(void *reg, intptr_t reg_ofs)
223
+{
224
+ return (uint32_t)*(uint64_t *)(reg + reg_ofs);
225
+}
226
227
-DO_LD1_ZPZ_S(sve_ldbsu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
228
-DO_LD1_ZPZ_S(sve_ldhsu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
229
-DO_LD1_ZPZ_S(sve_ldssu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
230
-DO_LD1_ZPZ_S(sve_ldbss_zss, int32_t, int8_t, cpu_ldub_data_ra)
231
-DO_LD1_ZPZ_S(sve_ldhss_zss, int32_t, int16_t, cpu_lduw_data_ra)
232
+static target_ulong off_zss_d(void *reg, intptr_t reg_ofs)
233
+{
234
+ return (int32_t)*(uint64_t *)(reg + reg_ofs);
235
+}
236
237
-DO_LD1_ZPZ_D(sve_ldbdu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
238
-DO_LD1_ZPZ_D(sve_ldhdu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
239
-DO_LD1_ZPZ_D(sve_ldsdu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
240
-DO_LD1_ZPZ_D(sve_ldddu_zsu, uint32_t, uint64_t, cpu_ldq_data_ra)
241
-DO_LD1_ZPZ_D(sve_ldbds_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
242
-DO_LD1_ZPZ_D(sve_ldhds_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
243
-DO_LD1_ZPZ_D(sve_ldsds_zsu, uint32_t, int32_t, cpu_ldl_data_ra)
244
+static target_ulong off_zd_d(void *reg, intptr_t reg_ofs)
245
+{
246
+ return *(uint64_t *)(reg + reg_ofs);
247
+}
248
249
-DO_LD1_ZPZ_D(sve_ldbdu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
250
-DO_LD1_ZPZ_D(sve_ldhdu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
251
-DO_LD1_ZPZ_D(sve_ldsdu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
252
-DO_LD1_ZPZ_D(sve_ldddu_zss, int32_t, uint64_t, cpu_ldq_data_ra)
253
-DO_LD1_ZPZ_D(sve_ldbds_zss, int32_t, int8_t, cpu_ldub_data_ra)
254
-DO_LD1_ZPZ_D(sve_ldhds_zss, int32_t, int16_t, cpu_lduw_data_ra)
255
-DO_LD1_ZPZ_D(sve_ldsds_zss, int32_t, int32_t, cpu_ldl_data_ra)
256
+static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
257
+ target_ulong base, uint32_t desc, uintptr_t ra,
258
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
259
+{
260
+ const int mmu_idx = cpu_mmu_index(env, false);
261
+ intptr_t i, oprsz = simd_oprsz(desc);
262
+ unsigned scale = simd_data(desc);
263
+ ARMVectorReg scratch = { };
264
265
-DO_LD1_ZPZ_D(sve_ldbdu_zd, uint64_t, uint8_t, cpu_ldub_data_ra)
266
-DO_LD1_ZPZ_D(sve_ldhdu_zd, uint64_t, uint16_t, cpu_lduw_data_ra)
267
-DO_LD1_ZPZ_D(sve_ldsdu_zd, uint64_t, uint32_t, cpu_ldl_data_ra)
268
-DO_LD1_ZPZ_D(sve_ldddu_zd, uint64_t, uint64_t, cpu_ldq_data_ra)
269
-DO_LD1_ZPZ_D(sve_ldbds_zd, uint64_t, int8_t, cpu_ldub_data_ra)
270
-DO_LD1_ZPZ_D(sve_ldhds_zd, uint64_t, int16_t, cpu_lduw_data_ra)
271
-DO_LD1_ZPZ_D(sve_ldsds_zd, uint64_t, int32_t, cpu_ldl_data_ra)
272
+ set_helper_retaddr(ra);
273
+ for (i = 0; i < oprsz; ) {
274
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
275
+ do {
276
+ if (likely(pg & 1)) {
277
+ target_ulong off = off_fn(vm, i);
278
+ tlb_fn(env, &scratch, i, base + (off << scale), mmu_idx, ra);
279
+ }
280
+ i += 4, pg >>= 4;
281
+ } while (i & 15);
282
+ }
283
+ set_helper_retaddr(0);
284
+
285
+ /* Wait until all exceptions have been raised to write back. */
286
+ memcpy(vd, &scratch, oprsz);
287
+}
288
+
289
+static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
290
+ target_ulong base, uint32_t desc, uintptr_t ra,
291
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
292
+{
293
+ const int mmu_idx = cpu_mmu_index(env, false);
294
+ intptr_t i, oprsz = simd_oprsz(desc) / 8;
295
+ unsigned scale = simd_data(desc);
296
+ ARMVectorReg scratch = { };
297
+
298
+ set_helper_retaddr(ra);
299
+ for (i = 0; i < oprsz; i++) {
300
+ uint8_t pg = *(uint8_t *)(vg + H1(i));
301
+ if (likely(pg & 1)) {
302
+ target_ulong off = off_fn(vm, i * 8);
303
+ tlb_fn(env, &scratch, i * 8, base + (off << scale), mmu_idx, ra);
304
+ }
305
+ }
306
+ set_helper_retaddr(0);
307
+
308
+ /* Wait until all exceptions have been raised to write back. */
309
+ memcpy(vd, &scratch, oprsz * 8);
310
+}
311
+
312
+#define DO_LD1_ZPZ_S(MEM, OFS) \
313
+void __attribute__((flatten)) HELPER(sve_ld##MEM##_##OFS) \
314
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
315
+ target_ulong base, uint32_t desc) \
316
+{ \
317
+ sve_ld1_zs(env, vd, vg, vm, base, desc, GETPC(), \
318
+ off_##OFS##_s, sve_ld1##MEM##_tlb); \
319
+}
320
+
321
+#define DO_LD1_ZPZ_D(MEM, OFS) \
322
+void __attribute__((flatten)) HELPER(sve_ld##MEM##_##OFS) \
323
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
324
+ target_ulong base, uint32_t desc) \
325
+{ \
326
+ sve_ld1_zd(env, vd, vg, vm, base, desc, GETPC(), \
327
+ off_##OFS##_d, sve_ld1##MEM##_tlb); \
328
+}
329
+
330
+DO_LD1_ZPZ_S(bsu, zsu)
331
+DO_LD1_ZPZ_S(bsu, zss)
332
+DO_LD1_ZPZ_D(bdu, zsu)
333
+DO_LD1_ZPZ_D(bdu, zss)
334
+DO_LD1_ZPZ_D(bdu, zd)
335
+
336
+DO_LD1_ZPZ_S(bss, zsu)
337
+DO_LD1_ZPZ_S(bss, zss)
338
+DO_LD1_ZPZ_D(bds, zsu)
339
+DO_LD1_ZPZ_D(bds, zss)
340
+DO_LD1_ZPZ_D(bds, zd)
341
+
342
+DO_LD1_ZPZ_S(hsu_le, zsu)
343
+DO_LD1_ZPZ_S(hsu_le, zss)
344
+DO_LD1_ZPZ_D(hdu_le, zsu)
345
+DO_LD1_ZPZ_D(hdu_le, zss)
346
+DO_LD1_ZPZ_D(hdu_le, zd)
347
+
348
+DO_LD1_ZPZ_S(hsu_be, zsu)
349
+DO_LD1_ZPZ_S(hsu_be, zss)
350
+DO_LD1_ZPZ_D(hdu_be, zsu)
351
+DO_LD1_ZPZ_D(hdu_be, zss)
352
+DO_LD1_ZPZ_D(hdu_be, zd)
353
+
354
+DO_LD1_ZPZ_S(hss_le, zsu)
355
+DO_LD1_ZPZ_S(hss_le, zss)
356
+DO_LD1_ZPZ_D(hds_le, zsu)
357
+DO_LD1_ZPZ_D(hds_le, zss)
358
+DO_LD1_ZPZ_D(hds_le, zd)
359
+
360
+DO_LD1_ZPZ_S(hss_be, zsu)
361
+DO_LD1_ZPZ_S(hss_be, zss)
362
+DO_LD1_ZPZ_D(hds_be, zsu)
363
+DO_LD1_ZPZ_D(hds_be, zss)
364
+DO_LD1_ZPZ_D(hds_be, zd)
365
+
366
+DO_LD1_ZPZ_S(ss_le, zsu)
367
+DO_LD1_ZPZ_S(ss_le, zss)
368
+DO_LD1_ZPZ_D(sdu_le, zsu)
369
+DO_LD1_ZPZ_D(sdu_le, zss)
370
+DO_LD1_ZPZ_D(sdu_le, zd)
371
+
372
+DO_LD1_ZPZ_S(ss_be, zsu)
373
+DO_LD1_ZPZ_S(ss_be, zss)
374
+DO_LD1_ZPZ_D(sdu_be, zsu)
375
+DO_LD1_ZPZ_D(sdu_be, zss)
376
+DO_LD1_ZPZ_D(sdu_be, zd)
377
+
378
+DO_LD1_ZPZ_D(sds_le, zsu)
379
+DO_LD1_ZPZ_D(sds_le, zss)
380
+DO_LD1_ZPZ_D(sds_le, zd)
381
+
382
+DO_LD1_ZPZ_D(sds_be, zsu)
383
+DO_LD1_ZPZ_D(sds_be, zss)
384
+DO_LD1_ZPZ_D(sds_be, zd)
385
+
386
+DO_LD1_ZPZ_D(dd_le, zsu)
387
+DO_LD1_ZPZ_D(dd_le, zss)
388
+DO_LD1_ZPZ_D(dd_le, zd)
389
+
390
+DO_LD1_ZPZ_D(dd_be, zsu)
391
+DO_LD1_ZPZ_D(dd_be, zss)
392
+DO_LD1_ZPZ_D(dd_be, zd)
393
+
394
+#undef DO_LD1_ZPZ_S
395
+#undef DO_LD1_ZPZ_D
396
397
/* First fault loads with a vector index. */
398
399
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
400
index XXXXXXX..XXXXXXX 100644
401
--- a/target/arm/translate-sve.c
402
+++ b/target/arm/translate-sve.c
403
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, int scale,
404
tcg_temp_free_i32(desc);
405
}
406
407
-/* Indexed by [ff][xs][u][msz]. */
408
-static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][3] = {
409
- { { { gen_helper_sve_ldbss_zsu,
410
- gen_helper_sve_ldhss_zsu,
411
- NULL, },
412
- { gen_helper_sve_ldbsu_zsu,
413
- gen_helper_sve_ldhsu_zsu,
414
- gen_helper_sve_ldssu_zsu, } },
415
- { { gen_helper_sve_ldbss_zss,
416
- gen_helper_sve_ldhss_zss,
417
- NULL, },
418
- { gen_helper_sve_ldbsu_zss,
419
- gen_helper_sve_ldhsu_zss,
420
- gen_helper_sve_ldssu_zss, } } },
421
+/* Indexed by [be][ff][xs][u][msz]. */
422
+static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][2][3] = {
423
+ /* Little-endian */
424
+ { { { { gen_helper_sve_ldbss_zsu,
425
+ gen_helper_sve_ldhss_le_zsu,
426
+ NULL, },
427
+ { gen_helper_sve_ldbsu_zsu,
428
+ gen_helper_sve_ldhsu_le_zsu,
429
+ gen_helper_sve_ldss_le_zsu, } },
430
+ { { gen_helper_sve_ldbss_zss,
431
+ gen_helper_sve_ldhss_le_zss,
432
+ NULL, },
433
+ { gen_helper_sve_ldbsu_zss,
434
+ gen_helper_sve_ldhsu_le_zss,
435
+ gen_helper_sve_ldss_le_zss, } } },
436
437
- { { { gen_helper_sve_ldffbss_zsu,
438
- gen_helper_sve_ldffhss_zsu,
439
- NULL, },
440
- { gen_helper_sve_ldffbsu_zsu,
441
- gen_helper_sve_ldffhsu_zsu,
442
- gen_helper_sve_ldffssu_zsu, } },
443
- { { gen_helper_sve_ldffbss_zss,
444
- gen_helper_sve_ldffhss_zss,
445
- NULL, },
446
- { gen_helper_sve_ldffbsu_zss,
447
- gen_helper_sve_ldffhsu_zss,
448
- gen_helper_sve_ldffssu_zss, } } }
449
+ /* First-fault */
450
+ { { { gen_helper_sve_ldffbss_zsu,
451
+ gen_helper_sve_ldffhss_zsu,
452
+ NULL, },
453
+ { gen_helper_sve_ldffbsu_zsu,
454
+ gen_helper_sve_ldffhsu_zsu,
455
+ gen_helper_sve_ldffssu_zsu, } },
456
+ { { gen_helper_sve_ldffbss_zss,
457
+ gen_helper_sve_ldffhss_zss,
458
+ NULL, },
459
+ { gen_helper_sve_ldffbsu_zss,
460
+ gen_helper_sve_ldffhsu_zss,
461
+ gen_helper_sve_ldffssu_zss, } } } },
462
+
463
+ /* Big-endian */
464
+ { { { { gen_helper_sve_ldbss_zsu,
465
+ gen_helper_sve_ldhss_be_zsu,
466
+ NULL, },
467
+ { gen_helper_sve_ldbsu_zsu,
468
+ gen_helper_sve_ldhsu_be_zsu,
469
+ gen_helper_sve_ldss_be_zsu, } },
470
+ { { gen_helper_sve_ldbss_zss,
471
+ gen_helper_sve_ldhss_be_zss,
472
+ NULL, },
473
+ { gen_helper_sve_ldbsu_zss,
474
+ gen_helper_sve_ldhsu_be_zss,
475
+ gen_helper_sve_ldss_be_zss, } } },
476
+
477
+ /* First-fault */
478
+ { { { gen_helper_sve_ldffbss_zsu,
479
+ gen_helper_sve_ldffhss_zsu,
480
+ NULL, },
481
+ { gen_helper_sve_ldffbsu_zsu,
482
+ gen_helper_sve_ldffhsu_zsu,
483
+ gen_helper_sve_ldffssu_zsu, } },
484
+ { { gen_helper_sve_ldffbss_zss,
485
+ gen_helper_sve_ldffhss_zss,
486
+ NULL, },
487
+ { gen_helper_sve_ldffbsu_zss,
488
+ gen_helper_sve_ldffhsu_zss,
489
+ gen_helper_sve_ldffssu_zss, } } } },
490
};
491
492
/* Note that we overload xs=2 to indicate 64-bit offset. */
493
-static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][3][2][4] = {
494
- { { { gen_helper_sve_ldbds_zsu,
495
- gen_helper_sve_ldhds_zsu,
496
- gen_helper_sve_ldsds_zsu,
497
- NULL, },
498
- { gen_helper_sve_ldbdu_zsu,
499
- gen_helper_sve_ldhdu_zsu,
500
- gen_helper_sve_ldsdu_zsu,
501
- gen_helper_sve_ldddu_zsu, } },
502
- { { gen_helper_sve_ldbds_zss,
503
- gen_helper_sve_ldhds_zss,
504
- gen_helper_sve_ldsds_zss,
505
- NULL, },
506
- { gen_helper_sve_ldbdu_zss,
507
- gen_helper_sve_ldhdu_zss,
508
- gen_helper_sve_ldsdu_zss,
509
- gen_helper_sve_ldddu_zss, } },
510
- { { gen_helper_sve_ldbds_zd,
511
- gen_helper_sve_ldhds_zd,
512
- gen_helper_sve_ldsds_zd,
513
- NULL, },
514
- { gen_helper_sve_ldbdu_zd,
515
- gen_helper_sve_ldhdu_zd,
516
- gen_helper_sve_ldsdu_zd,
517
- gen_helper_sve_ldddu_zd, } } },
518
+static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][2][3][2][4] = {
519
+ /* Little-endian */
520
+ { { { { gen_helper_sve_ldbds_zsu,
521
+ gen_helper_sve_ldhds_le_zsu,
522
+ gen_helper_sve_ldsds_le_zsu,
523
+ NULL, },
524
+ { gen_helper_sve_ldbdu_zsu,
525
+ gen_helper_sve_ldhdu_le_zsu,
526
+ gen_helper_sve_ldsdu_le_zsu,
527
+ gen_helper_sve_lddd_le_zsu, } },
528
+ { { gen_helper_sve_ldbds_zss,
529
+ gen_helper_sve_ldhds_le_zss,
530
+ gen_helper_sve_ldsds_le_zss,
531
+ NULL, },
532
+ { gen_helper_sve_ldbdu_zss,
533
+ gen_helper_sve_ldhdu_le_zss,
534
+ gen_helper_sve_ldsdu_le_zss,
535
+ gen_helper_sve_lddd_le_zss, } },
536
+ { { gen_helper_sve_ldbds_zd,
537
+ gen_helper_sve_ldhds_le_zd,
538
+ gen_helper_sve_ldsds_le_zd,
539
+ NULL, },
540
+ { gen_helper_sve_ldbdu_zd,
541
+ gen_helper_sve_ldhdu_le_zd,
542
+ gen_helper_sve_ldsdu_le_zd,
543
+ gen_helper_sve_lddd_le_zd, } } },
544
545
- { { { gen_helper_sve_ldffbds_zsu,
546
- gen_helper_sve_ldffhds_zsu,
547
- gen_helper_sve_ldffsds_zsu,
548
- NULL, },
549
- { gen_helper_sve_ldffbdu_zsu,
550
- gen_helper_sve_ldffhdu_zsu,
551
- gen_helper_sve_ldffsdu_zsu,
552
- gen_helper_sve_ldffddu_zsu, } },
553
- { { gen_helper_sve_ldffbds_zss,
554
- gen_helper_sve_ldffhds_zss,
555
- gen_helper_sve_ldffsds_zss,
556
- NULL, },
557
- { gen_helper_sve_ldffbdu_zss,
558
- gen_helper_sve_ldffhdu_zss,
559
- gen_helper_sve_ldffsdu_zss,
560
- gen_helper_sve_ldffddu_zss, } },
561
- { { gen_helper_sve_ldffbds_zd,
562
- gen_helper_sve_ldffhds_zd,
563
- gen_helper_sve_ldffsds_zd,
564
- NULL, },
565
- { gen_helper_sve_ldffbdu_zd,
566
- gen_helper_sve_ldffhdu_zd,
567
- gen_helper_sve_ldffsdu_zd,
568
- gen_helper_sve_ldffddu_zd, } } }
569
+ /* First-fault */
570
+ { { { gen_helper_sve_ldffbds_zsu,
571
+ gen_helper_sve_ldffhds_zsu,
572
+ gen_helper_sve_ldffsds_zsu,
573
+ NULL, },
574
+ { gen_helper_sve_ldffbdu_zsu,
575
+ gen_helper_sve_ldffhdu_zsu,
576
+ gen_helper_sve_ldffsdu_zsu,
577
+ gen_helper_sve_ldffddu_zsu, } },
578
+ { { gen_helper_sve_ldffbds_zss,
579
+ gen_helper_sve_ldffhds_zss,
580
+ gen_helper_sve_ldffsds_zss,
581
+ NULL, },
582
+ { gen_helper_sve_ldffbdu_zss,
583
+ gen_helper_sve_ldffhdu_zss,
584
+ gen_helper_sve_ldffsdu_zss,
585
+ gen_helper_sve_ldffddu_zss, } },
586
+ { { gen_helper_sve_ldffbds_zd,
587
+ gen_helper_sve_ldffhds_zd,
588
+ gen_helper_sve_ldffsds_zd,
589
+ NULL, },
590
+ { gen_helper_sve_ldffbdu_zd,
591
+ gen_helper_sve_ldffhdu_zd,
592
+ gen_helper_sve_ldffsdu_zd,
593
+ gen_helper_sve_ldffddu_zd, } } } },
594
+
595
+ /* Big-endian */
596
+ { { { { gen_helper_sve_ldbds_zsu,
597
+ gen_helper_sve_ldhds_be_zsu,
598
+ gen_helper_sve_ldsds_be_zsu,
599
+ NULL, },
600
+ { gen_helper_sve_ldbdu_zsu,
601
+ gen_helper_sve_ldhdu_be_zsu,
602
+ gen_helper_sve_ldsdu_be_zsu,
603
+ gen_helper_sve_lddd_be_zsu, } },
604
+ { { gen_helper_sve_ldbds_zss,
605
+ gen_helper_sve_ldhds_be_zss,
606
+ gen_helper_sve_ldsds_be_zss,
607
+ NULL, },
608
+ { gen_helper_sve_ldbdu_zss,
609
+ gen_helper_sve_ldhdu_be_zss,
610
+ gen_helper_sve_ldsdu_be_zss,
611
+ gen_helper_sve_lddd_be_zss, } },
612
+ { { gen_helper_sve_ldbds_zd,
613
+ gen_helper_sve_ldhds_be_zd,
614
+ gen_helper_sve_ldsds_be_zd,
615
+ NULL, },
616
+ { gen_helper_sve_ldbdu_zd,
617
+ gen_helper_sve_ldhdu_be_zd,
618
+ gen_helper_sve_ldsdu_be_zd,
619
+ gen_helper_sve_lddd_be_zd, } } },
620
+
621
+ /* First-fault */
622
+ { { { gen_helper_sve_ldffbds_zsu,
623
+ gen_helper_sve_ldffhds_zsu,
624
+ gen_helper_sve_ldffsds_zsu,
625
+ NULL, },
626
+ { gen_helper_sve_ldffbdu_zsu,
627
+ gen_helper_sve_ldffhdu_zsu,
628
+ gen_helper_sve_ldffsdu_zsu,
629
+ gen_helper_sve_ldffddu_zsu, } },
630
+ { { gen_helper_sve_ldffbds_zss,
631
+ gen_helper_sve_ldffhds_zss,
632
+ gen_helper_sve_ldffsds_zss,
633
+ NULL, },
634
+ { gen_helper_sve_ldffbdu_zss,
635
+ gen_helper_sve_ldffhdu_zss,
636
+ gen_helper_sve_ldffsdu_zss,
637
+ gen_helper_sve_ldffddu_zss, } },
638
+ { { gen_helper_sve_ldffbds_zd,
639
+ gen_helper_sve_ldffhds_zd,
640
+ gen_helper_sve_ldffsds_zd,
641
+ NULL, },
642
+ { gen_helper_sve_ldffbdu_zd,
643
+ gen_helper_sve_ldffhdu_zd,
644
+ gen_helper_sve_ldffsdu_zd,
645
+ gen_helper_sve_ldffddu_zd, } } } },
646
};
647
648
static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
649
{
650
gen_helper_gvec_mem_scatter *fn = NULL;
651
+ int be = s->be_data == MO_BE;
652
653
if (!sve_access_check(s)) {
654
return true;
655
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
656
657
switch (a->esz) {
658
case MO_32:
659
- fn = gather_load_fn32[a->ff][a->xs][a->u][a->msz];
660
+ fn = gather_load_fn32[be][a->ff][a->xs][a->u][a->msz];
661
break;
662
case MO_64:
663
- fn = gather_load_fn64[a->ff][a->xs][a->u][a->msz];
664
+ fn = gather_load_fn64[be][a->ff][a->xs][a->u][a->msz];
665
break;
666
}
667
assert(fn != NULL);
668
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
669
static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
670
{
671
gen_helper_gvec_mem_scatter *fn = NULL;
672
+ int be = s->be_data == MO_BE;
673
TCGv_i64 imm;
674
675
if (a->esz < a->msz || (a->esz == a->msz && !a->u)) {
676
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
677
678
switch (a->esz) {
679
case MO_32:
680
- fn = gather_load_fn32[a->ff][0][a->u][a->msz];
681
+ fn = gather_load_fn32[be][a->ff][0][a->u][a->msz];
682
break;
683
case MO_64:
684
- fn = gather_load_fn64[a->ff][2][a->u][a->msz];
685
+ fn = gather_load_fn64[be][a->ff][2][a->u][a->msz];
686
break;
687
}
688
assert(fn != NULL);
689
--
106
--
690
2.19.0
107
2.20.1
691
108
692
109
diff view generated by jsdifflib
1
Add the v8M stack checks for the VLDM/VSTM
1
From: Subbaraya Sundeep <sundeep.lkml@gmail.com>
2
(aka VPUSH/VPOP) instructions. This code is currently
3
unreachable because we haven't yet implemented M profile
4
floating point support, but since the change is simple,
5
we add it now because otherwise we're likely to forget to
6
do it later.
7
2
3
In addition to simple serial test this patch uses ping
4
to test the ethernet block modelled in SmartFusion2 SoC.
5
6
Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 1587048891-30493-4-git-send-email-sundeep.lkml@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20181002163556.10279-13-peter.maydell@linaro.org
12
---
11
---
13
target/arm/translate.c | 12 ++++++++++++
12
tests/acceptance/boot_linux_console.py | 15 ++++++++++-----
14
1 file changed, 12 insertions(+)
13
1 file changed, 10 insertions(+), 5 deletions(-)
15
14
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
17
--- a/tests/acceptance/boot_linux_console.py
19
+++ b/target/arm/translate.c
18
+++ b/tests/acceptance/boot_linux_console.py
20
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
21
if (insn & (1 << 24)) /* pre-decrement */
20
"""
22
tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
21
uboot_url = ('https://raw.githubusercontent.com/'
23
22
'Subbaraya-Sundeep/qemu-test-binaries/'
24
+ if (s->v8m_stackcheck && rn == 13 && w) {
23
- 'fa030bd77a014a0b8e360d3b7011df89283a2f0b/u-boot')
25
+ /*
24
- uboot_hash = 'abba5d9c24cdd2d49cdc2a8aa92976cf20737eff'
26
+ * Here 'addr' is the lowest address we will store to,
25
+ 'fe371d32e50ca682391e1e70ab98c2942aeffb01/u-boot')
27
+ * and is either the old SP (if post-increment) or
26
+ uboot_hash = 'cbb8cbab970f594bf6523b9855be209c08374ae2'
28
+ * the new SP (if pre-decrement). For post-increment
27
uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash)
29
+ * where the old value is below the limit and the new
28
spi_url = ('https://raw.githubusercontent.com/'
30
+ * value is above, it is UNKNOWN whether the limit check
29
'Subbaraya-Sundeep/qemu-test-binaries/'
31
+ * triggers; we choose to trigger.
30
- 'fa030bd77a014a0b8e360d3b7011df89283a2f0b/spi.bin')
32
+ */
31
- spi_hash = '85f698329d38de63aea6e884a86fbde70890a78a'
33
+ gen_helper_v8m_stackcheck(cpu_env, addr);
32
+ 'fe371d32e50ca682391e1e70ab98c2942aeffb01/spi.bin')
34
+ }
33
+ spi_hash = '65523a1835949b6f4553be96dec1b6a38fb05501'
34
spi_path = self.fetch_asset(spi_url, asset_hash=spi_hash)
35
36
self.vm.set_console()
37
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
38
'-drive', 'file=' + spi_path + ',if=mtd,format=raw',
39
'-no-reboot')
40
self.vm.launch()
41
- self.wait_for_console_pattern('init started: BusyBox')
42
+ self.wait_for_console_pattern('Enter \'help\' for a list')
35
+
43
+
36
if (dp)
44
+ exec_command_and_wait_for_pattern(self, 'ifconfig eth0 10.0.2.15',
37
offset = 8;
45
+ 'eth0: link becomes ready')
38
else
46
+ exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2',
47
+ '3 packets transmitted, 3 packets received, 0% packet loss')
48
49
def do_test_arm_raspi2(self, uart_id):
50
"""
39
--
51
--
40
2.19.0
52
2.20.1
41
53
42
54
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
This object may be used to represent a clock inside a clock tree.
2
2
3
This implements the feature for softmmu, and moves the
3
A clock may be connected to another clock so that it receives update,
4
main loop out of a macro and into a function.
4
through a callback, whenever the source/parent clock is updated.
5
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Although only the root clock of a clock tree controls the values
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
(represented as periods) of all clocks in tree, each clock holds
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
a local state containing the current value so that it can be fetched
9
Message-id: 20181005175350.30752-15-richard.henderson@linaro.org
9
independently. It will allows us to fullfill migration requirements
10
by migrating each clock independently of others.
11
12
This is based on the original work of Frederic Konrad.
13
14
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
17
Message-id: 20200406135251.157596-2-damien.hedde@greensocs.com
18
[PMM: Use uint64_t rather than unsigned long long in trace events;
19
the dtrace backend can't handle the latter]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
21
---
12
target/arm/helper-sve.h | 84 ++++++++---
22
hw/core/Makefile.objs | 1 +
13
target/arm/sve_helper.c | 290 +++++++++++++++++++++++++++----------
23
include/hw/clock.h | 216 ++++++++++++++++++++++++++++++++++++++++++
14
target/arm/translate-sve.c | 84 +++++------
24
hw/core/clock.c | 130 +++++++++++++++++++++++++
15
3 files changed, 321 insertions(+), 137 deletions(-)
25
hw/core/trace-events | 7 ++
16
26
4 files changed, 354 insertions(+)
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
27
create mode 100644 include/hw/clock.h
28
create mode 100644 hw/core/clock.c
29
30
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
18
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-sve.h
32
--- a/hw/core/Makefile.objs
20
+++ b/target/arm/helper-sve.h
33
+++ b/hw/core/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve_ldsds_be_zd, TCG_CALL_NO_WG,
34
@@ -XXX,XX +XXX,XX @@ common-obj-y += hotplug.o
22
35
common-obj-y += vmstate-if.o
23
DEF_HELPER_FLAGS_6(sve_ldffbsu_zsu, TCG_CALL_NO_WG,
36
# irq.o needed for qdev GPIO handling:
24
void, env, ptr, ptr, ptr, tl, i32)
37
common-obj-y += irq.o
25
-DEF_HELPER_FLAGS_6(sve_ldffhsu_zsu, TCG_CALL_NO_WG,
38
+common-obj-y += clock.o
26
+DEF_HELPER_FLAGS_6(sve_ldffhsu_le_zsu, TCG_CALL_NO_WG,
39
27
void, env, ptr, ptr, ptr, tl, i32)
40
common-obj-$(CONFIG_SOFTMMU) += reset.o
28
-DEF_HELPER_FLAGS_6(sve_ldffssu_zsu, TCG_CALL_NO_WG,
41
common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
29
+DEF_HELPER_FLAGS_6(sve_ldffhsu_be_zsu, TCG_CALL_NO_WG,
42
diff --git a/include/hw/clock.h b/include/hw/clock.h
30
+ void, env, ptr, ptr, ptr, tl, i32)
43
new file mode 100644
31
+DEF_HELPER_FLAGS_6(sve_ldffss_le_zsu, TCG_CALL_NO_WG,
44
index XXXXXXX..XXXXXXX
32
+ void, env, ptr, ptr, ptr, tl, i32)
45
--- /dev/null
33
+DEF_HELPER_FLAGS_6(sve_ldffss_be_zsu, TCG_CALL_NO_WG,
46
+++ b/include/hw/clock.h
34
void, env, ptr, ptr, ptr, tl, i32)
47
@@ -XXX,XX +XXX,XX @@
35
DEF_HELPER_FLAGS_6(sve_ldffbss_zsu, TCG_CALL_NO_WG,
36
void, env, ptr, ptr, ptr, tl, i32)
37
-DEF_HELPER_FLAGS_6(sve_ldffhss_zsu, TCG_CALL_NO_WG,
38
+DEF_HELPER_FLAGS_6(sve_ldffhss_le_zsu, TCG_CALL_NO_WG,
39
+ void, env, ptr, ptr, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_6(sve_ldffhss_be_zsu, TCG_CALL_NO_WG,
41
void, env, ptr, ptr, ptr, tl, i32)
42
43
DEF_HELPER_FLAGS_6(sve_ldffbsu_zss, TCG_CALL_NO_WG,
44
void, env, ptr, ptr, ptr, tl, i32)
45
-DEF_HELPER_FLAGS_6(sve_ldffhsu_zss, TCG_CALL_NO_WG,
46
+DEF_HELPER_FLAGS_6(sve_ldffhsu_le_zss, TCG_CALL_NO_WG,
47
void, env, ptr, ptr, ptr, tl, i32)
48
-DEF_HELPER_FLAGS_6(sve_ldffssu_zss, TCG_CALL_NO_WG,
49
+DEF_HELPER_FLAGS_6(sve_ldffhsu_be_zss, TCG_CALL_NO_WG,
50
+ void, env, ptr, ptr, ptr, tl, i32)
51
+DEF_HELPER_FLAGS_6(sve_ldffss_le_zss, TCG_CALL_NO_WG,
52
+ void, env, ptr, ptr, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_6(sve_ldffss_be_zss, TCG_CALL_NO_WG,
54
void, env, ptr, ptr, ptr, tl, i32)
55
DEF_HELPER_FLAGS_6(sve_ldffbss_zss, TCG_CALL_NO_WG,
56
void, env, ptr, ptr, ptr, tl, i32)
57
-DEF_HELPER_FLAGS_6(sve_ldffhss_zss, TCG_CALL_NO_WG,
58
+DEF_HELPER_FLAGS_6(sve_ldffhss_le_zss, TCG_CALL_NO_WG,
59
+ void, env, ptr, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_6(sve_ldffhss_be_zss, TCG_CALL_NO_WG,
61
void, env, ptr, ptr, ptr, tl, i32)
62
63
DEF_HELPER_FLAGS_6(sve_ldffbdu_zsu, TCG_CALL_NO_WG,
64
void, env, ptr, ptr, ptr, tl, i32)
65
-DEF_HELPER_FLAGS_6(sve_ldffhdu_zsu, TCG_CALL_NO_WG,
66
+DEF_HELPER_FLAGS_6(sve_ldffhdu_le_zsu, TCG_CALL_NO_WG,
67
void, env, ptr, ptr, ptr, tl, i32)
68
-DEF_HELPER_FLAGS_6(sve_ldffsdu_zsu, TCG_CALL_NO_WG,
69
+DEF_HELPER_FLAGS_6(sve_ldffhdu_be_zsu, TCG_CALL_NO_WG,
70
void, env, ptr, ptr, ptr, tl, i32)
71
-DEF_HELPER_FLAGS_6(sve_ldffddu_zsu, TCG_CALL_NO_WG,
72
+DEF_HELPER_FLAGS_6(sve_ldffsdu_le_zsu, TCG_CALL_NO_WG,
73
+ void, env, ptr, ptr, ptr, tl, i32)
74
+DEF_HELPER_FLAGS_6(sve_ldffsdu_be_zsu, TCG_CALL_NO_WG,
75
+ void, env, ptr, ptr, ptr, tl, i32)
76
+DEF_HELPER_FLAGS_6(sve_ldffdd_le_zsu, TCG_CALL_NO_WG,
77
+ void, env, ptr, ptr, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_6(sve_ldffdd_be_zsu, TCG_CALL_NO_WG,
79
void, env, ptr, ptr, ptr, tl, i32)
80
DEF_HELPER_FLAGS_6(sve_ldffbds_zsu, TCG_CALL_NO_WG,
81
void, env, ptr, ptr, ptr, tl, i32)
82
-DEF_HELPER_FLAGS_6(sve_ldffhds_zsu, TCG_CALL_NO_WG,
83
+DEF_HELPER_FLAGS_6(sve_ldffhds_le_zsu, TCG_CALL_NO_WG,
84
void, env, ptr, ptr, ptr, tl, i32)
85
-DEF_HELPER_FLAGS_6(sve_ldffsds_zsu, TCG_CALL_NO_WG,
86
+DEF_HELPER_FLAGS_6(sve_ldffhds_be_zsu, TCG_CALL_NO_WG,
87
+ void, env, ptr, ptr, ptr, tl, i32)
88
+DEF_HELPER_FLAGS_6(sve_ldffsds_le_zsu, TCG_CALL_NO_WG,
89
+ void, env, ptr, ptr, ptr, tl, i32)
90
+DEF_HELPER_FLAGS_6(sve_ldffsds_be_zsu, TCG_CALL_NO_WG,
91
void, env, ptr, ptr, ptr, tl, i32)
92
93
DEF_HELPER_FLAGS_6(sve_ldffbdu_zss, TCG_CALL_NO_WG,
94
void, env, ptr, ptr, ptr, tl, i32)
95
-DEF_HELPER_FLAGS_6(sve_ldffhdu_zss, TCG_CALL_NO_WG,
96
+DEF_HELPER_FLAGS_6(sve_ldffhdu_le_zss, TCG_CALL_NO_WG,
97
void, env, ptr, ptr, ptr, tl, i32)
98
-DEF_HELPER_FLAGS_6(sve_ldffsdu_zss, TCG_CALL_NO_WG,
99
+DEF_HELPER_FLAGS_6(sve_ldffhdu_be_zss, TCG_CALL_NO_WG,
100
void, env, ptr, ptr, ptr, tl, i32)
101
-DEF_HELPER_FLAGS_6(sve_ldffddu_zss, TCG_CALL_NO_WG,
102
+DEF_HELPER_FLAGS_6(sve_ldffsdu_le_zss, TCG_CALL_NO_WG,
103
+ void, env, ptr, ptr, ptr, tl, i32)
104
+DEF_HELPER_FLAGS_6(sve_ldffsdu_be_zss, TCG_CALL_NO_WG,
105
+ void, env, ptr, ptr, ptr, tl, i32)
106
+DEF_HELPER_FLAGS_6(sve_ldffdd_le_zss, TCG_CALL_NO_WG,
107
+ void, env, ptr, ptr, ptr, tl, i32)
108
+DEF_HELPER_FLAGS_6(sve_ldffdd_be_zss, TCG_CALL_NO_WG,
109
void, env, ptr, ptr, ptr, tl, i32)
110
DEF_HELPER_FLAGS_6(sve_ldffbds_zss, TCG_CALL_NO_WG,
111
void, env, ptr, ptr, ptr, tl, i32)
112
-DEF_HELPER_FLAGS_6(sve_ldffhds_zss, TCG_CALL_NO_WG,
113
+DEF_HELPER_FLAGS_6(sve_ldffhds_le_zss, TCG_CALL_NO_WG,
114
void, env, ptr, ptr, ptr, tl, i32)
115
-DEF_HELPER_FLAGS_6(sve_ldffsds_zss, TCG_CALL_NO_WG,
116
+DEF_HELPER_FLAGS_6(sve_ldffhds_be_zss, TCG_CALL_NO_WG,
117
+ void, env, ptr, ptr, ptr, tl, i32)
118
+DEF_HELPER_FLAGS_6(sve_ldffsds_le_zss, TCG_CALL_NO_WG,
119
+ void, env, ptr, ptr, ptr, tl, i32)
120
+DEF_HELPER_FLAGS_6(sve_ldffsds_be_zss, TCG_CALL_NO_WG,
121
void, env, ptr, ptr, ptr, tl, i32)
122
123
DEF_HELPER_FLAGS_6(sve_ldffbdu_zd, TCG_CALL_NO_WG,
124
void, env, ptr, ptr, ptr, tl, i32)
125
-DEF_HELPER_FLAGS_6(sve_ldffhdu_zd, TCG_CALL_NO_WG,
126
+DEF_HELPER_FLAGS_6(sve_ldffhdu_le_zd, TCG_CALL_NO_WG,
127
void, env, ptr, ptr, ptr, tl, i32)
128
-DEF_HELPER_FLAGS_6(sve_ldffsdu_zd, TCG_CALL_NO_WG,
129
+DEF_HELPER_FLAGS_6(sve_ldffhdu_be_zd, TCG_CALL_NO_WG,
130
void, env, ptr, ptr, ptr, tl, i32)
131
-DEF_HELPER_FLAGS_6(sve_ldffddu_zd, TCG_CALL_NO_WG,
132
+DEF_HELPER_FLAGS_6(sve_ldffsdu_le_zd, TCG_CALL_NO_WG,
133
+ void, env, ptr, ptr, ptr, tl, i32)
134
+DEF_HELPER_FLAGS_6(sve_ldffsdu_be_zd, TCG_CALL_NO_WG,
135
+ void, env, ptr, ptr, ptr, tl, i32)
136
+DEF_HELPER_FLAGS_6(sve_ldffdd_le_zd, TCG_CALL_NO_WG,
137
+ void, env, ptr, ptr, ptr, tl, i32)
138
+DEF_HELPER_FLAGS_6(sve_ldffdd_be_zd, TCG_CALL_NO_WG,
139
void, env, ptr, ptr, ptr, tl, i32)
140
DEF_HELPER_FLAGS_6(sve_ldffbds_zd, TCG_CALL_NO_WG,
141
void, env, ptr, ptr, ptr, tl, i32)
142
-DEF_HELPER_FLAGS_6(sve_ldffhds_zd, TCG_CALL_NO_WG,
143
+DEF_HELPER_FLAGS_6(sve_ldffhds_le_zd, TCG_CALL_NO_WG,
144
void, env, ptr, ptr, ptr, tl, i32)
145
-DEF_HELPER_FLAGS_6(sve_ldffsds_zd, TCG_CALL_NO_WG,
146
+DEF_HELPER_FLAGS_6(sve_ldffhds_be_zd, TCG_CALL_NO_WG,
147
+ void, env, ptr, ptr, ptr, tl, i32)
148
+DEF_HELPER_FLAGS_6(sve_ldffsds_le_zd, TCG_CALL_NO_WG,
149
+ void, env, ptr, ptr, ptr, tl, i32)
150
+DEF_HELPER_FLAGS_6(sve_ldffsds_be_zd, TCG_CALL_NO_WG,
151
void, env, ptr, ptr, ptr, tl, i32)
152
153
DEF_HELPER_FLAGS_6(sve_stbs_zsu, TCG_CALL_NO_WG,
154
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
155
index XXXXXXX..XXXXXXX 100644
156
--- a/target/arm/sve_helper.c
157
+++ b/target/arm/sve_helper.c
158
@@ -XXX,XX +XXX,XX @@ DO_LD1_ZPZ_D(dd_be, zd)
159
160
/* First fault loads with a vector index. */
161
162
-#ifdef CONFIG_USER_ONLY
163
+/* Load one element into VD+REG_OFF from (ENV,VADDR) without faulting.
164
+ * The controlling predicate is known to be true. Return true if the
165
+ * load was successful.
166
+ */
167
+typedef bool sve_ld1_nf_fn(CPUARMState *env, void *vd, intptr_t reg_off,
168
+ target_ulong vaddr, int mmu_idx);
169
170
-#define DO_LDFF1_ZPZ(NAME, TYPEE, TYPEI, TYPEM, FN, H) \
171
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
172
- target_ulong base, uint32_t desc) \
173
-{ \
174
- intptr_t i, oprsz = simd_oprsz(desc); \
175
- unsigned scale = simd_data(desc); \
176
- uintptr_t ra = GETPC(); \
177
- bool first = true; \
178
- mmap_lock(); \
179
- for (i = 0; i < oprsz; ) { \
180
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
181
- do { \
182
- TYPEM m = 0; \
183
- if (pg & 1) { \
184
- target_ulong off = *(TYPEI *)(vm + H(i)); \
185
- target_ulong addr = base + (off << scale); \
186
- if (!first && \
187
- page_check_range(addr, sizeof(TYPEM), PAGE_READ)) { \
188
- record_fault(env, i, oprsz); \
189
- goto exit; \
190
- } \
191
- m = FN(env, addr, ra); \
192
- first = false; \
193
- } \
194
- *(TYPEE *)(vd + H(i)) = m; \
195
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
196
- } while (i & 15); \
197
- } \
198
- exit: \
199
- mmap_unlock(); \
200
+#ifdef CONFIG_SOFTMMU
201
+#define DO_LD_NF(NAME, H, TYPEE, TYPEM, HOST) \
202
+static bool sve_ld##NAME##_nf(CPUARMState *env, void *vd, intptr_t reg_off, \
203
+ target_ulong addr, int mmu_idx) \
204
+{ \
205
+ target_ulong next_page = -(addr | TARGET_PAGE_MASK); \
206
+ if (likely(next_page - addr >= sizeof(TYPEM))) { \
207
+ void *host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, mmu_idx); \
208
+ if (likely(host)) { \
209
+ TYPEM val = HOST(host); \
210
+ *(TYPEE *)(vd + H(reg_off)) = val; \
211
+ return true; \
212
+ } \
213
+ } \
214
+ return false; \
215
}
216
-
217
#else
218
-
219
-#define DO_LDFF1_ZPZ(NAME, TYPEE, TYPEI, TYPEM, FN, H) \
220
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
221
- target_ulong base, uint32_t desc) \
222
-{ \
223
- g_assert_not_reached(); \
224
+#define DO_LD_NF(NAME, H, TYPEE, TYPEM, HOST) \
225
+static bool sve_ld##NAME##_nf(CPUARMState *env, void *vd, intptr_t reg_off, \
226
+ target_ulong addr, int mmu_idx) \
227
+{ \
228
+ if (likely(page_check_range(addr, sizeof(TYPEM), PAGE_READ))) { \
229
+ TYPEM val = HOST(g2h(addr)); \
230
+ *(TYPEE *)(vd + H(reg_off)) = val; \
231
+ return true; \
232
+ } \
233
+ return false; \
234
}
235
-
236
#endif
237
238
-#define DO_LDFF1_ZPZ_S(NAME, TYPEI, TYPEM, FN) \
239
- DO_LDFF1_ZPZ(NAME, uint32_t, TYPEI, TYPEM, FN, H1_4)
240
-#define DO_LDFF1_ZPZ_D(NAME, TYPEI, TYPEM, FN) \
241
- DO_LDFF1_ZPZ(NAME, uint64_t, TYPEI, TYPEM, FN, )
242
+DO_LD_NF(bsu, H1_4, uint32_t, uint8_t, ldub_p)
243
+DO_LD_NF(bss, H1_4, uint32_t, int8_t, ldsb_p)
244
+DO_LD_NF(bdu, , uint64_t, uint8_t, ldub_p)
245
+DO_LD_NF(bds, , uint64_t, int8_t, ldsb_p)
246
247
-DO_LDFF1_ZPZ_S(sve_ldffbsu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
248
-DO_LDFF1_ZPZ_S(sve_ldffhsu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
249
-DO_LDFF1_ZPZ_S(sve_ldffssu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
250
-DO_LDFF1_ZPZ_S(sve_ldffbss_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
251
-DO_LDFF1_ZPZ_S(sve_ldffhss_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
252
+DO_LD_NF(hsu_le, H1_4, uint32_t, uint16_t, lduw_le_p)
253
+DO_LD_NF(hss_le, H1_4, uint32_t, int16_t, ldsw_le_p)
254
+DO_LD_NF(hsu_be, H1_4, uint32_t, uint16_t, lduw_be_p)
255
+DO_LD_NF(hss_be, H1_4, uint32_t, int16_t, ldsw_be_p)
256
+DO_LD_NF(hdu_le, , uint64_t, uint16_t, lduw_le_p)
257
+DO_LD_NF(hds_le, , uint64_t, int16_t, ldsw_le_p)
258
+DO_LD_NF(hdu_be, , uint64_t, uint16_t, lduw_be_p)
259
+DO_LD_NF(hds_be, , uint64_t, int16_t, ldsw_be_p)
260
261
-DO_LDFF1_ZPZ_S(sve_ldffbsu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
262
-DO_LDFF1_ZPZ_S(sve_ldffhsu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
263
-DO_LDFF1_ZPZ_S(sve_ldffssu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
264
-DO_LDFF1_ZPZ_S(sve_ldffbss_zss, int32_t, int8_t, cpu_ldub_data_ra)
265
-DO_LDFF1_ZPZ_S(sve_ldffhss_zss, int32_t, int16_t, cpu_lduw_data_ra)
266
+DO_LD_NF(ss_le, H1_4, uint32_t, uint32_t, ldl_le_p)
267
+DO_LD_NF(ss_be, H1_4, uint32_t, uint32_t, ldl_be_p)
268
+DO_LD_NF(sdu_le, , uint64_t, uint32_t, ldl_le_p)
269
+DO_LD_NF(sds_le, , uint64_t, int32_t, ldl_le_p)
270
+DO_LD_NF(sdu_be, , uint64_t, uint32_t, ldl_be_p)
271
+DO_LD_NF(sds_be, , uint64_t, int32_t, ldl_be_p)
272
273
-DO_LDFF1_ZPZ_D(sve_ldffbdu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
274
-DO_LDFF1_ZPZ_D(sve_ldffhdu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
275
-DO_LDFF1_ZPZ_D(sve_ldffsdu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
276
-DO_LDFF1_ZPZ_D(sve_ldffddu_zsu, uint32_t, uint64_t, cpu_ldq_data_ra)
277
-DO_LDFF1_ZPZ_D(sve_ldffbds_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
278
-DO_LDFF1_ZPZ_D(sve_ldffhds_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
279
-DO_LDFF1_ZPZ_D(sve_ldffsds_zsu, uint32_t, int32_t, cpu_ldl_data_ra)
280
+DO_LD_NF(dd_le, , uint64_t, uint64_t, ldq_le_p)
281
+DO_LD_NF(dd_be, , uint64_t, uint64_t, ldq_be_p)
282
283
-DO_LDFF1_ZPZ_D(sve_ldffbdu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
284
-DO_LDFF1_ZPZ_D(sve_ldffhdu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
285
-DO_LDFF1_ZPZ_D(sve_ldffsdu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
286
-DO_LDFF1_ZPZ_D(sve_ldffddu_zss, int32_t, uint64_t, cpu_ldq_data_ra)
287
-DO_LDFF1_ZPZ_D(sve_ldffbds_zss, int32_t, int8_t, cpu_ldub_data_ra)
288
-DO_LDFF1_ZPZ_D(sve_ldffhds_zss, int32_t, int16_t, cpu_lduw_data_ra)
289
-DO_LDFF1_ZPZ_D(sve_ldffsds_zss, int32_t, int32_t, cpu_ldl_data_ra)
290
+/*
48
+/*
291
+ * Common helper for all gather first-faulting loads.
49
+ * Hardware Clocks
292
+ */
50
+ *
293
+static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
51
+ * Copyright GreenSocs 2016-2020
294
+ target_ulong base, uint32_t desc, uintptr_t ra,
52
+ *
295
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn,
53
+ * Authors:
296
+ sve_ld1_nf_fn *nonfault_fn)
54
+ * Frederic Konrad
297
+{
55
+ * Damien Hedde
298
+ const int mmu_idx = cpu_mmu_index(env, false);
56
+ *
299
+ intptr_t reg_off, reg_max = simd_oprsz(desc);
57
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
300
+ unsigned scale = simd_data(desc);
58
+ * See the COPYING file in the top-level directory.
301
+ target_ulong addr;
59
+ */
302
60
+
303
-DO_LDFF1_ZPZ_D(sve_ldffbdu_zd, uint64_t, uint8_t, cpu_ldub_data_ra)
61
+#ifndef QEMU_HW_CLOCK_H
304
-DO_LDFF1_ZPZ_D(sve_ldffhdu_zd, uint64_t, uint16_t, cpu_lduw_data_ra)
62
+#define QEMU_HW_CLOCK_H
305
-DO_LDFF1_ZPZ_D(sve_ldffsdu_zd, uint64_t, uint32_t, cpu_ldl_data_ra)
63
+
306
-DO_LDFF1_ZPZ_D(sve_ldffddu_zd, uint64_t, uint64_t, cpu_ldq_data_ra)
64
+#include "qom/object.h"
307
-DO_LDFF1_ZPZ_D(sve_ldffbds_zd, uint64_t, int8_t, cpu_ldub_data_ra)
65
+#include "qemu/queue.h"
308
-DO_LDFF1_ZPZ_D(sve_ldffhds_zd, uint64_t, int16_t, cpu_lduw_data_ra)
66
+
309
-DO_LDFF1_ZPZ_D(sve_ldffsds_zd, uint64_t, int32_t, cpu_ldl_data_ra)
67
+#define TYPE_CLOCK "clock"
310
+ /* Skip to the first true predicate. */
68
+#define CLOCK(obj) OBJECT_CHECK(Clock, (obj), TYPE_CLOCK)
311
+ reg_off = find_next_active(vg, 0, reg_max, MO_32);
69
+
312
+ if (likely(reg_off < reg_max)) {
70
+typedef void ClockCallback(void *opaque);
313
+ /* Perform one normal read, which will fault or not. */
71
+
314
+ set_helper_retaddr(ra);
72
+/*
315
+ addr = off_fn(vm, reg_off);
73
+ * clock store a value representing the clock's period in 2^-32ns unit.
316
+ addr = base + (addr << scale);
74
+ * It can represent:
317
+ tlb_fn(env, vd, reg_off, addr, mmu_idx, ra);
75
+ * + periods from 2^-32ns up to 4seconds
318
+
76
+ * + frequency from ~0.25Hz 2e10Ghz
319
+ /* The rest of the reads will be non-faulting. */
77
+ * Resolution of frequency representation decreases with frequency:
320
+ set_helper_retaddr(0);
78
+ * + at 100MHz, resolution is ~2mHz
321
+ }
79
+ * + at 1Ghz, resolution is ~0.2Hz
322
+
80
+ * + at 10Ghz, resolution is ~20Hz
323
+ /* After any fault, zero the leading predicated false elements. */
81
+ */
324
+ swap_memzero(vd, reg_off);
82
+#define CLOCK_SECOND (1000000000llu << 32)
325
+
83
+
326
+ while (likely((reg_off += 4) < reg_max)) {
84
+/*
327
+ uint64_t pg = *(uint64_t *)(vg + (reg_off >> 6) * 8);
85
+ * macro helpers to convert to hertz / nanosecond
328
+ if (likely((pg >> (reg_off & 63)) & 1)) {
86
+ */
329
+ addr = off_fn(vm, reg_off);
87
+#define CLOCK_PERIOD_FROM_NS(ns) ((ns) * (CLOCK_SECOND / 1000000000llu))
330
+ addr = base + (addr << scale);
88
+#define CLOCK_PERIOD_TO_NS(per) ((per) / (CLOCK_SECOND / 1000000000llu))
331
+ if (!nonfault_fn(env, vd, reg_off, addr, mmu_idx)) {
89
+#define CLOCK_PERIOD_FROM_HZ(hz) (((hz) != 0) ? CLOCK_SECOND / (hz) : 0u)
332
+ record_fault(env, reg_off, reg_max);
90
+#define CLOCK_PERIOD_TO_HZ(per) (((per) != 0) ? CLOCK_SECOND / (per) : 0u)
333
+ break;
91
+
92
+/**
93
+ * Clock:
94
+ * @parent_obj: parent class
95
+ * @period: unsigned integer representing the period of the clock
96
+ * @canonical_path: clock path string cache (used for trace purpose)
97
+ * @callback: called when clock changes
98
+ * @callback_opaque: argument for @callback
99
+ * @source: source (or parent in clock tree) of the clock
100
+ * @children: list of clocks connected to this one (it is their source)
101
+ * @sibling: structure used to form a clock list
102
+ */
103
+
104
+typedef struct Clock Clock;
105
+
106
+struct Clock {
107
+ /*< private >*/
108
+ Object parent_obj;
109
+
110
+ /* all fields are private and should not be modified directly */
111
+
112
+ /* fields */
113
+ uint64_t period;
114
+ char *canonical_path;
115
+ ClockCallback *callback;
116
+ void *callback_opaque;
117
+
118
+ /* Clocks are organized in a clock tree */
119
+ Clock *source;
120
+ QLIST_HEAD(, Clock) children;
121
+ QLIST_ENTRY(Clock) sibling;
122
+};
123
+
124
+/**
125
+ * clock_setup_canonical_path:
126
+ * @clk: clock
127
+ *
128
+ * compute the canonical path of the clock (used by log messages)
129
+ */
130
+void clock_setup_canonical_path(Clock *clk);
131
+
132
+/**
133
+ * clock_set_callback:
134
+ * @clk: the clock to register the callback into
135
+ * @cb: the callback function
136
+ * @opaque: the argument to the callback
137
+ *
138
+ * Register a callback called on every clock update.
139
+ */
140
+void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque);
141
+
142
+/**
143
+ * clock_clear_callback:
144
+ * @clk: the clock to delete the callback from
145
+ *
146
+ * Unregister the callback registered with clock_set_callback.
147
+ */
148
+void clock_clear_callback(Clock *clk);
149
+
150
+/**
151
+ * clock_set_source:
152
+ * @clk: the clock.
153
+ * @src: the source clock
154
+ *
155
+ * Setup @src as the clock source of @clk. The current @src period
156
+ * value is also copied to @clk and its subtree but no callback is
157
+ * called.
158
+ * Further @src update will be propagated to @clk and its subtree.
159
+ */
160
+void clock_set_source(Clock *clk, Clock *src);
161
+
162
+/**
163
+ * clock_set:
164
+ * @clk: the clock to initialize.
165
+ * @value: the clock's value, 0 means unclocked
166
+ *
167
+ * Set the local cached period value of @clk to @value.
168
+ */
169
+void clock_set(Clock *clk, uint64_t value);
170
+
171
+static inline void clock_set_hz(Clock *clk, unsigned hz)
172
+{
173
+ clock_set(clk, CLOCK_PERIOD_FROM_HZ(hz));
174
+}
175
+
176
+static inline void clock_set_ns(Clock *clk, unsigned ns)
177
+{
178
+ clock_set(clk, CLOCK_PERIOD_FROM_NS(ns));
179
+}
180
+
181
+/**
182
+ * clock_propagate:
183
+ * @clk: the clock
184
+ *
185
+ * Propagate the clock period that has been previously configured using
186
+ * @clock_set(). This will update recursively all connected clocks.
187
+ * It is an error to call this function on a clock which has a source.
188
+ * Note: this function must not be called during device inititialization
189
+ * or migration.
190
+ */
191
+void clock_propagate(Clock *clk);
192
+
193
+/**
194
+ * clock_update:
195
+ * @clk: the clock to update.
196
+ * @value: the new clock's value, 0 means unclocked
197
+ *
198
+ * Update the @clk to the new @value. All connected clocks will be informed
199
+ * of this update. This is equivalent to call @clock_set() then
200
+ * @clock_propagate().
201
+ */
202
+static inline void clock_update(Clock *clk, uint64_t value)
203
+{
204
+ clock_set(clk, value);
205
+ clock_propagate(clk);
206
+}
207
+
208
+static inline void clock_update_hz(Clock *clk, unsigned hz)
209
+{
210
+ clock_update(clk, CLOCK_PERIOD_FROM_HZ(hz));
211
+}
212
+
213
+static inline void clock_update_ns(Clock *clk, unsigned ns)
214
+{
215
+ clock_update(clk, CLOCK_PERIOD_FROM_NS(ns));
216
+}
217
+
218
+/**
219
+ * clock_get:
220
+ * @clk: the clk to fetch the clock
221
+ *
222
+ * @return: the current period.
223
+ */
224
+static inline uint64_t clock_get(const Clock *clk)
225
+{
226
+ return clk->period;
227
+}
228
+
229
+static inline unsigned clock_get_hz(Clock *clk)
230
+{
231
+ return CLOCK_PERIOD_TO_HZ(clock_get(clk));
232
+}
233
+
234
+static inline unsigned clock_get_ns(Clock *clk)
235
+{
236
+ return CLOCK_PERIOD_TO_NS(clock_get(clk));
237
+}
238
+
239
+/**
240
+ * clock_is_enabled:
241
+ * @clk: a clock
242
+ *
243
+ * @return: true if the clock is running.
244
+ */
245
+static inline bool clock_is_enabled(const Clock *clk)
246
+{
247
+ return clock_get(clk) != 0;
248
+}
249
+
250
+static inline void clock_init(Clock *clk, uint64_t value)
251
+{
252
+ clock_set(clk, value);
253
+}
254
+static inline void clock_init_hz(Clock *clk, uint64_t value)
255
+{
256
+ clock_set_hz(clk, value);
257
+}
258
+static inline void clock_init_ns(Clock *clk, uint64_t value)
259
+{
260
+ clock_set_ns(clk, value);
261
+}
262
+
263
+#endif /* QEMU_HW_CLOCK_H */
264
diff --git a/hw/core/clock.c b/hw/core/clock.c
265
new file mode 100644
266
index XXXXXXX..XXXXXXX
267
--- /dev/null
268
+++ b/hw/core/clock.c
269
@@ -XXX,XX +XXX,XX @@
270
+/*
271
+ * Hardware Clocks
272
+ *
273
+ * Copyright GreenSocs 2016-2020
274
+ *
275
+ * Authors:
276
+ * Frederic Konrad
277
+ * Damien Hedde
278
+ *
279
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
280
+ * See the COPYING file in the top-level directory.
281
+ */
282
+
283
+#include "qemu/osdep.h"
284
+#include "hw/clock.h"
285
+#include "trace.h"
286
+
287
+#define CLOCK_PATH(_clk) (_clk->canonical_path)
288
+
289
+void clock_setup_canonical_path(Clock *clk)
290
+{
291
+ g_free(clk->canonical_path);
292
+ clk->canonical_path = object_get_canonical_path(OBJECT(clk));
293
+}
294
+
295
+void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque)
296
+{
297
+ clk->callback = cb;
298
+ clk->callback_opaque = opaque;
299
+}
300
+
301
+void clock_clear_callback(Clock *clk)
302
+{
303
+ clock_set_callback(clk, NULL, NULL);
304
+}
305
+
306
+void clock_set(Clock *clk, uint64_t period)
307
+{
308
+ trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_NS(clk->period),
309
+ CLOCK_PERIOD_TO_NS(period));
310
+ clk->period = period;
311
+}
312
+
313
+static void clock_propagate_period(Clock *clk, bool call_callbacks)
314
+{
315
+ Clock *child;
316
+
317
+ QLIST_FOREACH(child, &clk->children, sibling) {
318
+ if (child->period != clk->period) {
319
+ child->period = clk->period;
320
+ trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
321
+ CLOCK_PERIOD_TO_NS(clk->period),
322
+ call_callbacks);
323
+ if (call_callbacks && child->callback) {
324
+ child->callback(child->callback_opaque);
334
+ }
325
+ }
335
+ } else {
326
+ clock_propagate_period(child, call_callbacks);
336
+ *(uint32_t *)(vd + H1_4(reg_off)) = 0;
337
+ }
327
+ }
338
+ }
328
+ }
339
+}
329
+}
340
+
330
+
341
+static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
331
+void clock_propagate(Clock *clk)
342
+ target_ulong base, uint32_t desc, uintptr_t ra,
332
+{
343
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn,
333
+ assert(clk->source == NULL);
344
+ sve_ld1_nf_fn *nonfault_fn)
334
+ trace_clock_propagate(CLOCK_PATH(clk));
345
+{
335
+ clock_propagate_period(clk, true);
346
+ const int mmu_idx = cpu_mmu_index(env, false);
336
+}
347
+ intptr_t reg_off, reg_max = simd_oprsz(desc);
337
+
348
+ unsigned scale = simd_data(desc);
338
+void clock_set_source(Clock *clk, Clock *src)
349
+ target_ulong addr;
339
+{
350
+
340
+ /* changing clock source is not supported */
351
+ /* Skip to the first true predicate. */
341
+ assert(!clk->source);
352
+ reg_off = find_next_active(vg, 0, reg_max, MO_64);
342
+
353
+ if (likely(reg_off < reg_max)) {
343
+ trace_clock_set_source(CLOCK_PATH(clk), CLOCK_PATH(src));
354
+ /* Perform one normal read, which will fault or not. */
344
+
355
+ set_helper_retaddr(ra);
345
+ clk->period = src->period;
356
+ addr = off_fn(vm, reg_off);
346
+ QLIST_INSERT_HEAD(&src->children, clk, sibling);
357
+ addr = base + (addr << scale);
347
+ clk->source = src;
358
+ tlb_fn(env, vd, reg_off, addr, mmu_idx, ra);
348
+ clock_propagate_period(clk, false);
359
+
349
+}
360
+ /* The rest of the reads will be non-faulting. */
350
+
361
+ set_helper_retaddr(0);
351
+static void clock_disconnect(Clock *clk)
352
+{
353
+ if (clk->source == NULL) {
354
+ return;
362
+ }
355
+ }
363
+
356
+
364
+ /* After any fault, zero the leading predicated false elements. */
357
+ trace_clock_disconnect(CLOCK_PATH(clk));
365
+ swap_memzero(vd, reg_off);
358
+
366
+
359
+ clk->source = NULL;
367
+ while (likely((reg_off += 8) < reg_max)) {
360
+ QLIST_REMOVE(clk, sibling);
368
+ uint8_t pg = *(uint8_t *)(vg + H1(reg_off >> 3));
361
+}
369
+ if (likely(pg & 1)) {
362
+
370
+ addr = off_fn(vm, reg_off);
363
+static void clock_initfn(Object *obj)
371
+ addr = base + (addr << scale);
364
+{
372
+ if (!nonfault_fn(env, vd, reg_off, addr, mmu_idx)) {
365
+ Clock *clk = CLOCK(obj);
373
+ record_fault(env, reg_off, reg_max);
366
+
374
+ break;
367
+ QLIST_INIT(&clk->children);
375
+ }
368
+}
376
+ } else {
369
+
377
+ *(uint64_t *)(vd + reg_off) = 0;
370
+static void clock_finalizefn(Object *obj)
378
+ }
371
+{
372
+ Clock *clk = CLOCK(obj);
373
+ Clock *child, *next;
374
+
375
+ /* clear our list of children */
376
+ QLIST_FOREACH_SAFE(child, &clk->children, sibling, next) {
377
+ clock_disconnect(child);
379
+ }
378
+ }
380
+}
379
+
381
+
380
+ /* remove us from source's children list */
382
+#define DO_LDFF1_ZPZ_S(MEM, OFS) \
381
+ clock_disconnect(clk);
383
+void HELPER(sve_ldff##MEM##_##OFS) \
382
+
384
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
383
+ g_free(clk->canonical_path);
385
+ target_ulong base, uint32_t desc) \
384
+}
386
+{ \
385
+
387
+ sve_ldff1_zs(env, vd, vg, vm, base, desc, GETPC(), \
386
+static const TypeInfo clock_info = {
388
+ off_##OFS##_s, sve_ld1##MEM##_tlb, sve_ld##MEM##_nf); \
387
+ .name = TYPE_CLOCK,
389
+}
388
+ .parent = TYPE_OBJECT,
390
+
389
+ .instance_size = sizeof(Clock),
391
+#define DO_LDFF1_ZPZ_D(MEM, OFS) \
390
+ .instance_init = clock_initfn,
392
+void HELPER(sve_ldff##MEM##_##OFS) \
391
+ .instance_finalize = clock_finalizefn,
393
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
392
+};
394
+ target_ulong base, uint32_t desc) \
393
+
395
+{ \
394
+static void clock_register_types(void)
396
+ sve_ldff1_zd(env, vd, vg, vm, base, desc, GETPC(), \
395
+{
397
+ off_##OFS##_d, sve_ld1##MEM##_tlb, sve_ld##MEM##_nf); \
396
+ type_register_static(&clock_info);
398
+}
397
+}
399
+
398
+
400
+DO_LDFF1_ZPZ_S(bsu, zsu)
399
+type_init(clock_register_types)
401
+DO_LDFF1_ZPZ_S(bsu, zss)
400
diff --git a/hw/core/trace-events b/hw/core/trace-events
402
+DO_LDFF1_ZPZ_D(bdu, zsu)
403
+DO_LDFF1_ZPZ_D(bdu, zss)
404
+DO_LDFF1_ZPZ_D(bdu, zd)
405
+
406
+DO_LDFF1_ZPZ_S(bss, zsu)
407
+DO_LDFF1_ZPZ_S(bss, zss)
408
+DO_LDFF1_ZPZ_D(bds, zsu)
409
+DO_LDFF1_ZPZ_D(bds, zss)
410
+DO_LDFF1_ZPZ_D(bds, zd)
411
+
412
+DO_LDFF1_ZPZ_S(hsu_le, zsu)
413
+DO_LDFF1_ZPZ_S(hsu_le, zss)
414
+DO_LDFF1_ZPZ_D(hdu_le, zsu)
415
+DO_LDFF1_ZPZ_D(hdu_le, zss)
416
+DO_LDFF1_ZPZ_D(hdu_le, zd)
417
+
418
+DO_LDFF1_ZPZ_S(hsu_be, zsu)
419
+DO_LDFF1_ZPZ_S(hsu_be, zss)
420
+DO_LDFF1_ZPZ_D(hdu_be, zsu)
421
+DO_LDFF1_ZPZ_D(hdu_be, zss)
422
+DO_LDFF1_ZPZ_D(hdu_be, zd)
423
+
424
+DO_LDFF1_ZPZ_S(hss_le, zsu)
425
+DO_LDFF1_ZPZ_S(hss_le, zss)
426
+DO_LDFF1_ZPZ_D(hds_le, zsu)
427
+DO_LDFF1_ZPZ_D(hds_le, zss)
428
+DO_LDFF1_ZPZ_D(hds_le, zd)
429
+
430
+DO_LDFF1_ZPZ_S(hss_be, zsu)
431
+DO_LDFF1_ZPZ_S(hss_be, zss)
432
+DO_LDFF1_ZPZ_D(hds_be, zsu)
433
+DO_LDFF1_ZPZ_D(hds_be, zss)
434
+DO_LDFF1_ZPZ_D(hds_be, zd)
435
+
436
+DO_LDFF1_ZPZ_S(ss_le, zsu)
437
+DO_LDFF1_ZPZ_S(ss_le, zss)
438
+DO_LDFF1_ZPZ_D(sdu_le, zsu)
439
+DO_LDFF1_ZPZ_D(sdu_le, zss)
440
+DO_LDFF1_ZPZ_D(sdu_le, zd)
441
+
442
+DO_LDFF1_ZPZ_S(ss_be, zsu)
443
+DO_LDFF1_ZPZ_S(ss_be, zss)
444
+DO_LDFF1_ZPZ_D(sdu_be, zsu)
445
+DO_LDFF1_ZPZ_D(sdu_be, zss)
446
+DO_LDFF1_ZPZ_D(sdu_be, zd)
447
+
448
+DO_LDFF1_ZPZ_D(sds_le, zsu)
449
+DO_LDFF1_ZPZ_D(sds_le, zss)
450
+DO_LDFF1_ZPZ_D(sds_le, zd)
451
+
452
+DO_LDFF1_ZPZ_D(sds_be, zsu)
453
+DO_LDFF1_ZPZ_D(sds_be, zss)
454
+DO_LDFF1_ZPZ_D(sds_be, zd)
455
+
456
+DO_LDFF1_ZPZ_D(dd_le, zsu)
457
+DO_LDFF1_ZPZ_D(dd_le, zss)
458
+DO_LDFF1_ZPZ_D(dd_le, zd)
459
+
460
+DO_LDFF1_ZPZ_D(dd_be, zsu)
461
+DO_LDFF1_ZPZ_D(dd_be, zss)
462
+DO_LDFF1_ZPZ_D(dd_be, zd)
463
464
/* Stores with a vector index. */
465
466
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
467
index XXXXXXX..XXXXXXX 100644
401
index XXXXXXX..XXXXXXX 100644
468
--- a/target/arm/translate-sve.c
402
--- a/hw/core/trace-events
469
+++ b/target/arm/translate-sve.c
403
+++ b/hw/core/trace-events
470
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][2][3] = {
404
@@ -XXX,XX +XXX,XX @@ resettable_phase_exit_begin(void *obj, const char *objtype, unsigned count, int
471
405
resettable_phase_exit_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d"
472
/* First-fault */
406
resettable_phase_exit_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
473
{ { { gen_helper_sve_ldffbss_zsu,
407
resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)"
474
- gen_helper_sve_ldffhss_zsu,
408
+
475
+ gen_helper_sve_ldffhss_le_zsu,
409
+# clock.c
476
NULL, },
410
+clock_set_source(const char *clk, const char *src) "'%s', src='%s'"
477
{ gen_helper_sve_ldffbsu_zsu,
411
+clock_disconnect(const char *clk) "'%s'"
478
- gen_helper_sve_ldffhsu_zsu,
412
+clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', ns=%"PRIu64"->%"PRIu64
479
- gen_helper_sve_ldffssu_zsu, } },
413
+clock_propagate(const char *clk) "'%s'"
480
+ gen_helper_sve_ldffhsu_le_zsu,
414
+clock_update(const char *clk, const char *src, uint64_t val, int cb) "'%s', src='%s', ns=%"PRIu64", cb=%d"
481
+ gen_helper_sve_ldffss_le_zsu, } },
482
{ { gen_helper_sve_ldffbss_zss,
483
- gen_helper_sve_ldffhss_zss,
484
+ gen_helper_sve_ldffhss_le_zss,
485
NULL, },
486
{ gen_helper_sve_ldffbsu_zss,
487
- gen_helper_sve_ldffhsu_zss,
488
- gen_helper_sve_ldffssu_zss, } } } },
489
+ gen_helper_sve_ldffhsu_le_zss,
490
+ gen_helper_sve_ldffss_le_zss, } } } },
491
492
/* Big-endian */
493
{ { { { gen_helper_sve_ldbss_zsu,
494
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][2][3] = {
495
496
/* First-fault */
497
{ { { gen_helper_sve_ldffbss_zsu,
498
- gen_helper_sve_ldffhss_zsu,
499
+ gen_helper_sve_ldffhss_be_zsu,
500
NULL, },
501
{ gen_helper_sve_ldffbsu_zsu,
502
- gen_helper_sve_ldffhsu_zsu,
503
- gen_helper_sve_ldffssu_zsu, } },
504
+ gen_helper_sve_ldffhsu_be_zsu,
505
+ gen_helper_sve_ldffss_be_zsu, } },
506
{ { gen_helper_sve_ldffbss_zss,
507
- gen_helper_sve_ldffhss_zss,
508
+ gen_helper_sve_ldffhss_be_zss,
509
NULL, },
510
{ gen_helper_sve_ldffbsu_zss,
511
- gen_helper_sve_ldffhsu_zss,
512
- gen_helper_sve_ldffssu_zss, } } } },
513
+ gen_helper_sve_ldffhsu_be_zss,
514
+ gen_helper_sve_ldffss_be_zss, } } } },
515
};
516
517
/* Note that we overload xs=2 to indicate 64-bit offset. */
518
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][2][3][2][4] = {
519
520
/* First-fault */
521
{ { { gen_helper_sve_ldffbds_zsu,
522
- gen_helper_sve_ldffhds_zsu,
523
- gen_helper_sve_ldffsds_zsu,
524
+ gen_helper_sve_ldffhds_le_zsu,
525
+ gen_helper_sve_ldffsds_le_zsu,
526
NULL, },
527
{ gen_helper_sve_ldffbdu_zsu,
528
- gen_helper_sve_ldffhdu_zsu,
529
- gen_helper_sve_ldffsdu_zsu,
530
- gen_helper_sve_ldffddu_zsu, } },
531
+ gen_helper_sve_ldffhdu_le_zsu,
532
+ gen_helper_sve_ldffsdu_le_zsu,
533
+ gen_helper_sve_ldffdd_le_zsu, } },
534
{ { gen_helper_sve_ldffbds_zss,
535
- gen_helper_sve_ldffhds_zss,
536
- gen_helper_sve_ldffsds_zss,
537
+ gen_helper_sve_ldffhds_le_zss,
538
+ gen_helper_sve_ldffsds_le_zss,
539
NULL, },
540
{ gen_helper_sve_ldffbdu_zss,
541
- gen_helper_sve_ldffhdu_zss,
542
- gen_helper_sve_ldffsdu_zss,
543
- gen_helper_sve_ldffddu_zss, } },
544
+ gen_helper_sve_ldffhdu_le_zss,
545
+ gen_helper_sve_ldffsdu_le_zss,
546
+ gen_helper_sve_ldffdd_le_zss, } },
547
{ { gen_helper_sve_ldffbds_zd,
548
- gen_helper_sve_ldffhds_zd,
549
- gen_helper_sve_ldffsds_zd,
550
+ gen_helper_sve_ldffhds_le_zd,
551
+ gen_helper_sve_ldffsds_le_zd,
552
NULL, },
553
{ gen_helper_sve_ldffbdu_zd,
554
- gen_helper_sve_ldffhdu_zd,
555
- gen_helper_sve_ldffsdu_zd,
556
- gen_helper_sve_ldffddu_zd, } } } },
557
+ gen_helper_sve_ldffhdu_le_zd,
558
+ gen_helper_sve_ldffsdu_le_zd,
559
+ gen_helper_sve_ldffdd_le_zd, } } } },
560
561
/* Big-endian */
562
{ { { { gen_helper_sve_ldbds_zsu,
563
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][2][3][2][4] = {
564
565
/* First-fault */
566
{ { { gen_helper_sve_ldffbds_zsu,
567
- gen_helper_sve_ldffhds_zsu,
568
- gen_helper_sve_ldffsds_zsu,
569
+ gen_helper_sve_ldffhds_be_zsu,
570
+ gen_helper_sve_ldffsds_be_zsu,
571
NULL, },
572
{ gen_helper_sve_ldffbdu_zsu,
573
- gen_helper_sve_ldffhdu_zsu,
574
- gen_helper_sve_ldffsdu_zsu,
575
- gen_helper_sve_ldffddu_zsu, } },
576
+ gen_helper_sve_ldffhdu_be_zsu,
577
+ gen_helper_sve_ldffsdu_be_zsu,
578
+ gen_helper_sve_ldffdd_be_zsu, } },
579
{ { gen_helper_sve_ldffbds_zss,
580
- gen_helper_sve_ldffhds_zss,
581
- gen_helper_sve_ldffsds_zss,
582
+ gen_helper_sve_ldffhds_be_zss,
583
+ gen_helper_sve_ldffsds_be_zss,
584
NULL, },
585
{ gen_helper_sve_ldffbdu_zss,
586
- gen_helper_sve_ldffhdu_zss,
587
- gen_helper_sve_ldffsdu_zss,
588
- gen_helper_sve_ldffddu_zss, } },
589
+ gen_helper_sve_ldffhdu_be_zss,
590
+ gen_helper_sve_ldffsdu_be_zss,
591
+ gen_helper_sve_ldffdd_be_zss, } },
592
{ { gen_helper_sve_ldffbds_zd,
593
- gen_helper_sve_ldffhds_zd,
594
- gen_helper_sve_ldffsds_zd,
595
+ gen_helper_sve_ldffhds_be_zd,
596
+ gen_helper_sve_ldffsds_be_zd,
597
NULL, },
598
{ gen_helper_sve_ldffbdu_zd,
599
- gen_helper_sve_ldffhdu_zd,
600
- gen_helper_sve_ldffsdu_zd,
601
- gen_helper_sve_ldffddu_zd, } } } },
602
+ gen_helper_sve_ldffhdu_be_zd,
603
+ gen_helper_sve_ldffsdu_be_zd,
604
+ gen_helper_sve_ldffdd_be_zd, } } } },
605
};
606
607
static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
608
--
415
--
609
2.19.0
416
2.20.1
610
417
611
418
diff view generated by jsdifflib
1
Add v8M stack checks for the 16-bit Thumb push/pop
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
encodings: STMDB, STMFD, LDM, LDMIA, LDMFD.
3
2
3
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20200406135251.157596-3-damien.hedde@greensocs.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20181002163556.10279-12-peter.maydell@linaro.org
8
---
10
---
9
target/arm/translate.c | 16 +++++++++++++++-
11
hw/core/Makefile.objs | 1 +
10
1 file changed, 15 insertions(+), 1 deletion(-)
12
include/hw/clock.h | 9 +++++++++
13
hw/core/clock-vmstate.c | 25 +++++++++++++++++++++++++
14
3 files changed, 35 insertions(+)
15
create mode 100644 hw/core/clock-vmstate.c
11
16
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate.c
19
--- a/hw/core/Makefile.objs
15
+++ b/target/arm/translate.c
20
+++ b/hw/core/Makefile.objs
16
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
21
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SOFTMMU) += null-machine.o
17
store_reg(s, rd, tmp);
22
common-obj-$(CONFIG_SOFTMMU) += loader.o
18
break;
23
common-obj-$(CONFIG_SOFTMMU) += machine-hmp-cmds.o
19
case 4: case 5: case 0xc: case 0xd:
24
common-obj-$(CONFIG_SOFTMMU) += numa.o
20
- /* push/pop */
25
+common-obj-$(CONFIG_SOFTMMU) += clock-vmstate.o
21
+ /*
26
obj-$(CONFIG_SOFTMMU) += machine-qmp-cmds.o
22
+ * 0b1011_x10x_xxxx_xxxx
27
23
+ * - push/pop
28
common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
24
+ */
29
diff --git a/include/hw/clock.h b/include/hw/clock.h
25
addr = load_reg(s, 13);
30
index XXXXXXX..XXXXXXX 100644
26
if (insn & (1 << 8))
31
--- a/include/hw/clock.h
27
offset = 4;
32
+++ b/include/hw/clock.h
28
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
33
@@ -XXX,XX +XXX,XX @@ struct Clock {
29
if ((insn & (1 << 11)) == 0) {
34
QLIST_ENTRY(Clock) sibling;
30
tcg_gen_addi_i32(addr, addr, -offset);
35
};
31
}
36
37
+/*
38
+ * vmstate description entry to be added in device vmsd.
39
+ */
40
+extern const VMStateDescription vmstate_clock;
41
+#define VMSTATE_CLOCK(field, state) \
42
+ VMSTATE_CLOCK_V(field, state, 0)
43
+#define VMSTATE_CLOCK_V(field, state, version) \
44
+ VMSTATE_STRUCT_POINTER_V(field, state, version, vmstate_clock, Clock)
32
+
45
+
33
+ if (s->v8m_stackcheck) {
46
/**
34
+ /*
47
* clock_setup_canonical_path:
35
+ * Here 'addr' is the lower of "old SP" and "new SP";
48
* @clk: clock
36
+ * if this is a pop that starts below the limit and ends
49
diff --git a/hw/core/clock-vmstate.c b/hw/core/clock-vmstate.c
37
+ * above it, it is UNKNOWN whether the limit check triggers;
50
new file mode 100644
38
+ * we choose to trigger.
51
index XXXXXXX..XXXXXXX
39
+ */
52
--- /dev/null
40
+ gen_helper_v8m_stackcheck(cpu_env, addr);
53
+++ b/hw/core/clock-vmstate.c
41
+ }
54
@@ -XXX,XX +XXX,XX @@
55
+/*
56
+ * Clock migration structure
57
+ *
58
+ * Copyright GreenSocs 2019-2020
59
+ *
60
+ * Authors:
61
+ * Damien Hedde
62
+ *
63
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
64
+ * See the COPYING file in the top-level directory.
65
+ */
42
+
66
+
43
for (i = 0; i < 8; i++) {
67
+#include "qemu/osdep.h"
44
if (insn & (1 << i)) {
68
+#include "migration/vmstate.h"
45
if (insn & (1 << 11)) {
69
+#include "hw/clock.h"
70
+
71
+const VMStateDescription vmstate_clock = {
72
+ .name = "clock",
73
+ .version_id = 0,
74
+ .minimum_version_id = 0,
75
+ .fields = (VMStateField[]) {
76
+ VMSTATE_UINT64(period, Clock),
77
+ VMSTATE_END_OF_LIST()
78
+ }
79
+};
46
--
80
--
47
2.19.0
81
2.20.1
48
82
49
83
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
2
3
Check for EL3 before testing CPTR_EL3.EZ. Return 0 when the exception
3
Add functions to easily handle clocks with devices.
4
should be routed via AdvSIMDFPAccessTrap. Mirror the structure of
4
Clock inputs and outputs should be used to handle clock propagation
5
CheckSVEEnabled more closely.
5
between devices.
6
6
The API is very similar the GPIO API.
7
Fixes: 5be5e8eda78
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
This is based on the original work of Frederic Konrad.
9
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
11
Message-id: 20181005175350.30752-3-richard.henderson@linaro.org
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-id: 20200406135251.157596-4-damien.hedde@greensocs.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
15
---
14
target/arm/helper.c | 96 ++++++++++++++++++++++-----------------------
16
hw/core/Makefile.objs | 2 +-
15
1 file changed, 46 insertions(+), 50 deletions(-)
17
tests/Makefile.include | 1 +
16
18
include/hw/qdev-clock.h | 104 +++++++++++++++++++++++++
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
include/hw/qdev-core.h | 12 +++
20
hw/core/qdev-clock.c | 168 ++++++++++++++++++++++++++++++++++++++++
21
hw/core/qdev.c | 12 +++
22
6 files changed, 298 insertions(+), 1 deletion(-)
23
create mode 100644 include/hw/qdev-clock.h
24
create mode 100644 hw/core/qdev-clock.c
25
26
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
18
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
28
--- a/hw/core/Makefile.objs
20
+++ b/target/arm/helper.c
29
+++ b/hw/core/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
30
@@ -XXX,XX +XXX,XX @@ common-obj-y += hotplug.o
22
REGINFO_SENTINEL
31
common-obj-y += vmstate-if.o
32
# irq.o needed for qdev GPIO handling:
33
common-obj-y += irq.o
34
-common-obj-y += clock.o
35
+common-obj-y += clock.o qdev-clock.o
36
37
common-obj-$(CONFIG_SOFTMMU) += reset.o
38
common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
39
diff --git a/tests/Makefile.include b/tests/Makefile.include
40
index XXXXXXX..XXXXXXX 100644
41
--- a/tests/Makefile.include
42
+++ b/tests/Makefile.include
43
@@ -XXX,XX +XXX,XX @@ tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
44
    hw/core/fw-path-provider.o \
45
    hw/core/reset.o \
46
    hw/core/vmstate-if.o \
47
+    hw/core/clock.o hw/core/qdev-clock.o \
48
    $(test-qapi-obj-y)
49
tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
50
    migration/vmstate.o migration/vmstate-types.o migration/qemu-file.o \
51
diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h
52
new file mode 100644
53
index XXXXXXX..XXXXXXX
54
--- /dev/null
55
+++ b/include/hw/qdev-clock.h
56
@@ -XXX,XX +XXX,XX @@
57
+/*
58
+ * Device's clock input and output
59
+ *
60
+ * Copyright GreenSocs 2016-2020
61
+ *
62
+ * Authors:
63
+ * Frederic Konrad
64
+ * Damien Hedde
65
+ *
66
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
67
+ * See the COPYING file in the top-level directory.
68
+ */
69
+
70
+#ifndef QDEV_CLOCK_H
71
+#define QDEV_CLOCK_H
72
+
73
+#include "hw/clock.h"
74
+
75
+/**
76
+ * qdev_init_clock_in:
77
+ * @dev: the device to add an input clock to
78
+ * @name: the name of the clock (can't be NULL).
79
+ * @callback: optional callback to be called on update or NULL.
80
+ * @opaque: argument for the callback
81
+ * @returns: a pointer to the newly added clock
82
+ *
83
+ * Add an input clock to device @dev as a clock named @name.
84
+ * This adds a child<> property.
85
+ * The callback will be called with @opaque as opaque parameter.
86
+ */
87
+Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
88
+ ClockCallback *callback, void *opaque);
89
+
90
+/**
91
+ * qdev_init_clock_out:
92
+ * @dev: the device to add an output clock to
93
+ * @name: the name of the clock (can't be NULL).
94
+ * @returns: a pointer to the newly added clock
95
+ *
96
+ * Add an output clock to device @dev as a clock named @name.
97
+ * This adds a child<> property.
98
+ */
99
+Clock *qdev_init_clock_out(DeviceState *dev, const char *name);
100
+
101
+/**
102
+ * qdev_get_clock_in:
103
+ * @dev: the device which has the clock
104
+ * @name: the name of the clock (can't be NULL).
105
+ * @returns: a pointer to the clock
106
+ *
107
+ * Get the input clock @name from @dev or NULL if does not exist.
108
+ */
109
+Clock *qdev_get_clock_in(DeviceState *dev, const char *name);
110
+
111
+/**
112
+ * qdev_get_clock_out:
113
+ * @dev: the device which has the clock
114
+ * @name: the name of the clock (can't be NULL).
115
+ * @returns: a pointer to the clock
116
+ *
117
+ * Get the output clock @name from @dev or NULL if does not exist.
118
+ */
119
+Clock *qdev_get_clock_out(DeviceState *dev, const char *name);
120
+
121
+/**
122
+ * qdev_connect_clock_in:
123
+ * @dev: a device
124
+ * @name: the name of an input clock in @dev
125
+ * @source: the source clock (an output clock of another device for example)
126
+ *
127
+ * Set the source clock of input clock @name of device @dev to @source.
128
+ * @source period update will be propagated to @name clock.
129
+ */
130
+static inline void qdev_connect_clock_in(DeviceState *dev, const char *name,
131
+ Clock *source)
132
+{
133
+ clock_set_source(qdev_get_clock_in(dev, name), source);
134
+}
135
+
136
+/**
137
+ * qdev_alias_clock:
138
+ * @dev: the device which has the clock
139
+ * @name: the name of the clock in @dev (can't be NULL)
140
+ * @alias_dev: the device to add the clock
141
+ * @alias_name: the name of the clock in @container
142
+ * @returns: a pointer to the clock
143
+ *
144
+ * Add a clock @alias_name in @alias_dev which is an alias of the clock @name
145
+ * in @dev. The direction _in_ or _out_ will the same as the original.
146
+ * An alias clock must not be modified or used by @alias_dev and should
147
+ * typically be only only for device composition purpose.
148
+ */
149
+Clock *qdev_alias_clock(DeviceState *dev, const char *name,
150
+ DeviceState *alias_dev, const char *alias_name);
151
+
152
+/**
153
+ * qdev_finalize_clocklist:
154
+ * @dev: the device being finalized
155
+ *
156
+ * Clear the clocklist from @dev. Only used internally in qdev.
157
+ */
158
+void qdev_finalize_clocklist(DeviceState *dev);
159
+
160
+#endif /* QDEV_CLOCK_H */
161
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
162
index XXXXXXX..XXXXXXX 100644
163
--- a/include/hw/qdev-core.h
164
+++ b/include/hw/qdev-core.h
165
@@ -XXX,XX +XXX,XX @@ struct NamedGPIOList {
166
QLIST_ENTRY(NamedGPIOList) node;
23
};
167
};
24
168
25
-/* Return the exception level to which SVE-disabled exceptions should
169
+typedef struct Clock Clock;
26
- * be taken, or 0 if SVE is enabled.
170
+typedef struct NamedClockList NamedClockList;
27
+/* Return the exception level to which exceptions should be taken
171
+
28
+ * via SVEAccessTrap. If an exception should be routed through
172
+struct NamedClockList {
29
+ * AArch64.AdvSIMDFPAccessTrap, return 0; fp_exception_el should
173
+ char *name;
30
+ * take care of raising that exception.
174
+ Clock *clock;
31
+ * C.f. the ARM pseudocode function CheckSVEEnabled.
175
+ bool output;
32
*/
176
+ bool alias;
33
static int sve_exception_el(CPUARMState *env)
177
+ QLIST_ENTRY(NamedClockList) node;
34
{
178
+};
35
#ifndef CONFIG_USER_ONLY
179
+
36
unsigned current_el = arm_current_el(env);
180
/**
37
181
* DeviceState:
38
- /* The CPACR.ZEN controls traps to EL1:
182
* @realized: Indicates whether the device has been fully constructed.
39
- * 0, 2 : trap EL0 and EL1 accesses
183
@@ -XXX,XX +XXX,XX @@ struct DeviceState {
40
- * 1 : trap only EL0 accesses
184
bool allow_unplug_during_migration;
41
- * 3 : trap no accesses
185
BusState *parent_bus;
42
+ if (current_el <= 1) {
186
QLIST_HEAD(, NamedGPIOList) gpios;
43
+ bool disabled = false;
187
+ QLIST_HEAD(, NamedClockList) clocks;
44
+
188
QLIST_HEAD(, BusState) child_bus;
45
+ /* The CPACR.ZEN controls traps to EL1:
189
int num_child_bus;
46
+ * 0, 2 : trap EL0 and EL1 accesses
190
int instance_id_alias;
47
+ * 1 : trap only EL0 accesses
191
diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c
48
+ * 3 : trap no accesses
192
new file mode 100644
49
+ */
193
index XXXXXXX..XXXXXXX
50
+ if (!extract32(env->cp15.cpacr_el1, 16, 1)) {
194
--- /dev/null
51
+ disabled = true;
195
+++ b/hw/core/qdev-clock.c
52
+ } else if (!extract32(env->cp15.cpacr_el1, 17, 1)) {
196
@@ -XXX,XX +XXX,XX @@
53
+ disabled = current_el == 0;
197
+/*
198
+ * Device's clock input and output
199
+ *
200
+ * Copyright GreenSocs 2016-2020
201
+ *
202
+ * Authors:
203
+ * Frederic Konrad
204
+ * Damien Hedde
205
+ *
206
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
207
+ * See the COPYING file in the top-level directory.
208
+ */
209
+
210
+#include "qemu/osdep.h"
211
+#include "hw/qdev-clock.h"
212
+#include "hw/qdev-core.h"
213
+#include "qapi/error.h"
214
+
215
+/*
216
+ * qdev_init_clocklist:
217
+ * Add a new clock in a device
218
+ */
219
+static NamedClockList *qdev_init_clocklist(DeviceState *dev, const char *name,
220
+ bool output, Clock *clk)
221
+{
222
+ NamedClockList *ncl;
223
+
224
+ /*
225
+ * Clock must be added before realize() so that we can compute the
226
+ * clock's canonical path during device_realize().
227
+ */
228
+ assert(!dev->realized);
229
+
230
+ /*
231
+ * The ncl structure is freed by qdev_finalize_clocklist() which will
232
+ * be called during @dev's device_finalize().
233
+ */
234
+ ncl = g_new0(NamedClockList, 1);
235
+ ncl->name = g_strdup(name);
236
+ ncl->output = output;
237
+ ncl->alias = (clk != NULL);
238
+
239
+ /*
240
+ * Trying to create a clock whose name clashes with some other
241
+ * clock or property is a bug in the caller and we will abort().
242
+ */
243
+ if (clk == NULL) {
244
+ clk = CLOCK(object_new(TYPE_CLOCK));
245
+ object_property_add_child(OBJECT(dev), name, OBJECT(clk), &error_abort);
246
+ if (output) {
247
+ /*
248
+ * Remove object_new()'s initial reference.
249
+ * Note that for inputs, the reference created by object_new()
250
+ * will be deleted in qdev_finalize_clocklist().
251
+ */
252
+ object_unref(OBJECT(clk));
54
+ }
253
+ }
55
+ if (disabled) {
254
+ } else {
56
+ /* route_to_el2 */
255
+ object_property_add_link(OBJECT(dev), name,
57
+ return (arm_feature(env, ARM_FEATURE_EL2)
256
+ object_get_typename(OBJECT(clk)),
58
+ && !arm_is_secure(env)
257
+ (Object **) &ncl->clock,
59
+ && (env->cp15.hcr_el2 & HCR_TGE) ? 2 : 1);
258
+ NULL, OBJ_PROP_LINK_STRONG, &error_abort);
259
+ }
260
+
261
+ ncl->clock = clk;
262
+
263
+ QLIST_INSERT_HEAD(&dev->clocks, ncl, node);
264
+ return ncl;
265
+}
266
+
267
+void qdev_finalize_clocklist(DeviceState *dev)
268
+{
269
+ /* called by @dev's device_finalize() */
270
+ NamedClockList *ncl, *ncl_next;
271
+
272
+ QLIST_FOREACH_SAFE(ncl, &dev->clocks, node, ncl_next) {
273
+ QLIST_REMOVE(ncl, node);
274
+ if (!ncl->output && !ncl->alias) {
275
+ /*
276
+ * We kept a reference on the input clock to ensure it lives up to
277
+ * this point so we can safely remove the callback.
278
+ * It avoids having a callback to a deleted object if ncl->clock
279
+ * is still referenced somewhere else (eg: by a clock output).
280
+ */
281
+ clock_clear_callback(ncl->clock);
282
+ object_unref(OBJECT(ncl->clock));
60
+ }
283
+ }
61
+
284
+ g_free(ncl->name);
62
+ /* Check CPACR.FPEN. */
285
+ g_free(ncl);
63
+ if (!extract32(env->cp15.cpacr_el1, 20, 1)) {
286
+ }
64
+ disabled = true;
287
+}
65
+ } else if (!extract32(env->cp15.cpacr_el1, 21, 1)) {
288
+
66
+ disabled = current_el == 0;
289
+Clock *qdev_init_clock_out(DeviceState *dev, const char *name)
67
+ }
290
+{
68
+ if (disabled) {
291
+ NamedClockList *ncl;
69
+ return 0;
292
+
293
+ assert(name);
294
+
295
+ ncl = qdev_init_clocklist(dev, name, true, NULL);
296
+
297
+ return ncl->clock;
298
+}
299
+
300
+Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
301
+ ClockCallback *callback, void *opaque)
302
+{
303
+ NamedClockList *ncl;
304
+
305
+ assert(name);
306
+
307
+ ncl = qdev_init_clocklist(dev, name, false, NULL);
308
+
309
+ if (callback) {
310
+ clock_set_callback(ncl->clock, callback, opaque);
311
+ }
312
+ return ncl->clock;
313
+}
314
+
315
+static NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name)
316
+{
317
+ NamedClockList *ncl;
318
+
319
+ QLIST_FOREACH(ncl, &dev->clocks, node) {
320
+ if (strcmp(name, ncl->name) == 0) {
321
+ return ncl;
70
+ }
322
+ }
71
+ }
323
+ }
72
+
324
+
73
+ /* CPTR_EL2. Since TZ and TFP are positive,
325
+ return NULL;
74
+ * they will be zero when EL2 is not present.
326
+}
75
*/
327
+
76
- switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
328
+Clock *qdev_get_clock_in(DeviceState *dev, const char *name)
77
- default:
329
+{
78
- if (current_el <= 1) {
330
+ NamedClockList *ncl;
79
- /* Trap to PL1, which might be EL1 or EL3 */
331
+
80
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
332
+ assert(name);
81
- return 3;
333
+
82
- }
334
+ ncl = qdev_get_clocklist(dev, name);
83
- return 1;
335
+ assert(!ncl->output);
84
+ if (current_el <= 2 && !arm_is_secure_below_el3(env)) {
336
+
85
+ if (env->cp15.cptr_el[2] & CPTR_TZ) {
337
+ return ncl->clock;
86
+ return 2;
338
+}
87
}
339
+
88
- break;
340
+Clock *qdev_get_clock_out(DeviceState *dev, const char *name)
89
- case 1:
341
+{
90
- if (current_el == 0) {
342
+ NamedClockList *ncl;
91
- return 1;
343
+
92
+ if (env->cp15.cptr_el[2] & CPTR_TFP) {
344
+ assert(name);
93
+ return 0;
345
+
94
}
346
+ ncl = qdev_get_clocklist(dev, name);
95
- break;
347
+ assert(ncl->output);
96
- case 3:
348
+
97
- break;
349
+ return ncl->clock;
350
+}
351
+
352
+Clock *qdev_alias_clock(DeviceState *dev, const char *name,
353
+ DeviceState *alias_dev, const char *alias_name)
354
+{
355
+ NamedClockList *ncl;
356
+
357
+ assert(name && alias_name);
358
+
359
+ ncl = qdev_get_clocklist(dev, name);
360
+
361
+ qdev_init_clocklist(alias_dev, alias_name, ncl->output, ncl->clock);
362
+
363
+ return ncl->clock;
364
+}
365
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
366
index XXXXXXX..XXXXXXX 100644
367
--- a/hw/core/qdev.c
368
+++ b/hw/core/qdev.c
369
@@ -XXX,XX +XXX,XX @@
370
#include "hw/qdev-properties.h"
371
#include "hw/boards.h"
372
#include "hw/sysbus.h"
373
+#include "hw/qdev-clock.h"
374
#include "migration/vmstate.h"
375
#include "trace.h"
376
377
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
378
DeviceClass *dc = DEVICE_GET_CLASS(dev);
379
HotplugHandler *hotplug_ctrl;
380
BusState *bus;
381
+ NamedClockList *ncl;
382
Error *local_err = NULL;
383
bool unattached_parent = false;
384
static int unattached_count;
385
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
386
*/
387
g_free(dev->canonical_path);
388
dev->canonical_path = object_get_canonical_path(OBJECT(dev));
389
+ QLIST_FOREACH(ncl, &dev->clocks, node) {
390
+ if (ncl->alias) {
391
+ continue;
392
+ } else {
393
+ clock_setup_canonical_path(ncl->clock);
394
+ }
395
+ }
396
397
if (qdev_get_vmsd(dev)) {
398
if (vmstate_register_with_alias_id(VMSTATE_IF(dev),
399
@@ -XXX,XX +XXX,XX @@ static void device_initfn(Object *obj)
400
dev->allow_unplug_during_migration = false;
401
402
QLIST_INIT(&dev->gpios);
403
+ QLIST_INIT(&dev->clocks);
404
}
405
406
static void device_post_init(Object *obj)
407
@@ -XXX,XX +XXX,XX @@ static void device_finalize(Object *obj)
408
*/
98
}
409
}
99
410
100
- /* Similarly for CPACR.FPEN, after having checked ZEN. */
411
+ qdev_finalize_clocklist(dev);
101
- switch (extract32(env->cp15.cpacr_el1, 20, 2)) {
412
+
102
- default:
413
/* Only send event if the device had been completely realized */
103
- if (current_el <= 1) {
414
if (dev->pending_deleted_event) {
104
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
415
g_assert(dev->canonical_path);
105
- return 3;
106
- }
107
- return 1;
108
- }
109
- break;
110
- case 1:
111
- if (current_el == 0) {
112
- return 1;
113
- }
114
- break;
115
- case 3:
116
- break;
117
- }
118
-
119
- /* CPTR_EL2. Check both TZ and TFP. */
120
- if (current_el <= 2
121
- && (env->cp15.cptr_el[2] & (CPTR_TFP | CPTR_TZ))
122
- && !arm_is_secure_below_el3(env)) {
123
- return 2;
124
- }
125
-
126
- /* CPTR_EL3. Check both EZ and TFP. */
127
- if (!(env->cp15.cptr_el[3] & CPTR_EZ)
128
- || (env->cp15.cptr_el[3] & CPTR_TFP)) {
129
+ /* CPTR_EL3. Since EZ is negative we must check for EL3. */
130
+ if (arm_feature(env, ARM_FEATURE_EL3)
131
+ && !(env->cp15.cptr_el[3] & CPTR_EZ)) {
132
return 3;
133
}
134
#endif
135
--
416
--
136
2.19.0
417
2.20.1
137
418
138
419
diff view generated by jsdifflib
1
We're going to want v7m_using_psp() in op_helper.c in the
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
next patch, so move it from helper.c to internals.h.
3
2
3
Introduce a function and macro helpers to setup several clocks
4
in a device from a static array description.
5
6
An element of the array describes the clock (name and direction) as
7
well as the related callback and an optional offset to store the
8
created object pointer in the device state structure.
9
10
The array must be terminated by a special element QDEV_CLOCK_END.
11
12
This is based on the original work of Frederic Konrad.
13
14
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
18
Message-id: 20200406135251.157596-5-damien.hedde@greensocs.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20181002163556.10279-4-peter.maydell@linaro.org
8
---
20
---
9
target/arm/internals.h | 16 ++++++++++++++++
21
include/hw/qdev-clock.h | 55 +++++++++++++++++++++++++++++++++++++++++
10
target/arm/helper.c | 12 ------------
22
hw/core/qdev-clock.c | 17 +++++++++++++
11
2 files changed, 16 insertions(+), 12 deletions(-)
23
2 files changed, 72 insertions(+)
12
24
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
25
diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h
14
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/internals.h
27
--- a/include/hw/qdev-clock.h
16
+++ b/target/arm/internals.h
28
+++ b/include/hw/qdev-clock.h
17
@@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
29
@@ -XXX,XX +XXX,XX @@ Clock *qdev_alias_clock(DeviceState *dev, const char *name,
18
*/
30
*/
19
#define MEMOPIDX_SHIFT 8
31
void qdev_finalize_clocklist(DeviceState *dev);
20
32
21
+/**
33
+/**
22
+ * v7m_using_psp: Return true if using process stack pointer
34
+ * ClockPortInitElem:
23
+ * Return true if the CPU is currently using the process stack
35
+ * @name: name of the clock (can't be NULL)
24
+ * pointer, or false if it is using the main stack pointer.
36
+ * @output: indicates whether the clock is input or output
37
+ * @callback: for inputs, optional callback to be called on clock's update
38
+ * with device as opaque
39
+ * @offset: optional offset to store the ClockIn or ClockOut pointer in device
40
+ * state structure (0 means unused)
25
+ */
41
+ */
26
+static inline bool v7m_using_psp(CPUARMState *env)
42
+struct ClockPortInitElem {
27
+{
43
+ const char *name;
28
+ /* Handler mode always uses the main stack; for thread mode
44
+ bool is_output;
29
+ * the CONTROL.SPSEL bit determines the answer.
45
+ ClockCallback *callback;
30
+ * Note that in v7M it is not possible to be in Handler mode with
46
+ size_t offset;
31
+ * CONTROL.SPSEL non-zero, but in v8M it is, so we must check both.
47
+};
32
+ */
48
+
33
+ return !arm_v7m_is_handler_mode(env) &&
49
+#define clock_offset_value(devstate, field) \
34
+ env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
50
+ (offsetof(devstate, field) + \
51
+ type_check(Clock *, typeof_field(devstate, field)))
52
+
53
+#define QDEV_CLOCK(out_not_in, devstate, field, cb) { \
54
+ .name = (stringify(field)), \
55
+ .is_output = out_not_in, \
56
+ .callback = cb, \
57
+ .offset = clock_offset_value(devstate, field), \
35
+}
58
+}
36
+
59
+
37
#endif
60
+/**
38
diff --git a/target/arm/helper.c b/target/arm/helper.c
61
+ * QDEV_CLOCK_(IN|OUT):
62
+ * @devstate: structure type. @dev argument of qdev_init_clocks below must be
63
+ * a pointer to that same type.
64
+ * @field: a field in @_devstate (must be Clock*)
65
+ * @callback: (for input only) callback (or NULL) to be called with the device
66
+ * state as argument
67
+ *
68
+ * The name of the clock will be derived from @field
69
+ */
70
+#define QDEV_CLOCK_IN(devstate, field, callback) \
71
+ QDEV_CLOCK(false, devstate, field, callback)
72
+
73
+#define QDEV_CLOCK_OUT(devstate, field) \
74
+ QDEV_CLOCK(true, devstate, field, NULL)
75
+
76
+#define QDEV_CLOCK_END { .name = NULL }
77
+
78
+typedef struct ClockPortInitElem ClockPortInitArray[];
79
+
80
+/**
81
+ * qdev_init_clocks:
82
+ * @dev: the device to add clocks to
83
+ * @clocks: a QDEV_CLOCK_END-terminated array which contains the
84
+ * clocks information.
85
+ */
86
+void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks);
87
+
88
#endif /* QDEV_CLOCK_H */
89
diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c
39
index XXXXXXX..XXXXXXX 100644
90
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/helper.c
91
--- a/hw/core/qdev-clock.c
41
+++ b/target/arm/helper.c
92
+++ b/hw/core/qdev-clock.c
42
@@ -XXX,XX +XXX,XX @@ pend_fault:
93
@@ -XXX,XX +XXX,XX @@ Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
43
return false;
94
return ncl->clock;
44
}
95
}
45
96
46
-/* Return true if we're using the process stack pointer (not the MSP) */
97
+void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks)
47
-static bool v7m_using_psp(CPUARMState *env)
98
+{
48
-{
99
+ const struct ClockPortInitElem *elem;
49
- /* Handler mode always uses the main stack; for thread mode
100
+
50
- * the CONTROL.SPSEL bit determines the answer.
101
+ for (elem = &clocks[0]; elem->name != NULL; elem++) {
51
- * Note that in v7M it is not possible to be in Handler mode with
102
+ Clock **clkp;
52
- * CONTROL.SPSEL non-zero, but in v8M it is, so we must check both.
103
+ /* offset cannot be inside the DeviceState part */
53
- */
104
+ assert(elem->offset > sizeof(DeviceState));
54
- return !arm_v7m_is_handler_mode(env) &&
105
+ clkp = (Clock **)(((void *) dev) + elem->offset);
55
- env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
106
+ if (elem->is_output) {
56
-}
107
+ *clkp = qdev_init_clock_out(dev, elem->name);
57
-
108
+ } else {
58
/* Write to v7M CONTROL.SPSEL bit for the specified security bank.
109
+ *clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev);
59
* This may change the current stack pointer between Main and Process
110
+ }
60
* stack pointers if it is done for the CONTROL register for the current
111
+ }
112
+}
113
+
114
static NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name)
115
{
116
NamedClockList *ncl;
61
--
117
--
62
2.19.0
118
2.20.1
63
119
64
120
diff view generated by jsdifflib
1
Add the v8M stack checks for:
1
Add the documentation about the clock inputs and outputs in devices.
2
* LDM (T2 encoding)
3
* STM (T2 encoding)
4
2
5
This includes the 32-bit encodings of the instructions listed
3
This is based on the original work of Frederic Konrad.
6
in v8M ARM ARM rule R_YVWT as
7
* LDM, LDMIA, LDMFD
8
* LDMDB, LDMEA
9
* POP (multiple registers)
10
* PUSH (muliple registers)
11
* STM, STMIA, STMEA
12
* STMDB, STMFD
13
4
14
We perform the stack limit before doing any other part
5
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
15
of the load or store.
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20200406135251.157596-6-damien.hedde@greensocs.com
9
[PMM: Editing pass for minor grammar, style and Sphinx
10
formatting fixes]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
docs/devel/clocks.rst | 391 ++++++++++++++++++++++++++++++++++++++++++
15
docs/devel/index.rst | 1 +
16
2 files changed, 392 insertions(+)
17
create mode 100644 docs/devel/clocks.rst
16
18
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
20
new file mode 100644
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
index XXXXXXX..XXXXXXX
20
Message-id: 20181002163556.10279-10-peter.maydell@linaro.org
22
--- /dev/null
21
---
23
+++ b/docs/devel/clocks.rst
22
target/arm/translate.c | 19 ++++++++++++++++++-
24
@@ -XXX,XX +XXX,XX @@
23
1 file changed, 18 insertions(+), 1 deletion(-)
25
+Modelling a clock tree in QEMU
24
26
+==============================
25
diff --git a/target/arm/translate.c b/target/arm/translate.c
27
+
28
+What are clocks?
29
+----------------
30
+
31
+Clocks are QOM objects developed for the purpose of modelling the
32
+distribution of clocks in QEMU.
33
+
34
+They allow us to model the clock distribution of a platform and detect
35
+configuration errors in the clock tree such as badly configured PLL, clock
36
+source selection or disabled clock.
37
+
38
+The object is *Clock* and its QOM name is ``clock`` (in C code, the macro
39
+``TYPE_CLOCK``).
40
+
41
+Clocks are typically used with devices where they are used to model inputs
42
+and outputs. They are created in a similar way to GPIOs. Inputs and outputs
43
+of different devices can be connected together.
44
+
45
+In these cases a Clock object is a child of a Device object, but this
46
+is not a requirement. Clocks can be independent of devices. For
47
+example it is possible to create a clock outside of any device to
48
+model the main clock source of a machine.
49
+
50
+Here is an example of clocks::
51
+
52
+ +---------+ +----------------------+ +--------------+
53
+ | Clock 1 | | Device B | | Device C |
54
+ | | | +-------+ +-------+ | | +-------+ |
55
+ | |>>-+-->>|Clock 2| |Clock 3|>>--->>|Clock 6| |
56
+ +---------+ | | | (in) | | (out) | | | | (in) | |
57
+ | | +-------+ +-------+ | | +-------+ |
58
+ | | +-------+ | +--------------+
59
+ | | |Clock 4|>>
60
+ | | | (out) | | +--------------+
61
+ | | +-------+ | | Device D |
62
+ | | +-------+ | | +-------+ |
63
+ | | |Clock 5|>>--->>|Clock 7| |
64
+ | | | (out) | | | | (in) | |
65
+ | | +-------+ | | +-------+ |
66
+ | +----------------------+ | |
67
+ | | +-------+ |
68
+ +----------------------------->>|Clock 8| |
69
+ | | (in) | |
70
+ | +-------+ |
71
+ +--------------+
72
+
73
+Clocks are defined in the ``include/hw/clock.h`` header and device
74
+related functions are defined in the ``include/hw/qdev-clock.h``
75
+header.
76
+
77
+The clock state
78
+---------------
79
+
80
+The state of a clock is its period; it is stored as an integer
81
+representing it in units of 2 :sup:`-32` ns. The special value of 0 is used to
82
+represent the clock being inactive or gated. The clocks do not model
83
+the signal itself (pin toggling) or other properties such as the duty
84
+cycle.
85
+
86
+All clocks contain this state: outputs as well as inputs. This allows
87
+the current period of a clock to be fetched at any time. When a clock
88
+is updated, the value is immediately propagated to all connected
89
+clocks in the tree.
90
+
91
+To ease interaction with clocks, helpers with a unit suffix are defined for
92
+every clock state setter or getter. The suffixes are:
93
+
94
+- ``_ns`` for handling periods in nanoseconds
95
+- ``_hz`` for handling frequencies in hertz
96
+
97
+The 0 period value is converted to 0 in hertz and vice versa. 0 always means
98
+that the clock is disabled.
99
+
100
+Adding a new clock
101
+------------------
102
+
103
+Adding clocks to a device must be done during the init method of the Device
104
+instance.
105
+
106
+To add an input clock to a device, the function ``qdev_init_clock_in()``
107
+must be used. It takes the name, a callback and an opaque parameter
108
+for the callback (this will be explained in a following section).
109
+Output is simpler; only the name is required. Typically::
110
+
111
+ qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev);
112
+ qdev_init_clock_out(DEVICE(dev), "clk_out");
113
+
114
+Both functions return the created Clock pointer, which should be saved in the
115
+device's state structure for further use.
116
+
117
+These objects will be automatically deleted by the QOM reference mechanism.
118
+
119
+Note that it is possible to create a static array describing clock inputs and
120
+outputs. The function ``qdev_init_clocks()`` must be called with the array as
121
+parameter to initialize the clocks: it has the same behaviour as calling the
122
+``qdev_init_clock_in/out()`` for each clock in the array. To ease the array
123
+construction, some macros are defined in ``include/hw/qdev-clock.h``.
124
+As an example, the following creates 2 clocks to a device: one input and one
125
+output.
126
+
127
+.. code-block:: c
128
+
129
+ /* device structure containing pointers to the clock objects */
130
+ typedef struct MyDeviceState {
131
+ DeviceState parent_obj;
132
+ Clock *clk_in;
133
+ Clock *clk_out;
134
+ } MyDeviceState;
135
+
136
+ /*
137
+ * callback for the input clock (see "Callback on input clock
138
+ * change" section below for more information).
139
+ */
140
+ static void clk_in_callback(void *opaque);
141
+
142
+ /*
143
+ * static array describing clocks:
144
+ * + a clock input named "clk_in", whose pointer is stored in
145
+ * the clk_in field of a MyDeviceState structure with callback
146
+ * clk_in_callback.
147
+ * + a clock output named "clk_out" whose pointer is stored in
148
+ * the clk_out field of a MyDeviceState structure.
149
+ */
150
+ static const ClockPortInitArray mydev_clocks = {
151
+ QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback),
152
+ QDEV_CLOCK_OUT(MyDeviceState, clk_out),
153
+ QDEV_CLOCK_END
154
+ };
155
+
156
+ /* device initialization function */
157
+ static void mydev_init(Object *obj)
158
+ {
159
+ /* cast to MyDeviceState */
160
+ MyDeviceState *mydev = MYDEVICE(obj);
161
+ /* create and fill the pointer fields in the MyDeviceState */
162
+ qdev_init_clocks(mydev, mydev_clocks);
163
+ [...]
164
+ }
165
+
166
+An alternative way to create a clock is to simply call
167
+``object_new(TYPE_CLOCK)``. In that case the clock will neither be an
168
+input nor an output of a device. After the whole QOM hierarchy of the
169
+clock has been set ``clock_setup_canonical_path()`` should be called.
170
+
171
+At creation, the period of the clock is 0: the clock is disabled. You can
172
+change it using ``clock_set_ns()`` or ``clock_set_hz()``.
173
+
174
+Note that if you are creating a clock with a fixed period which will never
175
+change (for example the main clock source of a board), then you'll have
176
+nothing else to do. This value will be propagated to other clocks when
177
+connecting the clocks together and devices will fetch the right value during
178
+the first reset.
179
+
180
+Retrieving clocks from a device
181
+-------------------------------
182
+
183
+``qdev_get_clock_in()`` and ``dev_get_clock_out()`` are available to
184
+get the clock inputs or outputs of a device. For example:
185
+
186
+.. code-block:: c
187
+
188
+ Clock *clk = qdev_get_clock_in(DEVICE(mydev), "clk_in");
189
+
190
+or:
191
+
192
+.. code-block:: c
193
+
194
+ Clock *clk = qdev_get_clock_out(DEVICE(mydev), "clk_out");
195
+
196
+Connecting two clocks together
197
+------------------------------
198
+
199
+To connect two clocks together, use the ``clock_set_source()`` function.
200
+Given two clocks ``clk1``, and ``clk2``, ``clock_set_source(clk2, clk1);``
201
+configures ``clk2`` to follow the ``clk1`` period changes. Every time ``clk1``
202
+is updated, ``clk2`` will be updated too.
203
+
204
+When connecting clock between devices, prefer using the
205
+``qdev_connect_clock_in()`` function to set the source of an input
206
+device clock. For example, to connect the input clock ``clk2`` of
207
+``devB`` to the output clock ``clk1`` of ``devA``, do:
208
+
209
+.. code-block:: c
210
+
211
+ qdev_connect_clock_in(devB, "clk2", qdev_get_clock_out(devA, "clk1"))
212
+
213
+We used ``qdev_get_clock_out()`` above, but any clock can drive an
214
+input clock, even another input clock. The following diagram shows
215
+some examples of connections. Note also that a clock can drive several
216
+other clocks.
217
+
218
+::
219
+
220
+ +------------+ +--------------------------------------------------+
221
+ | Device A | | Device B |
222
+ | | | +---------------------+ |
223
+ | | | | Device C | |
224
+ | +-------+ | | +-------+ | +-------+ +-------+ | +-------+ |
225
+ | |Clock 1|>>-->>|Clock 2|>>+-->>|Clock 3| |Clock 5|>>>>|Clock 6|>>
226
+ | | (out) | | | | (in) | | | | (in) | | (out) | | | (out) | |
227
+ | +-------+ | | +-------+ | | +-------+ +-------+ | +-------+ |
228
+ +------------+ | | +---------------------+ |
229
+ | | |
230
+ | | +--------------+ |
231
+ | | | Device D | |
232
+ | | | +-------+ | |
233
+ | +-->>|Clock 4| | |
234
+ | | | (in) | | |
235
+ | | +-------+ | |
236
+ | +--------------+ |
237
+ +--------------------------------------------------+
238
+
239
+In the above example, when *Clock 1* is updated by *Device A*, three
240
+clocks get the new clock period value: *Clock 2*, *Clock 3* and *Clock 4*.
241
+
242
+It is not possible to disconnect a clock or to change the clock connection
243
+after it is connected.
244
+
245
+Unconnected input clocks
246
+------------------------
247
+
248
+A newly created input clock is disabled (period of 0). This means the
249
+clock will be considered as disabled until the period is updated. If
250
+the clock remains unconnected it will always keep its initial value
251
+of 0. If this is not the desired behaviour, ``clock_set()``,
252
+``clock_set_ns()`` or ``clock_set_hz()`` should be called on the Clock
253
+object during device instance init. For example:
254
+
255
+.. code-block:: c
256
+
257
+ clk = qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback,
258
+ dev);
259
+ /* set initial value to 10ns / 100MHz */
260
+ clock_set_ns(clk, 10);
261
+
262
+Fetching clock frequency/period
263
+-------------------------------
264
+
265
+To get the current state of a clock, use the functions ``clock_get()``,
266
+``clock_get_ns()`` or ``clock_get_hz()``.
267
+
268
+It is also possible to register a callback on clock frequency changes.
269
+Here is an example:
270
+
271
+.. code-block:: c
272
+
273
+ void clock_callback(void *opaque) {
274
+ MyDeviceState *s = (MyDeviceState *) opaque;
275
+ /*
276
+ * 'opaque' is the argument passed to qdev_init_clock_in();
277
+ * usually this will be the device state pointer.
278
+ */
279
+
280
+ /* do something with the new period */
281
+ fprintf(stdout, "device new period is %" PRIu64 "ns\n",
282
+ clock_get_ns(dev->my_clk_input));
283
+ }
284
+
285
+Changing a clock period
286
+-----------------------
287
+
288
+A device can change its outputs using the ``clock_update()``,
289
+``clock_update_ns()`` or ``clock_update_hz()`` function. It will trigger
290
+updates on every connected input.
291
+
292
+For example, let's say that we have an output clock *clkout* and we
293
+have a pointer to it in the device state because we did the following
294
+in init phase:
295
+
296
+.. code-block:: c
297
+
298
+ dev->clkout = qdev_init_clock_out(DEVICE(dev), "clkout");
299
+
300
+Then at any time (apart from the cases listed below), it is possible to
301
+change the clock value by doing:
302
+
303
+.. code-block:: c
304
+
305
+ clock_update_hz(dev->clkout, 1000 * 1000 * 1000); /* 1GHz */
306
+
307
+Because updating a clock may trigger any side effects through
308
+connected clocks and their callbacks, this operation must be done
309
+while holding the qemu io lock.
310
+
311
+For the same reason, one can update clocks only when it is allowed to have
312
+side effects on other objects. In consequence, it is forbidden:
313
+
314
+* during migration,
315
+* and in the enter phase of reset.
316
+
317
+Note that calling ``clock_update[_ns|_hz]()`` is equivalent to calling
318
+``clock_set[_ns|_hz]()`` (with the same arguments) then
319
+``clock_propagate()`` on the clock. Thus, setting the clock value can
320
+be separated from triggering the side-effects. This is often required
321
+to factorize code to handle reset and migration in devices.
322
+
323
+Aliasing clocks
324
+---------------
325
+
326
+Sometimes, one needs to forward, or inherit, a clock from another
327
+device. Typically, when doing device composition, a device might
328
+expose a sub-device's clock without interfering with it. The function
329
+``qdev_alias_clock()`` can be used to achieve this behaviour. Note
330
+that it is possible to expose the clock under a different name.
331
+``qdev_alias_clock()`` works for both input and output clocks.
332
+
333
+For example, if device B is a child of device A,
334
+``device_a_instance_init()`` may do something like this:
335
+
336
+.. code-block:: c
337
+
338
+ void device_a_instance_init(Object *obj)
339
+ {
340
+ AState *A = DEVICE_A(obj);
341
+ BState *B;
342
+ /* create object B as child of A */
343
+ [...]
344
+ qdev_alias_clock(B, "clk", A, "b_clk");
345
+ /*
346
+ * Now A has a clock "b_clk" which is an alias to
347
+ * the clock "clk" of its child B.
348
+ */
349
+ }
350
+
351
+This function does not return any clock object. The new clock has the
352
+same direction (input or output) as the original one. This function
353
+only adds a link to the existing clock. In the above example, object B
354
+remains the only object allowed to use the clock and device A must not
355
+try to change the clock period or set a callback to the clock. This
356
+diagram describes the example with an input clock::
357
+
358
+ +--------------------------+
359
+ | Device A |
360
+ | +--------------+ |
361
+ | | Device B | |
362
+ | | +-------+ | |
363
+ >>"b_clk">>>| "clk" | | |
364
+ | (in) | | (in) | | |
365
+ | | +-------+ | |
366
+ | +--------------+ |
367
+ +--------------------------+
368
+
369
+Migration
370
+---------
371
+
372
+Clock state is not migrated automatically. Every device must handle its
373
+clock migration. Alias clocks must not be migrated.
374
+
375
+To ensure clock states are restored correctly during migration, there
376
+are two solutions.
377
+
378
+Clock states can be migrated by adding an entry into the device
379
+vmstate description. You should use the ``VMSTATE_CLOCK`` macro for this.
380
+This is typically used to migrate an input clock state. For example:
381
+
382
+.. code-block:: c
383
+
384
+ MyDeviceState {
385
+ DeviceState parent_obj;
386
+ [...] /* some fields */
387
+ Clock *clk;
388
+ };
389
+
390
+ VMStateDescription my_device_vmstate = {
391
+ .name = "my_device",
392
+ .fields = (VMStateField[]) {
393
+ [...], /* other migrated fields */
394
+ VMSTATE_CLOCK(clk, MyDeviceState),
395
+ VMSTATE_END_OF_LIST()
396
+ }
397
+ };
398
+
399
+The second solution is to restore the clock state using information already
400
+at our disposal. This can be used to restore output clock states using the
401
+device state. The functions ``clock_set[_ns|_hz]()`` can be used during the
402
+``post_load()`` migration callback.
403
+
404
+When adding clock support to an existing device, if you care about
405
+migration compatibility you will need to be careful, as simply adding
406
+a ``VMSTATE_CLOCK()`` line will break compatibility. Instead, you can
407
+put the ``VMSTATE_CLOCK()`` line into a vmstate subsection with a
408
+suitable ``needed`` function, and use ``clock_set()`` in a
409
+``pre_load()`` function to set the default value that will be used if
410
+the source virtual machine in the migration does not send the clock
411
+state.
412
+
413
+Care should be taken not to use ``clock_update[_ns|_hz]()`` or
414
+``clock_propagate()`` during the whole migration procedure because it
415
+will trigger side effects to other devices in an unknown state.
416
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
26
index XXXXXXX..XXXXXXX 100644
417
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate.c
418
--- a/docs/devel/index.rst
28
+++ b/target/arm/translate.c
419
+++ b/docs/devel/index.rst
29
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
420
@@ -XXX,XX +XXX,XX @@ Contents:
30
} else {
421
bitops
31
int i, loaded_base = 0;
422
reset
32
TCGv_i32 loaded_var;
423
s390-dasd-ipl
33
+ bool wback = extract32(insn, 21, 1);
424
+ clocks
34
/* Load/store multiple. */
35
addr = load_reg(s, rn);
36
offset = 0;
37
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
38
if (insn & (1 << i))
39
offset += 4;
40
}
41
+
42
if (insn & (1 << 24)) {
43
tcg_gen_addi_i32(addr, addr, -offset);
44
}
45
46
+ if (s->v8m_stackcheck && rn == 13 && wback) {
47
+ /*
48
+ * If the writeback is incrementing SP rather than
49
+ * decrementing it, and the initial SP is below the
50
+ * stack limit but the final written-back SP would
51
+ * be above, then then we must not perform any memory
52
+ * accesses, but it is IMPDEF whether we generate
53
+ * an exception. We choose to do so in this case.
54
+ * At this point 'addr' is the lowest address, so
55
+ * either the original SP (if incrementing) or our
56
+ * final SP (if decrementing), so that's what we check.
57
+ */
58
+ gen_helper_v8m_stackcheck(cpu_env, addr);
59
+ }
60
+
61
loaded_var = NULL;
62
for (i = 0; i < 16; i++) {
63
if ((insn & (1 << i)) == 0)
64
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
65
if (loaded_base) {
66
store_reg(s, rn, loaded_var);
67
}
68
- if (insn & (1 << 21)) {
69
+ if (wback) {
70
/* Base register writeback. */
71
if (insn & (1 << 24)) {
72
tcg_gen_addi_i32(addr, addr, -offset);
73
--
425
--
74
2.19.0
426
2.20.1
75
427
76
428
diff view generated by jsdifflib
1
Add the v8M stack checks for:
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
* LDRD (immediate)
2
3
* STRD (immediate)
3
Add some clocks to zynq_slcr
4
4
+ the main input clock (ps_clk)
5
Loads and stores are more complicated than ADD/SUB/MOV, because we
5
+ the reference clock outputs for each uart (uart0 & 1)
6
must ensure that memory accesses below the stack limit are not
6
7
performed, so we can't simply do the check when we actually update
7
This commit also transitional the slcr to multi-phase reset as it is
8
SP.
8
required to initialize the clocks correctly.
9
9
10
For these instructions, if the stack limit check triggers
10
The clock frequencies are computed using the internal pll & uart configuration
11
we must not:
11
registers and the input ps_clk frequency.
12
* perform any memory access below the SP limit
12
13
* update PC, SP or the load/store base register
13
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
14
but it is IMPDEF whether we:
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
* perform any accesses above or equal to the SP limit
15
Acked-by: Alistair Francis <alistair.francis@wdc.com>
16
* update destination registers for loads
16
Message-id: 20200406135251.157596-7-damien.hedde@greensocs.com
17
18
For QEMU we choose to always check the limit before doing any other
19
part of the load or store, so we won't update any registers or
20
perform any memory accesses.
21
22
It is UNKNOWN whether the limit check triggers for a load or store
23
where the initial SP value is below the limit and one of the stores
24
would be below the limit, but the writeback moves SP to above the
25
limit. For QEMU we choose to trigger the check in this situation.
26
27
Note that limit checks happen only for loads and stores which update
28
SP via writeback; they do not happen for loads and stores which
29
simply use SP as a base register.
30
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
33
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
34
Message-id: 20181002163556.10279-9-peter.maydell@linaro.org
35
---
18
---
36
target/arm/translate.c | 27 +++++++++++++++++++++++++--
19
hw/misc/zynq_slcr.c | 172 ++++++++++++++++++++++++++++++++++++++++++--
37
1 file changed, 25 insertions(+), 2 deletions(-)
20
1 file changed, 168 insertions(+), 4 deletions(-)
38
21
39
diff --git a/target/arm/translate.c b/target/arm/translate.c
22
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
40
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate.c
24
--- a/hw/misc/zynq_slcr.c
42
+++ b/target/arm/translate.c
25
+++ b/hw/misc/zynq_slcr.c
43
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
26
@@ -XXX,XX +XXX,XX @@
44
* 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
27
#include "qemu/log.h"
45
* - load/store dual (pre-indexed)
28
#include "qemu/module.h"
46
*/
29
#include "hw/registerfields.h"
47
+ bool wback = extract32(insn, 21, 1);
30
+#include "hw/qdev-clock.h"
48
+
31
49
if (rn == 15) {
32
#ifndef ZYNQ_SLCR_ERR_DEBUG
50
if (insn & (1 << 21)) {
33
#define ZYNQ_SLCR_ERR_DEBUG 0
51
/* UNPREDICTABLE */
34
@@ -XXX,XX +XXX,XX @@ REG32(LOCKSTA, 0x00c)
52
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
35
REG32(ARM_PLL_CTRL, 0x100)
53
addr = load_reg(s, rn);
36
REG32(DDR_PLL_CTRL, 0x104)
54
}
37
REG32(IO_PLL_CTRL, 0x108)
55
offset = (insn & 0xff) * 4;
38
+/* fields for [ARM|DDR|IO]_PLL_CTRL registers */
56
- if ((insn & (1 << 23)) == 0)
39
+ FIELD(xxx_PLL_CTRL, PLL_RESET, 0, 1)
57
+ if ((insn & (1 << 23)) == 0) {
40
+ FIELD(xxx_PLL_CTRL, PLL_PWRDWN, 1, 1)
58
offset = -offset;
41
+ FIELD(xxx_PLL_CTRL, PLL_BYPASS_QUAL, 3, 1)
59
+ }
42
+ FIELD(xxx_PLL_CTRL, PLL_BYPASS_FORCE, 4, 1)
60
+
43
+ FIELD(xxx_PLL_CTRL, PLL_FPDIV, 12, 7)
61
+ if (s->v8m_stackcheck && rn == 13 && wback) {
44
REG32(PLL_STATUS, 0x10c)
62
+ /*
45
REG32(ARM_PLL_CFG, 0x110)
63
+ * Here 'addr' is the current SP; if offset is +ve we're
46
REG32(DDR_PLL_CFG, 0x114)
64
+ * moving SP up, else down. It is UNKNOWN whether the limit
47
@@ -XXX,XX +XXX,XX @@ REG32(SMC_CLK_CTRL, 0x148)
65
+ * check triggers when SP starts below the limit and ends
48
REG32(LQSPI_CLK_CTRL, 0x14c)
66
+ * up above it; check whichever of the current and final
49
REG32(SDIO_CLK_CTRL, 0x150)
67
+ * SP is lower, so QEMU will trigger in that situation.
50
REG32(UART_CLK_CTRL, 0x154)
68
+ */
51
+ FIELD(UART_CLK_CTRL, CLKACT0, 0, 1)
69
+ if ((int32_t)offset < 0) {
52
+ FIELD(UART_CLK_CTRL, CLKACT1, 1, 1)
70
+ TCGv_i32 newsp = tcg_temp_new_i32();
53
+ FIELD(UART_CLK_CTRL, SRCSEL, 4, 2)
71
+
54
+ FIELD(UART_CLK_CTRL, DIVISOR, 8, 6)
72
+ tcg_gen_addi_i32(newsp, addr, offset);
55
REG32(SPI_CLK_CTRL, 0x158)
73
+ gen_helper_v8m_stackcheck(cpu_env, newsp);
56
REG32(CAN_CLK_CTRL, 0x15c)
74
+ tcg_temp_free_i32(newsp);
57
REG32(CAN_MIOCLK_CTRL, 0x160)
75
+ } else {
58
@@ -XXX,XX +XXX,XX @@ typedef struct ZynqSLCRState {
76
+ gen_helper_v8m_stackcheck(cpu_env, addr);
59
MemoryRegion iomem;
77
+ }
60
78
+ }
61
uint32_t regs[ZYNQ_SLCR_NUM_REGS];
79
+
62
+
80
if (insn & (1 << 24)) {
63
+ Clock *ps_clk;
81
tcg_gen_addi_i32(addr, addr, offset);
64
+ Clock *uart0_ref_clk;
82
offset = 0;
65
+ Clock *uart1_ref_clk;
83
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
66
} ZynqSLCRState;
84
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
67
85
tcg_temp_free_i32(tmp);
68
-static void zynq_slcr_reset(DeviceState *d)
86
}
69
+/*
87
- if (insn & (1 << 21)) {
70
+ * return the output frequency of ARM/DDR/IO pll
88
+ if (wback) {
71
+ * using input frequency and PLL_CTRL register
89
/* Base writeback. */
72
+ */
90
tcg_gen_addi_i32(addr, addr, offset - 4);
73
+static uint64_t zynq_slcr_compute_pll(uint64_t input, uint32_t ctrl_reg)
91
store_reg(s, rn, addr);
74
{
75
- ZynqSLCRState *s = ZYNQ_SLCR(d);
76
+ uint32_t mult = ((ctrl_reg & R_xxx_PLL_CTRL_PLL_FPDIV_MASK) >>
77
+ R_xxx_PLL_CTRL_PLL_FPDIV_SHIFT);
78
+
79
+ /* first, check if pll is bypassed */
80
+ if (ctrl_reg & R_xxx_PLL_CTRL_PLL_BYPASS_FORCE_MASK) {
81
+ return input;
82
+ }
83
+
84
+ /* is pll disabled ? */
85
+ if (ctrl_reg & (R_xxx_PLL_CTRL_PLL_RESET_MASK |
86
+ R_xxx_PLL_CTRL_PLL_PWRDWN_MASK)) {
87
+ return 0;
88
+ }
89
+
90
+ /* frequency multiplier -> period division */
91
+ return input / mult;
92
+}
93
+
94
+/*
95
+ * return the output period of a clock given:
96
+ * + the periods in an array corresponding to input mux selector
97
+ * + the register xxx_CLK_CTRL value
98
+ * + enable bit index in ctrl register
99
+ *
100
+ * This function makes the assumption that the ctrl_reg value is organized as
101
+ * follows:
102
+ * + bits[13:8] clock frequency divisor
103
+ * + bits[5:4] clock mux selector (index in array)
104
+ * + bits[index] clock enable
105
+ */
106
+static uint64_t zynq_slcr_compute_clock(const uint64_t periods[],
107
+ uint32_t ctrl_reg,
108
+ unsigned index)
109
+{
110
+ uint32_t srcsel = extract32(ctrl_reg, 4, 2); /* bits [5:4] */
111
+ uint32_t divisor = extract32(ctrl_reg, 8, 6); /* bits [13:8] */
112
+
113
+ /* first, check if clock is disabled */
114
+ if (((ctrl_reg >> index) & 1u) == 0) {
115
+ return 0;
116
+ }
117
+
118
+ /*
119
+ * according to the Zynq technical ref. manual UG585 v1.12.2 in
120
+ * Clocks chapter, section 25.10.1 page 705:
121
+ * "The 6-bit divider provides a divide range of 1 to 63"
122
+ * We follow here what is implemented in linux kernel and consider
123
+ * the 0 value as a bypass (no division).
124
+ */
125
+ /* frequency divisor -> period multiplication */
126
+ return periods[srcsel] * (divisor ? divisor : 1u);
127
+}
128
+
129
+/*
130
+ * macro helper around zynq_slcr_compute_clock to avoid repeating
131
+ * the register name.
132
+ */
133
+#define ZYNQ_COMPUTE_CLK(state, plls, reg, enable_field) \
134
+ zynq_slcr_compute_clock((plls), (state)->regs[reg], \
135
+ reg ## _ ## enable_field ## _SHIFT)
136
+
137
+/**
138
+ * Compute and set the ouputs clocks periods.
139
+ * But do not propagate them further. Connected clocks
140
+ * will not receive any updates (See zynq_slcr_compute_clocks())
141
+ */
142
+static void zynq_slcr_compute_clocks(ZynqSLCRState *s)
143
+{
144
+ uint64_t ps_clk = clock_get(s->ps_clk);
145
+
146
+ /* consider outputs clocks are disabled while in reset */
147
+ if (device_is_in_reset(DEVICE(s))) {
148
+ ps_clk = 0;
149
+ }
150
+
151
+ uint64_t io_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_IO_PLL_CTRL]);
152
+ uint64_t arm_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_ARM_PLL_CTRL]);
153
+ uint64_t ddr_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_DDR_PLL_CTRL]);
154
+
155
+ uint64_t uart_mux[4] = {io_pll, io_pll, arm_pll, ddr_pll};
156
+
157
+ /* compute uartX reference clocks */
158
+ clock_set(s->uart0_ref_clk,
159
+ ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT0));
160
+ clock_set(s->uart1_ref_clk,
161
+ ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT1));
162
+}
163
+
164
+/**
165
+ * Propagate the outputs clocks.
166
+ * zynq_slcr_compute_clocks() should have been called before
167
+ * to configure them.
168
+ */
169
+static void zynq_slcr_propagate_clocks(ZynqSLCRState *s)
170
+{
171
+ clock_propagate(s->uart0_ref_clk);
172
+ clock_propagate(s->uart1_ref_clk);
173
+}
174
+
175
+static void zynq_slcr_ps_clk_callback(void *opaque)
176
+{
177
+ ZynqSLCRState *s = (ZynqSLCRState *) opaque;
178
+ zynq_slcr_compute_clocks(s);
179
+ zynq_slcr_propagate_clocks(s);
180
+}
181
+
182
+static void zynq_slcr_reset_init(Object *obj, ResetType type)
183
+{
184
+ ZynqSLCRState *s = ZYNQ_SLCR(obj);
185
int i;
186
187
DB_PRINT("RESET\n");
188
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_reset(DeviceState *d)
189
s->regs[R_DDRIOB + 12] = 0x00000021;
190
}
191
192
+static void zynq_slcr_reset_hold(Object *obj)
193
+{
194
+ ZynqSLCRState *s = ZYNQ_SLCR(obj);
195
+
196
+ /* will disable all output clocks */
197
+ zynq_slcr_compute_clocks(s);
198
+ zynq_slcr_propagate_clocks(s);
199
+}
200
+
201
+static void zynq_slcr_reset_exit(Object *obj)
202
+{
203
+ ZynqSLCRState *s = ZYNQ_SLCR(obj);
204
+
205
+ /* will compute output clocks according to ps_clk and registers */
206
+ zynq_slcr_compute_clocks(s);
207
+ zynq_slcr_propagate_clocks(s);
208
+}
209
210
static bool zynq_slcr_check_offset(hwaddr offset, bool rnw)
211
{
212
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
213
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
214
}
215
break;
216
+ case R_IO_PLL_CTRL:
217
+ case R_ARM_PLL_CTRL:
218
+ case R_DDR_PLL_CTRL:
219
+ case R_UART_CLK_CTRL:
220
+ zynq_slcr_compute_clocks(s);
221
+ zynq_slcr_propagate_clocks(s);
222
+ break;
223
}
224
}
225
226
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps slcr_ops = {
227
.endianness = DEVICE_NATIVE_ENDIAN,
228
};
229
230
+static const ClockPortInitArray zynq_slcr_clocks = {
231
+ QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback),
232
+ QDEV_CLOCK_OUT(ZynqSLCRState, uart0_ref_clk),
233
+ QDEV_CLOCK_OUT(ZynqSLCRState, uart1_ref_clk),
234
+ QDEV_CLOCK_END
235
+};
236
+
237
static void zynq_slcr_init(Object *obj)
238
{
239
ZynqSLCRState *s = ZYNQ_SLCR(obj);
240
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_init(Object *obj)
241
memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr",
242
ZYNQ_SLCR_MMIO_SIZE);
243
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
244
+
245
+ qdev_init_clocks(DEVICE(obj), zynq_slcr_clocks);
246
}
247
248
static const VMStateDescription vmstate_zynq_slcr = {
249
.name = "zynq_slcr",
250
- .version_id = 2,
251
+ .version_id = 3,
252
.minimum_version_id = 2,
253
.fields = (VMStateField[]) {
254
VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS),
255
+ VMSTATE_CLOCK_V(ps_clk, ZynqSLCRState, 3),
256
VMSTATE_END_OF_LIST()
257
}
258
};
259
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_zynq_slcr = {
260
static void zynq_slcr_class_init(ObjectClass *klass, void *data)
261
{
262
DeviceClass *dc = DEVICE_CLASS(klass);
263
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
264
265
dc->vmsd = &vmstate_zynq_slcr;
266
- dc->reset = zynq_slcr_reset;
267
+ rc->phases.enter = zynq_slcr_reset_init;
268
+ rc->phases.hold = zynq_slcr_reset_hold;
269
+ rc->phases.exit = zynq_slcr_reset_exit;
270
}
271
272
static const TypeInfo zynq_slcr_info = {
92
--
273
--
93
2.19.0
274
2.20.1
94
275
95
276
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
2
3
Uses tlb_vaddr_to_host for correct operation with softmmu.
3
Switch the cadence uart to multi-phase reset and add the
4
Optimize for accesses within a single page or pair of pages.
4
reference clock input.
5
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
The input clock frequency is added to the migration structure.
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
8
Message-id: 20181005175350.30752-8-richard.henderson@linaro.org
8
The reference clock controls the baudrate generation. If it disabled,
9
any input characters and events are ignored.
10
11
If this clock remains unconnected, the uart behaves as before
12
(it default to a 50MHz ref clock).
13
14
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
15
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
16
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Message-id: 20200406135251.157596-8-damien.hedde@greensocs.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
19
---
11
target/arm/sve_helper.c | 731 +++++++++++++++++++++++++++++++---------
20
include/hw/char/cadence_uart.h | 1 +
12
1 file changed, 569 insertions(+), 162 deletions(-)
21
hw/char/cadence_uart.c | 73 +++++++++++++++++++++++++++++-----
13
22
hw/char/trace-events | 3 ++
14
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
23
3 files changed, 67 insertions(+), 10 deletions(-)
24
25
diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h
15
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/sve_helper.c
27
--- a/include/hw/char/cadence_uart.h
17
+++ b/target/arm/sve_helper.c
28
+++ b/include/hw/char/cadence_uart.h
18
@@ -XXX,XX +XXX,XX @@ static void swap_memmove(void *vd, void *vs, size_t n)
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
30
CharBackend chr;
31
qemu_irq irq;
32
QEMUTimer *fifo_trigger_handle;
33
+ Clock *refclk;
34
} CadenceUARTState;
35
36
static inline DeviceState *cadence_uart_create(hwaddr addr,
37
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/char/cadence_uart.c
40
+++ b/hw/char/cadence_uart.c
41
@@ -XXX,XX +XXX,XX @@
42
#include "qemu/module.h"
43
#include "hw/char/cadence_uart.h"
44
#include "hw/irq.h"
45
+#include "hw/qdev-clock.h"
46
+#include "trace.h"
47
48
#ifdef CADENCE_UART_ERR_DEBUG
49
#define DB_PRINT(...) do { \
50
@@ -XXX,XX +XXX,XX @@
51
#define LOCAL_LOOPBACK (0x2 << UART_MR_CHMODE_SH)
52
#define REMOTE_LOOPBACK (0x3 << UART_MR_CHMODE_SH)
53
54
-#define UART_INPUT_CLK 50000000
55
+#define UART_DEFAULT_REF_CLK (50 * 1000 * 1000)
56
57
#define R_CR (0x00/4)
58
#define R_MR (0x04/4)
59
@@ -XXX,XX +XXX,XX @@ static void uart_send_breaks(CadenceUARTState *s)
60
static void uart_parameters_setup(CadenceUARTState *s)
61
{
62
QEMUSerialSetParams ssp;
63
- unsigned int baud_rate, packet_size;
64
+ unsigned int baud_rate, packet_size, input_clk;
65
+ input_clk = clock_get_hz(s->refclk);
66
67
- baud_rate = (s->r[R_MR] & UART_MR_CLKS) ?
68
- UART_INPUT_CLK / 8 : UART_INPUT_CLK;
69
+ baud_rate = (s->r[R_MR] & UART_MR_CLKS) ? input_clk / 8 : input_clk;
70
+ baud_rate /= (s->r[R_BRGR] * (s->r[R_BDIV] + 1));
71
+ trace_cadence_uart_baudrate(baud_rate);
72
+
73
+ ssp.speed = baud_rate;
74
75
- ssp.speed = baud_rate / (s->r[R_BRGR] * (s->r[R_BDIV] + 1));
76
packet_size = 1;
77
78
switch (s->r[R_MR] & UART_MR_PAR) {
79
@@ -XXX,XX +XXX,XX @@ static void uart_parameters_setup(CadenceUARTState *s)
19
}
80
}
81
82
packet_size += ssp.data_bits + ssp.stop_bits;
83
+ if (ssp.speed == 0) {
84
+ /*
85
+ * Avoid division-by-zero below.
86
+ * TODO: find something better
87
+ */
88
+ ssp.speed = 1;
89
+ }
90
s->char_tx_time = (NANOSECONDS_PER_SECOND / ssp.speed) * packet_size;
91
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
20
}
92
}
21
93
@@ -XXX,XX +XXX,XX @@ static void uart_receive(void *opaque, const uint8_t *buf, int size)
22
+/* Similarly for memset of 0. */
94
CadenceUARTState *s = opaque;
23
+static void swap_memzero(void *vd, size_t n)
95
uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
24
+{
96
25
+ uintptr_t d = (uintptr_t)vd;
97
+ /* ignore characters when unclocked or in reset */
26
+ uintptr_t o = (d | n) & 7;
98
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
27
+ size_t i;
28
+
29
+ /* Usually, the first bit of a predicate is set, so N is 0. */
30
+ if (likely(n == 0)) {
31
+ return;
99
+ return;
32
+ }
100
+ }
33
+
101
+
34
+#ifndef HOST_WORDS_BIGENDIAN
102
if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
35
+ o = 0;
103
uart_write_rx_fifo(opaque, buf, size);
36
+#endif
104
}
37
+ switch (o) {
105
@@ -XXX,XX +XXX,XX @@ static void uart_event(void *opaque, QEMUChrEvent event)
38
+ case 0:
106
CadenceUARTState *s = opaque;
39
+ memset(vd, 0, n);
107
uint8_t buf = '\0';
40
+ break;
108
41
+
109
+ /* ignore characters when unclocked or in reset */
42
+ case 4:
110
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
43
+ for (i = 0; i < n; i += 4) {
44
+ *(uint32_t *)H1_4(d + i) = 0;
45
+ }
46
+ break;
47
+
48
+ case 2:
49
+ case 6:
50
+ for (i = 0; i < n; i += 2) {
51
+ *(uint16_t *)H1_2(d + i) = 0;
52
+ }
53
+ break;
54
+
55
+ default:
56
+ for (i = 0; i < n; i++) {
57
+ *(uint8_t *)H1(d + i) = 0;
58
+ }
59
+ break;
60
+ }
61
+}
62
+
63
void HELPER(sve_ext)(void *vd, void *vn, void *vm, uint32_t desc)
64
{
65
intptr_t opr_sz = simd_oprsz(desc);
66
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_fcmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc)
67
/*
68
* Load contiguous data, protected by a governing predicate.
69
*/
70
-#define DO_LD1(NAME, FN, TYPEE, TYPEM, H) \
71
-static void do_##NAME(CPUARMState *env, void *vd, void *vg, \
72
- target_ulong addr, intptr_t oprsz, \
73
- uintptr_t ra) \
74
-{ \
75
- intptr_t i = 0; \
76
- do { \
77
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
78
- do { \
79
- TYPEM m = 0; \
80
- if (pg & 1) { \
81
- m = FN(env, addr, ra); \
82
- } \
83
- *(TYPEE *)(vd + H(i)) = m; \
84
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
85
- addr += sizeof(TYPEM); \
86
- } while (i & 15); \
87
- } while (i < oprsz); \
88
-} \
89
-void HELPER(NAME)(CPUARMState *env, void *vg, \
90
- target_ulong addr, uint32_t desc) \
91
-{ \
92
- do_##NAME(env, &env->vfp.zregs[simd_data(desc)], vg, \
93
- addr, simd_oprsz(desc), GETPC()); \
94
+
95
+/*
96
+ * Load elements into @vd, controlled by @vg, from @host + @mem_ofs.
97
+ * Memory is valid through @host + @mem_max. The register element
98
+ * indicies are inferred from @mem_ofs, as modified by the types for
99
+ * which the helper is built. Return the @mem_ofs of the first element
100
+ * not loaded (which is @mem_max if they are all loaded).
101
+ *
102
+ * For softmmu, we have fully validated the guest page. For user-only,
103
+ * we cannot fully validate without taking the mmap lock, but since we
104
+ * know the access is within one host page, if any access is valid they
105
+ * all must be valid. However, when @vg is all false, it may be that
106
+ * no access is valid.
107
+ */
108
+typedef intptr_t sve_ld1_host_fn(void *vd, void *vg, void *host,
109
+ intptr_t mem_ofs, intptr_t mem_max);
110
+
111
+/*
112
+ * Load one element into @vd + @reg_off from (@env, @vaddr, @ra).
113
+ * The controlling predicate is known to be true.
114
+ */
115
+typedef void sve_ld1_tlb_fn(CPUARMState *env, void *vd, intptr_t reg_off,
116
+ target_ulong vaddr, int mmu_idx, uintptr_t ra);
117
+
118
+/*
119
+ * Generate the above primitives.
120
+ */
121
+
122
+#define DO_LD_HOST(NAME, H, TYPEE, TYPEM, HOST) \
123
+static intptr_t sve_##NAME##_host(void *vd, void *vg, void *host, \
124
+ intptr_t mem_off, const intptr_t mem_max) \
125
+{ \
126
+ intptr_t reg_off = mem_off * (sizeof(TYPEE) / sizeof(TYPEM)); \
127
+ uint64_t *pg = vg; \
128
+ while (mem_off + sizeof(TYPEM) <= mem_max) { \
129
+ TYPEM val = 0; \
130
+ if (likely((pg[reg_off >> 6] >> (reg_off & 63)) & 1)) { \
131
+ val = HOST(host + mem_off); \
132
+ } \
133
+ *(TYPEE *)(vd + H(reg_off)) = val; \
134
+ mem_off += sizeof(TYPEM), reg_off += sizeof(TYPEE); \
135
+ } \
136
+ return mem_off; \
137
}
138
139
+#ifdef CONFIG_SOFTMMU
140
+#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \
141
+static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
142
+ target_ulong addr, int mmu_idx, uintptr_t ra) \
143
+{ \
144
+ TCGMemOpIdx oi = make_memop_idx(ctz32(sizeof(TYPEM)) | MOEND, mmu_idx); \
145
+ TYPEM val = TLB(env, addr, oi, ra); \
146
+ *(TYPEE *)(vd + H(reg_off)) = val; \
147
+}
148
+#else
149
+#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \
150
+static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
151
+ target_ulong addr, int mmu_idx, uintptr_t ra) \
152
+{ \
153
+ TYPEM val = HOST(g2h(addr)); \
154
+ *(TYPEE *)(vd + H(reg_off)) = val; \
155
+}
156
+#endif
157
+
158
+#define DO_LD_PRIM_1(NAME, H, TE, TM) \
159
+ DO_LD_HOST(NAME, H, TE, TM, ldub_p) \
160
+ DO_LD_TLB(NAME, H, TE, TM, ldub_p, 0, helper_ret_ldub_mmu)
161
+
162
+DO_LD_PRIM_1(ld1bb, H1, uint8_t, uint8_t)
163
+DO_LD_PRIM_1(ld1bhu, H1_2, uint16_t, uint8_t)
164
+DO_LD_PRIM_1(ld1bhs, H1_2, uint16_t, int8_t)
165
+DO_LD_PRIM_1(ld1bsu, H1_4, uint32_t, uint8_t)
166
+DO_LD_PRIM_1(ld1bss, H1_4, uint32_t, int8_t)
167
+DO_LD_PRIM_1(ld1bdu, , uint64_t, uint8_t)
168
+DO_LD_PRIM_1(ld1bds, , uint64_t, int8_t)
169
+
170
+#define DO_LD_PRIM_2(NAME, end, MOEND, H, TE, TM, PH, PT) \
171
+ DO_LD_HOST(NAME##_##end, H, TE, TM, PH##_##end##_p) \
172
+ DO_LD_TLB(NAME##_##end, H, TE, TM, PH##_##end##_p, \
173
+ MOEND, helper_##end##_##PT##_mmu)
174
+
175
+DO_LD_PRIM_2(ld1hh, le, MO_LE, H1_2, uint16_t, uint16_t, lduw, lduw)
176
+DO_LD_PRIM_2(ld1hsu, le, MO_LE, H1_4, uint32_t, uint16_t, lduw, lduw)
177
+DO_LD_PRIM_2(ld1hss, le, MO_LE, H1_4, uint32_t, int16_t, lduw, lduw)
178
+DO_LD_PRIM_2(ld1hdu, le, MO_LE, , uint64_t, uint16_t, lduw, lduw)
179
+DO_LD_PRIM_2(ld1hds, le, MO_LE, , uint64_t, int16_t, lduw, lduw)
180
+
181
+DO_LD_PRIM_2(ld1ss, le, MO_LE, H1_4, uint32_t, uint32_t, ldl, ldul)
182
+DO_LD_PRIM_2(ld1sdu, le, MO_LE, , uint64_t, uint32_t, ldl, ldul)
183
+DO_LD_PRIM_2(ld1sds, le, MO_LE, , uint64_t, int32_t, ldl, ldul)
184
+
185
+DO_LD_PRIM_2(ld1dd, le, MO_LE, , uint64_t, uint64_t, ldq, ldq)
186
+
187
+DO_LD_PRIM_2(ld1hh, be, MO_BE, H1_2, uint16_t, uint16_t, lduw, lduw)
188
+DO_LD_PRIM_2(ld1hsu, be, MO_BE, H1_4, uint32_t, uint16_t, lduw, lduw)
189
+DO_LD_PRIM_2(ld1hss, be, MO_BE, H1_4, uint32_t, int16_t, lduw, lduw)
190
+DO_LD_PRIM_2(ld1hdu, be, MO_BE, , uint64_t, uint16_t, lduw, lduw)
191
+DO_LD_PRIM_2(ld1hds, be, MO_BE, , uint64_t, int16_t, lduw, lduw)
192
+
193
+DO_LD_PRIM_2(ld1ss, be, MO_BE, H1_4, uint32_t, uint32_t, ldl, ldul)
194
+DO_LD_PRIM_2(ld1sdu, be, MO_BE, , uint64_t, uint32_t, ldl, ldul)
195
+DO_LD_PRIM_2(ld1sds, be, MO_BE, , uint64_t, int32_t, ldl, ldul)
196
+
197
+DO_LD_PRIM_2(ld1dd, be, MO_BE, , uint64_t, uint64_t, ldq, ldq)
198
+
199
+#undef DO_LD_TLB
200
+#undef DO_LD_HOST
201
+#undef DO_LD_PRIM_1
202
+#undef DO_LD_PRIM_2
203
+
204
+/*
205
+ * Skip through a sequence of inactive elements in the guarding predicate @vg,
206
+ * beginning at @reg_off bounded by @reg_max. Return the offset of the active
207
+ * element >= @reg_off, or @reg_max if there were no active elements at all.
208
+ */
209
+static intptr_t find_next_active(uint64_t *vg, intptr_t reg_off,
210
+ intptr_t reg_max, int esz)
211
+{
212
+ uint64_t pg_mask = pred_esz_masks[esz];
213
+ uint64_t pg = (vg[reg_off >> 6] & pg_mask) >> (reg_off & 63);
214
+
215
+ /* In normal usage, the first element is active. */
216
+ if (likely(pg & 1)) {
217
+ return reg_off;
218
+ }
219
+
220
+ if (pg == 0) {
221
+ reg_off &= -64;
222
+ do {
223
+ reg_off += 64;
224
+ if (unlikely(reg_off >= reg_max)) {
225
+ /* The entire predicate was false. */
226
+ return reg_max;
227
+ }
228
+ pg = vg[reg_off >> 6] & pg_mask;
229
+ } while (pg == 0);
230
+ }
231
+ reg_off += ctz64(pg);
232
+
233
+ /* We should never see an out of range predicate bit set. */
234
+ tcg_debug_assert(reg_off < reg_max);
235
+ return reg_off;
236
+}
237
+
238
+/*
239
+ * Return the maximum offset <= @mem_max which is still within the page
240
+ * referenced by @base + @mem_off.
241
+ */
242
+static intptr_t max_for_page(target_ulong base, intptr_t mem_off,
243
+ intptr_t mem_max)
244
+{
245
+ target_ulong addr = base + mem_off;
246
+ intptr_t split = -(intptr_t)(addr | TARGET_PAGE_MASK);
247
+ return MIN(split, mem_max - mem_off) + mem_off;
248
+}
249
+
250
+static inline void set_helper_retaddr(uintptr_t ra)
251
+{
252
+#ifdef CONFIG_USER_ONLY
253
+ helper_retaddr = ra;
254
+#endif
255
+}
256
+
257
+/*
258
+ * The result of tlb_vaddr_to_host for user-only is just g2h(x),
259
+ * which is always non-null. Elide the useless test.
260
+ */
261
+static inline bool test_host_page(void *host)
262
+{
263
+#ifdef CONFIG_USER_ONLY
264
+ return true;
265
+#else
266
+ return likely(host != NULL);
267
+#endif
268
+}
269
+
270
+/*
271
+ * Common helper for all contiguous one-register predicated loads.
272
+ */
273
+static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr,
274
+ uint32_t desc, const uintptr_t retaddr,
275
+ const int esz, const int msz,
276
+ sve_ld1_host_fn *host_fn,
277
+ sve_ld1_tlb_fn *tlb_fn)
278
+{
279
+ void *vd = &env->vfp.zregs[simd_data(desc)];
280
+ const int diffsz = esz - msz;
281
+ const intptr_t reg_max = simd_oprsz(desc);
282
+ const intptr_t mem_max = reg_max >> diffsz;
283
+ const int mmu_idx = cpu_mmu_index(env, false);
284
+ ARMVectorReg scratch;
285
+ void *host;
286
+ intptr_t split, reg_off, mem_off;
287
+
288
+ /* Find the first active element. */
289
+ reg_off = find_next_active(vg, 0, reg_max, esz);
290
+ if (unlikely(reg_off == reg_max)) {
291
+ /* The entire predicate was false; no load occurs. */
292
+ memset(vd, 0, reg_max);
293
+ return;
111
+ return;
294
+ }
112
+ }
295
+ mem_off = reg_off >> diffsz;
113
+
296
+ set_helper_retaddr(retaddr);
114
if (event == CHR_EVENT_BREAK) {
297
+
115
uart_write_rx_fifo(opaque, &buf, 1);
298
+ /*
116
}
299
+ * If the (remaining) load is entirely within a single page, then:
117
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps uart_ops = {
300
+ * For softmmu, and the tlb hits, then no faults will occur;
118
.endianness = DEVICE_NATIVE_ENDIAN,
301
+ * For user-only, either the first load will fault or none will.
119
};
302
+ * We can thus perform the load directly to the destination and
120
303
+ * Vd will be unmodified on any exception path.
121
-static void cadence_uart_reset(DeviceState *dev)
304
+ */
122
+static void cadence_uart_reset_init(Object *obj, ResetType type)
305
+ split = max_for_page(addr, mem_off, mem_max);
123
{
306
+ if (likely(split == mem_max)) {
124
- CadenceUARTState *s = CADENCE_UART(dev);
307
+ host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
125
+ CadenceUARTState *s = CADENCE_UART(obj);
308
+ if (test_host_page(host)) {
126
309
+ mem_off = host_fn(vd, vg, host - mem_off, mem_off, mem_max);
127
s->r[R_CR] = 0x00000128;
310
+ tcg_debug_assert(mem_off == mem_max);
128
s->r[R_IMR] = 0;
311
+ set_helper_retaddr(0);
129
@@ -XXX,XX +XXX,XX @@ static void cadence_uart_reset(DeviceState *dev)
312
+ /* After having taken any fault, zero leading inactive elements. */
130
s->r[R_BRGR] = 0x0000028B;
313
+ swap_memzero(vd, reg_off);
131
s->r[R_BDIV] = 0x0000000F;
314
+ return;
132
s->r[R_TTRIG] = 0x00000020;
315
+ }
316
+ }
317
+
318
+ /*
319
+ * Perform the predicated read into a temporary, thus ensuring
320
+ * if the load of the last element faults, Vd is not modified.
321
+ */
322
+#ifdef CONFIG_USER_ONLY
323
+ swap_memzero(&scratch, reg_off);
324
+ host_fn(&scratch, vg, g2h(addr), mem_off, mem_max);
325
+#else
326
+ memset(&scratch, 0, reg_max);
327
+ goto start;
328
+ while (1) {
329
+ reg_off = find_next_active(vg, reg_off, reg_max, esz);
330
+ if (reg_off >= reg_max) {
331
+ break;
332
+ }
333
+ mem_off = reg_off >> diffsz;
334
+ split = max_for_page(addr, mem_off, mem_max);
335
+
336
+ start:
337
+ if (split - mem_off >= (1 << msz)) {
338
+ /* At least one whole element on this page. */
339
+ host = tlb_vaddr_to_host(env, addr + mem_off,
340
+ MMU_DATA_LOAD, mmu_idx);
341
+ if (host) {
342
+ mem_off = host_fn(&scratch, vg, host - mem_off,
343
+ mem_off, split);
344
+ reg_off = mem_off << diffsz;
345
+ continue;
346
+ }
347
+ }
348
+
349
+ /*
350
+ * Perform one normal read. This may fault, longjmping out to the
351
+ * main loop in order to raise an exception. It may succeed, and
352
+ * as a side-effect load the TLB entry for the next round. Finally,
353
+ * in the extremely unlikely case we're performing this operation
354
+ * on I/O memory, it may succeed but not bring in the TLB entry.
355
+ * But even then we have still made forward progress.
356
+ */
357
+ tlb_fn(env, &scratch, reg_off, addr + mem_off, mmu_idx, retaddr);
358
+ reg_off += 1 << esz;
359
+ }
360
+#endif
361
+
362
+ set_helper_retaddr(0);
363
+ memcpy(vd, &scratch, reg_max);
364
+}
133
+}
365
+
134
+
366
+#define DO_LD1_1(NAME, ESZ) \
135
+static void cadence_uart_reset_hold(Object *obj)
367
+void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \
136
+{
368
+ target_ulong addr, uint32_t desc) \
137
+ CadenceUARTState *s = CADENCE_UART(obj);
369
+{ \
138
370
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, 0, \
139
uart_rx_reset(s);
371
+ sve_##NAME##_host, sve_##NAME##_tlb); \
140
uart_tx_reset(s);
141
@@ -XXX,XX +XXX,XX @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
142
uart_event, NULL, s, NULL, true);
143
}
144
145
+static void cadence_uart_refclk_update(void *opaque)
146
+{
147
+ CadenceUARTState *s = opaque;
148
+
149
+ /* recompute uart's speed on clock change */
150
+ uart_parameters_setup(s);
372
+}
151
+}
373
+
152
+
374
+/* TODO: Propagate the endian check back to the translator. */
153
static void cadence_uart_init(Object *obj)
375
+#define DO_LD1_2(NAME, ESZ, MSZ) \
154
{
376
+void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \
155
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
377
+ target_ulong addr, uint32_t desc) \
156
@@ -XXX,XX +XXX,XX @@ static void cadence_uart_init(Object *obj)
378
+{ \
157
sysbus_init_mmio(sbd, &s->iomem);
379
+ if (arm_cpu_data_is_big_endian(env)) { \
158
sysbus_init_irq(sbd, &s->irq);
380
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
159
381
+ sve_##NAME##_be_host, sve_##NAME##_be_tlb); \
160
+ s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk",
382
+ } else { \
161
+ cadence_uart_refclk_update, s);
383
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
162
+ /* initialize the frequency in case the clock remains unconnected */
384
+ sve_##NAME##_le_host, sve_##NAME##_le_tlb); \
163
+ clock_set_hz(s->refclk, UART_DEFAULT_REF_CLK);
385
+ } \
164
+
165
s->char_tx_time = (NANOSECONDS_PER_SECOND / 9600) * 10;
166
}
167
168
+static int cadence_uart_pre_load(void *opaque)
169
+{
170
+ CadenceUARTState *s = opaque;
171
+
172
+ /* the frequency will be overriden if the refclk field is present */
173
+ clock_set_hz(s->refclk, UART_DEFAULT_REF_CLK);
174
+ return 0;
386
+}
175
+}
387
+
176
+
388
+DO_LD1_1(ld1bb, 0)
177
static int cadence_uart_post_load(void *opaque, int version_id)
389
+DO_LD1_1(ld1bhu, 1)
178
{
390
+DO_LD1_1(ld1bhs, 1)
179
CadenceUARTState *s = opaque;
391
+DO_LD1_1(ld1bsu, 2)
180
@@ -XXX,XX +XXX,XX @@ static int cadence_uart_post_load(void *opaque, int version_id)
392
+DO_LD1_1(ld1bss, 2)
181
393
+DO_LD1_1(ld1bdu, 3)
182
static const VMStateDescription vmstate_cadence_uart = {
394
+DO_LD1_1(ld1bds, 3)
183
.name = "cadence_uart",
395
+
184
- .version_id = 2,
396
+DO_LD1_2(ld1hh, 1, 1)
185
+ .version_id = 3,
397
+DO_LD1_2(ld1hsu, 2, 1)
186
.minimum_version_id = 2,
398
+DO_LD1_2(ld1hss, 2, 1)
187
+ .pre_load = cadence_uart_pre_load,
399
+DO_LD1_2(ld1hdu, 3, 1)
188
.post_load = cadence_uart_post_load,
400
+DO_LD1_2(ld1hds, 3, 1)
189
.fields = (VMStateField[]) {
401
+
190
VMSTATE_UINT32_ARRAY(r, CadenceUARTState, CADENCE_UART_R_MAX),
402
+DO_LD1_2(ld1ss, 2, 2)
191
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_cadence_uart = {
403
+DO_LD1_2(ld1sdu, 3, 2)
192
VMSTATE_UINT32(tx_count, CadenceUARTState),
404
+DO_LD1_2(ld1sds, 3, 2)
193
VMSTATE_UINT32(rx_wpos, CadenceUARTState),
405
+
194
VMSTATE_TIMER_PTR(fifo_trigger_handle, CadenceUARTState),
406
+DO_LD1_2(ld1dd, 3, 3)
195
+ VMSTATE_CLOCK_V(refclk, CadenceUARTState, 3),
407
+
196
VMSTATE_END_OF_LIST()
408
+#undef DO_LD1_1
197
- }
409
+#undef DO_LD1_2
198
+ },
410
+
199
};
411
#define DO_LD2(NAME, FN, TYPEE, TYPEM, H) \
200
412
void HELPER(NAME)(CPUARMState *env, void *vg, \
201
static Property cadence_uart_properties[] = {
413
target_ulong addr, uint32_t desc) \
202
@@ -XXX,XX +XXX,XX @@ static Property cadence_uart_properties[] = {
414
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(CPUARMState *env, void *vg, \
203
static void cadence_uart_class_init(ObjectClass *klass, void *data)
415
} \
204
{
416
}
205
DeviceClass *dc = DEVICE_CLASS(klass);
417
206
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
418
-DO_LD1(sve_ld1bhu_r, cpu_ldub_data_ra, uint16_t, uint8_t, H1_2)
207
419
-DO_LD1(sve_ld1bhs_r, cpu_ldsb_data_ra, uint16_t, int8_t, H1_2)
208
dc->realize = cadence_uart_realize;
420
-DO_LD1(sve_ld1bsu_r, cpu_ldub_data_ra, uint32_t, uint8_t, H1_4)
209
dc->vmsd = &vmstate_cadence_uart;
421
-DO_LD1(sve_ld1bss_r, cpu_ldsb_data_ra, uint32_t, int8_t, H1_4)
210
- dc->reset = cadence_uart_reset;
422
-DO_LD1(sve_ld1bdu_r, cpu_ldub_data_ra, uint64_t, uint8_t, )
211
+ rc->phases.enter = cadence_uart_reset_init;
423
-DO_LD1(sve_ld1bds_r, cpu_ldsb_data_ra, uint64_t, int8_t, )
212
+ rc->phases.hold = cadence_uart_reset_hold;
424
-
213
device_class_set_props(dc, cadence_uart_properties);
425
-DO_LD1(sve_ld1hsu_r, cpu_lduw_data_ra, uint32_t, uint16_t, H1_4)
214
}
426
-DO_LD1(sve_ld1hss_r, cpu_ldsw_data_ra, uint32_t, int16_t, H1_4)
215
427
-DO_LD1(sve_ld1hdu_r, cpu_lduw_data_ra, uint64_t, uint16_t, )
216
diff --git a/hw/char/trace-events b/hw/char/trace-events
428
-DO_LD1(sve_ld1hds_r, cpu_ldsw_data_ra, uint64_t, int16_t, )
217
index XXXXXXX..XXXXXXX 100644
429
-
218
--- a/hw/char/trace-events
430
-DO_LD1(sve_ld1sdu_r, cpu_ldl_data_ra, uint64_t, uint32_t, )
219
+++ b/hw/char/trace-events
431
-DO_LD1(sve_ld1sds_r, cpu_ldl_data_ra, uint64_t, int32_t, )
220
@@ -XXX,XX +XXX,XX @@ exynos_uart_wo_read(uint32_t channel, const char *name, uint32_t reg) "UART%d: T
432
-
221
exynos_uart_rxsize(uint32_t channel, uint32_t size) "UART%d: Rx FIFO size: %d"
433
-DO_LD1(sve_ld1bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
222
exynos_uart_channel_error(uint32_t channel) "Wrong UART channel number: %d"
434
DO_LD2(sve_ld2bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
223
exynos_uart_rx_timeout(uint32_t channel, uint32_t stat, uint32_t intsp) "UART%d: Rx timeout stat=0x%x intsp=0x%x"
435
DO_LD3(sve_ld3bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
224
+
436
DO_LD4(sve_ld4bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
225
+# hw/char/cadence_uart.c
437
226
+cadence_uart_baudrate(unsigned baudrate) "baudrate %u"
438
-DO_LD1(sve_ld1hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
439
DO_LD2(sve_ld2hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
440
DO_LD3(sve_ld3hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
441
DO_LD4(sve_ld4hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
442
443
-DO_LD1(sve_ld1ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
444
DO_LD2(sve_ld2ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
445
DO_LD3(sve_ld3ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
446
DO_LD4(sve_ld4ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
447
448
-DO_LD1(sve_ld1dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
449
DO_LD2(sve_ld2dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
450
DO_LD3(sve_ld3dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
451
DO_LD4(sve_ld4dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
452
453
-#undef DO_LD1
454
#undef DO_LD2
455
#undef DO_LD3
456
#undef DO_LD4
457
458
/*
459
* Load contiguous data, first-fault and no-fault.
460
+ *
461
+ * For user-only, one could argue that we should hold the mmap_lock during
462
+ * the operation so that there is no race between page_check_range and the
463
+ * load operation. However, unmapping pages out from under a running thread
464
+ * is extraordinarily unlikely. This theoretical race condition also affects
465
+ * linux-user/ in its get_user/put_user macros.
466
+ *
467
+ * TODO: Construct some helpers, written in assembly, that interact with
468
+ * handle_cpu_signal to produce memory ops which can properly report errors
469
+ * without racing.
470
*/
471
472
-#ifdef CONFIG_USER_ONLY
473
-
474
/* Fault on byte I. All bits in FFR from I are cleared. The vector
475
* result from I is CONSTRAINED UNPREDICTABLE; we choose the MERGE
476
* option, which leaves subsequent data unchanged.
477
@@ -XXX,XX +XXX,XX @@ static void record_fault(CPUARMState *env, uintptr_t i, uintptr_t oprsz)
478
}
479
}
480
481
-/* Hold the mmap lock during the operation so that there is no race
482
- * between page_check_range and the load operation. We expect the
483
- * usual case to have no faults at all, so we check the whole range
484
- * first and if successful defer to the normal load operation.
485
- *
486
- * TODO: Change mmap_lock to a rwlock so that multiple readers
487
- * can run simultaneously. This will probably help other uses
488
- * within QEMU as well.
489
+/*
490
+ * Common helper for all contiguous first-fault loads.
491
*/
492
-#define DO_LDFF1(PART, FN, TYPEE, TYPEM, H) \
493
-static void do_sve_ldff1##PART(CPUARMState *env, void *vd, void *vg, \
494
- target_ulong addr, intptr_t oprsz, \
495
- bool first, uintptr_t ra) \
496
-{ \
497
- intptr_t i = 0; \
498
- do { \
499
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
500
- do { \
501
- TYPEM m = 0; \
502
- if (pg & 1) { \
503
- if (!first && \
504
- unlikely(page_check_range(addr, sizeof(TYPEM), \
505
- PAGE_READ))) { \
506
- record_fault(env, i, oprsz); \
507
- return; \
508
- } \
509
- m = FN(env, addr, ra); \
510
- first = false; \
511
- } \
512
- *(TYPEE *)(vd + H(i)) = m; \
513
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
514
- addr += sizeof(TYPEM); \
515
- } while (i & 15); \
516
- } while (i < oprsz); \
517
-} \
518
-void HELPER(sve_ldff1##PART)(CPUARMState *env, void *vg, \
519
- target_ulong addr, uint32_t desc) \
520
-{ \
521
- intptr_t oprsz = simd_oprsz(desc); \
522
- unsigned rd = simd_data(desc); \
523
- void *vd = &env->vfp.zregs[rd]; \
524
- mmap_lock(); \
525
- if (likely(page_check_range(addr, oprsz, PAGE_READ) == 0)) { \
526
- do_sve_ld1##PART(env, vd, vg, addr, oprsz, GETPC()); \
527
- } else { \
528
- do_sve_ldff1##PART(env, vd, vg, addr, oprsz, true, GETPC()); \
529
- } \
530
- mmap_unlock(); \
531
-}
532
+static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr,
533
+ uint32_t desc, const uintptr_t retaddr,
534
+ const int esz, const int msz,
535
+ sve_ld1_host_fn *host_fn,
536
+ sve_ld1_tlb_fn *tlb_fn)
537
+{
538
+ void *vd = &env->vfp.zregs[simd_data(desc)];
539
+ const int diffsz = esz - msz;
540
+ const intptr_t reg_max = simd_oprsz(desc);
541
+ const intptr_t mem_max = reg_max >> diffsz;
542
+ const int mmu_idx = cpu_mmu_index(env, false);
543
+ intptr_t split, reg_off, mem_off;
544
+ void *host;
545
546
-/* No-fault loads are like first-fault loads without the
547
- * first faulting special case.
548
- */
549
-#define DO_LDNF1(PART) \
550
-void HELPER(sve_ldnf1##PART)(CPUARMState *env, void *vg, \
551
- target_ulong addr, uint32_t desc) \
552
-{ \
553
- intptr_t oprsz = simd_oprsz(desc); \
554
- unsigned rd = simd_data(desc); \
555
- void *vd = &env->vfp.zregs[rd]; \
556
- mmap_lock(); \
557
- if (likely(page_check_range(addr, oprsz, PAGE_READ) == 0)) { \
558
- do_sve_ld1##PART(env, vd, vg, addr, oprsz, GETPC()); \
559
- } else { \
560
- do_sve_ldff1##PART(env, vd, vg, addr, oprsz, false, GETPC()); \
561
- } \
562
- mmap_unlock(); \
563
-}
564
+ /* Skip to the first active element. */
565
+ reg_off = find_next_active(vg, 0, reg_max, esz);
566
+ if (unlikely(reg_off == reg_max)) {
567
+ /* The entire predicate was false; no load occurs. */
568
+ memset(vd, 0, reg_max);
569
+ return;
570
+ }
571
+ mem_off = reg_off >> diffsz;
572
+ set_helper_retaddr(retaddr);
573
574
+ /*
575
+ * If the (remaining) load is entirely within a single page, then:
576
+ * For softmmu, and the tlb hits, then no faults will occur;
577
+ * For user-only, either the first load will fault or none will.
578
+ * We can thus perform the load directly to the destination and
579
+ * Vd will be unmodified on any exception path.
580
+ */
581
+ split = max_for_page(addr, mem_off, mem_max);
582
+ if (likely(split == mem_max)) {
583
+ host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
584
+ if (test_host_page(host)) {
585
+ mem_off = host_fn(vd, vg, host - mem_off, mem_off, mem_max);
586
+ tcg_debug_assert(mem_off == mem_max);
587
+ set_helper_retaddr(0);
588
+ /* After any fault, zero any leading inactive elements. */
589
+ swap_memzero(vd, reg_off);
590
+ return;
591
+ }
592
+ }
593
+
594
+#ifdef CONFIG_USER_ONLY
595
+ /*
596
+ * The page(s) containing this first element at ADDR+MEM_OFF must
597
+ * be valid. Considering that this first element may be misaligned
598
+ * and cross a page boundary itself, take the rest of the page from
599
+ * the last byte of the element.
600
+ */
601
+ split = max_for_page(addr, mem_off + (1 << msz) - 1, mem_max);
602
+ mem_off = host_fn(vd, vg, g2h(addr), mem_off, split);
603
+
604
+ /* After any fault, zero any leading inactive elements. */
605
+ swap_memzero(vd, reg_off);
606
+ reg_off = mem_off << diffsz;
607
#else
608
+ /*
609
+ * Perform one normal read, which will fault or not.
610
+ * But it is likely to bring the page into the tlb.
611
+ */
612
+ tlb_fn(env, vd, reg_off, addr + mem_off, mmu_idx, retaddr);
613
614
-/* TODO: System mode is not yet supported.
615
- * This would probably use tlb_vaddr_to_host.
616
- */
617
-#define DO_LDFF1(PART, FN, TYPEE, TYPEM, H) \
618
-void HELPER(sve_ldff1##PART)(CPUARMState *env, void *vg, \
619
- target_ulong addr, uint32_t desc) \
620
-{ \
621
- g_assert_not_reached(); \
622
-}
623
-
624
-#define DO_LDNF1(PART) \
625
-void HELPER(sve_ldnf1##PART)(CPUARMState *env, void *vg, \
626
- target_ulong addr, uint32_t desc) \
627
-{ \
628
- g_assert_not_reached(); \
629
-}
630
+ /* After any fault, zero any leading predicated false elts. */
631
+ swap_memzero(vd, reg_off);
632
+ mem_off += 1 << msz;
633
+ reg_off += 1 << esz;
634
635
+ /* Try again to read the balance of the page. */
636
+ split = max_for_page(addr, mem_off - 1, mem_max);
637
+ if (split >= (1 << msz)) {
638
+ host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
639
+ if (host) {
640
+ mem_off = host_fn(vd, vg, host - mem_off, mem_off, split);
641
+ reg_off = mem_off << diffsz;
642
+ }
643
+ }
644
#endif
645
646
-DO_LDFF1(bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
647
-DO_LDFF1(bhu_r, cpu_ldub_data_ra, uint16_t, uint8_t, H1_2)
648
-DO_LDFF1(bhs_r, cpu_ldsb_data_ra, uint16_t, int8_t, H1_2)
649
-DO_LDFF1(bsu_r, cpu_ldub_data_ra, uint32_t, uint8_t, H1_4)
650
-DO_LDFF1(bss_r, cpu_ldsb_data_ra, uint32_t, int8_t, H1_4)
651
-DO_LDFF1(bdu_r, cpu_ldub_data_ra, uint64_t, uint8_t, )
652
-DO_LDFF1(bds_r, cpu_ldsb_data_ra, uint64_t, int8_t, )
653
+ set_helper_retaddr(0);
654
+ record_fault(env, reg_off, reg_max);
655
+}
656
657
-DO_LDFF1(hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
658
-DO_LDFF1(hsu_r, cpu_lduw_data_ra, uint32_t, uint16_t, H1_4)
659
-DO_LDFF1(hss_r, cpu_ldsw_data_ra, uint32_t, int8_t, H1_4)
660
-DO_LDFF1(hdu_r, cpu_lduw_data_ra, uint64_t, uint16_t, )
661
-DO_LDFF1(hds_r, cpu_ldsw_data_ra, uint64_t, int16_t, )
662
+/*
663
+ * Common helper for all contiguous no-fault loads.
664
+ */
665
+static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr,
666
+ uint32_t desc, const int esz, const int msz,
667
+ sve_ld1_host_fn *host_fn)
668
+{
669
+ void *vd = &env->vfp.zregs[simd_data(desc)];
670
+ const int diffsz = esz - msz;
671
+ const intptr_t reg_max = simd_oprsz(desc);
672
+ const intptr_t mem_max = reg_max >> diffsz;
673
+ const int mmu_idx = cpu_mmu_index(env, false);
674
+ intptr_t split, reg_off, mem_off;
675
+ void *host;
676
677
-DO_LDFF1(ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
678
-DO_LDFF1(sdu_r, cpu_ldl_data_ra, uint64_t, uint32_t, )
679
-DO_LDFF1(sds_r, cpu_ldl_data_ra, uint64_t, int32_t, )
680
+#ifdef CONFIG_USER_ONLY
681
+ host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, mmu_idx);
682
+ if (likely(page_check_range(addr, mem_max, PAGE_READ) == 0)) {
683
+ /* The entire operation is valid and will not fault. */
684
+ host_fn(vd, vg, host, 0, mem_max);
685
+ return;
686
+ }
687
+#endif
688
689
-DO_LDFF1(dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
690
+ /* There will be no fault, so we may modify in advance. */
691
+ memset(vd, 0, reg_max);
692
693
-#undef DO_LDFF1
694
+ /* Skip to the first active element. */
695
+ reg_off = find_next_active(vg, 0, reg_max, esz);
696
+ if (unlikely(reg_off == reg_max)) {
697
+ /* The entire predicate was false; no load occurs. */
698
+ return;
699
+ }
700
+ mem_off = reg_off >> diffsz;
701
702
-DO_LDNF1(bb_r)
703
-DO_LDNF1(bhu_r)
704
-DO_LDNF1(bhs_r)
705
-DO_LDNF1(bsu_r)
706
-DO_LDNF1(bss_r)
707
-DO_LDNF1(bdu_r)
708
-DO_LDNF1(bds_r)
709
+#ifdef CONFIG_USER_ONLY
710
+ if (page_check_range(addr + mem_off, 1 << msz, PAGE_READ) == 0) {
711
+ /* At least one load is valid; take the rest of the page. */
712
+ split = max_for_page(addr, mem_off + (1 << msz) - 1, mem_max);
713
+ mem_off = host_fn(vd, vg, host, mem_off, split);
714
+ reg_off = mem_off << diffsz;
715
+ }
716
+#else
717
+ /*
718
+ * If the address is not in the TLB, we have no way to bring the
719
+ * entry into the TLB without also risking a fault. Note that
720
+ * the corollary is that we never load from an address not in RAM.
721
+ *
722
+ * This last is out of spec, in a weird corner case.
723
+ * Per the MemNF/MemSingleNF pseudocode, a NF load from Device memory
724
+ * must not actually hit the bus -- it returns UNKNOWN data instead.
725
+ * But if you map non-RAM with Normal memory attributes and do a NF
726
+ * load then it should access the bus. (Nobody ought actually do this
727
+ * in the real world, obviously.)
728
+ *
729
+ * Then there are the annoying special cases with watchpoints...
730
+ *
731
+ * TODO: Add a form of tlb_fill that does not raise an exception,
732
+ * with a form of tlb_vaddr_to_host and a set of loads to match.
733
+ * The non_fault_vaddr_to_host would handle everything, usually,
734
+ * and the loads would handle the iomem path for watchpoints.
735
+ */
736
+ host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
737
+ split = max_for_page(addr, mem_off, mem_max);
738
+ if (host && split >= (1 << msz)) {
739
+ mem_off = host_fn(vd, vg, host - mem_off, mem_off, split);
740
+ reg_off = mem_off << diffsz;
741
+ }
742
+#endif
743
744
-DO_LDNF1(hh_r)
745
-DO_LDNF1(hsu_r)
746
-DO_LDNF1(hss_r)
747
-DO_LDNF1(hdu_r)
748
-DO_LDNF1(hds_r)
749
+ record_fault(env, reg_off, reg_max);
750
+}
751
752
-DO_LDNF1(ss_r)
753
-DO_LDNF1(sdu_r)
754
-DO_LDNF1(sds_r)
755
+#define DO_LDFF1_LDNF1_1(PART, ESZ) \
756
+void HELPER(sve_ldff1##PART##_r)(CPUARMState *env, void *vg, \
757
+ target_ulong addr, uint32_t desc) \
758
+{ \
759
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, 0, \
760
+ sve_ld1##PART##_host, sve_ld1##PART##_tlb); \
761
+} \
762
+void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \
763
+ target_ulong addr, uint32_t desc) \
764
+{ \
765
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, 0, sve_ld1##PART##_host); \
766
+}
767
768
-DO_LDNF1(dd_r)
769
+/* TODO: Propagate the endian check back to the translator. */
770
+#define DO_LDFF1_LDNF1_2(PART, ESZ, MSZ) \
771
+void HELPER(sve_ldff1##PART##_r)(CPUARMState *env, void *vg, \
772
+ target_ulong addr, uint32_t desc) \
773
+{ \
774
+ if (arm_cpu_data_is_big_endian(env)) { \
775
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
776
+ sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \
777
+ } else { \
778
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
779
+ sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \
780
+ } \
781
+} \
782
+void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \
783
+ target_ulong addr, uint32_t desc) \
784
+{ \
785
+ if (arm_cpu_data_is_big_endian(env)) { \
786
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, \
787
+ sve_ld1##PART##_be_host); \
788
+ } else { \
789
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, \
790
+ sve_ld1##PART##_le_host); \
791
+ } \
792
+}
793
794
-#undef DO_LDNF1
795
+DO_LDFF1_LDNF1_1(bb, 0)
796
+DO_LDFF1_LDNF1_1(bhu, 1)
797
+DO_LDFF1_LDNF1_1(bhs, 1)
798
+DO_LDFF1_LDNF1_1(bsu, 2)
799
+DO_LDFF1_LDNF1_1(bss, 2)
800
+DO_LDFF1_LDNF1_1(bdu, 3)
801
+DO_LDFF1_LDNF1_1(bds, 3)
802
+
803
+DO_LDFF1_LDNF1_2(hh, 1, 1)
804
+DO_LDFF1_LDNF1_2(hsu, 2, 1)
805
+DO_LDFF1_LDNF1_2(hss, 2, 1)
806
+DO_LDFF1_LDNF1_2(hdu, 3, 1)
807
+DO_LDFF1_LDNF1_2(hds, 3, 1)
808
+
809
+DO_LDFF1_LDNF1_2(ss, 2, 2)
810
+DO_LDFF1_LDNF1_2(sdu, 3, 2)
811
+DO_LDFF1_LDNF1_2(sds, 3, 2)
812
+
813
+DO_LDFF1_LDNF1_2(dd, 3, 3)
814
+
815
+#undef DO_LDFF1_LDNF1_1
816
+#undef DO_LDFF1_LDNF1_2
817
818
/*
819
* Store contiguous data, protected by a governing predicate.
820
--
227
--
821
2.19.0
228
2.20.1
822
229
823
230
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
2
3
We can choose the endianness at translation time, rather than
3
Add the connection between the slcr's output clocks and the uarts inputs.
4
re-computing it at execution time.
5
4
6
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
Also add the main board clock 'ps_clk', which is hard-coded to 33.33MHz
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
(the default frequency). This clock is used to feed the slcr's input
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
clock.
9
Message-id: 20181005175350.30752-12-richard.henderson@linaro.org
8
9
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Message-id: 20200406135251.157596-9-damien.hedde@greensocs.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
14
---
12
target/arm/helper-sve.h | 48 +++++++++++++++++--------
15
hw/arm/xilinx_zynq.c | 57 +++++++++++++++++++++++++++++++++++++-------
13
target/arm/sve_helper.c | 11 ++++--
16
1 file changed, 49 insertions(+), 8 deletions(-)
14
target/arm/translate-sve.c | 72 +++++++++++++++++++++++++++++---------
15
3 files changed, 96 insertions(+), 35 deletions(-)
16
17
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
18
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-sve.h
20
--- a/hw/arm/xilinx_zynq.c
20
+++ b/target/arm/helper-sve.h
21
+++ b/hw/arm/xilinx_zynq.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_st2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
22
@@ -XXX,XX +XXX,XX @@
22
DEF_HELPER_FLAGS_4(sve_st3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
23
#include "hw/char/cadence_uart.h"
23
DEF_HELPER_FLAGS_4(sve_st4bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
24
#include "hw/net/cadence_gem.h"
24
25
#include "hw/cpu/a9mpcore.h"
25
-DEF_HELPER_FLAGS_4(sve_st1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
26
+#include "hw/qdev-clock.h"
26
-DEF_HELPER_FLAGS_4(sve_st2hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
27
+#include "sysemu/reset.h"
27
-DEF_HELPER_FLAGS_4(sve_st3hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
28
-DEF_HELPER_FLAGS_4(sve_st4hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
29
+DEF_HELPER_FLAGS_4(sve_st1hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
30
+DEF_HELPER_FLAGS_4(sve_st2hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
31
+DEF_HELPER_FLAGS_4(sve_st3hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
32
+DEF_HELPER_FLAGS_4(sve_st4hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
33
34
-DEF_HELPER_FLAGS_4(sve_st1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
35
-DEF_HELPER_FLAGS_4(sve_st2ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
36
-DEF_HELPER_FLAGS_4(sve_st3ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
37
-DEF_HELPER_FLAGS_4(sve_st4ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
38
+DEF_HELPER_FLAGS_4(sve_st1hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
39
+DEF_HELPER_FLAGS_4(sve_st2hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_4(sve_st3hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
41
+DEF_HELPER_FLAGS_4(sve_st4hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
43
-DEF_HELPER_FLAGS_4(sve_st1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
44
-DEF_HELPER_FLAGS_4(sve_st2dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
45
-DEF_HELPER_FLAGS_4(sve_st3dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
46
-DEF_HELPER_FLAGS_4(sve_st4dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_4(sve_st1ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_4(sve_st2ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
49
+DEF_HELPER_FLAGS_4(sve_st3ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
50
+DEF_HELPER_FLAGS_4(sve_st4ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
51
+
28
+
52
+DEF_HELPER_FLAGS_4(sve_st1ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
29
+#define TYPE_ZYNQ_MACHINE MACHINE_TYPE_NAME("xilinx-zynq-a9")
53
+DEF_HELPER_FLAGS_4(sve_st2ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
30
+#define ZYNQ_MACHINE(obj) \
54
+DEF_HELPER_FLAGS_4(sve_st3ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
31
+ OBJECT_CHECK(ZynqMachineState, (obj), TYPE_ZYNQ_MACHINE)
55
+DEF_HELPER_FLAGS_4(sve_st4ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
56
+
32
+
57
+DEF_HELPER_FLAGS_4(sve_st1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
33
+/* board base frequency: 33.333333 MHz */
58
+DEF_HELPER_FLAGS_4(sve_st2dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
34
+#define PS_CLK_FREQUENCY (100 * 1000 * 1000 / 3)
59
+DEF_HELPER_FLAGS_4(sve_st3dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
35
60
+DEF_HELPER_FLAGS_4(sve_st4dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
36
#define NUM_SPI_FLASHES 4
37
#define NUM_QSPI_FLASHES 2
38
@@ -XXX,XX +XXX,XX @@ static const int dma_irqs[8] = {
39
0xe3401000 + ARMV7_IMM16(extract32((val), 16, 16)), /* movt r1 ... */ \
40
0xe5801000 + (addr)
41
42
+typedef struct ZynqMachineState {
43
+ MachineState parent;
44
+ Clock *ps_clk;
45
+} ZynqMachineState;
61
+
46
+
62
+DEF_HELPER_FLAGS_4(sve_st1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
47
static void zynq_write_board_setup(ARMCPU *cpu,
63
+DEF_HELPER_FLAGS_4(sve_st2dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
48
const struct arm_boot_info *info)
64
+DEF_HELPER_FLAGS_4(sve_st3dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
49
{
65
+DEF_HELPER_FLAGS_4(sve_st4dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
50
@@ -XXX,XX +XXX,XX @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
66
51
67
DEF_HELPER_FLAGS_4(sve_st1bh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
52
static void zynq_init(MachineState *machine)
68
DEF_HELPER_FLAGS_4(sve_st1bs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
53
{
69
DEF_HELPER_FLAGS_4(sve_st1bd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
54
+ ZynqMachineState *zynq_machine = ZYNQ_MACHINE(machine);
70
55
ARMCPU *cpu;
71
-DEF_HELPER_FLAGS_4(sve_st1hs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
56
MemoryRegion *address_space_mem = get_system_memory();
72
-DEF_HELPER_FLAGS_4(sve_st1hd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
57
MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
73
+DEF_HELPER_FLAGS_4(sve_st1hs_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
58
- DeviceState *dev;
74
+DEF_HELPER_FLAGS_4(sve_st1hd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
59
+ DeviceState *dev, *slcr;
75
+DEF_HELPER_FLAGS_4(sve_st1hs_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
60
SysBusDevice *busdev;
76
+DEF_HELPER_FLAGS_4(sve_st1hd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
61
qemu_irq pic[64];
77
62
int n;
78
-DEF_HELPER_FLAGS_4(sve_st1sd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
63
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
79
+DEF_HELPER_FLAGS_4(sve_st1sd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
64
1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
80
+DEF_HELPER_FLAGS_4(sve_st1sd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
65
0);
81
66
82
DEF_HELPER_FLAGS_6(sve_ldbsu_zsu, TCG_CALL_NO_WG,
67
- dev = qdev_create(NULL, "xilinx,zynq_slcr");
83
void, env, ptr, ptr, ptr, tl, i32)
68
- qdev_init_nofail(dev);
84
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
69
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000);
85
index XXXXXXX..XXXXXXX 100644
70
+ /* Create slcr, keep a pointer to connect clocks */
86
--- a/target/arm/sve_helper.c
71
+ slcr = qdev_create(NULL, "xilinx,zynq_slcr");
87
+++ b/target/arm/sve_helper.c
72
+ qdev_init_nofail(slcr);
88
@@ -XXX,XX +XXX,XX @@ void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
73
+ sysbus_mmio_map(SYS_BUS_DEVICE(slcr), 0, 0xF8000000);
74
+
75
+ /* Create the main clock source, and feed slcr with it */
76
+ zynq_machine->ps_clk = CLOCK(object_new(TYPE_CLOCK));
77
+ object_property_add_child(OBJECT(zynq_machine), "ps_clk",
78
+ OBJECT(zynq_machine->ps_clk), &error_abort);
79
+ object_unref(OBJECT(zynq_machine->ps_clk));
80
+ clock_set_hz(zynq_machine->ps_clk, PS_CLK_FREQUENCY);
81
+ qdev_connect_clock_in(slcr, "ps_clk", zynq_machine->ps_clk);
82
83
dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
84
qdev_prop_set_uint32(dev, "num-cpu", 1);
85
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
86
sysbus_create_simple(TYPE_CHIPIDEA, 0xE0002000, pic[53 - IRQ_OFFSET]);
87
sysbus_create_simple(TYPE_CHIPIDEA, 0xE0003000, pic[76 - IRQ_OFFSET]);
88
89
- cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0));
90
- cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1));
91
+ dev = cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0));
92
+ qdev_connect_clock_in(dev, "refclk",
93
+ qdev_get_clock_out(slcr, "uart0_ref_clk"));
94
+ dev = cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1));
95
+ qdev_connect_clock_in(dev, "refclk",
96
+ qdev_get_clock_out(slcr, "uart1_ref_clk"));
97
98
sysbus_create_varargs("cadence_ttc", 0xF8001000,
99
pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
100
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
101
arm_load_kernel(ARM_CPU(first_cpu), machine, &zynq_binfo);
89
}
102
}
90
103
91
#define DO_STN_2(N, NAME, ESIZE, MSIZE) \
104
-static void zynq_machine_init(MachineClass *mc)
92
-void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
105
+static void zynq_machine_class_init(ObjectClass *oc, void *data)
93
+void __attribute__((flatten)) HELPER(sve_st##N##NAME##_le_r) \
106
{
94
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
107
+ MachineClass *mc = MACHINE_CLASS(oc);
95
{ \
108
mc->desc = "Xilinx Zynq Platform Baseboard for Cortex-A9";
96
sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \
109
mc->init = zynq_init;
97
- arm_cpu_data_is_big_endian(env) \
110
mc->max_cpus = 1;
98
- ? sve_st1##NAME##_be_tlb : sve_st1##NAME##_le_tlb); \
111
@@ -XXX,XX +XXX,XX @@ static void zynq_machine_init(MachineClass *mc)
99
+ sve_st1##NAME##_le_tlb); \
112
mc->default_ram_id = "zynq.ext_ram";
100
+} \
101
+void __attribute__((flatten)) HELPER(sve_st##N##NAME##_be_r) \
102
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
103
+{ \
104
+ sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \
105
+ sve_st1##NAME##_be_tlb); \
106
}
113
}
107
114
108
DO_STN_1(1, bb, 1)
115
-DEFINE_MACHINE("xilinx-zynq-a9", zynq_machine_init)
109
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
116
+static const TypeInfo zynq_machine_type = {
110
index XXXXXXX..XXXXXXX 100644
117
+ .name = TYPE_ZYNQ_MACHINE,
111
--- a/target/arm/translate-sve.c
118
+ .parent = TYPE_MACHINE,
112
+++ b/target/arm/translate-sve.c
119
+ .class_init = zynq_machine_class_init,
113
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
120
+ .instance_size = sizeof(ZynqMachineState),
114
static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
121
+};
115
int msz, int esz, int nreg)
122
+
116
{
123
+static void zynq_machine_register_types(void)
117
- static gen_helper_gvec_mem * const fn_single[4][4] = {
124
+{
118
- { gen_helper_sve_st1bb_r, gen_helper_sve_st1bh_r,
125
+ type_register_static(&zynq_machine_type);
119
- gen_helper_sve_st1bs_r, gen_helper_sve_st1bd_r },
126
+}
120
- { NULL, gen_helper_sve_st1hh_r,
127
+
121
- gen_helper_sve_st1hs_r, gen_helper_sve_st1hd_r },
128
+type_init(zynq_machine_register_types)
122
- { NULL, NULL,
123
- gen_helper_sve_st1ss_r, gen_helper_sve_st1sd_r },
124
- { NULL, NULL, NULL, gen_helper_sve_st1dd_r },
125
+ static gen_helper_gvec_mem * const fn_single[2][4][4] = {
126
+ { { gen_helper_sve_st1bb_r,
127
+ gen_helper_sve_st1bh_r,
128
+ gen_helper_sve_st1bs_r,
129
+ gen_helper_sve_st1bd_r },
130
+ { NULL,
131
+ gen_helper_sve_st1hh_le_r,
132
+ gen_helper_sve_st1hs_le_r,
133
+ gen_helper_sve_st1hd_le_r },
134
+ { NULL, NULL,
135
+ gen_helper_sve_st1ss_le_r,
136
+ gen_helper_sve_st1sd_le_r },
137
+ { NULL, NULL, NULL,
138
+ gen_helper_sve_st1dd_le_r } },
139
+ { { gen_helper_sve_st1bb_r,
140
+ gen_helper_sve_st1bh_r,
141
+ gen_helper_sve_st1bs_r,
142
+ gen_helper_sve_st1bd_r },
143
+ { NULL,
144
+ gen_helper_sve_st1hh_be_r,
145
+ gen_helper_sve_st1hs_be_r,
146
+ gen_helper_sve_st1hd_be_r },
147
+ { NULL, NULL,
148
+ gen_helper_sve_st1ss_be_r,
149
+ gen_helper_sve_st1sd_be_r },
150
+ { NULL, NULL, NULL,
151
+ gen_helper_sve_st1dd_be_r } },
152
};
153
- static gen_helper_gvec_mem * const fn_multiple[3][4] = {
154
- { gen_helper_sve_st2bb_r, gen_helper_sve_st2hh_r,
155
- gen_helper_sve_st2ss_r, gen_helper_sve_st2dd_r },
156
- { gen_helper_sve_st3bb_r, gen_helper_sve_st3hh_r,
157
- gen_helper_sve_st3ss_r, gen_helper_sve_st3dd_r },
158
- { gen_helper_sve_st4bb_r, gen_helper_sve_st4hh_r,
159
- gen_helper_sve_st4ss_r, gen_helper_sve_st4dd_r },
160
+ static gen_helper_gvec_mem * const fn_multiple[2][3][4] = {
161
+ { { gen_helper_sve_st2bb_r,
162
+ gen_helper_sve_st2hh_le_r,
163
+ gen_helper_sve_st2ss_le_r,
164
+ gen_helper_sve_st2dd_le_r },
165
+ { gen_helper_sve_st3bb_r,
166
+ gen_helper_sve_st3hh_le_r,
167
+ gen_helper_sve_st3ss_le_r,
168
+ gen_helper_sve_st3dd_le_r },
169
+ { gen_helper_sve_st4bb_r,
170
+ gen_helper_sve_st4hh_le_r,
171
+ gen_helper_sve_st4ss_le_r,
172
+ gen_helper_sve_st4dd_le_r } },
173
+ { { gen_helper_sve_st2bb_r,
174
+ gen_helper_sve_st2hh_be_r,
175
+ gen_helper_sve_st2ss_be_r,
176
+ gen_helper_sve_st2dd_be_r },
177
+ { gen_helper_sve_st3bb_r,
178
+ gen_helper_sve_st3hh_be_r,
179
+ gen_helper_sve_st3ss_be_r,
180
+ gen_helper_sve_st3dd_be_r },
181
+ { gen_helper_sve_st4bb_r,
182
+ gen_helper_sve_st4hh_be_r,
183
+ gen_helper_sve_st4ss_be_r,
184
+ gen_helper_sve_st4dd_be_r } },
185
};
186
gen_helper_gvec_mem *fn;
187
+ int be = s->be_data == MO_BE;
188
189
if (nreg == 0) {
190
/* ST1 */
191
- fn = fn_single[msz][esz];
192
+ fn = fn_single[be][msz][esz];
193
} else {
194
/* ST2, ST3, ST4 -- msz == esz, enforced by encoding */
195
assert(msz == esz);
196
- fn = fn_multiple[nreg - 1][msz];
197
+ fn = fn_multiple[be][nreg - 1][msz];
198
}
199
assert(fn != NULL);
200
do_mem_zpa(s, zt, pg, addr, fn);
201
--
129
--
202
2.19.0
130
2.20.1
203
131
204
132
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
2
3
This fixes the endianness problem for softmmu, and moves the
3
This prints the clocks attached to a DeviceState when using
4
main loop out of a macro and into an inlined function.
4
"info qtree" monitor command. For every clock, it displays the
5
direction, the name and if the clock is forwarded. For input clock,
6
it displays also the frequency.
5
7
8
This is based on the original work of Frederic Konrad.
9
10
Here follows a sample of `info qtree` output on xilinx_zynq machine
11
after linux boot with only one uart clocked:
12
> bus: main-system-bus
13
> type System
14
> [...]
15
> dev: cadence_uart, id ""
16
> gpio-out "sysbus-irq" 1
17
> clock-in "refclk" freq_hz=0.000000e+00
18
> chardev = ""
19
> mmio 00000000e0001000/0000000000001000
20
> dev: cadence_uart, id ""
21
> gpio-out "sysbus-irq" 1
22
> clock-in "refclk" freq_hz=1.375661e+07
23
> chardev = "serial0"
24
> mmio 00000000e0000000/0000000000001000
25
> [...]
26
> dev: xilinx,zynq_slcr, id ""
27
> clock-out "uart1_ref_clk" freq_hz=0.000000e+00
28
> clock-out "uart0_ref_clk" freq_hz=1.375661e+07
29
> clock-in "ps_clk" freq_hz=3.333333e+07
30
> mmio 00000000f8000000/0000000000001000
31
32
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
33
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
34
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
35
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
36
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Message-id: 20181005175350.30752-10-richard.henderson@linaro.org
37
Message-id: 20200406135251.157596-10-damien.hedde@greensocs.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
39
---
12
target/arm/sve_helper.c | 351 ++++++++++++++++++++--------------------
40
qdev-monitor.c | 9 +++++++++
13
1 file changed, 172 insertions(+), 179 deletions(-)
41
1 file changed, 9 insertions(+)
14
42
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
43
diff --git a/qdev-monitor.c b/qdev-monitor.c
16
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sve_helper.c
45
--- a/qdev-monitor.c
18
+++ b/target/arm/sve_helper.c
46
+++ b/qdev-monitor.c
19
@@ -XXX,XX +XXX,XX @@ typedef intptr_t sve_ld1_host_fn(void *vd, void *vg, void *host,
47
@@ -XXX,XX +XXX,XX @@
20
*/
48
#include "migration/misc.h"
21
typedef void sve_ld1_tlb_fn(CPUARMState *env, void *vd, intptr_t reg_off,
49
#include "migration/migration.h"
22
target_ulong vaddr, int mmu_idx, uintptr_t ra);
50
#include "qemu/cutils.h"
23
+typedef sve_ld1_tlb_fn sve_st1_tlb_fn;
51
+#include "hw/clock.h"
24
52
25
/*
53
/*
26
* Generate the above primitives.
54
* Aliases were a bad idea from the start. Let's keep them
27
@@ -XXX,XX +XXX,XX @@ DO_LDFF1_LDNF1_2(dd, 3, 3)
55
@@ -XXX,XX +XXX,XX @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
28
/*
56
ObjectClass *class;
29
* Store contiguous data, protected by a governing predicate.
57
BusState *child;
30
*/
58
NamedGPIOList *ngl;
31
-#define DO_ST1(NAME, FN, TYPEE, TYPEM, H) \
59
+ NamedClockList *ncl;
32
-void HELPER(NAME)(CPUARMState *env, void *vg, \
60
33
- target_ulong addr, uint32_t desc) \
61
qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
34
-{ \
62
dev->id ? dev->id : "");
35
- intptr_t i, oprsz = simd_oprsz(desc); \
63
@@ -XXX,XX +XXX,XX @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
36
- intptr_t ra = GETPC(); \
64
ngl->num_out);
37
- unsigned rd = simd_data(desc); \
65
}
38
- void *vd = &env->vfp.zregs[rd]; \
39
- for (i = 0; i < oprsz; ) { \
40
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
41
- do { \
42
- if (pg & 1) { \
43
- TYPEM m = *(TYPEE *)(vd + H(i)); \
44
- FN(env, addr, m, ra); \
45
- } \
46
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
47
- addr += sizeof(TYPEM); \
48
- } while (i & 15); \
49
- } \
50
+
51
+#ifdef CONFIG_SOFTMMU
52
+#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \
53
+static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
54
+ target_ulong addr, int mmu_idx, uintptr_t ra) \
55
+{ \
56
+ TCGMemOpIdx oi = make_memop_idx(ctz32(sizeof(TYPEM)) | MOEND, mmu_idx); \
57
+ TLB(env, addr, *(TYPEM *)(vd + H(reg_off)), oi, ra); \
58
}
59
-
60
-#define DO_ST1_D(NAME, FN, TYPEM) \
61
-void HELPER(NAME)(CPUARMState *env, void *vg, \
62
- target_ulong addr, uint32_t desc) \
63
-{ \
64
- intptr_t i, oprsz = simd_oprsz(desc) / 8; \
65
- intptr_t ra = GETPC(); \
66
- unsigned rd = simd_data(desc); \
67
- uint64_t *d = &env->vfp.zregs[rd].d[0]; \
68
- uint8_t *pg = vg; \
69
- for (i = 0; i < oprsz; i += 1) { \
70
- if (pg[H1(i)] & 1) { \
71
- FN(env, addr, d[i], ra); \
72
- } \
73
- addr += sizeof(TYPEM); \
74
- } \
75
+#else
76
+#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \
77
+static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
78
+ target_ulong addr, int mmu_idx, uintptr_t ra) \
79
+{ \
80
+ HOST(g2h(addr), *(TYPEM *)(vd + H(reg_off))); \
81
}
82
+#endif
83
84
-#define DO_ST2(NAME, FN, TYPEE, TYPEM, H) \
85
-void HELPER(NAME)(CPUARMState *env, void *vg, \
86
- target_ulong addr, uint32_t desc) \
87
-{ \
88
- intptr_t i, oprsz = simd_oprsz(desc); \
89
- intptr_t ra = GETPC(); \
90
- unsigned rd = simd_data(desc); \
91
- void *d1 = &env->vfp.zregs[rd]; \
92
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
93
- for (i = 0; i < oprsz; ) { \
94
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
95
- do { \
96
- if (pg & 1) { \
97
- TYPEM m1 = *(TYPEE *)(d1 + H(i)); \
98
- TYPEM m2 = *(TYPEE *)(d2 + H(i)); \
99
- FN(env, addr, m1, ra); \
100
- FN(env, addr + sizeof(TYPEM), m2, ra); \
101
- } \
102
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
103
- addr += 2 * sizeof(TYPEM); \
104
- } while (i & 15); \
105
- } \
106
-}
107
+DO_ST_TLB(st1bb, H1, uint8_t, stb_p, 0, helper_ret_stb_mmu)
108
+DO_ST_TLB(st1bh, H1_2, uint16_t, stb_p, 0, helper_ret_stb_mmu)
109
+DO_ST_TLB(st1bs, H1_4, uint32_t, stb_p, 0, helper_ret_stb_mmu)
110
+DO_ST_TLB(st1bd, , uint64_t, stb_p, 0, helper_ret_stb_mmu)
111
112
-#define DO_ST3(NAME, FN, TYPEE, TYPEM, H) \
113
-void HELPER(NAME)(CPUARMState *env, void *vg, \
114
- target_ulong addr, uint32_t desc) \
115
-{ \
116
- intptr_t i, oprsz = simd_oprsz(desc); \
117
- intptr_t ra = GETPC(); \
118
- unsigned rd = simd_data(desc); \
119
- void *d1 = &env->vfp.zregs[rd]; \
120
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
121
- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
122
- for (i = 0; i < oprsz; ) { \
123
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
124
- do { \
125
- if (pg & 1) { \
126
- TYPEM m1 = *(TYPEE *)(d1 + H(i)); \
127
- TYPEM m2 = *(TYPEE *)(d2 + H(i)); \
128
- TYPEM m3 = *(TYPEE *)(d3 + H(i)); \
129
- FN(env, addr, m1, ra); \
130
- FN(env, addr + sizeof(TYPEM), m2, ra); \
131
- FN(env, addr + 2 * sizeof(TYPEM), m3, ra); \
132
- } \
133
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
134
- addr += 3 * sizeof(TYPEM); \
135
- } while (i & 15); \
136
- } \
137
-}
138
+DO_ST_TLB(st1hh_le, H1_2, uint16_t, stw_le_p, MO_LE, helper_le_stw_mmu)
139
+DO_ST_TLB(st1hs_le, H1_4, uint32_t, stw_le_p, MO_LE, helper_le_stw_mmu)
140
+DO_ST_TLB(st1hd_le, , uint64_t, stw_le_p, MO_LE, helper_le_stw_mmu)
141
142
-#define DO_ST4(NAME, FN, TYPEE, TYPEM, H) \
143
-void HELPER(NAME)(CPUARMState *env, void *vg, \
144
- target_ulong addr, uint32_t desc) \
145
-{ \
146
- intptr_t i, oprsz = simd_oprsz(desc); \
147
- intptr_t ra = GETPC(); \
148
- unsigned rd = simd_data(desc); \
149
- void *d1 = &env->vfp.zregs[rd]; \
150
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
151
- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
152
- void *d4 = &env->vfp.zregs[(rd + 3) & 31]; \
153
- for (i = 0; i < oprsz; ) { \
154
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
155
- do { \
156
- if (pg & 1) { \
157
- TYPEM m1 = *(TYPEE *)(d1 + H(i)); \
158
- TYPEM m2 = *(TYPEE *)(d2 + H(i)); \
159
- TYPEM m3 = *(TYPEE *)(d3 + H(i)); \
160
- TYPEM m4 = *(TYPEE *)(d4 + H(i)); \
161
- FN(env, addr, m1, ra); \
162
- FN(env, addr + sizeof(TYPEM), m2, ra); \
163
- FN(env, addr + 2 * sizeof(TYPEM), m3, ra); \
164
- FN(env, addr + 3 * sizeof(TYPEM), m4, ra); \
165
- } \
166
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
167
- addr += 4 * sizeof(TYPEM); \
168
- } while (i & 15); \
169
- } \
170
-}
171
+DO_ST_TLB(st1ss_le, H1_4, uint32_t, stl_le_p, MO_LE, helper_le_stl_mmu)
172
+DO_ST_TLB(st1sd_le, , uint64_t, stl_le_p, MO_LE, helper_le_stl_mmu)
173
174
-DO_ST1(sve_st1bh_r, cpu_stb_data_ra, uint16_t, uint8_t, H1_2)
175
-DO_ST1(sve_st1bs_r, cpu_stb_data_ra, uint32_t, uint8_t, H1_4)
176
-DO_ST1_D(sve_st1bd_r, cpu_stb_data_ra, uint8_t)
177
+DO_ST_TLB(st1dd_le, , uint64_t, stq_le_p, MO_LE, helper_le_stq_mmu)
178
179
-DO_ST1(sve_st1hs_r, cpu_stw_data_ra, uint32_t, uint16_t, H1_4)
180
-DO_ST1_D(sve_st1hd_r, cpu_stw_data_ra, uint16_t)
181
+DO_ST_TLB(st1hh_be, H1_2, uint16_t, stw_be_p, MO_BE, helper_be_stw_mmu)
182
+DO_ST_TLB(st1hs_be, H1_4, uint32_t, stw_be_p, MO_BE, helper_be_stw_mmu)
183
+DO_ST_TLB(st1hd_be, , uint64_t, stw_be_p, MO_BE, helper_be_stw_mmu)
184
185
-DO_ST1_D(sve_st1sd_r, cpu_stl_data_ra, uint32_t)
186
+DO_ST_TLB(st1ss_be, H1_4, uint32_t, stl_be_p, MO_BE, helper_be_stl_mmu)
187
+DO_ST_TLB(st1sd_be, , uint64_t, stl_be_p, MO_BE, helper_be_stl_mmu)
188
189
-DO_ST1(sve_st1bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
190
-DO_ST2(sve_st2bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
191
-DO_ST3(sve_st3bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
192
-DO_ST4(sve_st4bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
193
+DO_ST_TLB(st1dd_be, , uint64_t, stq_be_p, MO_BE, helper_be_stq_mmu)
194
195
-DO_ST1(sve_st1hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
196
-DO_ST2(sve_st2hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
197
-DO_ST3(sve_st3hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
198
-DO_ST4(sve_st4hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
199
+#undef DO_ST_TLB
200
201
-DO_ST1(sve_st1ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
202
-DO_ST2(sve_st2ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
203
-DO_ST3(sve_st3ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
204
-DO_ST4(sve_st4ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
205
-
206
-DO_ST1_D(sve_st1dd_r, cpu_stq_data_ra, uint64_t)
207
-
208
-void HELPER(sve_st2dd_r)(CPUARMState *env, void *vg,
209
- target_ulong addr, uint32_t desc)
210
+/*
211
+ * Common helpers for all contiguous 1,2,3,4-register predicated stores.
212
+ */
213
+static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr,
214
+ uint32_t desc, const uintptr_t ra,
215
+ const int esize, const int msize,
216
+ sve_st1_tlb_fn *tlb_fn)
217
{
218
- intptr_t i, oprsz = simd_oprsz(desc) / 8;
219
- intptr_t ra = GETPC();
220
+ const int mmu_idx = cpu_mmu_index(env, false);
221
+ intptr_t i, oprsz = simd_oprsz(desc);
222
unsigned rd = simd_data(desc);
223
- uint64_t *d1 = &env->vfp.zregs[rd].d[0];
224
- uint64_t *d2 = &env->vfp.zregs[(rd + 1) & 31].d[0];
225
- uint8_t *pg = vg;
226
+ void *vd = &env->vfp.zregs[rd];
227
228
- for (i = 0; i < oprsz; i += 1) {
229
- if (pg[H1(i)] & 1) {
230
- cpu_stq_data_ra(env, addr, d1[i], ra);
231
- cpu_stq_data_ra(env, addr + 8, d2[i], ra);
232
- }
233
- addr += 2 * 8;
234
+ set_helper_retaddr(ra);
235
+ for (i = 0; i < oprsz; ) {
236
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
237
+ do {
238
+ if (pg & 1) {
239
+ tlb_fn(env, vd, i, addr, mmu_idx, ra);
240
+ }
241
+ i += esize, pg >>= esize;
242
+ addr += msize;
243
+ } while (i & 15);
244
}
66
}
245
+ set_helper_retaddr(0);
67
+ QLIST_FOREACH(ncl, &dev->clocks, node) {
246
}
68
+ qdev_printf("clock-%s%s \"%s\" freq_hz=%e\n",
247
69
+ ncl->output ? "out" : "in",
248
-void HELPER(sve_st3dd_r)(CPUARMState *env, void *vg,
70
+ ncl->alias ? " (alias)" : "",
249
- target_ulong addr, uint32_t desc)
71
+ ncl->name,
250
+static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr,
72
+ CLOCK_PERIOD_TO_HZ(1.0 * clock_get(ncl->clock)));
251
+ uint32_t desc, const uintptr_t ra,
252
+ const int esize, const int msize,
253
+ sve_st1_tlb_fn *tlb_fn)
254
{
255
- intptr_t i, oprsz = simd_oprsz(desc) / 8;
256
- intptr_t ra = GETPC();
257
+ const int mmu_idx = cpu_mmu_index(env, false);
258
+ intptr_t i, oprsz = simd_oprsz(desc);
259
unsigned rd = simd_data(desc);
260
- uint64_t *d1 = &env->vfp.zregs[rd].d[0];
261
- uint64_t *d2 = &env->vfp.zregs[(rd + 1) & 31].d[0];
262
- uint64_t *d3 = &env->vfp.zregs[(rd + 2) & 31].d[0];
263
- uint8_t *pg = vg;
264
+ void *d1 = &env->vfp.zregs[rd];
265
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31];
266
267
- for (i = 0; i < oprsz; i += 1) {
268
- if (pg[H1(i)] & 1) {
269
- cpu_stq_data_ra(env, addr, d1[i], ra);
270
- cpu_stq_data_ra(env, addr + 8, d2[i], ra);
271
- cpu_stq_data_ra(env, addr + 16, d3[i], ra);
272
- }
273
- addr += 3 * 8;
274
+ set_helper_retaddr(ra);
275
+ for (i = 0; i < oprsz; ) {
276
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
277
+ do {
278
+ if (pg & 1) {
279
+ tlb_fn(env, d1, i, addr, mmu_idx, ra);
280
+ tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
281
+ }
282
+ i += esize, pg >>= esize;
283
+ addr += 2 * msize;
284
+ } while (i & 15);
285
}
286
+ set_helper_retaddr(0);
287
}
288
289
-void HELPER(sve_st4dd_r)(CPUARMState *env, void *vg,
290
- target_ulong addr, uint32_t desc)
291
+static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr,
292
+ uint32_t desc, const uintptr_t ra,
293
+ const int esize, const int msize,
294
+ sve_st1_tlb_fn *tlb_fn)
295
{
296
- intptr_t i, oprsz = simd_oprsz(desc) / 8;
297
- intptr_t ra = GETPC();
298
+ const int mmu_idx = cpu_mmu_index(env, false);
299
+ intptr_t i, oprsz = simd_oprsz(desc);
300
unsigned rd = simd_data(desc);
301
- uint64_t *d1 = &env->vfp.zregs[rd].d[0];
302
- uint64_t *d2 = &env->vfp.zregs[(rd + 1) & 31].d[0];
303
- uint64_t *d3 = &env->vfp.zregs[(rd + 2) & 31].d[0];
304
- uint64_t *d4 = &env->vfp.zregs[(rd + 3) & 31].d[0];
305
- uint8_t *pg = vg;
306
+ void *d1 = &env->vfp.zregs[rd];
307
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31];
308
+ void *d3 = &env->vfp.zregs[(rd + 2) & 31];
309
310
- for (i = 0; i < oprsz; i += 1) {
311
- if (pg[H1(i)] & 1) {
312
- cpu_stq_data_ra(env, addr, d1[i], ra);
313
- cpu_stq_data_ra(env, addr + 8, d2[i], ra);
314
- cpu_stq_data_ra(env, addr + 16, d3[i], ra);
315
- cpu_stq_data_ra(env, addr + 24, d4[i], ra);
316
- }
317
- addr += 4 * 8;
318
+ set_helper_retaddr(ra);
319
+ for (i = 0; i < oprsz; ) {
320
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
321
+ do {
322
+ if (pg & 1) {
323
+ tlb_fn(env, d1, i, addr, mmu_idx, ra);
324
+ tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
325
+ tlb_fn(env, d3, i, addr + 2 * msize, mmu_idx, ra);
326
+ }
327
+ i += esize, pg >>= esize;
328
+ addr += 3 * msize;
329
+ } while (i & 15);
330
}
331
+ set_helper_retaddr(0);
332
}
333
334
+static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr,
335
+ uint32_t desc, const uintptr_t ra,
336
+ const int esize, const int msize,
337
+ sve_st1_tlb_fn *tlb_fn)
338
+{
339
+ const int mmu_idx = cpu_mmu_index(env, false);
340
+ intptr_t i, oprsz = simd_oprsz(desc);
341
+ unsigned rd = simd_data(desc);
342
+ void *d1 = &env->vfp.zregs[rd];
343
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31];
344
+ void *d3 = &env->vfp.zregs[(rd + 2) & 31];
345
+ void *d4 = &env->vfp.zregs[(rd + 3) & 31];
346
+
347
+ set_helper_retaddr(ra);
348
+ for (i = 0; i < oprsz; ) {
349
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
350
+ do {
351
+ if (pg & 1) {
352
+ tlb_fn(env, d1, i, addr, mmu_idx, ra);
353
+ tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
354
+ tlb_fn(env, d3, i, addr + 2 * msize, mmu_idx, ra);
355
+ tlb_fn(env, d4, i, addr + 3 * msize, mmu_idx, ra);
356
+ }
357
+ i += esize, pg >>= esize;
358
+ addr += 4 * msize;
359
+ } while (i & 15);
360
+ }
73
+ }
361
+ set_helper_retaddr(0);
74
class = object_get_class(OBJECT(dev));
362
+}
75
do {
363
+
76
qdev_print_props(mon, dev, DEVICE_CLASS(class)->props_, indent);
364
+#define DO_STN_1(N, NAME, ESIZE) \
365
+void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
366
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
367
+{ \
368
+ sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, 1, \
369
+ sve_st1##NAME##_tlb); \
370
+}
371
+
372
+#define DO_STN_2(N, NAME, ESIZE, MSIZE) \
373
+void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
374
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
375
+{ \
376
+ sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \
377
+ arm_cpu_data_is_big_endian(env) \
378
+ ? sve_st1##NAME##_be_tlb : sve_st1##NAME##_le_tlb); \
379
+}
380
+
381
+DO_STN_1(1, bb, 1)
382
+DO_STN_1(1, bh, 2)
383
+DO_STN_1(1, bs, 4)
384
+DO_STN_1(1, bd, 8)
385
+DO_STN_1(2, bb, 1)
386
+DO_STN_1(3, bb, 1)
387
+DO_STN_1(4, bb, 1)
388
+
389
+DO_STN_2(1, hh, 2, 2)
390
+DO_STN_2(1, hs, 4, 2)
391
+DO_STN_2(1, hd, 8, 2)
392
+DO_STN_2(2, hh, 2, 2)
393
+DO_STN_2(3, hh, 2, 2)
394
+DO_STN_2(4, hh, 2, 2)
395
+
396
+DO_STN_2(1, ss, 4, 4)
397
+DO_STN_2(1, sd, 8, 4)
398
+DO_STN_2(2, ss, 4, 4)
399
+DO_STN_2(3, ss, 4, 4)
400
+DO_STN_2(4, ss, 4, 4)
401
+
402
+DO_STN_2(1, dd, 8, 8)
403
+DO_STN_2(2, dd, 8, 8)
404
+DO_STN_2(3, dd, 8, 8)
405
+DO_STN_2(4, dd, 8, 8)
406
+
407
+#undef DO_STN_1
408
+#undef DO_STN_2
409
+
410
/* Loads with a vector index. */
411
412
#define DO_LD1_ZPZ_S(NAME, TYPEI, TYPEM, FN) \
413
--
77
--
414
2.19.0
78
2.20.1
415
79
416
80
diff view generated by jsdifflib
1
The Arm v8M architecture includes hardware stack limit checking.
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
When certain instructions update the stack pointer, if the new
3
value of SP is below the limit set in the associated limit register
4
then an exception is taken. Add a TB flag that tracks whether
5
the limit-checking code needs to be emitted.
6
2
3
Setup the ADMA with 128bit bus-width. This matters when
4
FIXED BURST mode is used.
5
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Message-id: 20200417153800.27399-2-edgar.iglesias@gmail.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20181002163556.10279-2-peter.maydell@linaro.org
11
---
11
---
12
target/arm/cpu.h | 7 +++++++
12
hw/arm/xlnx-versal.c | 2 ++
13
target/arm/translate.h | 1 +
13
1 file changed, 2 insertions(+)
14
target/arm/helper.c | 10 ++++++++++
15
target/arm/translate.c | 1 +
16
4 files changed, 19 insertions(+)
17
14
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
17
--- a/hw/arm/xlnx-versal.c
21
+++ b/target/arm/cpu.h
18
+++ b/hw/arm/xlnx-versal.c
22
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, UNALIGN_TRP, 3, 1)
19
@@ -XXX,XX +XXX,XX @@ static void versal_create_admas(Versal *s, qemu_irq *pic)
23
FIELD(V7M_CCR, DIV_0_TRP, 4, 1)
20
24
FIELD(V7M_CCR, BFHFNMIGN, 8, 1)
21
dev = qdev_create(NULL, "xlnx.zdma");
25
FIELD(V7M_CCR, STKALIGN, 9, 1)
22
s->lpd.iou.adma[i] = SYS_BUS_DEVICE(dev);
26
+FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
23
+ object_property_set_int(OBJECT(s->lpd.iou.adma[i]), 128, "bus-width",
27
FIELD(V7M_CCR, DC, 16, 1)
24
+ &error_abort);
28
FIELD(V7M_CCR, IC, 17, 1)
25
object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
29
+FIELD(V7M_CCR, BP, 18, 1)
26
qdev_init_nofail(dev);
30
31
/* V7M SCR bits */
32
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
33
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
34
/* For M profile only, Handler (ie not Thread) mode */
35
#define ARM_TBFLAG_HANDLER_SHIFT 21
36
#define ARM_TBFLAG_HANDLER_MASK (1 << ARM_TBFLAG_HANDLER_SHIFT)
37
+/* For M profile only, whether we should generate stack-limit checks */
38
+#define ARM_TBFLAG_STACKCHECK_SHIFT 22
39
+#define ARM_TBFLAG_STACKCHECK_MASK (1 << ARM_TBFLAG_STACKCHECK_SHIFT)
40
41
/* Bit usage when in AArch64 state */
42
#define ARM_TBFLAG_TBI0_SHIFT 0 /* TBI0 for EL0/1 or TBI for EL2/3 */
43
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
44
(((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
45
#define ARM_TBFLAG_HANDLER(F) \
46
(((F) & ARM_TBFLAG_HANDLER_MASK) >> ARM_TBFLAG_HANDLER_SHIFT)
47
+#define ARM_TBFLAG_STACKCHECK(F) \
48
+ (((F) & ARM_TBFLAG_STACKCHECK_MASK) >> ARM_TBFLAG_STACKCHECK_SHIFT)
49
#define ARM_TBFLAG_TBI0(F) \
50
(((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
51
#define ARM_TBFLAG_TBI1(F) \
52
diff --git a/target/arm/translate.h b/target/arm/translate.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/translate.h
55
+++ b/target/arm/translate.h
56
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
57
int vec_stride;
58
bool v7m_handler_mode;
59
bool v8m_secure; /* true if v8M and we're in Secure mode */
60
+ bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
61
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
62
* so that top level loop can generate correct syndrome information.
63
*/
64
diff --git a/target/arm/helper.c b/target/arm/helper.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/helper.c
67
+++ b/target/arm/helper.c
68
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
69
flags |= ARM_TBFLAG_HANDLER_MASK;
70
}
71
72
+ /* v8M always applies stack limit checks unless CCR.STKOFHFNMIGN is
73
+ * suppressing them because the requested execution priority is less than 0.
74
+ */
75
+ if (arm_feature(env, ARM_FEATURE_V8) &&
76
+ arm_feature(env, ARM_FEATURE_M) &&
77
+ !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
78
+ (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
79
+ flags |= ARM_TBFLAG_STACKCHECK_MASK;
80
+ }
81
+
82
*pflags = flags;
83
*cs_base = 0;
84
}
85
diff --git a/target/arm/translate.c b/target/arm/translate.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/translate.c
88
+++ b/target/arm/translate.c
89
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
90
dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(dc->base.tb->flags);
91
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
92
regime_is_secure(env, dc->mmu_idx);
93
+ dc->v8m_stackcheck = ARM_TBFLAG_STACKCHECK(dc->base.tb->flags);
94
dc->cp_regs = cpu->cp_regs;
95
dc->features = env->features;
96
27
97
--
28
--
98
2.19.0
29
2.20.1
99
30
100
31
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Ramon Fried <rfried.dev@gmail.com>
2
2
3
We are going to want to determine whether sve is enabled
3
Wraparound of TX descriptor cyclic buffer only updated
4
for EL other than current.
4
the low 32 bits of the descriptor.
5
Fix that by checking if we're working with 64bit descriptors.
5
6
6
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Ramon Fried <rfried.dev@gmail.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200417171736.441607-1-rfried.dev@gmail.com
9
Message-id: 20181005175350.30752-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/helper.c | 21 +++++++++------------
12
hw/net/cadence_gem.c | 9 ++++++++-
13
1 file changed, 9 insertions(+), 12 deletions(-)
13
1 file changed, 8 insertions(+), 1 deletion(-)
14
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
17
--- a/hw/net/cadence_gem.c
18
+++ b/target/arm/helper.c
18
+++ b/hw/net/cadence_gem.c
19
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
19
@@ -XXX,XX +XXX,XX @@ static void gem_transmit(CadenceGEMState *s)
20
* take care of raising that exception.
20
/* read next descriptor */
21
* C.f. the ARM pseudocode function CheckSVEEnabled.
21
if (tx_desc_get_wrap(desc)) {
22
*/
22
tx_desc_set_last(desc);
23
-static int sve_exception_el(CPUARMState *env)
23
- packet_desc_addr = s->regs[GEM_TXQBASE];
24
+static int sve_exception_el(CPUARMState *env, int el)
24
+
25
{
25
+ if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
26
#ifndef CONFIG_USER_ONLY
26
+ packet_desc_addr = s->regs[GEM_TBQPH];
27
- unsigned current_el = arm_current_el(env);
27
+ packet_desc_addr <<= 32;
28
-
28
+ } else {
29
- if (current_el <= 1) {
29
+ packet_desc_addr = 0;
30
+ if (el <= 1) {
30
+ }
31
bool disabled = false;
31
+ packet_desc_addr |= s->regs[GEM_TXQBASE];
32
33
/* The CPACR.ZEN controls traps to EL1:
34
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env)
35
if (!extract32(env->cp15.cpacr_el1, 16, 1)) {
36
disabled = true;
37
} else if (!extract32(env->cp15.cpacr_el1, 17, 1)) {
38
- disabled = current_el == 0;
39
+ disabled = el == 0;
40
}
41
if (disabled) {
42
/* route_to_el2 */
43
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env)
44
if (!extract32(env->cp15.cpacr_el1, 20, 1)) {
45
disabled = true;
46
} else if (!extract32(env->cp15.cpacr_el1, 21, 1)) {
47
- disabled = current_el == 0;
48
+ disabled = el == 0;
49
}
50
if (disabled) {
51
return 0;
52
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env)
53
/* CPTR_EL2. Since TZ and TFP are positive,
54
* they will be zero when EL2 is not present.
55
*/
56
- if (current_el <= 2 && !arm_is_secure_below_el3(env)) {
57
+ if (el <= 2 && !arm_is_secure_below_el3(env)) {
58
if (env->cp15.cptr_el[2] & CPTR_TZ) {
59
return 2;
60
}
61
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
62
/* Return the exception level to which FP-disabled exceptions should
63
* be taken, or 0 if FP is enabled.
64
*/
65
-static inline int fp_exception_el(CPUARMState *env)
66
+static int fp_exception_el(CPUARMState *env, int cur_el)
67
{
68
#ifndef CONFIG_USER_ONLY
69
int fpen;
70
- int cur_el = arm_current_el(env);
71
72
/* CPACR and the CPTR registers don't exist before v6, so FP is
73
* always accessible
74
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
75
target_ulong *cs_base, uint32_t *pflags)
76
{
77
ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
78
- int fp_el = fp_exception_el(env);
79
+ int current_el = arm_current_el(env);
80
+ int fp_el = fp_exception_el(env, current_el);
81
uint32_t flags;
82
83
if (is_a64(env)) {
84
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
85
flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
86
87
if (arm_feature(env, ARM_FEATURE_SVE)) {
88
- int sve_el = sve_exception_el(env);
89
+ int sve_el = sve_exception_el(env, current_el);
90
uint32_t zcr_len;
91
92
/* If SVE is disabled, but FP is enabled,
93
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
94
if (sve_el != 0 && fp_el == 0) {
95
zcr_len = 0;
96
} else {
32
} else {
97
- int current_el = arm_current_el(env);
33
packet_desc_addr += 4 * gem_get_desc_len(s, false);
98
ARMCPU *cpu = arm_env_get_cpu(env);
34
}
99
100
zcr_len = cpu->sve_max_vq - 1;
101
--
35
--
102
2.19.0
36
2.20.1
103
37
104
38
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Ramon Fried <rfried.dev@gmail.com>
2
2
3
Given that the only field defined for this new register may only
3
The RX ring descriptors control field is used for setting
4
be 0, we don't actually need to change anything except the name.
4
SOF and EOF (start of frame and end of frame).
5
The SOF and EOF weren't cleared from the previous descriptors,
6
causing inconsistencies in ring buffer.
7
Fix that by clearing the control field of every descriptors we're
8
processing.
5
9
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Ramon Fried <rfried.dev@gmail.com>
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Message-id: 20181005175350.30752-2-richard.henderson@linaro.org
13
Message-id: 20200418085145.489726-1-rfried.dev@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
15
---
12
target/arm/helper.c | 3 ++-
16
hw/net/cadence_gem.c | 7 +++++++
13
1 file changed, 2 insertions(+), 1 deletion(-)
17
1 file changed, 7 insertions(+)
14
18
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
21
--- a/hw/net/cadence_gem.c
18
+++ b/target/arm/helper.c
22
+++ b/hw/net/cadence_gem.c
19
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
23
@@ -XXX,XX +XXX,XX @@ static inline void rx_desc_set_sof(uint32_t *desc)
20
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 3,
24
desc[1] |= DESC_1_RX_SOF;
21
.access = PL1_R, .type = ARM_CP_CONST,
25
}
22
.resetvalue = 0 },
26
23
- { .name = "ID_AA64PFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
27
+static inline void rx_desc_clear_control(uint32_t *desc)
24
+ { .name = "ID_AA64ZFR0_EL1", .state = ARM_CP_STATE_AA64,
28
+{
25
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4,
29
+ desc[1] = 0;
26
.access = PL1_R, .type = ARM_CP_CONST,
30
+}
27
+ /* At present, only SVEver == 0 is defined anyway. */
31
+
28
.resetvalue = 0 },
32
static inline void rx_desc_set_eof(uint32_t *desc)
29
{ .name = "ID_AA64PFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
33
{
30
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5,
34
desc[1] |= DESC_1_RX_EOF;
35
@@ -XXX,XX +XXX,XX @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
36
rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
37
bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
38
39
+ rx_desc_clear_control(s->rx_desc[q]);
40
+
41
/* Update the descriptor. */
42
if (first_desc) {
43
rx_desc_set_sof(s->rx_desc[q]);
31
--
44
--
32
2.19.0
45
2.20.1
33
46
34
47
diff view generated by jsdifflib
1
Add code to insert calls to a helper function to do the stack
1
From: Richard Henderson <richard.henderson@linaro.org>
2
limit checking when we handle these forms of instruction
3
that write to SP:
4
* ADD (SP plus immediate)
5
* ADD (SP plus register)
6
* SUB (SP minus immediate)
7
* SUB (SP minus register)
8
* MOV (register)
9
2
3
These instructions are often used in glibc's string routines.
4
They were the final uses of the 32-bit at a time neon helpers.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200418162808.4680-1-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20181002163556.10279-5-peter.maydell@linaro.org
13
---
10
---
14
target/arm/helper.h | 2 ++
11
target/arm/helper.h | 27 ++--
15
target/arm/internals.h | 14 ++++++++
12
target/arm/translate.h | 5 +
16
target/arm/op_helper.c | 19 ++++++++++
13
target/arm/neon_helper.c | 24 ----
17
target/arm/translate.c | 80 +++++++++++++++++++++++++++++++++++++-----
14
target/arm/translate-a64.c | 64 +++-------
18
4 files changed, 106 insertions(+), 9 deletions(-)
15
target/arm/translate.c | 256 +++++++++++++++++++++++++++++++------
16
target/arm/vec_helper.c | 25 ++++
17
6 files changed, 278 insertions(+), 123 deletions(-)
19
18
20
diff --git a/target/arm/helper.h b/target/arm/helper.h
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.h
21
--- a/target/arm/helper.h
23
+++ b/target/arm/helper.h
22
+++ b/target/arm/helper.h
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(v7m_blxns, void, env, i32)
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(neon_hsub_u16, i32, i32, i32)
25
24
DEF_HELPER_2(neon_hsub_s32, s32, s32, s32)
26
DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
25
DEF_HELPER_2(neon_hsub_u32, i32, i32, i32)
27
26
28
+DEF_HELPER_2(v8m_stackcheck, void, env, i32)
27
-DEF_HELPER_2(neon_cgt_u8, i32, i32, i32)
29
+
28
-DEF_HELPER_2(neon_cgt_s8, i32, i32, i32)
30
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
29
-DEF_HELPER_2(neon_cgt_u16, i32, i32, i32)
31
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
30
-DEF_HELPER_2(neon_cgt_s16, i32, i32, i32)
32
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
31
-DEF_HELPER_2(neon_cgt_u32, i32, i32, i32)
33
diff --git a/target/arm/internals.h b/target/arm/internals.h
32
-DEF_HELPER_2(neon_cgt_s32, i32, i32, i32)
33
-DEF_HELPER_2(neon_cge_u8, i32, i32, i32)
34
-DEF_HELPER_2(neon_cge_s8, i32, i32, i32)
35
-DEF_HELPER_2(neon_cge_u16, i32, i32, i32)
36
-DEF_HELPER_2(neon_cge_s16, i32, i32, i32)
37
-DEF_HELPER_2(neon_cge_u32, i32, i32, i32)
38
-DEF_HELPER_2(neon_cge_s32, i32, i32, i32)
39
-
40
DEF_HELPER_2(neon_pmin_u8, i32, i32, i32)
41
DEF_HELPER_2(neon_pmin_s8, i32, i32, i32)
42
DEF_HELPER_2(neon_pmin_u16, i32, i32, i32)
43
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(neon_mul_u16, i32, i32, i32)
44
DEF_HELPER_2(neon_tst_u8, i32, i32, i32)
45
DEF_HELPER_2(neon_tst_u16, i32, i32, i32)
46
DEF_HELPER_2(neon_tst_u32, i32, i32, i32)
47
-DEF_HELPER_2(neon_ceq_u8, i32, i32, i32)
48
-DEF_HELPER_2(neon_ceq_u16, i32, i32, i32)
49
-DEF_HELPER_2(neon_ceq_u32, i32, i32, i32)
50
51
DEF_HELPER_1(neon_clz_u8, i32, i32)
52
DEF_HELPER_1(neon_clz_u16, i32, i32)
53
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(frint64_s, TCG_CALL_NO_RWG, f32, f32, ptr)
54
DEF_HELPER_FLAGS_2(frint32_d, TCG_CALL_NO_RWG, f64, f64, ptr)
55
DEF_HELPER_FLAGS_2(frint64_d, TCG_CALL_NO_RWG, f64, f64, ptr)
56
57
+DEF_HELPER_FLAGS_3(gvec_ceq0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
58
+DEF_HELPER_FLAGS_3(gvec_ceq0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
59
+DEF_HELPER_FLAGS_3(gvec_clt0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
60
+DEF_HELPER_FLAGS_3(gvec_clt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
61
+DEF_HELPER_FLAGS_3(gvec_cle0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
62
+DEF_HELPER_FLAGS_3(gvec_cle0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
63
+DEF_HELPER_FLAGS_3(gvec_cgt0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
64
+DEF_HELPER_FLAGS_3(gvec_cgt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
65
+DEF_HELPER_FLAGS_3(gvec_cge0_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
66
+DEF_HELPER_FLAGS_3(gvec_cge0_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
67
+
68
DEF_HELPER_FLAGS_4(gvec_sshl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
69
DEF_HELPER_FLAGS_4(gvec_sshl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
70
DEF_HELPER_FLAGS_4(gvec_ushl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
71
diff --git a/target/arm/translate.h b/target/arm/translate.h
34
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/internals.h
73
--- a/target/arm/translate.h
36
+++ b/target/arm/internals.h
74
+++ b/target/arm/translate.h
37
@@ -XXX,XX +XXX,XX @@ static inline bool v7m_using_psp(CPUARMState *env)
75
@@ -XXX,XX +XXX,XX @@ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
38
env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
76
uint64_t vfp_expand_imm(int size, uint8_t imm8);
77
78
/* Vector operations shared between ARM and AArch64. */
79
+extern const GVecGen2 ceq0_op[4];
80
+extern const GVecGen2 clt0_op[4];
81
+extern const GVecGen2 cgt0_op[4];
82
+extern const GVecGen2 cle0_op[4];
83
+extern const GVecGen2 cge0_op[4];
84
extern const GVecGen3 mla_op[4];
85
extern const GVecGen3 mls_op[4];
86
extern const GVecGen3 cmtst_op[4];
87
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/neon_helper.c
90
+++ b/target/arm/neon_helper.c
91
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_hsub_u32)(uint32_t src1, uint32_t src2)
92
return dest;
39
}
93
}
40
94
41
+/**
95
-#define NEON_FN(dest, src1, src2) dest = (src1 > src2) ? ~0 : 0
42
+ * v7m_sp_limit: Return SP limit for current CPU state
96
-NEON_VOP(cgt_s8, neon_s8, 4)
43
+ * Return the SP limit value for the current CPU security state
97
-NEON_VOP(cgt_u8, neon_u8, 4)
44
+ * and stack pointer.
98
-NEON_VOP(cgt_s16, neon_s16, 2)
45
+ */
99
-NEON_VOP(cgt_u16, neon_u16, 2)
46
+static inline uint32_t v7m_sp_limit(CPUARMState *env)
100
-NEON_VOP(cgt_s32, neon_s32, 1)
47
+{
101
-NEON_VOP(cgt_u32, neon_u32, 1)
48
+ if (v7m_using_psp(env)) {
102
-#undef NEON_FN
49
+ return env->v7m.psplim[env->v7m.secure];
103
-
50
+ } else {
104
-#define NEON_FN(dest, src1, src2) dest = (src1 >= src2) ? ~0 : 0
51
+ return env->v7m.msplim[env->v7m.secure];
105
-NEON_VOP(cge_s8, neon_s8, 4)
52
+ }
106
-NEON_VOP(cge_u8, neon_u8, 4)
53
+}
107
-NEON_VOP(cge_s16, neon_s16, 2)
54
+
108
-NEON_VOP(cge_u16, neon_u16, 2)
55
#endif
109
-NEON_VOP(cge_s32, neon_s32, 1)
56
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
110
-NEON_VOP(cge_u32, neon_u32, 1)
111
-#undef NEON_FN
112
-
113
#define NEON_FN(dest, src1, src2) dest = (src1 < src2) ? src1 : src2
114
NEON_POP(pmin_s8, neon_s8, 4)
115
NEON_POP(pmin_u8, neon_u8, 4)
116
@@ -XXX,XX +XXX,XX @@ NEON_VOP(tst_u16, neon_u16, 2)
117
NEON_VOP(tst_u32, neon_u32, 1)
118
#undef NEON_FN
119
120
-#define NEON_FN(dest, src1, src2) dest = (src1 == src2) ? -1 : 0
121
-NEON_VOP(ceq_u8, neon_u8, 4)
122
-NEON_VOP(ceq_u16, neon_u16, 2)
123
-NEON_VOP(ceq_u32, neon_u32, 1)
124
-#undef NEON_FN
125
-
126
/* Count Leading Sign/Zero Bits. */
127
static inline int do_clz8(uint8_t x)
128
{
129
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
57
index XXXXXXX..XXXXXXX 100644
130
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/op_helper.c
131
--- a/target/arm/translate-a64.c
59
+++ b/target/arm/op_helper.c
132
+++ b/target/arm/translate-a64.c
60
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
133
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
61
134
is_q ? 16 : 8, vec_full_reg_size(s));
62
#endif /* !defined(CONFIG_USER_ONLY) */
135
}
63
136
64
+void HELPER(v8m_stackcheck)(CPUARMState *env, uint32_t newvalue)
137
+/* Expand a 2-operand AdvSIMD vector operation using an op descriptor. */
65
+{
138
+static void gen_gvec_op2(DisasContext *s, bool is_q, int rd,
66
+ /*
139
+ int rn, const GVecGen2 *gvec_op)
67
+ * Perform the v8M stack limit check for SP updates from translated code,
140
+{
68
+ * raising an exception if the limit is breached.
141
+ tcg_gen_gvec_2(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
69
+ */
142
+ is_q ? 16 : 8, vec_full_reg_size(s), gvec_op);
70
+ if (newvalue < v7m_sp_limit(env)) {
143
+}
71
+ CPUState *cs = CPU(arm_env_get_cpu(env));
144
+
72
+
145
/* Expand a 2-operand + immediate AdvSIMD vector operation using
73
+ /*
146
* an op descriptor.
74
+ * Stack limit exceptions are a rare case, so rather than syncing
147
*/
75
+ * PC/condbits before the call, we use cpu_restore_state() to
148
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
76
+ * get them right before raising the exception.
149
return;
77
+ */
150
}
78
+ cpu_restore_state(cs, GETPC(), true);
151
break;
79
+ raise_exception(env, EXCP_STKOF, 0, 1);
152
+ case 0x8: /* CMGT, CMGE */
80
+ }
153
+ gen_gvec_op2(s, is_q, rd, rn, u ? &cge0_op[size] : &cgt0_op[size]);
81
+}
154
+ return;
82
+
155
+ case 0x9: /* CMEQ, CMLE */
83
uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
156
+ gen_gvec_op2(s, is_q, rd, rn, u ? &cle0_op[size] : &ceq0_op[size]);
84
{
157
+ return;
85
uint32_t res = a + b;
158
+ case 0xa: /* CMLT */
159
+ gen_gvec_op2(s, is_q, rd, rn, &clt0_op[size]);
160
+ return;
161
case 0xb:
162
if (u) { /* ABS, NEG */
163
gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_neg, size);
164
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
165
for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
166
TCGv_i32 tcg_op = tcg_temp_new_i32();
167
TCGv_i32 tcg_res = tcg_temp_new_i32();
168
- TCGCond cond;
169
170
read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
171
172
if (size == 2) {
173
/* Special cases for 32 bit elements */
174
switch (opcode) {
175
- case 0xa: /* CMLT */
176
- /* 32 bit integer comparison against zero, result is
177
- * test ? (2^32 - 1) : 0. We implement via setcond(test)
178
- * and inverting.
179
- */
180
- cond = TCG_COND_LT;
181
- do_cmop:
182
- tcg_gen_setcondi_i32(cond, tcg_res, tcg_op, 0);
183
- tcg_gen_neg_i32(tcg_res, tcg_res);
184
- break;
185
- case 0x8: /* CMGT, CMGE */
186
- cond = u ? TCG_COND_GE : TCG_COND_GT;
187
- goto do_cmop;
188
- case 0x9: /* CMEQ, CMLE */
189
- cond = u ? TCG_COND_LE : TCG_COND_EQ;
190
- goto do_cmop;
191
case 0x4: /* CLS */
192
if (u) {
193
tcg_gen_clzi_i32(tcg_res, tcg_op, 32);
194
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
195
genfn(tcg_res, cpu_env, tcg_op);
196
break;
197
}
198
- case 0x8: /* CMGT, CMGE */
199
- case 0x9: /* CMEQ, CMLE */
200
- case 0xa: /* CMLT */
201
- {
202
- static NeonGenTwoOpFn * const fns[3][2] = {
203
- { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_s16 },
204
- { gen_helper_neon_cge_s8, gen_helper_neon_cge_s16 },
205
- { gen_helper_neon_ceq_u8, gen_helper_neon_ceq_u16 },
206
- };
207
- NeonGenTwoOpFn *genfn;
208
- int comp;
209
- bool reverse;
210
- TCGv_i32 tcg_zero = tcg_const_i32(0);
211
-
212
- /* comp = index into [CMGT, CMGE, CMEQ, CMLE, CMLT] */
213
- comp = (opcode - 0x8) * 2 + u;
214
- /* ...but LE, LT are implemented as reverse GE, GT */
215
- reverse = (comp > 2);
216
- if (reverse) {
217
- comp = 4 - comp;
218
- }
219
- genfn = fns[comp][size];
220
- if (reverse) {
221
- genfn(tcg_res, tcg_zero, tcg_op);
222
- } else {
223
- genfn(tcg_res, tcg_op, tcg_zero);
224
- }
225
- tcg_temp_free_i32(tcg_zero);
226
- break;
227
- }
228
case 0x4: /* CLS, CLZ */
229
if (u) {
230
if (size == 0) {
86
diff --git a/target/arm/translate.c b/target/arm/translate.c
231
diff --git a/target/arm/translate.c b/target/arm/translate.c
87
index XXXXXXX..XXXXXXX 100644
232
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/translate.c
233
--- a/target/arm/translate.c
89
+++ b/target/arm/translate.c
234
+++ b/target/arm/translate.c
90
@@ -XXX,XX +XXX,XX @@ static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
235
@@ -XXX,XX +XXX,XX @@ static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
91
tcg_temp_free_i32(var);
236
return 1;
92
}
237
}
93
238
94
+/*
239
+static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a)
95
+ * Variant of store_reg which applies v8M stack-limit checks before updating
240
+{
96
+ * SP. If the check fails this will result in an exception being taken.
241
+ tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0);
97
+ * We disable the stack checks for CONFIG_USER_ONLY because we have
242
+ tcg_gen_neg_i32(d, d);
98
+ * no idea what the stack limits should be in that case.
243
+}
99
+ * If stack checking is not being done this just acts like store_reg().
244
+
100
+ */
245
+static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a)
101
+static void store_sp_checked(DisasContext *s, TCGv_i32 var)
246
+{
102
+{
247
+ tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0);
103
+#ifndef CONFIG_USER_ONLY
248
+ tcg_gen_neg_i64(d, d);
104
+ if (s->v8m_stackcheck) {
249
+}
105
+ gen_helper_v8m_stackcheck(cpu_env, var);
250
+
106
+ }
251
+static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
107
+#endif
252
+{
108
+ store_reg(s, 13, var);
253
+ TCGv_vec zero = tcg_const_zeros_vec_matching(d);
109
+}
254
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero);
110
+
255
+ tcg_temp_free_vec(zero);
111
/* Value extensions. */
256
+}
112
#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
257
+
113
#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
258
+static const TCGOpcode vecop_list_cmp[] = {
114
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
259
+ INDEX_op_cmp_vec, 0
115
if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
260
+};
116
goto illegal_op;
261
+
117
tcg_temp_free_i32(tmp2);
262
+const GVecGen2 ceq0_op[4] = {
118
- if (rd != 15) {
263
+ { .fno = gen_helper_gvec_ceq0_b,
119
+ if (rd == 13 &&
264
+ .fniv = gen_ceq0_vec,
120
+ ((op == 2 && rn == 15) ||
265
+ .opt_opc = vecop_list_cmp,
121
+ (op == 8 && rn == 13) ||
266
+ .vece = MO_8 },
122
+ (op == 13 && rn == 13))) {
267
+ { .fno = gen_helper_gvec_ceq0_h,
123
+ /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
268
+ .fniv = gen_ceq0_vec,
124
+ store_sp_checked(s, tmp);
269
+ .opt_opc = vecop_list_cmp,
125
+ } else if (rd != 15) {
270
+ .vece = MO_16 },
126
store_reg(s, rd, tmp);
271
+ { .fni4 = gen_ceq0_i32,
127
} else {
272
+ .fniv = gen_ceq0_vec,
128
tcg_temp_free_i32(tmp);
273
+ .opt_opc = vecop_list_cmp,
129
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
274
+ .vece = MO_32 },
130
gen_jmp(s, s->pc + offset);
275
+ { .fni8 = gen_ceq0_i64,
131
}
276
+ .fniv = gen_ceq0_vec,
132
} else {
277
+ .opt_opc = vecop_list_cmp,
133
- /* Data processing immediate. */
278
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
134
+ /*
279
+ .vece = MO_64 },
135
+ * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
280
+};
136
+ * - Data-processing (modified immediate, plain binary immediate)
281
+
137
+ */
282
+static void gen_cle0_i32(TCGv_i32 d, TCGv_i32 a)
138
if (insn & (1 << 25)) {
283
+{
139
+ /*
284
+ tcg_gen_setcondi_i32(TCG_COND_LE, d, a, 0);
140
+ * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
285
+ tcg_gen_neg_i32(d, d);
141
+ * - Data-processing (plain binary immediate)
286
+}
142
+ */
287
+
143
if (insn & (1 << 24)) {
288
+static void gen_cle0_i64(TCGv_i64 d, TCGv_i64 a)
144
if (insn & (1 << 20))
289
+{
145
goto illegal_op;
290
+ tcg_gen_setcondi_i64(TCG_COND_LE, d, a, 0);
146
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
291
+ tcg_gen_neg_i64(d, d);
147
tmp = tcg_temp_new_i32();
292
+}
148
tcg_gen_movi_i32(tmp, imm);
293
+
149
}
294
+static void gen_cle0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
150
+ store_reg(s, rd, tmp);
295
+{
151
} else {
296
+ TCGv_vec zero = tcg_const_zeros_vec_matching(d);
152
/* Add/sub 12-bit immediate. */
297
+ tcg_gen_cmp_vec(TCG_COND_LE, vece, d, a, zero);
153
if (rn == 15) {
298
+ tcg_temp_free_vec(zero);
154
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
299
+}
155
offset += imm;
300
+
156
tmp = tcg_temp_new_i32();
301
+const GVecGen2 cle0_op[4] = {
157
tcg_gen_movi_i32(tmp, offset);
302
+ { .fno = gen_helper_gvec_cle0_b,
158
+ store_reg(s, rd, tmp);
303
+ .fniv = gen_cle0_vec,
159
} else {
304
+ .opt_opc = vecop_list_cmp,
160
tmp = load_reg(s, rn);
305
+ .vece = MO_8 },
161
if (insn & (1 << 23))
306
+ { .fno = gen_helper_gvec_cle0_h,
162
tcg_gen_subi_i32(tmp, tmp, imm);
307
+ .fniv = gen_cle0_vec,
163
else
308
+ .opt_opc = vecop_list_cmp,
164
tcg_gen_addi_i32(tmp, tmp, imm);
309
+ .vece = MO_16 },
165
+ if (rn == 13 && rd == 13) {
310
+ { .fni4 = gen_cle0_i32,
166
+ /* ADD SP, SP, imm or SUB SP, SP, imm */
311
+ .fniv = gen_cle0_vec,
167
+ store_sp_checked(s, tmp);
312
+ .opt_opc = vecop_list_cmp,
168
+ } else {
313
+ .vece = MO_32 },
169
+ store_reg(s, rd, tmp);
314
+ { .fni8 = gen_cle0_i64,
170
+ }
315
+ .fniv = gen_cle0_vec,
171
}
316
+ .opt_opc = vecop_list_cmp,
172
}
317
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
173
- store_reg(s, rd, tmp);
318
+ .vece = MO_64 },
174
}
319
+};
175
} else {
320
+
176
+ /*
321
+static void gen_cge0_i32(TCGv_i32 d, TCGv_i32 a)
177
+ * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
322
+{
178
+ * - Data-processing (modified immediate)
323
+ tcg_gen_setcondi_i32(TCG_COND_GE, d, a, 0);
179
+ */
324
+ tcg_gen_neg_i32(d, d);
180
int shifter_out = 0;
325
+}
181
/* modified 12-bit immediate. */
326
+
182
shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
327
+static void gen_cge0_i64(TCGv_i64 d, TCGv_i64 a)
183
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
328
+{
184
goto illegal_op;
329
+ tcg_gen_setcondi_i64(TCG_COND_GE, d, a, 0);
185
tcg_temp_free_i32(tmp2);
330
+ tcg_gen_neg_i64(d, d);
186
rd = (insn >> 8) & 0xf;
331
+}
187
- if (rd != 15) {
332
+
188
+ if (rd == 13 && rn == 13
333
+static void gen_cge0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
189
+ && (op == 8 || op == 13)) {
334
+{
190
+ /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
335
+ TCGv_vec zero = tcg_const_zeros_vec_matching(d);
191
+ store_sp_checked(s, tmp);
336
+ tcg_gen_cmp_vec(TCG_COND_GE, vece, d, a, zero);
192
+ } else if (rd != 15) {
337
+ tcg_temp_free_vec(zero);
193
store_reg(s, rd, tmp);
338
+}
194
} else {
339
+
195
tcg_temp_free_i32(tmp);
340
+const GVecGen2 cge0_op[4] = {
196
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
341
+ { .fno = gen_helper_gvec_cge0_b,
197
tmp2 = load_reg(s, rm);
342
+ .fniv = gen_cge0_vec,
198
tcg_gen_add_i32(tmp, tmp, tmp2);
343
+ .opt_opc = vecop_list_cmp,
199
tcg_temp_free_i32(tmp2);
344
+ .vece = MO_8 },
200
- store_reg(s, rd, tmp);
345
+ { .fno = gen_helper_gvec_cge0_h,
201
+ if (rd == 13) {
346
+ .fniv = gen_cge0_vec,
202
+ /* ADD SP, SP, reg */
347
+ .opt_opc = vecop_list_cmp,
203
+ store_sp_checked(s, tmp);
348
+ .vece = MO_16 },
204
+ } else {
349
+ { .fni4 = gen_cge0_i32,
205
+ store_reg(s, rd, tmp);
350
+ .fniv = gen_cge0_vec,
206
+ }
351
+ .opt_opc = vecop_list_cmp,
207
break;
352
+ .vece = MO_32 },
208
case 1: /* cmp */
353
+ { .fni8 = gen_cge0_i64,
209
tmp = load_reg(s, rd);
354
+ .fniv = gen_cge0_vec,
210
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
355
+ .opt_opc = vecop_list_cmp,
211
break;
356
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
212
case 2: /* mov/cpy */
357
+ .vece = MO_64 },
213
tmp = load_reg(s, rm);
358
+};
214
- store_reg(s, rd, tmp);
359
+
215
+ if (rd == 13) {
360
+static void gen_clt0_i32(TCGv_i32 d, TCGv_i32 a)
216
+ /* MOV SP, reg */
361
+{
217
+ store_sp_checked(s, tmp);
362
+ tcg_gen_setcondi_i32(TCG_COND_LT, d, a, 0);
218
+ } else {
363
+ tcg_gen_neg_i32(d, d);
219
+ store_reg(s, rd, tmp);
364
+}
220
+ }
365
+
221
break;
366
+static void gen_clt0_i64(TCGv_i64 d, TCGv_i64 a)
222
case 3:
367
+{
223
{
368
+ tcg_gen_setcondi_i64(TCG_COND_LT, d, a, 0);
224
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
369
+ tcg_gen_neg_i64(d, d);
225
break;
370
+}
226
371
+
227
case 10:
372
+static void gen_clt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
228
- /* add to high reg */
373
+{
229
+ /*
374
+ TCGv_vec zero = tcg_const_zeros_vec_matching(d);
230
+ * 0b1010_xxxx_xxxx_xxxx
375
+ tcg_gen_cmp_vec(TCG_COND_LT, vece, d, a, zero);
231
+ * - Add PC/SP (immediate)
376
+ tcg_temp_free_vec(zero);
232
+ */
377
+}
233
rd = (insn >> 8) & 7;
378
+
234
if (insn & (1 << 11)) {
379
+const GVecGen2 clt0_op[4] = {
235
/* SP */
380
+ { .fno = gen_helper_gvec_clt0_b,
236
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
381
+ .fniv = gen_clt0_vec,
237
op = (insn >> 8) & 0xf;
382
+ .opt_opc = vecop_list_cmp,
238
switch (op) {
383
+ .vece = MO_8 },
239
case 0:
384
+ { .fno = gen_helper_gvec_clt0_h,
240
- /* adjust stack pointer */
385
+ .fniv = gen_clt0_vec,
241
+ /*
386
+ .opt_opc = vecop_list_cmp,
242
+ * 0b1011_0000_xxxx_xxxx
387
+ .vece = MO_16 },
243
+ * - ADD (SP plus immediate)
388
+ { .fni4 = gen_clt0_i32,
244
+ * - SUB (SP minus immediate)
389
+ .fniv = gen_clt0_vec,
245
+ */
390
+ .opt_opc = vecop_list_cmp,
246
tmp = load_reg(s, 13);
391
+ .vece = MO_32 },
247
val = (insn & 0x7f) * 4;
392
+ { .fni8 = gen_clt0_i64,
248
if (insn & (1 << 7))
393
+ .fniv = gen_clt0_vec,
249
val = -(int32_t)val;
394
+ .opt_opc = vecop_list_cmp,
250
tcg_gen_addi_i32(tmp, tmp, val);
395
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
251
- store_reg(s, 13, tmp);
396
+ .vece = MO_64 },
252
+ store_sp_checked(s, tmp);
397
+};
253
break;
398
+
254
399
+static void gen_cgt0_i32(TCGv_i32 d, TCGv_i32 a)
255
case 2: /* sign/zero extend. */
400
+{
401
+ tcg_gen_setcondi_i32(TCG_COND_GT, d, a, 0);
402
+ tcg_gen_neg_i32(d, d);
403
+}
404
+
405
+static void gen_cgt0_i64(TCGv_i64 d, TCGv_i64 a)
406
+{
407
+ tcg_gen_setcondi_i64(TCG_COND_GT, d, a, 0);
408
+ tcg_gen_neg_i64(d, d);
409
+}
410
+
411
+static void gen_cgt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
412
+{
413
+ TCGv_vec zero = tcg_const_zeros_vec_matching(d);
414
+ tcg_gen_cmp_vec(TCG_COND_GT, vece, d, a, zero);
415
+ tcg_temp_free_vec(zero);
416
+}
417
+
418
+const GVecGen2 cgt0_op[4] = {
419
+ { .fno = gen_helper_gvec_cgt0_b,
420
+ .fniv = gen_cgt0_vec,
421
+ .opt_opc = vecop_list_cmp,
422
+ .vece = MO_8 },
423
+ { .fno = gen_helper_gvec_cgt0_h,
424
+ .fniv = gen_cgt0_vec,
425
+ .opt_opc = vecop_list_cmp,
426
+ .vece = MO_16 },
427
+ { .fni4 = gen_cgt0_i32,
428
+ .fniv = gen_cgt0_vec,
429
+ .opt_opc = vecop_list_cmp,
430
+ .vece = MO_32 },
431
+ { .fni8 = gen_cgt0_i64,
432
+ .fniv = gen_cgt0_vec,
433
+ .opt_opc = vecop_list_cmp,
434
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
435
+ .vece = MO_64 },
436
+};
437
+
438
static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
439
{
440
tcg_gen_vec_sar8i_i64(a, a, shift);
441
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
442
tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
443
break;
444
445
+ case NEON_2RM_VCEQ0:
446
+ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
447
+ vec_size, &ceq0_op[size]);
448
+ break;
449
+ case NEON_2RM_VCGT0:
450
+ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
451
+ vec_size, &cgt0_op[size]);
452
+ break;
453
+ case NEON_2RM_VCLE0:
454
+ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
455
+ vec_size, &cle0_op[size]);
456
+ break;
457
+ case NEON_2RM_VCGE0:
458
+ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
459
+ vec_size, &cge0_op[size]);
460
+ break;
461
+ case NEON_2RM_VCLT0:
462
+ tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
463
+ vec_size, &clt0_op[size]);
464
+ break;
465
+
466
default:
467
elementwise:
468
for (pass = 0; pass < (q ? 4 : 2); pass++) {
469
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
470
default: abort();
471
}
472
break;
473
- case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
474
- tmp2 = tcg_const_i32(0);
475
- switch(size) {
476
- case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
477
- case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
478
- case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
479
- default: abort();
480
- }
481
- tcg_temp_free_i32(tmp2);
482
- if (op == NEON_2RM_VCLE0) {
483
- tcg_gen_not_i32(tmp, tmp);
484
- }
485
- break;
486
- case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
487
- tmp2 = tcg_const_i32(0);
488
- switch(size) {
489
- case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
490
- case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
491
- case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
492
- default: abort();
493
- }
494
- tcg_temp_free_i32(tmp2);
495
- if (op == NEON_2RM_VCLT0) {
496
- tcg_gen_not_i32(tmp, tmp);
497
- }
498
- break;
499
- case NEON_2RM_VCEQ0:
500
- tmp2 = tcg_const_i32(0);
501
- switch(size) {
502
- case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
503
- case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
504
- case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
505
- default: abort();
506
- }
507
- tcg_temp_free_i32(tmp2);
508
- break;
509
case NEON_2RM_VCGT0_F:
510
{
511
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
512
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
513
index XXXXXXX..XXXXXXX 100644
514
--- a/target/arm/vec_helper.c
515
+++ b/target/arm/vec_helper.c
516
@@ -XXX,XX +XXX,XX @@ void HELPER(sve2_pmull_h)(void *vd, void *vn, void *vm, uint32_t desc)
517
}
518
}
519
#endif
520
+
521
+#define DO_CMP0(NAME, TYPE, OP) \
522
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
523
+{ \
524
+ intptr_t i, opr_sz = simd_oprsz(desc); \
525
+ for (i = 0; i < opr_sz; i += sizeof(TYPE)) { \
526
+ TYPE nn = *(TYPE *)(vn + i); \
527
+ *(TYPE *)(vd + i) = -(nn OP 0); \
528
+ } \
529
+ clear_tail(vd, opr_sz, simd_maxsz(desc)); \
530
+}
531
+
532
+DO_CMP0(gvec_ceq0_b, int8_t, ==)
533
+DO_CMP0(gvec_clt0_b, int8_t, <)
534
+DO_CMP0(gvec_cle0_b, int8_t, <=)
535
+DO_CMP0(gvec_cgt0_b, int8_t, >)
536
+DO_CMP0(gvec_cge0_b, int8_t, >=)
537
+
538
+DO_CMP0(gvec_ceq0_h, int16_t, ==)
539
+DO_CMP0(gvec_clt0_h, int16_t, <)
540
+DO_CMP0(gvec_cle0_h, int16_t, <=)
541
+DO_CMP0(gvec_cgt0_h, int16_t, >)
542
+DO_CMP0(gvec_cge0_h, int16_t, >=)
543
+
544
+#undef DO_CMP0
256
--
545
--
257
2.19.0
546
2.20.1
258
547
259
548
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Jerome Forissier <jerome@forissier.org>
2
2
3
The 16-byte load only uses 16 predicate bits. But while
3
The /secure-chosen node is currently used only by create_uart(), but
4
reusing the other load infrastructure, we find other bits
4
this will change. Therefore move the creation of this node to
5
that are set and trigger an assert. To avoid this and
5
create_fdt().
6
retain the assert, zero-extend the predicate that we pass
7
to the LD1 helper.
8
6
9
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Jerome Forissier <jerome@forissier.org>
10
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20200420121807.8204-2-jerome@forissier.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20181005175350.30752-7-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
target/arm/translate-sve.c | 25 +++++++++++++++++++++++--
12
hw/arm/virt.c | 5 ++++-
17
1 file changed, 23 insertions(+), 2 deletions(-)
13
1 file changed, 4 insertions(+), 1 deletion(-)
18
14
19
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
15
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate-sve.c
17
--- a/hw/arm/virt.c
22
+++ b/target/arm/translate-sve.c
18
+++ b/hw/arm/virt.c
23
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
19
@@ -XXX,XX +XXX,XX @@ static void create_fdt(VirtMachineState *vms)
24
unsigned vsz = vec_full_reg_size(s);
20
/* /chosen must exist for load_dtb to fill in necessary properties later */
25
TCGv_ptr t_pg;
21
qemu_fdt_add_subnode(fdt, "/chosen");
26
TCGv_i32 desc;
22
27
+ int poff;
23
+ if (vms->secure) {
28
24
+ qemu_fdt_add_subnode(fdt, "/secure-chosen");
29
/* Load the first quadword using the normal predicated load helpers. */
30
desc = tcg_const_i32(simd_desc(16, 16, zt));
31
- t_pg = tcg_temp_new_ptr();
32
33
- tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
34
+ poff = pred_full_reg_offset(s, pg);
35
+ if (vsz > 16) {
36
+ /*
37
+ * Zero-extend the first 16 bits of the predicate into a temporary.
38
+ * This avoids triggering an assert making sure we don't have bits
39
+ * set within a predicate beyond VQ, but we have lowered VQ to 1
40
+ * for this load operation.
41
+ */
42
+ TCGv_i64 tmp = tcg_temp_new_i64();
43
+#ifdef HOST_WORDS_BIGENDIAN
44
+ poff += 6;
45
+#endif
46
+ tcg_gen_ld16u_i64(tmp, cpu_env, poff);
47
+
48
+ poff = offsetof(CPUARMState, vfp.preg_tmp);
49
+ tcg_gen_st_i64(tmp, cpu_env, poff);
50
+ tcg_temp_free_i64(tmp);
51
+ }
25
+ }
52
+
26
+
53
+ t_pg = tcg_temp_new_ptr();
27
/* Clock node, for the benefit of the UART. The kernel device tree
54
+ tcg_gen_addi_ptr(t_pg, cpu_env, poff);
28
* binding documentation claims the PL011 node clock properties are
55
+
29
* optional but in practice if you omit them the kernel refuses to
56
fns[msz](cpu_env, t_pg, addr, desc);
30
@@ -XXX,XX +XXX,XX @@ static void create_uart(const VirtMachineState *vms, int uart,
57
31
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
58
tcg_temp_free_ptr(t_pg);
32
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
33
34
- qemu_fdt_add_subnode(vms->fdt, "/secure-chosen");
35
qemu_fdt_setprop_string(vms->fdt, "/secure-chosen", "stdout-path",
36
nodename);
37
}
59
--
38
--
60
2.19.0
39
2.20.1
61
40
62
41
diff view generated by jsdifflib
1
In commit c79c0a314c43b78 we enabled emulation of external aborts
1
From: Jerome Forissier <jerome@forissier.org>
2
when the guest attempts to access a physical address with no
3
mapped device. In commit 4672cbd7bed88dc6 we suppress this for
4
most legacy boards to prevent breakage of previously working
5
guests, but we didn't suppress it in the 'virt' board, with
6
the rationale "we know that guests won't try to prod devices
7
that we don't describe in the device tree or ACPI tables". This
8
is mostly true, but we've had a report of a Linux guest image
9
that this did break. The problem seems to be that the guest
10
is (incorrectly) configured with a DEBUG_UART_PHYS value that
11
tells it there is a uart at 0x10009000 (which is true for
12
vexpress but not for virt), so in early bootup the kernel
13
probes this bogus address.
14
2
15
This is a misconfigured guest, so we don't need to worry
3
Generate random seeds to be used by the non-secure and/or secure OSes
16
about it too much, but we can arrange that guests that ran
4
for ASLR. The seeds are 64-bit random values exported via the DT
17
on QEMU v2.10 (before c79c0a314c43b78) will still run on
5
properties /chosen/kaslr-seed [1] and /secure-chosen/kaslr-seed, the
18
the "virt-2.10" board model, by suppressing external aborts
6
latter being used by OP-TEE [2].
19
only for that version and earlier. This seems a reasonable
20
compromise: "virt-2.10" is supposed to behave the same way
21
that "virt" did in the 2.10 release, and making it do that
22
provides a usable workaround for guests with bugs like this.
23
7
24
Cc: qemu-stable@nongnu.org
8
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e5bc0c37c97e1
9
[2] https://github.com/OP-TEE/optee_os/commit/ef262691fe0e
10
11
Signed-off-by: Jerome Forissier <jerome@forissier.org>
12
Message-id: 20200420121807.8204-3-jerome@forissier.org
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Message-id: 20180925144127.31965-1-peter.maydell@linaro.org
27
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
28
---
15
---
29
hw/arm/virt.c | 2 ++
16
hw/arm/virt.c | 15 +++++++++++++++
30
1 file changed, 2 insertions(+)
17
1 file changed, 15 insertions(+)
31
18
32
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
19
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
33
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/virt.c
21
--- a/hw/arm/virt.c
35
+++ b/hw/arm/virt.c
22
+++ b/hw/arm/virt.c
36
@@ -XXX,XX +XXX,XX @@ static void virt_machine_2_10_options(MachineClass *mc)
23
@@ -XXX,XX +XXX,XX @@
24
#include "hw/acpi/generic_event_device.h"
25
#include "hw/virtio/virtio-iommu.h"
26
#include "hw/char/pl011.h"
27
+#include "qemu/guest-random.h"
28
29
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
30
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
31
@@ -XXX,XX +XXX,XX @@ static bool cpu_type_valid(const char *cpu)
32
return false;
33
}
34
35
+static void create_kaslr_seed(VirtMachineState *vms, const char *node)
36
+{
37
+ Error *err = NULL;
38
+ uint64_t seed;
39
+
40
+ if (qemu_guest_getrandom(&seed, sizeof(seed), &err)) {
41
+ error_free(err);
42
+ return;
43
+ }
44
+ qemu_fdt_setprop_u64(vms->fdt, node, "kaslr-seed", seed);
45
+}
46
+
47
static void create_fdt(VirtMachineState *vms)
37
{
48
{
38
virt_machine_2_11_options(mc);
49
MachineState *ms = MACHINE(vms);
39
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_10);
50
@@ -XXX,XX +XXX,XX @@ static void create_fdt(VirtMachineState *vms)
40
+ /* before 2.11 we never faulted accesses to bad addresses */
51
41
+ mc->ignore_memory_transaction_failures = true;
52
/* /chosen must exist for load_dtb to fill in necessary properties later */
42
}
53
qemu_fdt_add_subnode(fdt, "/chosen");
43
DEFINE_VIRT_MACHINE(2, 10)
54
+ create_kaslr_seed(vms, "/chosen");
44
55
56
if (vms->secure) {
57
qemu_fdt_add_subnode(fdt, "/secure-chosen");
58
+ create_kaslr_seed(vms, "/secure-chosen");
59
}
60
61
/* Clock node, for the benefit of the UART. The kernel device tree
45
--
62
--
46
2.19.0
63
2.20.1
47
64
48
65
diff view generated by jsdifflib
1
Add checks for breaches of the v8M stack limit when the
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
stack pointer is decremented to push the exception frame
3
for exception entry.
4
2
5
Note that the exception-entry case is unique in that the
3
Under KVM these registers are written by the hardware.
6
stack pointer is updated to be the limit value if the limit
4
Restrict the writefn handlers to TCG to avoid when building
7
is hit (per rule R_ZLZG).
5
without TCG:
8
6
7
LINK aarch64-softmmu/qemu-system-aarch64
8
target/arm/helper.o: In function `do_ats_write':
9
target/arm/helper.c:3524: undefined reference to `raise_exception'
10
11
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Message-id: 20200423073358.27155-2-philmd@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20181002163556.10279-7-peter.maydell@linaro.org
13
---
16
---
14
target/arm/helper.c | 54 ++++++++++++++++++++++++++++++++++++++-------
17
target/arm/helper.c | 17 +++++++++++++++++
15
1 file changed, 46 insertions(+), 8 deletions(-)
18
1 file changed, 17 insertions(+)
16
19
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
22
--- a/target/arm/helper.c
20
+++ b/target/arm/helper.c
23
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
24
@@ -XXX,XX +XXX,XX @@ static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri,
22
uint32_t frameptr;
25
return CP_ACCESS_OK;
26
}
27
28
+#ifdef CONFIG_TCG
29
static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
30
MMUAccessType access_type, ARMMMUIdx mmu_idx)
31
{
32
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
33
}
34
return par64;
35
}
36
+#endif /* CONFIG_TCG */
37
38
static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
39
{
40
+#ifdef CONFIG_TCG
41
MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
42
uint64_t par64;
23
ARMMMUIdx mmu_idx;
43
ARMMMUIdx mmu_idx;
24
bool stacked_ok;
44
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
25
+ uint32_t limit;
45
par64 = do_ats_write(env, value, access_type, mmu_idx);
26
+ bool want_psp;
46
27
47
A32_BANKED_CURRENT_REG_SET(env, par, par64);
28
if (dotailchain) {
48
+#else
29
bool mode = lr & R_V7M_EXCRET_MODE_MASK;
49
+ /* Handled by hardware accelerator. */
30
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
50
+ g_assert_not_reached();
31
mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, M_REG_S, priv);
51
+#endif /* CONFIG_TCG */
32
frame_sp_p = get_v7m_sp_ptr(env, M_REG_S, mode,
52
}
33
lr & R_V7M_EXCRET_SPSEL_MASK);
53
34
+ want_psp = mode && (lr & R_V7M_EXCRET_SPSEL_MASK);
54
static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
35
+ if (want_psp) {
55
uint64_t value)
36
+ limit = env->v7m.psplim[M_REG_S];
56
{
37
+ } else {
57
+#ifdef CONFIG_TCG
38
+ limit = env->v7m.msplim[M_REG_S];
58
MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
39
+ }
59
uint64_t par64;
40
} else {
60
41
mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
61
par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2);
42
frame_sp_p = &env->regs[13];
62
43
+ limit = v7m_sp_limit(env);
63
A32_BANKED_CURRENT_REG_SET(env, par, par64);
64
+#else
65
+ /* Handled by hardware accelerator. */
66
+ g_assert_not_reached();
67
+#endif /* CONFIG_TCG */
68
}
69
70
static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
71
@@ -XXX,XX +XXX,XX @@ static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
72
static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
73
uint64_t value)
74
{
75
+#ifdef CONFIG_TCG
76
MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
77
ARMMMUIdx mmu_idx;
78
int secure = arm_is_secure_below_el3(env);
79
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
44
}
80
}
45
81
46
frameptr = *frame_sp_p - 0x28;
82
env->cp15.par_el[1] = do_ats_write(env, value, access_type, mmu_idx);
47
+ if (frameptr < limit) {
83
+#else
48
+ /*
84
+ /* Handled by hardware accelerator. */
49
+ * Stack limit failure: set SP to the limit value, and generate
85
+ g_assert_not_reached();
50
+ * STKOF UsageFault. Stack pushes below the limit must not be
86
+#endif /* CONFIG_TCG */
51
+ * performed. It is IMPDEF whether pushes above the limit are
87
}
52
+ * performed; we choose not to.
88
#endif
53
+ */
89
54
+ qemu_log_mask(CPU_LOG_INT,
55
+ "...STKOF during callee-saves register stacking\n");
56
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_STKOF_MASK;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
58
+ env->v7m.secure);
59
+ *frame_sp_p = limit;
60
+ return true;
61
+ }
62
63
/* Write as much of the stack frame as we can. A write failure may
64
* cause us to pend a derived exception.
65
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
66
v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx,
67
ignore_faults);
68
69
- /* Update SP regardless of whether any of the stack accesses failed.
70
- * When we implement v8M stack limit checking then this attempt to
71
- * update SP might also fail and result in a derived exception.
72
- */
73
+ /* Update SP regardless of whether any of the stack accesses failed. */
74
*frame_sp_p = frameptr;
75
76
return !stacked_ok;
77
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
78
79
frameptr -= 0x20;
80
81
+ if (arm_feature(env, ARM_FEATURE_V8)) {
82
+ uint32_t limit = v7m_sp_limit(env);
83
+
84
+ if (frameptr < limit) {
85
+ /*
86
+ * Stack limit failure: set SP to the limit value, and generate
87
+ * STKOF UsageFault. Stack pushes below the limit must not be
88
+ * performed. It is IMPDEF whether pushes above the limit are
89
+ * performed; we choose not to.
90
+ */
91
+ qemu_log_mask(CPU_LOG_INT,
92
+ "...STKOF during stacking\n");
93
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_STKOF_MASK;
94
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
95
+ env->v7m.secure);
96
+ env->regs[13] = limit;
97
+ return true;
98
+ }
99
+ }
100
+
101
/* Write as much of the stack frame as we can. If we fail a stack
102
* write this will result in a derived exception being pended
103
* (which may be taken in preference to the one we started with
104
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
105
v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
106
v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
107
108
- /* Update SP regardless of whether any of the stack accesses failed.
109
- * When we implement v8M stack limit checking then this attempt to
110
- * update SP might also fail and result in a derived exception.
111
- */
112
+ /* Update SP regardless of whether any of the stack accesses failed. */
113
env->regs[13] = frameptr;
114
115
return !stacked_ok;
116
--
90
--
117
2.19.0
91
2.20.1
118
92
119
93
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
We can choose the endianness at translation time, rather than
3
Make cpu_register() (renamed to arm_cpu_register()) available
4
re-computing it at execution time.
4
from internals.h so we can register CPUs also from other files
5
in the future.
5
6
6
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20181005175350.30752-11-richard.henderson@linaro.org
10
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20200423073358.27155-3-philmd@redhat.com
12
Message-ID: <20190921150420.30743-2-thuth@redhat.com>
13
[PMD: Only take cpu_register() from Thomas's patch]
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
target/arm/helper-sve.h | 117 +++++++++++++++-------
17
target/arm/cpu-qom.h | 9 ++++++++-
13
target/arm/sve_helper.c | 70 ++++++-------
18
target/arm/cpu.c | 10 ++--------
14
target/arm/translate-sve.c | 196 +++++++++++++++++++++++++------------
19
target/arm/cpu64.c | 8 +-------
15
3 files changed, 252 insertions(+), 131 deletions(-)
20
3 files changed, 11 insertions(+), 16 deletions(-)
16
21
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
22
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
18
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-sve.h
24
--- a/target/arm/cpu-qom.h
20
+++ b/target/arm/helper-sve.h
25
+++ b/target/arm/cpu-qom.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ld2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
26
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info;
22
DEF_HELPER_FLAGS_4(sve_ld3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
27
23
DEF_HELPER_FLAGS_4(sve_ld4bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
28
#define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU
24
29
25
-DEF_HELPER_FLAGS_4(sve_ld1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
30
-typedef struct ARMCPUInfo ARMCPUInfo;
26
-DEF_HELPER_FLAGS_4(sve_ld2hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
31
+typedef struct ARMCPUInfo {
27
-DEF_HELPER_FLAGS_4(sve_ld3hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
32
+ const char *name;
28
-DEF_HELPER_FLAGS_4(sve_ld4hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
33
+ void (*initfn)(Object *obj);
29
+DEF_HELPER_FLAGS_4(sve_ld1hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
34
+ void (*class_init)(ObjectClass *oc, void *data);
30
+DEF_HELPER_FLAGS_4(sve_ld2hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
35
+} ARMCPUInfo;
31
+DEF_HELPER_FLAGS_4(sve_ld3hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
32
+DEF_HELPER_FLAGS_4(sve_ld4hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
33
34
-DEF_HELPER_FLAGS_4(sve_ld1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
35
-DEF_HELPER_FLAGS_4(sve_ld2ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
36
-DEF_HELPER_FLAGS_4(sve_ld3ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
37
-DEF_HELPER_FLAGS_4(sve_ld4ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
38
+DEF_HELPER_FLAGS_4(sve_ld1hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
39
+DEF_HELPER_FLAGS_4(sve_ld2hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_4(sve_ld3hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
41
+DEF_HELPER_FLAGS_4(sve_ld4hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
43
-DEF_HELPER_FLAGS_4(sve_ld1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
44
-DEF_HELPER_FLAGS_4(sve_ld2dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
45
-DEF_HELPER_FLAGS_4(sve_ld3dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
46
-DEF_HELPER_FLAGS_4(sve_ld4dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_4(sve_ld1ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_4(sve_ld2ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
49
+DEF_HELPER_FLAGS_4(sve_ld3ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
50
+DEF_HELPER_FLAGS_4(sve_ld4ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
51
+
36
+
52
+DEF_HELPER_FLAGS_4(sve_ld1ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
37
+void arm_cpu_register(const ARMCPUInfo *info);
53
+DEF_HELPER_FLAGS_4(sve_ld2ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
38
+void aarch64_cpu_register(const ARMCPUInfo *info);
54
+DEF_HELPER_FLAGS_4(sve_ld3ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
39
55
+DEF_HELPER_FLAGS_4(sve_ld4ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
40
/**
56
+
41
* ARMCPUClass:
57
+DEF_HELPER_FLAGS_4(sve_ld1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
58
+DEF_HELPER_FLAGS_4(sve_ld2dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
59
+DEF_HELPER_FLAGS_4(sve_ld3dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_4(sve_ld4dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
61
+
62
+DEF_HELPER_FLAGS_4(sve_ld1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
63
+DEF_HELPER_FLAGS_4(sve_ld2dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
64
+DEF_HELPER_FLAGS_4(sve_ld3dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
65
+DEF_HELPER_FLAGS_4(sve_ld4dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
66
67
DEF_HELPER_FLAGS_4(sve_ld1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
68
DEF_HELPER_FLAGS_4(sve_ld1bsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
69
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ld1bhs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
70
DEF_HELPER_FLAGS_4(sve_ld1bss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
71
DEF_HELPER_FLAGS_4(sve_ld1bds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
72
73
-DEF_HELPER_FLAGS_4(sve_ld1hsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
74
-DEF_HELPER_FLAGS_4(sve_ld1hdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
75
-DEF_HELPER_FLAGS_4(sve_ld1hss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
76
-DEF_HELPER_FLAGS_4(sve_ld1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
77
+DEF_HELPER_FLAGS_4(sve_ld1hsu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_4(sve_ld1hdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
79
+DEF_HELPER_FLAGS_4(sve_ld1hss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
80
+DEF_HELPER_FLAGS_4(sve_ld1hds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
81
82
-DEF_HELPER_FLAGS_4(sve_ld1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
83
-DEF_HELPER_FLAGS_4(sve_ld1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
84
+DEF_HELPER_FLAGS_4(sve_ld1hsu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
85
+DEF_HELPER_FLAGS_4(sve_ld1hdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
86
+DEF_HELPER_FLAGS_4(sve_ld1hss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
87
+DEF_HELPER_FLAGS_4(sve_ld1hds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
88
+
89
+DEF_HELPER_FLAGS_4(sve_ld1sdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
90
+DEF_HELPER_FLAGS_4(sve_ld1sds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
91
+
92
+DEF_HELPER_FLAGS_4(sve_ld1sdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
93
+DEF_HELPER_FLAGS_4(sve_ld1sds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
94
95
DEF_HELPER_FLAGS_4(sve_ldff1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
96
DEF_HELPER_FLAGS_4(sve_ldff1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
97
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ldff1bhs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
98
DEF_HELPER_FLAGS_4(sve_ldff1bss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
99
DEF_HELPER_FLAGS_4(sve_ldff1bds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
100
101
-DEF_HELPER_FLAGS_4(sve_ldff1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
102
-DEF_HELPER_FLAGS_4(sve_ldff1hsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
103
-DEF_HELPER_FLAGS_4(sve_ldff1hdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
104
-DEF_HELPER_FLAGS_4(sve_ldff1hss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
105
-DEF_HELPER_FLAGS_4(sve_ldff1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
106
+DEF_HELPER_FLAGS_4(sve_ldff1hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
107
+DEF_HELPER_FLAGS_4(sve_ldff1hsu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
108
+DEF_HELPER_FLAGS_4(sve_ldff1hdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
109
+DEF_HELPER_FLAGS_4(sve_ldff1hss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
110
+DEF_HELPER_FLAGS_4(sve_ldff1hds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
111
112
-DEF_HELPER_FLAGS_4(sve_ldff1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
113
-DEF_HELPER_FLAGS_4(sve_ldff1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
114
-DEF_HELPER_FLAGS_4(sve_ldff1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
115
+DEF_HELPER_FLAGS_4(sve_ldff1hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
116
+DEF_HELPER_FLAGS_4(sve_ldff1hsu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
117
+DEF_HELPER_FLAGS_4(sve_ldff1hdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
118
+DEF_HELPER_FLAGS_4(sve_ldff1hss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
119
+DEF_HELPER_FLAGS_4(sve_ldff1hds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
120
121
-DEF_HELPER_FLAGS_4(sve_ldff1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
122
+DEF_HELPER_FLAGS_4(sve_ldff1ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
123
+DEF_HELPER_FLAGS_4(sve_ldff1sdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
124
+DEF_HELPER_FLAGS_4(sve_ldff1sds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
125
+
126
+DEF_HELPER_FLAGS_4(sve_ldff1ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
127
+DEF_HELPER_FLAGS_4(sve_ldff1sdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
128
+DEF_HELPER_FLAGS_4(sve_ldff1sds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
129
+
130
+DEF_HELPER_FLAGS_4(sve_ldff1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
131
+DEF_HELPER_FLAGS_4(sve_ldff1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
132
133
DEF_HELPER_FLAGS_4(sve_ldnf1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
134
DEF_HELPER_FLAGS_4(sve_ldnf1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
135
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ldnf1bhs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
136
DEF_HELPER_FLAGS_4(sve_ldnf1bss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
137
DEF_HELPER_FLAGS_4(sve_ldnf1bds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
138
139
-DEF_HELPER_FLAGS_4(sve_ldnf1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
140
-DEF_HELPER_FLAGS_4(sve_ldnf1hsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
141
-DEF_HELPER_FLAGS_4(sve_ldnf1hdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
142
-DEF_HELPER_FLAGS_4(sve_ldnf1hss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
143
-DEF_HELPER_FLAGS_4(sve_ldnf1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
144
+DEF_HELPER_FLAGS_4(sve_ldnf1hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
145
+DEF_HELPER_FLAGS_4(sve_ldnf1hsu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
146
+DEF_HELPER_FLAGS_4(sve_ldnf1hdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
147
+DEF_HELPER_FLAGS_4(sve_ldnf1hss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
148
+DEF_HELPER_FLAGS_4(sve_ldnf1hds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
149
150
-DEF_HELPER_FLAGS_4(sve_ldnf1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
151
-DEF_HELPER_FLAGS_4(sve_ldnf1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
152
-DEF_HELPER_FLAGS_4(sve_ldnf1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
153
+DEF_HELPER_FLAGS_4(sve_ldnf1hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
154
+DEF_HELPER_FLAGS_4(sve_ldnf1hsu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
155
+DEF_HELPER_FLAGS_4(sve_ldnf1hdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
156
+DEF_HELPER_FLAGS_4(sve_ldnf1hss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
157
+DEF_HELPER_FLAGS_4(sve_ldnf1hds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
158
159
-DEF_HELPER_FLAGS_4(sve_ldnf1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
160
+DEF_HELPER_FLAGS_4(sve_ldnf1ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
161
+DEF_HELPER_FLAGS_4(sve_ldnf1sdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
162
+DEF_HELPER_FLAGS_4(sve_ldnf1sds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
163
+
164
+DEF_HELPER_FLAGS_4(sve_ldnf1ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
165
+DEF_HELPER_FLAGS_4(sve_ldnf1sdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
166
+DEF_HELPER_FLAGS_4(sve_ldnf1sds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
167
+
168
+DEF_HELPER_FLAGS_4(sve_ldnf1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
169
+DEF_HELPER_FLAGS_4(sve_ldnf1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
170
171
DEF_HELPER_FLAGS_4(sve_st1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
172
DEF_HELPER_FLAGS_4(sve_st2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
173
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
174
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
175
--- a/target/arm/sve_helper.c
44
--- a/target/arm/cpu.c
176
+++ b/target/arm/sve_helper.c
45
+++ b/target/arm/cpu.c
177
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \
46
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
178
sve_##NAME##_host, sve_##NAME##_tlb); \
47
48
#endif /* !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) */
49
50
-struct ARMCPUInfo {
51
- const char *name;
52
- void (*initfn)(Object *obj);
53
- void (*class_init)(ObjectClass *oc, void *data);
54
-};
55
-
56
static const ARMCPUInfo arm_cpus[] = {
57
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
58
{ .name = "arm926", .initfn = arm926_initfn },
59
@@ -XXX,XX +XXX,XX @@ static void cpu_register_class_init(ObjectClass *oc, void *data)
60
acc->info = data;
179
}
61
}
180
62
181
-/* TODO: Propagate the endian check back to the translator. */
63
-static void cpu_register(const ARMCPUInfo *info)
182
#define DO_LD1_2(NAME, ESZ, MSZ) \
64
+void arm_cpu_register(const ARMCPUInfo *info)
183
-void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \
65
{
184
- target_ulong addr, uint32_t desc) \
66
TypeInfo type_info = {
185
-{ \
67
.parent = TYPE_ARM_CPU,
186
- if (arm_cpu_data_is_big_endian(env)) { \
68
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_register_types(void)
187
- sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
69
type_register_static(&idau_interface_type_info);
188
- sve_##NAME##_be_host, sve_##NAME##_be_tlb); \
70
189
- } else { \
71
while (info->name) {
190
- sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
72
- cpu_register(info);
191
- sve_##NAME##_le_host, sve_##NAME##_le_tlb); \
73
+ arm_cpu_register(info);
192
- } \
74
info++;
193
+void HELPER(sve_##NAME##_le_r)(CPUARMState *env, void *vg, \
75
}
194
+ target_ulong addr, uint32_t desc) \
76
195
+{ \
77
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
196
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
78
index XXXXXXX..XXXXXXX 100644
197
+ sve_##NAME##_le_host, sve_##NAME##_le_tlb); \
79
--- a/target/arm/cpu64.c
198
+} \
80
+++ b/target/arm/cpu64.c
199
+void HELPER(sve_##NAME##_be_r)(CPUARMState *env, void *vg, \
81
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
200
+ target_ulong addr, uint32_t desc) \
82
cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
201
+{ \
202
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
203
+ sve_##NAME##_be_host, sve_##NAME##_be_tlb); \
204
}
83
}
205
84
206
DO_LD1_1(ld1bb, 0)
85
-struct ARMCPUInfo {
207
@@ -XXX,XX +XXX,XX @@ void __attribute__((flatten)) HELPER(sve_ld##N##bb_r) \
86
- const char *name;
87
- void (*initfn)(Object *obj);
88
- void (*class_init)(ObjectClass *oc, void *data);
89
-};
90
-
91
static const ARMCPUInfo aarch64_cpus[] = {
92
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
93
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
94
@@ -XXX,XX +XXX,XX @@ static void cpu_register_class_init(ObjectClass *oc, void *data)
95
acc->info = data;
208
}
96
}
209
97
210
#define DO_LDN_2(N, SUFF, SIZE) \
98
-static void aarch64_cpu_register(const ARMCPUInfo *info)
211
-void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_r) \
99
+void aarch64_cpu_register(const ARMCPUInfo *info)
212
+void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_le_r) \
213
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
214
{ \
215
sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \
216
- arm_cpu_data_is_big_endian(env) \
217
- ? sve_ld1##SUFF##_be_tlb : sve_ld1##SUFF##_le_tlb); \
218
+ sve_ld1##SUFF##_le_tlb); \
219
+} \
220
+void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_be_r) \
221
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
222
+{ \
223
+ sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \
224
+ sve_ld1##SUFF##_be_tlb); \
225
}
226
227
DO_LDN_1(2)
228
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \
229
sve_ldnf1_r(env, vg, addr, desc, ESZ, 0, sve_ld1##PART##_host); \
230
}
231
232
-/* TODO: Propagate the endian check back to the translator. */
233
#define DO_LDFF1_LDNF1_2(PART, ESZ, MSZ) \
234
-void HELPER(sve_ldff1##PART##_r)(CPUARMState *env, void *vg, \
235
- target_ulong addr, uint32_t desc) \
236
+void HELPER(sve_ldff1##PART##_le_r)(CPUARMState *env, void *vg, \
237
+ target_ulong addr, uint32_t desc) \
238
{ \
239
- if (arm_cpu_data_is_big_endian(env)) { \
240
- sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
241
- sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \
242
- } else { \
243
- sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
244
- sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \
245
- } \
246
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
247
+ sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \
248
} \
249
-void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \
250
- target_ulong addr, uint32_t desc) \
251
+void HELPER(sve_ldnf1##PART##_le_r)(CPUARMState *env, void *vg, \
252
+ target_ulong addr, uint32_t desc) \
253
{ \
254
- if (arm_cpu_data_is_big_endian(env)) { \
255
- sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, \
256
- sve_ld1##PART##_be_host); \
257
- } else { \
258
- sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, \
259
- sve_ld1##PART##_le_host); \
260
- } \
261
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, sve_ld1##PART##_le_host); \
262
+} \
263
+void HELPER(sve_ldff1##PART##_be_r)(CPUARMState *env, void *vg, \
264
+ target_ulong addr, uint32_t desc) \
265
+{ \
266
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
267
+ sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \
268
+} \
269
+void HELPER(sve_ldnf1##PART##_be_r)(CPUARMState *env, void *vg, \
270
+ target_ulong addr, uint32_t desc) \
271
+{ \
272
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, sve_ld1##PART##_be_host); \
273
}
274
275
DO_LDFF1_LDNF1_1(bb, 0)
276
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/target/arm/translate-sve.c
279
+++ b/target/arm/translate-sve.c
280
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
281
static void do_ld_zpa(DisasContext *s, int zt, int pg,
282
TCGv_i64 addr, int dtype, int nreg)
283
{
100
{
284
- static gen_helper_gvec_mem * const fns[16][4] = {
101
TypeInfo type_info = {
285
- { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r,
102
.parent = TYPE_AARCH64_CPU,
286
- gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r },
287
- { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL },
288
- { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL },
289
- { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL },
290
+ static gen_helper_gvec_mem * const fns[2][16][4] = {
291
+ /* Little-endian */
292
+ { { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r,
293
+ gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r },
294
+ { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL },
295
+ { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL },
296
+ { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL },
297
298
- { gen_helper_sve_ld1sds_r, NULL, NULL, NULL },
299
- { gen_helper_sve_ld1hh_r, gen_helper_sve_ld2hh_r,
300
- gen_helper_sve_ld3hh_r, gen_helper_sve_ld4hh_r },
301
- { gen_helper_sve_ld1hsu_r, NULL, NULL, NULL },
302
- { gen_helper_sve_ld1hdu_r, NULL, NULL, NULL },
303
+ { gen_helper_sve_ld1sds_le_r, NULL, NULL, NULL },
304
+ { gen_helper_sve_ld1hh_le_r, gen_helper_sve_ld2hh_le_r,
305
+ gen_helper_sve_ld3hh_le_r, gen_helper_sve_ld4hh_le_r },
306
+ { gen_helper_sve_ld1hsu_le_r, NULL, NULL, NULL },
307
+ { gen_helper_sve_ld1hdu_le_r, NULL, NULL, NULL },
308
309
- { gen_helper_sve_ld1hds_r, NULL, NULL, NULL },
310
- { gen_helper_sve_ld1hss_r, NULL, NULL, NULL },
311
- { gen_helper_sve_ld1ss_r, gen_helper_sve_ld2ss_r,
312
- gen_helper_sve_ld3ss_r, gen_helper_sve_ld4ss_r },
313
- { gen_helper_sve_ld1sdu_r, NULL, NULL, NULL },
314
+ { gen_helper_sve_ld1hds_le_r, NULL, NULL, NULL },
315
+ { gen_helper_sve_ld1hss_le_r, NULL, NULL, NULL },
316
+ { gen_helper_sve_ld1ss_le_r, gen_helper_sve_ld2ss_le_r,
317
+ gen_helper_sve_ld3ss_le_r, gen_helper_sve_ld4ss_le_r },
318
+ { gen_helper_sve_ld1sdu_le_r, NULL, NULL, NULL },
319
320
- { gen_helper_sve_ld1bds_r, NULL, NULL, NULL },
321
- { gen_helper_sve_ld1bss_r, NULL, NULL, NULL },
322
- { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL },
323
- { gen_helper_sve_ld1dd_r, gen_helper_sve_ld2dd_r,
324
- gen_helper_sve_ld3dd_r, gen_helper_sve_ld4dd_r },
325
+ { gen_helper_sve_ld1bds_r, NULL, NULL, NULL },
326
+ { gen_helper_sve_ld1bss_r, NULL, NULL, NULL },
327
+ { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL },
328
+ { gen_helper_sve_ld1dd_le_r, gen_helper_sve_ld2dd_le_r,
329
+ gen_helper_sve_ld3dd_le_r, gen_helper_sve_ld4dd_le_r } },
330
+
331
+ /* Big-endian */
332
+ { { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r,
333
+ gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r },
334
+ { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL },
335
+ { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL },
336
+ { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL },
337
+
338
+ { gen_helper_sve_ld1sds_be_r, NULL, NULL, NULL },
339
+ { gen_helper_sve_ld1hh_be_r, gen_helper_sve_ld2hh_be_r,
340
+ gen_helper_sve_ld3hh_be_r, gen_helper_sve_ld4hh_be_r },
341
+ { gen_helper_sve_ld1hsu_be_r, NULL, NULL, NULL },
342
+ { gen_helper_sve_ld1hdu_be_r, NULL, NULL, NULL },
343
+
344
+ { gen_helper_sve_ld1hds_be_r, NULL, NULL, NULL },
345
+ { gen_helper_sve_ld1hss_be_r, NULL, NULL, NULL },
346
+ { gen_helper_sve_ld1ss_be_r, gen_helper_sve_ld2ss_be_r,
347
+ gen_helper_sve_ld3ss_be_r, gen_helper_sve_ld4ss_be_r },
348
+ { gen_helper_sve_ld1sdu_be_r, NULL, NULL, NULL },
349
+
350
+ { gen_helper_sve_ld1bds_r, NULL, NULL, NULL },
351
+ { gen_helper_sve_ld1bss_r, NULL, NULL, NULL },
352
+ { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL },
353
+ { gen_helper_sve_ld1dd_be_r, gen_helper_sve_ld2dd_be_r,
354
+ gen_helper_sve_ld3dd_be_r, gen_helper_sve_ld4dd_be_r } }
355
};
356
- gen_helper_gvec_mem *fn = fns[dtype][nreg];
357
+ gen_helper_gvec_mem *fn = fns[s->be_data == MO_BE][dtype][nreg];
358
359
/* While there are holes in the table, they are not
360
* accessible via the instruction encoding.
361
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
362
363
static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
364
{
365
- static gen_helper_gvec_mem * const fns[16] = {
366
- gen_helper_sve_ldff1bb_r,
367
- gen_helper_sve_ldff1bhu_r,
368
- gen_helper_sve_ldff1bsu_r,
369
- gen_helper_sve_ldff1bdu_r,
370
+ static gen_helper_gvec_mem * const fns[2][16] = {
371
+ /* Little-endian */
372
+ { gen_helper_sve_ldff1bb_r,
373
+ gen_helper_sve_ldff1bhu_r,
374
+ gen_helper_sve_ldff1bsu_r,
375
+ gen_helper_sve_ldff1bdu_r,
376
377
- gen_helper_sve_ldff1sds_r,
378
- gen_helper_sve_ldff1hh_r,
379
- gen_helper_sve_ldff1hsu_r,
380
- gen_helper_sve_ldff1hdu_r,
381
+ gen_helper_sve_ldff1sds_le_r,
382
+ gen_helper_sve_ldff1hh_le_r,
383
+ gen_helper_sve_ldff1hsu_le_r,
384
+ gen_helper_sve_ldff1hdu_le_r,
385
386
- gen_helper_sve_ldff1hds_r,
387
- gen_helper_sve_ldff1hss_r,
388
- gen_helper_sve_ldff1ss_r,
389
- gen_helper_sve_ldff1sdu_r,
390
+ gen_helper_sve_ldff1hds_le_r,
391
+ gen_helper_sve_ldff1hss_le_r,
392
+ gen_helper_sve_ldff1ss_le_r,
393
+ gen_helper_sve_ldff1sdu_le_r,
394
395
- gen_helper_sve_ldff1bds_r,
396
- gen_helper_sve_ldff1bss_r,
397
- gen_helper_sve_ldff1bhs_r,
398
- gen_helper_sve_ldff1dd_r,
399
+ gen_helper_sve_ldff1bds_r,
400
+ gen_helper_sve_ldff1bss_r,
401
+ gen_helper_sve_ldff1bhs_r,
402
+ gen_helper_sve_ldff1dd_le_r },
403
+
404
+ /* Big-endian */
405
+ { gen_helper_sve_ldff1bb_r,
406
+ gen_helper_sve_ldff1bhu_r,
407
+ gen_helper_sve_ldff1bsu_r,
408
+ gen_helper_sve_ldff1bdu_r,
409
+
410
+ gen_helper_sve_ldff1sds_be_r,
411
+ gen_helper_sve_ldff1hh_be_r,
412
+ gen_helper_sve_ldff1hsu_be_r,
413
+ gen_helper_sve_ldff1hdu_be_r,
414
+
415
+ gen_helper_sve_ldff1hds_be_r,
416
+ gen_helper_sve_ldff1hss_be_r,
417
+ gen_helper_sve_ldff1ss_be_r,
418
+ gen_helper_sve_ldff1sdu_be_r,
419
+
420
+ gen_helper_sve_ldff1bds_r,
421
+ gen_helper_sve_ldff1bss_r,
422
+ gen_helper_sve_ldff1bhs_r,
423
+ gen_helper_sve_ldff1dd_be_r },
424
};
425
426
if (sve_access_check(s)) {
427
TCGv_i64 addr = new_tmp_a64(s);
428
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
429
tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
430
- do_mem_zpa(s, a->rd, a->pg, addr, fns[a->dtype]);
431
+ do_mem_zpa(s, a->rd, a->pg, addr, fns[s->be_data == MO_BE][a->dtype]);
432
}
433
return true;
434
}
435
436
static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
437
{
438
- static gen_helper_gvec_mem * const fns[16] = {
439
- gen_helper_sve_ldnf1bb_r,
440
- gen_helper_sve_ldnf1bhu_r,
441
- gen_helper_sve_ldnf1bsu_r,
442
- gen_helper_sve_ldnf1bdu_r,
443
+ static gen_helper_gvec_mem * const fns[2][16] = {
444
+ /* Little-endian */
445
+ { gen_helper_sve_ldnf1bb_r,
446
+ gen_helper_sve_ldnf1bhu_r,
447
+ gen_helper_sve_ldnf1bsu_r,
448
+ gen_helper_sve_ldnf1bdu_r,
449
450
- gen_helper_sve_ldnf1sds_r,
451
- gen_helper_sve_ldnf1hh_r,
452
- gen_helper_sve_ldnf1hsu_r,
453
- gen_helper_sve_ldnf1hdu_r,
454
+ gen_helper_sve_ldnf1sds_le_r,
455
+ gen_helper_sve_ldnf1hh_le_r,
456
+ gen_helper_sve_ldnf1hsu_le_r,
457
+ gen_helper_sve_ldnf1hdu_le_r,
458
459
- gen_helper_sve_ldnf1hds_r,
460
- gen_helper_sve_ldnf1hss_r,
461
- gen_helper_sve_ldnf1ss_r,
462
- gen_helper_sve_ldnf1sdu_r,
463
+ gen_helper_sve_ldnf1hds_le_r,
464
+ gen_helper_sve_ldnf1hss_le_r,
465
+ gen_helper_sve_ldnf1ss_le_r,
466
+ gen_helper_sve_ldnf1sdu_le_r,
467
468
- gen_helper_sve_ldnf1bds_r,
469
- gen_helper_sve_ldnf1bss_r,
470
- gen_helper_sve_ldnf1bhs_r,
471
- gen_helper_sve_ldnf1dd_r,
472
+ gen_helper_sve_ldnf1bds_r,
473
+ gen_helper_sve_ldnf1bss_r,
474
+ gen_helper_sve_ldnf1bhs_r,
475
+ gen_helper_sve_ldnf1dd_le_r },
476
+
477
+ /* Big-endian */
478
+ { gen_helper_sve_ldnf1bb_r,
479
+ gen_helper_sve_ldnf1bhu_r,
480
+ gen_helper_sve_ldnf1bsu_r,
481
+ gen_helper_sve_ldnf1bdu_r,
482
+
483
+ gen_helper_sve_ldnf1sds_be_r,
484
+ gen_helper_sve_ldnf1hh_be_r,
485
+ gen_helper_sve_ldnf1hsu_be_r,
486
+ gen_helper_sve_ldnf1hdu_be_r,
487
+
488
+ gen_helper_sve_ldnf1hds_be_r,
489
+ gen_helper_sve_ldnf1hss_be_r,
490
+ gen_helper_sve_ldnf1ss_be_r,
491
+ gen_helper_sve_ldnf1sdu_be_r,
492
+
493
+ gen_helper_sve_ldnf1bds_r,
494
+ gen_helper_sve_ldnf1bss_r,
495
+ gen_helper_sve_ldnf1bhs_r,
496
+ gen_helper_sve_ldnf1dd_be_r },
497
};
498
499
if (sve_access_check(s)) {
500
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
501
TCGv_i64 addr = new_tmp_a64(s);
502
503
tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), off);
504
- do_mem_zpa(s, a->rd, a->pg, addr, fns[a->dtype]);
505
+ do_mem_zpa(s, a->rd, a->pg, addr, fns[s->be_data == MO_BE][a->dtype]);
506
}
507
return true;
508
}
509
510
static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
511
{
512
- static gen_helper_gvec_mem * const fns[4] = {
513
- gen_helper_sve_ld1bb_r, gen_helper_sve_ld1hh_r,
514
- gen_helper_sve_ld1ss_r, gen_helper_sve_ld1dd_r,
515
+ static gen_helper_gvec_mem * const fns[2][4] = {
516
+ { gen_helper_sve_ld1bb_r, gen_helper_sve_ld1hh_le_r,
517
+ gen_helper_sve_ld1ss_le_r, gen_helper_sve_ld1dd_le_r },
518
+ { gen_helper_sve_ld1bb_r, gen_helper_sve_ld1hh_be_r,
519
+ gen_helper_sve_ld1ss_be_r, gen_helper_sve_ld1dd_be_r },
520
};
521
unsigned vsz = vec_full_reg_size(s);
522
TCGv_ptr t_pg;
523
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
524
t_pg = tcg_temp_new_ptr();
525
tcg_gen_addi_ptr(t_pg, cpu_env, poff);
526
527
- fns[msz](cpu_env, t_pg, addr, desc);
528
+ fns[s->be_data == MO_BE][msz](cpu_env, t_pg, addr, desc);
529
530
tcg_temp_free_ptr(t_pg);
531
tcg_temp_free_i32(desc);
532
--
103
--
533
2.19.0
104
2.20.1
534
105
535
106
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
SVE vector length can change when changing EL, or when writing
3
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
4
to one of the ZCR_ELn registers.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
For correctness, our implementation requires that predicate bits
6
Message-id: 20200423073358.27155-4-philmd@redhat.com
7
that are inaccessible are never set. Which means noticing length
8
changes and zeroing the appropriate register bits.
9
10
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20181005175350.30752-5-richard.henderson@linaro.org
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
8
---
16
target/arm/cpu.h | 4 ++
9
target/arm/cpu.c | 8 +++-----
17
target/arm/cpu64.c | 42 -------------
10
target/arm/cpu64.c | 8 +++-----
18
target/arm/helper.c | 133 +++++++++++++++++++++++++++++++++++++----
11
2 files changed, 6 insertions(+), 10 deletions(-)
19
target/arm/op_helper.c | 1 +
20
4 files changed, 125 insertions(+), 55 deletions(-)
21
12
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
15
--- a/target/arm/cpu.c
25
+++ b/target/arm/cpu.h
16
+++ b/target/arm/cpu.c
26
@@ -XXX,XX +XXX,XX @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
17
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
27
int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
18
{ .name = "any", .initfn = arm_max_initfn },
28
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
29
void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
30
+void aarch64_sve_change_el(CPUARMState *env, int old_el, int new_el);
31
+#else
32
+static inline void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) { }
33
+static inline void aarch64_sve_change_el(CPUARMState *env, int o, int n) { }
34
#endif
19
#endif
35
20
#endif
36
target_ulong do_arm_semihosting(CPUARMState *env);
21
- { .name = NULL }
22
};
23
24
static Property arm_cpu_properties[] = {
25
@@ -XXX,XX +XXX,XX @@ static const TypeInfo idau_interface_type_info = {
26
27
static void arm_cpu_register_types(void)
28
{
29
- const ARMCPUInfo *info = arm_cpus;
30
+ size_t i;
31
32
type_register_static(&arm_cpu_type_info);
33
type_register_static(&idau_interface_type_info);
34
35
- while (info->name) {
36
- arm_cpu_register(info);
37
- info++;
38
+ for (i = 0; i < ARRAY_SIZE(arm_cpus); ++i) {
39
+ arm_cpu_register(&arm_cpus[i]);
40
}
41
42
#ifdef CONFIG_KVM
37
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
43
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
38
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/cpu64.c
45
--- a/target/arm/cpu64.c
40
+++ b/target/arm/cpu64.c
46
+++ b/target/arm/cpu64.c
41
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_register_types(void)
47
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo aarch64_cpus[] = {
48
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
49
{ .name = "cortex-a72", .initfn = aarch64_a72_initfn },
50
{ .name = "max", .initfn = aarch64_max_initfn },
51
- { .name = NULL }
52
};
53
54
static bool aarch64_cpu_get_aarch64(Object *obj, Error **errp)
55
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aarch64_cpu_type_info = {
56
57
static void aarch64_cpu_register_types(void)
58
{
59
- const ARMCPUInfo *info = aarch64_cpus;
60
+ size_t i;
61
62
type_register_static(&aarch64_cpu_type_info);
63
64
- while (info->name) {
65
- aarch64_cpu_register(info);
66
- info++;
67
+ for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) {
68
+ aarch64_cpu_register(&aarch64_cpus[i]);
69
}
42
}
70
}
43
71
44
type_init(aarch64_cpu_register_types)
45
-
46
-/* The manual says that when SVE is enabled and VQ is widened the
47
- * implementation is allowed to zero the previously inaccessible
48
- * portion of the registers. The corollary to that is that when
49
- * SVE is enabled and VQ is narrowed we are also allowed to zero
50
- * the now inaccessible portion of the registers.
51
- *
52
- * The intent of this is that no predicate bit beyond VQ is ever set.
53
- * Which means that some operations on predicate registers themselves
54
- * may operate on full uint64_t or even unrolled across the maximum
55
- * uint64_t[4]. Performing 4 bits of host arithmetic unconditionally
56
- * may well be cheaper than conditionals to restrict the operation
57
- * to the relevant portion of a uint16_t[16].
58
- *
59
- * TODO: Need to call this for changes to the real system registers
60
- * and EL state changes.
61
- */
62
-void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
63
-{
64
- int i, j;
65
- uint64_t pmask;
66
-
67
- assert(vq >= 1 && vq <= ARM_MAX_VQ);
68
- assert(vq <= arm_env_get_cpu(env)->sve_max_vq);
69
-
70
- /* Zap the high bits of the zregs. */
71
- for (i = 0; i < 32; i++) {
72
- memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq));
73
- }
74
-
75
- /* Zap the high bits of the pregs and ffr. */
76
- pmask = 0;
77
- if (vq & 3) {
78
- pmask = ~(-1ULL << (16 * (vq & 3)));
79
- }
80
- for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) {
81
- for (i = 0; i < 17; ++i) {
82
- env->vfp.pregs[i].p[j] &= pmask;
83
- }
84
- pmask = 0;
85
- }
86
-}
87
diff --git a/target/arm/helper.c b/target/arm/helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/helper.c
90
+++ b/target/arm/helper.c
91
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env, int el)
92
return 0;
93
}
94
95
+/*
96
+ * Given that SVE is enabled, return the vector length for EL.
97
+ */
98
+static uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
99
+{
100
+ ARMCPU *cpu = arm_env_get_cpu(env);
101
+ uint32_t zcr_len = cpu->sve_max_vq - 1;
102
+
103
+ if (el <= 1) {
104
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
105
+ }
106
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
107
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
108
+ }
109
+ if (el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
110
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
111
+ }
112
+ return zcr_len;
113
+}
114
+
115
static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
uint64_t value)
117
{
118
+ int cur_el = arm_current_el(env);
119
+ int old_len = sve_zcr_len_for_el(env, cur_el);
120
+ int new_len;
121
+
122
/* Bits other than [3:0] are RAZ/WI. */
123
raw_write(env, ri, value & 0xf);
124
+
125
+ /*
126
+ * Because we arrived here, we know both FP and SVE are enabled;
127
+ * otherwise we would have trapped access to the ZCR_ELn register.
128
+ */
129
+ new_len = sve_zcr_len_for_el(env, cur_el);
130
+ if (new_len < old_len) {
131
+ aarch64_sve_narrow_vq(env, new_len + 1);
132
+ }
133
}
134
135
static const ARMCPRegInfo zcr_el1_reginfo = {
136
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
137
unsigned int new_el = env->exception.target_el;
138
target_ulong addr = env->cp15.vbar_el[new_el];
139
unsigned int new_mode = aarch64_pstate_mode(new_el, true);
140
+ unsigned int cur_el = arm_current_el(env);
141
142
- if (arm_current_el(env) < new_el) {
143
+ aarch64_sve_change_el(env, cur_el, new_el);
144
+
145
+ if (cur_el < new_el) {
146
/* Entry vector offset depends on whether the implemented EL
147
* immediately lower than the target level is using AArch32 or AArch64
148
*/
149
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
150
if (sve_el != 0 && fp_el == 0) {
151
zcr_len = 0;
152
} else {
153
- ARMCPU *cpu = arm_env_get_cpu(env);
154
-
155
- zcr_len = cpu->sve_max_vq - 1;
156
- if (current_el <= 1) {
157
- zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
158
- }
159
- if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
160
- zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
161
- }
162
- if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
163
- zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
164
- }
165
+ zcr_len = sve_zcr_len_for_el(env, current_el);
166
}
167
flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
168
flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
169
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
170
*pflags = flags;
171
*cs_base = 0;
172
}
173
+
174
+#ifdef TARGET_AARCH64
175
+/*
176
+ * The manual says that when SVE is enabled and VQ is widened the
177
+ * implementation is allowed to zero the previously inaccessible
178
+ * portion of the registers. The corollary to that is that when
179
+ * SVE is enabled and VQ is narrowed we are also allowed to zero
180
+ * the now inaccessible portion of the registers.
181
+ *
182
+ * The intent of this is that no predicate bit beyond VQ is ever set.
183
+ * Which means that some operations on predicate registers themselves
184
+ * may operate on full uint64_t or even unrolled across the maximum
185
+ * uint64_t[4]. Performing 4 bits of host arithmetic unconditionally
186
+ * may well be cheaper than conditionals to restrict the operation
187
+ * to the relevant portion of a uint16_t[16].
188
+ */
189
+void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
190
+{
191
+ int i, j;
192
+ uint64_t pmask;
193
+
194
+ assert(vq >= 1 && vq <= ARM_MAX_VQ);
195
+ assert(vq <= arm_env_get_cpu(env)->sve_max_vq);
196
+
197
+ /* Zap the high bits of the zregs. */
198
+ for (i = 0; i < 32; i++) {
199
+ memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq));
200
+ }
201
+
202
+ /* Zap the high bits of the pregs and ffr. */
203
+ pmask = 0;
204
+ if (vq & 3) {
205
+ pmask = ~(-1ULL << (16 * (vq & 3)));
206
+ }
207
+ for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) {
208
+ for (i = 0; i < 17; ++i) {
209
+ env->vfp.pregs[i].p[j] &= pmask;
210
+ }
211
+ pmask = 0;
212
+ }
213
+}
214
+
215
+/*
216
+ * Notice a change in SVE vector size when changing EL.
217
+ */
218
+void aarch64_sve_change_el(CPUARMState *env, int old_el, int new_el)
219
+{
220
+ int old_len, new_len;
221
+
222
+ /* Nothing to do if no SVE. */
223
+ if (!arm_feature(env, ARM_FEATURE_SVE)) {
224
+ return;
225
+ }
226
+
227
+ /* Nothing to do if FP is disabled in either EL. */
228
+ if (fp_exception_el(env, old_el) || fp_exception_el(env, new_el)) {
229
+ return;
230
+ }
231
+
232
+ /*
233
+ * DDI0584A.d sec 3.2: "If SVE instructions are disabled or trapped
234
+ * at ELx, or not available because the EL is in AArch32 state, then
235
+ * for all purposes other than a direct read, the ZCR_ELx.LEN field
236
+ * has an effective value of 0".
237
+ *
238
+ * Consider EL2 (aa64, vq=4) -> EL0 (aa32) -> EL1 (aa64, vq=0).
239
+ * If we ignore aa32 state, we would fail to see the vq4->vq0 transition
240
+ * from EL2->EL1. Thus we go ahead and narrow when entering aa32 so that
241
+ * we already have the correct register contents when encountering the
242
+ * vq0->vq0 transition between EL0->EL1.
243
+ */
244
+ old_len = (arm_el_is_aa64(env, old_el) && !sve_exception_el(env, old_el)
245
+ ? sve_zcr_len_for_el(env, old_el) : 0);
246
+ new_len = (arm_el_is_aa64(env, new_el) && !sve_exception_el(env, new_el)
247
+ ? sve_zcr_len_for_el(env, new_el) : 0);
248
+
249
+ /* When changing vector length, clear inaccessible state. */
250
+ if (new_len < old_len) {
251
+ aarch64_sve_narrow_vq(env, new_len + 1);
252
+ }
253
+}
254
+#endif
255
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
256
index XXXXXXX..XXXXXXX 100644
257
--- a/target/arm/op_helper.c
258
+++ b/target/arm/op_helper.c
259
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env)
260
"AArch64 EL%d PC 0x%" PRIx64 "\n",
261
cur_el, new_el, env->pc);
262
}
263
+ aarch64_sve_change_el(env, cur_el, new_el);
264
265
qemu_mutex_lock_iothread();
266
arm_call_el_change_hook(arm_env_get_cpu(env));
267
--
72
--
268
2.19.0
73
2.20.1
269
74
270
75
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Use the existing helpers to determine if (1) the fpu is enabled,
3
We will move this code in the next commit. Clean it up
4
(2) sve state is enabled, and (3) the current sve vector length.
4
first to avoid checkpatch.pl errors.
5
5
6
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200423073358.27155-5-philmd@redhat.com
9
Message-id: 20181005175350.30752-6-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/cpu.h | 4 ++++
11
target/arm/cpu.c | 9 ++++++---
13
target/arm/helper.c | 6 +++---
12
1 file changed, 6 insertions(+), 3 deletions(-)
14
target/arm/translate-a64.c | 8 ++++++--
15
3 files changed, 13 insertions(+), 5 deletions(-)
16
13
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
16
--- a/target/arm/cpu.c
20
+++ b/target/arm/cpu.h
17
+++ b/target/arm/cpu.c
21
@@ -XXX,XX +XXX,XX @@ target_ulong do_arm_semihosting(CPUARMState *env);
18
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
22
void aarch64_sync_32_to_64(CPUARMState *env);
19
CPUARMState *env = &cpu->env;
23
void aarch64_sync_64_to_32(CPUARMState *env);
20
bool ret = false;
24
21
25
+int fp_exception_el(CPUARMState *env, int cur_el);
22
- /* ARMv7-M interrupt masking works differently than -A or -R.
26
+int sve_exception_el(CPUARMState *env, int cur_el);
23
+ /*
27
+uint32_t sve_zcr_len_for_el(CPUARMState *env, int el);
24
+ * ARMv7-M interrupt masking works differently than -A or -R.
28
+
25
* There is no FIQ/IRQ distinction. Instead of I and F bits
29
static inline bool is_a64(CPUARMState *env)
26
* masking FIQ and IRQ interrupts, an exception is taken only
27
* if it is higher priority than the current execution priority
28
@@ -XXX,XX +XXX,XX @@ static void arm1026_initfn(Object *obj)
29
static void arm1136_r2_initfn(Object *obj)
30
{
30
{
31
return env->aarch64;
31
ARMCPU *cpu = ARM_CPU(obj);
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
32
- /* What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an
33
index XXXXXXX..XXXXXXX 100644
33
+ /*
34
--- a/target/arm/helper.c
34
+ * What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an
35
+++ b/target/arm/helper.c
35
* older core than plain "arm1136". In particular this does not
36
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
36
* have the v6K features.
37
* take care of raising that exception.
37
* These ID register values are correct for 1136 but may be wrong
38
* C.f. the ARM pseudocode function CheckSVEEnabled.
38
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
39
*/
39
{ .name = "arm926", .initfn = arm926_initfn },
40
-static int sve_exception_el(CPUARMState *env, int el)
40
{ .name = "arm946", .initfn = arm946_initfn },
41
+int sve_exception_el(CPUARMState *env, int el)
41
{ .name = "arm1026", .initfn = arm1026_initfn },
42
{
42
- /* What QEMU calls "arm1136-r2" is actually the 1136 r0p2, i.e. an
43
#ifndef CONFIG_USER_ONLY
43
+ /*
44
if (el <= 1) {
44
+ * What QEMU calls "arm1136-r2" is actually the 1136 r0p2, i.e. an
45
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env, int el)
45
* older core than plain "arm1136". In particular this does not
46
/*
46
* have the v6K features.
47
* Given that SVE is enabled, return the vector length for EL.
47
*/
48
*/
49
-static uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
50
+uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
51
{
52
ARMCPU *cpu = arm_env_get_cpu(env);
53
uint32_t zcr_len = cpu->sve_max_vq - 1;
54
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
55
/* Return the exception level to which FP-disabled exceptions should
56
* be taken, or 0 if FP is enabled.
57
*/
58
-static int fp_exception_el(CPUARMState *env, int cur_el)
59
+int fp_exception_el(CPUARMState *env, int cur_el)
60
{
61
#ifndef CONFIG_USER_ONLY
62
int fpen;
63
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-a64.c
66
+++ b/target/arm/translate-a64.c
67
@@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
68
cpu_fprintf(f, "\n");
69
return;
70
}
71
+ if (fp_exception_el(env, el) != 0) {
72
+ cpu_fprintf(f, " FPU disabled\n");
73
+ return;
74
+ }
75
cpu_fprintf(f, " FPCR=%08x FPSR=%08x\n",
76
vfp_get_fpcr(env), vfp_get_fpsr(env));
77
78
- if (arm_feature(env, ARM_FEATURE_SVE)) {
79
- int j, zcr_len = env->vfp.zcr_el[1] & 0xf; /* fix for system mode */
80
+ if (arm_feature(env, ARM_FEATURE_SVE) && sve_exception_el(env, el) == 0) {
81
+ int j, zcr_len = sve_zcr_len_for_el(env, el);
82
83
for (i = 0; i <= FFR_PRED_NUM; i++) {
84
bool eol;
85
--
48
--
86
2.19.0
49
2.20.1
87
50
88
51
diff view generated by jsdifflib
1
Add some comments to the Thumb decoder indicating what bits
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
of the instruction have been decoded at various points in
3
the code.
4
2
5
This is not an exhaustive set of comments; we're gradually
3
Allow name wildcards in qemu_fdt_node_path(). This is useful
6
adding comments as we work with particular bits of the code.
4
to find all nodes with a given compatibility string.
7
5
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20200423121114.4274-2-edgar.iglesias@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20181002163556.10279-6-peter.maydell@linaro.org
12
---
10
---
13
target/arm/translate.c | 20 +++++++++++++++++---
11
include/sysemu/device_tree.h | 3 +++
14
1 file changed, 17 insertions(+), 3 deletions(-)
12
device_tree.c | 2 +-
13
2 files changed, 4 insertions(+), 1 deletion(-)
15
14
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
17
--- a/include/sysemu/device_tree.h
19
+++ b/target/arm/translate.c
18
+++ b/include/sysemu/device_tree.h
20
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ void *load_device_tree_from_sysfs(void);
21
tmp2 = load_reg(s, rm);
20
* NULL. If there is no error but no matching node was found, the
22
if ((insn & 0x70) != 0)
21
* returned array contains a single element equal to NULL. If an error
23
goto illegal_op;
22
* was encountered when parsing the blob, the function returns NULL
24
+ /*
23
+ *
25
+ * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
24
+ * @name may be NULL to wildcard names and only match compatibility
26
+ * - MOV, MOVS (register-shifted register), flagsetting
25
+ * strings.
27
+ */
26
*/
28
op = (insn >> 21) & 3;
27
char **qemu_fdt_node_path(void *fdt, const char *name, char *compat,
29
logic_cc = (insn & (1 << 20)) != 0;
28
Error **errp);
30
gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
29
diff --git a/device_tree.c b/device_tree.c
31
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
30
index XXXXXXX..XXXXXXX 100644
32
rd = insn & 7;
31
--- a/device_tree.c
33
op = (insn >> 11) & 3;
32
+++ b/device_tree.c
34
if (op == 3) {
33
@@ -XXX,XX +XXX,XX @@ char **qemu_fdt_node_path(void *fdt, const char *name, char *compat,
35
- /* add/subtract */
34
offset = len;
36
+ /*
37
+ * 0b0001_1xxx_xxxx_xxxx
38
+ * - Add, subtract (three low registers)
39
+ * - Add, subtract (two low registers and immediate)
40
+ */
41
rn = (insn >> 3) & 7;
42
tmp = load_reg(s, rn);
43
if (insn & (1 << 10)) {
44
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
45
}
46
break;
47
case 2: case 3:
48
- /* arithmetic large immediate */
49
+ /*
50
+ * 0b001x_xxxx_xxxx_xxxx
51
+ * - Add, subtract, compare, move (one low register and immediate)
52
+ */
53
op = (insn >> 11) & 3;
54
rd = (insn >> 8) & 0x7;
55
if (op == 0) { /* mov */
56
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
57
break;
35
break;
58
}
36
}
59
37
- if (!strcmp(iter_name, name)) {
60
- /* data processing register */
38
+ if (!name || !strcmp(iter_name, name)) {
61
+ /*
39
char *path;
62
+ * 0b0100_00xx_xxxx_xxxx
40
63
+ * - Data-processing (two low registers)
41
path = g_malloc(path_len);
64
+ */
65
rd = insn & 7;
66
rm = (insn >> 3) & 7;
67
op = (insn >> 6) & 0xf;
68
--
42
--
69
2.19.0
43
2.20.1
70
44
71
45
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
The parameter of kvm_arm_init_cpreg_list() is ARMCPU instead of
3
Make compat in qemu_fdt_node_path() const char *.
4
CPUState, so correct the note to make it match the code.
5
4
6
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Message-id: 1538069046-5757-1-git-send-email-gengdongjiu@huawei.com
6
Message-id: 20200423121114.4274-3-edgar.iglesias@gmail.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
target/arm/kvm_arm.h | 4 ++--
10
include/sysemu/device_tree.h | 2 +-
12
target/arm/kvm.c | 2 +-
11
device_tree.c | 2 +-
13
2 files changed, 3 insertions(+), 3 deletions(-)
12
2 files changed, 2 insertions(+), 2 deletions(-)
14
13
15
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
14
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/kvm_arm.h
16
--- a/include/sysemu/device_tree.h
18
+++ b/target/arm/kvm_arm.h
17
+++ b/include/sysemu/device_tree.h
19
@@ -XXX,XX +XXX,XX @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
18
@@ -XXX,XX +XXX,XX @@ void *load_device_tree_from_sysfs(void);
19
* @name may be NULL to wildcard names and only match compatibility
20
* strings.
21
*/
22
-char **qemu_fdt_node_path(void *fdt, const char *name, char *compat,
23
+char **qemu_fdt_node_path(void *fdt, const char *name, const char *compat,
24
Error **errp);
20
25
21
/**
26
/**
22
* kvm_arm_init_cpreg_list:
27
diff --git a/device_tree.c b/device_tree.c
23
- * @cs: CPUState
24
+ * @cpu: ARMCPU
25
*
26
- * Initialize the CPUState's cpreg list according to the kernel's
27
+ * Initialize the ARMCPU cpreg list according to the kernel's
28
* definition of what CPU registers it knows about (and throw away
29
* the previous TCG-created cpreg list).
30
*
31
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
32
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/kvm.c
29
--- a/device_tree.c
34
+++ b/target/arm/kvm.c
30
+++ b/device_tree.c
35
@@ -XXX,XX +XXX,XX @@ static int compare_u64(const void *a, const void *b)
31
@@ -XXX,XX +XXX,XX @@ char **qemu_fdt_node_unit_path(void *fdt, const char *name, Error **errp)
36
return 0;
32
return path_array;
37
}
33
}
38
34
39
-/* Initialize the CPUState's cpreg list according to the kernel's
35
-char **qemu_fdt_node_path(void *fdt, const char *name, char *compat,
40
+/* Initialize the ARMCPU cpreg list according to the kernel's
36
+char **qemu_fdt_node_path(void *fdt, const char *name, const char *compat,
41
* definition of what CPU registers it knows about (and throw away
37
Error **errp)
42
* the previous TCG-created cpreg list).
38
{
43
*/
39
int offset, len, ret;
44
--
40
--
45
2.19.0
41
2.20.1
46
42
47
43
diff view generated by jsdifflib
Deleted patch
1
A cut-and-paste error meant we were reading r4 from the v8M
2
callee-saves exception stack frame twice. This is harmless
3
since it just meant we did two memory accesses to the same
4
location, but it's unnecessary. Delete it.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181002150304.2287-1-peter.maydell@linaro.org
10
---
11
target/arm/helper.c | 1 -
12
1 file changed, 1 deletion(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
19
}
20
21
pop_ok = pop_ok &&
22
- v7m_stack_read(cpu, &env->regs[4], frameptr + 0x8, mmu_idx) &&
23
v7m_stack_read(cpu, &env->regs[4], frameptr + 0x8, mmu_idx) &&
24
v7m_stack_read(cpu, &env->regs[5], frameptr + 0xc, mmu_idx) &&
25
v7m_stack_read(cpu, &env->regs[6], frameptr + 0x10, mmu_idx) &&
26
--
27
2.19.0
28
29
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
Use the same *_tlb primitives as we use for ld1.
3
Move arm_boot_info into XlnxZCU102.
4
4
5
For linux-user, this hoists the set of helper_retaddr. For softmmu,
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
hoists the computation of the current mmu_idx outside the loop,
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
fixes the endianness problem, and moves the main loop out of a
7
Message-id: 20200423121114.4274-4-edgar.iglesias@gmail.com
8
macro and into an inlined function.
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20181005175350.30752-9-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
9
---
16
target/arm/sve_helper.c | 210 ++++++++++++++++++++++------------------
10
hw/arm/xlnx-zcu102.c | 9 +++++----
17
1 file changed, 117 insertions(+), 93 deletions(-)
11
1 file changed, 5 insertions(+), 4 deletions(-)
18
12
19
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
13
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/sve_helper.c
15
--- a/hw/arm/xlnx-zcu102.c
22
+++ b/target/arm/sve_helper.c
16
+++ b/hw/arm/xlnx-zcu102.c
23
@@ -XXX,XX +XXX,XX @@ DO_LD1_2(ld1dd, 3, 3)
17
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZCU102 {
24
#undef DO_LD1_1
18
25
#undef DO_LD1_2
19
bool secure;
26
20
bool virt;
27
-#define DO_LD2(NAME, FN, TYPEE, TYPEM, H) \
28
-void HELPER(NAME)(CPUARMState *env, void *vg, \
29
- target_ulong addr, uint32_t desc) \
30
-{ \
31
- intptr_t i, oprsz = simd_oprsz(desc); \
32
- intptr_t ra = GETPC(); \
33
- unsigned rd = simd_data(desc); \
34
- void *d1 = &env->vfp.zregs[rd]; \
35
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
36
- for (i = 0; i < oprsz; ) { \
37
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
38
- do { \
39
- TYPEM m1 = 0, m2 = 0; \
40
- if (pg & 1) { \
41
- m1 = FN(env, addr, ra); \
42
- m2 = FN(env, addr + sizeof(TYPEM), ra); \
43
- } \
44
- *(TYPEE *)(d1 + H(i)) = m1; \
45
- *(TYPEE *)(d2 + H(i)) = m2; \
46
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
47
- addr += 2 * sizeof(TYPEM); \
48
- } while (i & 15); \
49
- } \
50
+/*
51
+ * Common helpers for all contiguous 2,3,4-register predicated loads.
52
+ */
53
+static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr,
54
+ uint32_t desc, int size, uintptr_t ra,
55
+ sve_ld1_tlb_fn *tlb_fn)
56
+{
57
+ const int mmu_idx = cpu_mmu_index(env, false);
58
+ intptr_t i, oprsz = simd_oprsz(desc);
59
+ unsigned rd = simd_data(desc);
60
+ ARMVectorReg scratch[2] = { };
61
+
21
+
62
+ set_helper_retaddr(ra);
22
+ struct arm_boot_info binfo;
63
+ for (i = 0; i < oprsz; ) {
23
} XlnxZCU102;
64
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
24
65
+ do {
25
#define TYPE_ZCU102_MACHINE MACHINE_TYPE_NAME("xlnx-zcu102")
66
+ if (pg & 1) {
26
#define ZCU102_MACHINE(obj) \
67
+ tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
27
OBJECT_CHECK(XlnxZCU102, (obj), TYPE_ZCU102_MACHINE)
68
+ tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
28
69
+ }
29
-static struct arm_boot_info xlnx_zcu102_binfo;
70
+ i += size, pg >>= size;
30
71
+ addr += 2 * size;
31
static bool zcu102_get_secure(Object *obj, Error **errp)
72
+ } while (i & 15);
32
{
73
+ }
33
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
74
+ set_helper_retaddr(0);
34
75
+
35
/* TODO create and connect IDE devices for ide_drive_get() */
76
+ /* Wait until all exceptions have been raised to write back. */
36
77
+ memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz);
37
- xlnx_zcu102_binfo.ram_size = ram_size;
78
+ memcpy(&env->vfp.zregs[(rd + 1) & 31], &scratch[1], oprsz);
38
- xlnx_zcu102_binfo.loader_start = 0;
39
- arm_load_kernel(s->soc.boot_cpu_ptr, machine, &xlnx_zcu102_binfo);
40
+ s->binfo.ram_size = ram_size;
41
+ s->binfo.loader_start = 0;
42
+ arm_load_kernel(s->soc.boot_cpu_ptr, machine, &s->binfo);
79
}
43
}
80
44
81
-#define DO_LD3(NAME, FN, TYPEE, TYPEM, H) \
45
static void xlnx_zcu102_machine_instance_init(Object *obj)
82
-void HELPER(NAME)(CPUARMState *env, void *vg, \
83
- target_ulong addr, uint32_t desc) \
84
-{ \
85
- intptr_t i, oprsz = simd_oprsz(desc); \
86
- intptr_t ra = GETPC(); \
87
- unsigned rd = simd_data(desc); \
88
- void *d1 = &env->vfp.zregs[rd]; \
89
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
90
- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
91
- for (i = 0; i < oprsz; ) { \
92
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
93
- do { \
94
- TYPEM m1 = 0, m2 = 0, m3 = 0; \
95
- if (pg & 1) { \
96
- m1 = FN(env, addr, ra); \
97
- m2 = FN(env, addr + sizeof(TYPEM), ra); \
98
- m3 = FN(env, addr + 2 * sizeof(TYPEM), ra); \
99
- } \
100
- *(TYPEE *)(d1 + H(i)) = m1; \
101
- *(TYPEE *)(d2 + H(i)) = m2; \
102
- *(TYPEE *)(d3 + H(i)) = m3; \
103
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
104
- addr += 3 * sizeof(TYPEM); \
105
- } while (i & 15); \
106
- } \
107
+static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr,
108
+ uint32_t desc, int size, uintptr_t ra,
109
+ sve_ld1_tlb_fn *tlb_fn)
110
+{
111
+ const int mmu_idx = cpu_mmu_index(env, false);
112
+ intptr_t i, oprsz = simd_oprsz(desc);
113
+ unsigned rd = simd_data(desc);
114
+ ARMVectorReg scratch[3] = { };
115
+
116
+ set_helper_retaddr(ra);
117
+ for (i = 0; i < oprsz; ) {
118
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
119
+ do {
120
+ if (pg & 1) {
121
+ tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
122
+ tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
123
+ tlb_fn(env, &scratch[2], i, addr + 2 * size, mmu_idx, ra);
124
+ }
125
+ i += size, pg >>= size;
126
+ addr += 3 * size;
127
+ } while (i & 15);
128
+ }
129
+ set_helper_retaddr(0);
130
+
131
+ /* Wait until all exceptions have been raised to write back. */
132
+ memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz);
133
+ memcpy(&env->vfp.zregs[(rd + 1) & 31], &scratch[1], oprsz);
134
+ memcpy(&env->vfp.zregs[(rd + 2) & 31], &scratch[2], oprsz);
135
}
136
137
-#define DO_LD4(NAME, FN, TYPEE, TYPEM, H) \
138
-void HELPER(NAME)(CPUARMState *env, void *vg, \
139
- target_ulong addr, uint32_t desc) \
140
-{ \
141
- intptr_t i, oprsz = simd_oprsz(desc); \
142
- intptr_t ra = GETPC(); \
143
- unsigned rd = simd_data(desc); \
144
- void *d1 = &env->vfp.zregs[rd]; \
145
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
146
- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
147
- void *d4 = &env->vfp.zregs[(rd + 3) & 31]; \
148
- for (i = 0; i < oprsz; ) { \
149
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
150
- do { \
151
- TYPEM m1 = 0, m2 = 0, m3 = 0, m4 = 0; \
152
- if (pg & 1) { \
153
- m1 = FN(env, addr, ra); \
154
- m2 = FN(env, addr + sizeof(TYPEM), ra); \
155
- m3 = FN(env, addr + 2 * sizeof(TYPEM), ra); \
156
- m4 = FN(env, addr + 3 * sizeof(TYPEM), ra); \
157
- } \
158
- *(TYPEE *)(d1 + H(i)) = m1; \
159
- *(TYPEE *)(d2 + H(i)) = m2; \
160
- *(TYPEE *)(d3 + H(i)) = m3; \
161
- *(TYPEE *)(d4 + H(i)) = m4; \
162
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
163
- addr += 4 * sizeof(TYPEM); \
164
- } while (i & 15); \
165
- } \
166
+static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr,
167
+ uint32_t desc, int size, uintptr_t ra,
168
+ sve_ld1_tlb_fn *tlb_fn)
169
+{
170
+ const int mmu_idx = cpu_mmu_index(env, false);
171
+ intptr_t i, oprsz = simd_oprsz(desc);
172
+ unsigned rd = simd_data(desc);
173
+ ARMVectorReg scratch[4] = { };
174
+
175
+ set_helper_retaddr(ra);
176
+ for (i = 0; i < oprsz; ) {
177
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
178
+ do {
179
+ if (pg & 1) {
180
+ tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
181
+ tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
182
+ tlb_fn(env, &scratch[2], i, addr + 2 * size, mmu_idx, ra);
183
+ tlb_fn(env, &scratch[3], i, addr + 3 * size, mmu_idx, ra);
184
+ }
185
+ i += size, pg >>= size;
186
+ addr += 4 * size;
187
+ } while (i & 15);
188
+ }
189
+ set_helper_retaddr(0);
190
+
191
+ /* Wait until all exceptions have been raised to write back. */
192
+ memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz);
193
+ memcpy(&env->vfp.zregs[(rd + 1) & 31], &scratch[1], oprsz);
194
+ memcpy(&env->vfp.zregs[(rd + 2) & 31], &scratch[2], oprsz);
195
+ memcpy(&env->vfp.zregs[(rd + 3) & 31], &scratch[3], oprsz);
196
}
197
198
-DO_LD2(sve_ld2bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
199
-DO_LD3(sve_ld3bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
200
-DO_LD4(sve_ld4bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
201
+#define DO_LDN_1(N) \
202
+void __attribute__((flatten)) HELPER(sve_ld##N##bb_r) \
203
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
204
+{ \
205
+ sve_ld##N##_r(env, vg, addr, desc, 1, GETPC(), sve_ld1bb_tlb); \
206
+}
207
208
-DO_LD2(sve_ld2hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
209
-DO_LD3(sve_ld3hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
210
-DO_LD4(sve_ld4hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
211
+#define DO_LDN_2(N, SUFF, SIZE) \
212
+void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_r) \
213
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
214
+{ \
215
+ sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \
216
+ arm_cpu_data_is_big_endian(env) \
217
+ ? sve_ld1##SUFF##_be_tlb : sve_ld1##SUFF##_le_tlb); \
218
+}
219
220
-DO_LD2(sve_ld2ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
221
-DO_LD3(sve_ld3ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
222
-DO_LD4(sve_ld4ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
223
+DO_LDN_1(2)
224
+DO_LDN_1(3)
225
+DO_LDN_1(4)
226
227
-DO_LD2(sve_ld2dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
228
-DO_LD3(sve_ld3dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
229
-DO_LD4(sve_ld4dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
230
+DO_LDN_2(2, hh, 2)
231
+DO_LDN_2(3, hh, 2)
232
+DO_LDN_2(4, hh, 2)
233
234
-#undef DO_LD2
235
-#undef DO_LD3
236
-#undef DO_LD4
237
+DO_LDN_2(2, ss, 4)
238
+DO_LDN_2(3, ss, 4)
239
+DO_LDN_2(4, ss, 4)
240
+
241
+DO_LDN_2(2, dd, 8)
242
+DO_LDN_2(3, dd, 8)
243
+DO_LDN_2(4, dd, 8)
244
+
245
+#undef DO_LDN_1
246
+#undef DO_LDN_2
247
248
/*
249
* Load contiguous data, first-fault and no-fault.
250
--
46
--
251
2.19.0
47
2.20.1
252
48
253
49
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
There is quite a lot of code required to compute cpu_mem_index,
3
Disable unsupported FDT firmware nodes if a user passes us
4
or even put together the full TCGMemOpIdx. This can easily be
4
a DTB with nodes enabled that the machine cannot support
5
done at translation time.
5
due to lack of EL3 or EL2 support.
6
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200423121114.4274-5-edgar.iglesias@gmail.com
10
Message-id: 20181005175350.30752-16-richard.henderson@linaro.org
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 | 5 ++
12
hw/arm/xlnx-zcu102.c | 30 ++++++++++++++++++++++++++++++
14
target/arm/sve_helper.c | 138 +++++++++++++++++++------------------
13
1 file changed, 30 insertions(+)
15
target/arm/translate-sve.c | 67 +++++++++++-------
16
3 files changed, 121 insertions(+), 89 deletions(-)
17
14
18
diff --git a/target/arm/internals.h b/target/arm/internals.h
15
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/internals.h
17
--- a/hw/arm/xlnx-zcu102.c
21
+++ b/target/arm/internals.h
18
+++ b/hw/arm/xlnx-zcu102.c
22
@@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
19
@@ -XXX,XX +XXX,XX @@
23
}
20
#include "qemu/error-report.h"
21
#include "qemu/log.h"
22
#include "sysemu/qtest.h"
23
+#include "sysemu/device_tree.h"
24
25
typedef struct XlnxZCU102 {
26
MachineState parent_obj;
27
@@ -XXX,XX +XXX,XX @@ static void zcu102_set_virt(Object *obj, bool value, Error **errp)
28
s->virt = value;
24
}
29
}
25
30
26
+/* Note make_memop_idx reserves 4 bits for mmu_idx, and MO_BSWAP is bit 3.
31
+static void zcu102_modify_dtb(const struct arm_boot_info *binfo, void *fdt)
27
+ * Thus a TCGMemOpIdx, without any MO_ALIGN bits, fits in 8 bits.
32
+{
28
+ */
33
+ XlnxZCU102 *s = container_of(binfo, XlnxZCU102, binfo);
29
+#define MEMOPIDX_SHIFT 8
34
+ bool method_is_hvc;
35
+ char **node_path;
36
+ const char *r;
37
+ int prop_len;
38
+ int i;
30
+
39
+
31
#endif
40
+ /* If EL3 is enabled, we keep all firmware nodes active. */
32
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
41
+ if (!s->secure) {
33
index XXXXXXX..XXXXXXX 100644
42
+ node_path = qemu_fdt_node_path(fdt, NULL, "xlnx,zynqmp-firmware",
34
--- a/target/arm/sve_helper.c
43
+ &error_fatal);
35
+++ b/target/arm/sve_helper.c
44
+
36
@@ -XXX,XX +XXX,XX @@
45
+ for (i = 0; node_path && node_path[i]; i++) {
37
46
+ r = qemu_fdt_getprop(fdt, node_path[i], "method", &prop_len, NULL);
38
#include "qemu/osdep.h"
47
+ method_is_hvc = r && !strcmp("hvc", r);
39
#include "cpu.h"
48
+
40
+#include "internals.h"
49
+ /* Allow HVC based firmware if EL2 is enabled. */
41
#include "exec/exec-all.h"
50
+ if (method_is_hvc && s->virt) {
42
#include "exec/cpu_ldst.h"
51
+ continue;
43
#include "exec/helper-proto.h"
52
+ }
44
@@ -XXX,XX +XXX,XX @@ typedef intptr_t sve_ld1_host_fn(void *vd, void *vg, void *host,
53
+ qemu_fdt_setprop_string(fdt, node_path[i], "status", "disabled");
45
* The controlling predicate is known to be true.
54
+ }
46
*/
55
+ g_strfreev(node_path);
47
typedef void sve_ld1_tlb_fn(CPUARMState *env, void *vd, intptr_t reg_off,
56
+ }
48
- target_ulong vaddr, int mmu_idx, uintptr_t ra);
49
+ target_ulong vaddr, TCGMemOpIdx oi, uintptr_t ra);
50
typedef sve_ld1_tlb_fn sve_st1_tlb_fn;
51
52
/*
53
@@ -XXX,XX +XXX,XX @@ static intptr_t sve_##NAME##_host(void *vd, void *vg, void *host, \
54
#ifdef CONFIG_SOFTMMU
55
#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \
56
static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
57
- target_ulong addr, int mmu_idx, uintptr_t ra) \
58
+ target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \
59
{ \
60
- TCGMemOpIdx oi = make_memop_idx(ctz32(sizeof(TYPEM)) | MOEND, mmu_idx); \
61
TYPEM val = TLB(env, addr, oi, ra); \
62
*(TYPEE *)(vd + H(reg_off)) = val; \
63
}
64
#else
65
#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \
66
static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
67
- target_ulong addr, int mmu_idx, uintptr_t ra) \
68
+ target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \
69
{ \
70
TYPEM val = HOST(g2h(addr)); \
71
*(TYPEE *)(vd + H(reg_off)) = val; \
72
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr,
73
sve_ld1_host_fn *host_fn,
74
sve_ld1_tlb_fn *tlb_fn)
75
{
76
- void *vd = &env->vfp.zregs[simd_data(desc)];
77
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
78
+ const int mmu_idx = get_mmuidx(oi);
79
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
80
+ void *vd = &env->vfp.zregs[rd];
81
const int diffsz = esz - msz;
82
const intptr_t reg_max = simd_oprsz(desc);
83
const intptr_t mem_max = reg_max >> diffsz;
84
- const int mmu_idx = cpu_mmu_index(env, false);
85
ARMVectorReg scratch;
86
void *host;
87
intptr_t split, reg_off, mem_off;
88
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr,
89
* on I/O memory, it may succeed but not bring in the TLB entry.
90
* But even then we have still made forward progress.
91
*/
92
- tlb_fn(env, &scratch, reg_off, addr + mem_off, mmu_idx, retaddr);
93
+ tlb_fn(env, &scratch, reg_off, addr + mem_off, oi, retaddr);
94
reg_off += 1 << esz;
95
}
96
#endif
97
@@ -XXX,XX +XXX,XX @@ static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr,
98
uint32_t desc, int size, uintptr_t ra,
99
sve_ld1_tlb_fn *tlb_fn)
100
{
101
- const int mmu_idx = cpu_mmu_index(env, false);
102
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
103
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
104
intptr_t i, oprsz = simd_oprsz(desc);
105
- unsigned rd = simd_data(desc);
106
ARMVectorReg scratch[2] = { };
107
108
set_helper_retaddr(ra);
109
@@ -XXX,XX +XXX,XX @@ static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr,
110
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
111
do {
112
if (pg & 1) {
113
- tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
114
- tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
115
+ tlb_fn(env, &scratch[0], i, addr, oi, ra);
116
+ tlb_fn(env, &scratch[1], i, addr + size, oi, ra);
117
}
118
i += size, pg >>= size;
119
addr += 2 * size;
120
@@ -XXX,XX +XXX,XX @@ static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr,
121
uint32_t desc, int size, uintptr_t ra,
122
sve_ld1_tlb_fn *tlb_fn)
123
{
124
- const int mmu_idx = cpu_mmu_index(env, false);
125
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
126
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
127
intptr_t i, oprsz = simd_oprsz(desc);
128
- unsigned rd = simd_data(desc);
129
ARMVectorReg scratch[3] = { };
130
131
set_helper_retaddr(ra);
132
@@ -XXX,XX +XXX,XX @@ static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr,
133
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
134
do {
135
if (pg & 1) {
136
- tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
137
- tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
138
- tlb_fn(env, &scratch[2], i, addr + 2 * size, mmu_idx, ra);
139
+ tlb_fn(env, &scratch[0], i, addr, oi, ra);
140
+ tlb_fn(env, &scratch[1], i, addr + size, oi, ra);
141
+ tlb_fn(env, &scratch[2], i, addr + 2 * size, oi, ra);
142
}
143
i += size, pg >>= size;
144
addr += 3 * size;
145
@@ -XXX,XX +XXX,XX @@ static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr,
146
uint32_t desc, int size, uintptr_t ra,
147
sve_ld1_tlb_fn *tlb_fn)
148
{
149
- const int mmu_idx = cpu_mmu_index(env, false);
150
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
151
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
152
intptr_t i, oprsz = simd_oprsz(desc);
153
- unsigned rd = simd_data(desc);
154
ARMVectorReg scratch[4] = { };
155
156
set_helper_retaddr(ra);
157
@@ -XXX,XX +XXX,XX @@ static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr,
158
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
159
do {
160
if (pg & 1) {
161
- tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
162
- tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
163
- tlb_fn(env, &scratch[2], i, addr + 2 * size, mmu_idx, ra);
164
- tlb_fn(env, &scratch[3], i, addr + 3 * size, mmu_idx, ra);
165
+ tlb_fn(env, &scratch[0], i, addr, oi, ra);
166
+ tlb_fn(env, &scratch[1], i, addr + size, oi, ra);
167
+ tlb_fn(env, &scratch[2], i, addr + 2 * size, oi, ra);
168
+ tlb_fn(env, &scratch[3], i, addr + 3 * size, oi, ra);
169
}
170
i += size, pg >>= size;
171
addr += 4 * size;
172
@@ -XXX,XX +XXX,XX @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr,
173
sve_ld1_host_fn *host_fn,
174
sve_ld1_tlb_fn *tlb_fn)
175
{
176
- void *vd = &env->vfp.zregs[simd_data(desc)];
177
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
178
+ const int mmu_idx = get_mmuidx(oi);
179
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
180
+ void *vd = &env->vfp.zregs[rd];
181
const int diffsz = esz - msz;
182
const intptr_t reg_max = simd_oprsz(desc);
183
const intptr_t mem_max = reg_max >> diffsz;
184
- const int mmu_idx = cpu_mmu_index(env, false);
185
intptr_t split, reg_off, mem_off;
186
void *host;
187
188
@@ -XXX,XX +XXX,XX @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr,
189
* Perform one normal read, which will fault or not.
190
* But it is likely to bring the page into the tlb.
191
*/
192
- tlb_fn(env, vd, reg_off, addr + mem_off, mmu_idx, retaddr);
193
+ tlb_fn(env, vd, reg_off, addr + mem_off, oi, retaddr);
194
195
/* After any fault, zero any leading predicated false elts. */
196
swap_memzero(vd, reg_off);
197
@@ -XXX,XX +XXX,XX @@ static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr,
198
uint32_t desc, const int esz, const int msz,
199
sve_ld1_host_fn *host_fn)
200
{
201
- void *vd = &env->vfp.zregs[simd_data(desc)];
202
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
203
+ void *vd = &env->vfp.zregs[rd];
204
const int diffsz = esz - msz;
205
const intptr_t reg_max = simd_oprsz(desc);
206
const intptr_t mem_max = reg_max >> diffsz;
207
@@ -XXX,XX +XXX,XX @@ DO_LDFF1_LDNF1_2(dd, 3, 3)
208
#ifdef CONFIG_SOFTMMU
209
#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \
210
static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
211
- target_ulong addr, int mmu_idx, uintptr_t ra) \
212
+ target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \
213
{ \
214
- TCGMemOpIdx oi = make_memop_idx(ctz32(sizeof(TYPEM)) | MOEND, mmu_idx); \
215
TLB(env, addr, *(TYPEM *)(vd + H(reg_off)), oi, ra); \
216
}
217
#else
218
#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \
219
static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
220
- target_ulong addr, int mmu_idx, uintptr_t ra) \
221
+ target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \
222
{ \
223
HOST(g2h(addr), *(TYPEM *)(vd + H(reg_off))); \
224
}
225
@@ -XXX,XX +XXX,XX @@ static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr,
226
const int esize, const int msize,
227
sve_st1_tlb_fn *tlb_fn)
228
{
229
- const int mmu_idx = cpu_mmu_index(env, false);
230
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
231
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
232
intptr_t i, oprsz = simd_oprsz(desc);
233
- unsigned rd = simd_data(desc);
234
void *vd = &env->vfp.zregs[rd];
235
236
set_helper_retaddr(ra);
237
@@ -XXX,XX +XXX,XX @@ static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr,
238
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
239
do {
240
if (pg & 1) {
241
- tlb_fn(env, vd, i, addr, mmu_idx, ra);
242
+ tlb_fn(env, vd, i, addr, oi, ra);
243
}
244
i += esize, pg >>= esize;
245
addr += msize;
246
@@ -XXX,XX +XXX,XX @@ static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr,
247
const int esize, const int msize,
248
sve_st1_tlb_fn *tlb_fn)
249
{
250
- const int mmu_idx = cpu_mmu_index(env, false);
251
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
252
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
253
intptr_t i, oprsz = simd_oprsz(desc);
254
- unsigned rd = simd_data(desc);
255
void *d1 = &env->vfp.zregs[rd];
256
void *d2 = &env->vfp.zregs[(rd + 1) & 31];
257
258
@@ -XXX,XX +XXX,XX @@ static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr,
259
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
260
do {
261
if (pg & 1) {
262
- tlb_fn(env, d1, i, addr, mmu_idx, ra);
263
- tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
264
+ tlb_fn(env, d1, i, addr, oi, ra);
265
+ tlb_fn(env, d2, i, addr + msize, oi, ra);
266
}
267
i += esize, pg >>= esize;
268
addr += 2 * msize;
269
@@ -XXX,XX +XXX,XX @@ static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr,
270
const int esize, const int msize,
271
sve_st1_tlb_fn *tlb_fn)
272
{
273
- const int mmu_idx = cpu_mmu_index(env, false);
274
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
275
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
276
intptr_t i, oprsz = simd_oprsz(desc);
277
- unsigned rd = simd_data(desc);
278
void *d1 = &env->vfp.zregs[rd];
279
void *d2 = &env->vfp.zregs[(rd + 1) & 31];
280
void *d3 = &env->vfp.zregs[(rd + 2) & 31];
281
@@ -XXX,XX +XXX,XX @@ static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr,
282
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
283
do {
284
if (pg & 1) {
285
- tlb_fn(env, d1, i, addr, mmu_idx, ra);
286
- tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
287
- tlb_fn(env, d3, i, addr + 2 * msize, mmu_idx, ra);
288
+ tlb_fn(env, d1, i, addr, oi, ra);
289
+ tlb_fn(env, d2, i, addr + msize, oi, ra);
290
+ tlb_fn(env, d3, i, addr + 2 * msize, oi, ra);
291
}
292
i += esize, pg >>= esize;
293
addr += 3 * msize;
294
@@ -XXX,XX +XXX,XX @@ static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr,
295
const int esize, const int msize,
296
sve_st1_tlb_fn *tlb_fn)
297
{
298
- const int mmu_idx = cpu_mmu_index(env, false);
299
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
300
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
301
intptr_t i, oprsz = simd_oprsz(desc);
302
- unsigned rd = simd_data(desc);
303
void *d1 = &env->vfp.zregs[rd];
304
void *d2 = &env->vfp.zregs[(rd + 1) & 31];
305
void *d3 = &env->vfp.zregs[(rd + 2) & 31];
306
@@ -XXX,XX +XXX,XX @@ static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr,
307
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
308
do {
309
if (pg & 1) {
310
- tlb_fn(env, d1, i, addr, mmu_idx, ra);
311
- tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
312
- tlb_fn(env, d3, i, addr + 2 * msize, mmu_idx, ra);
313
- tlb_fn(env, d4, i, addr + 3 * msize, mmu_idx, ra);
314
+ tlb_fn(env, d1, i, addr, oi, ra);
315
+ tlb_fn(env, d2, i, addr + msize, oi, ra);
316
+ tlb_fn(env, d3, i, addr + 2 * msize, oi, ra);
317
+ tlb_fn(env, d4, i, addr + 3 * msize, oi, ra);
318
}
319
i += esize, pg >>= esize;
320
addr += 4 * msize;
321
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
322
target_ulong base, uint32_t desc, uintptr_t ra,
323
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
324
{
325
- const int mmu_idx = cpu_mmu_index(env, false);
326
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
327
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
328
intptr_t i, oprsz = simd_oprsz(desc);
329
- unsigned scale = simd_data(desc);
330
ARMVectorReg scratch = { };
331
332
set_helper_retaddr(ra);
333
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
334
do {
335
if (likely(pg & 1)) {
336
target_ulong off = off_fn(vm, i);
337
- tlb_fn(env, &scratch, i, base + (off << scale), mmu_idx, ra);
338
+ tlb_fn(env, &scratch, i, base + (off << scale), oi, ra);
339
}
340
i += 4, pg >>= 4;
341
} while (i & 15);
342
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
343
target_ulong base, uint32_t desc, uintptr_t ra,
344
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
345
{
346
- const int mmu_idx = cpu_mmu_index(env, false);
347
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
348
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
349
intptr_t i, oprsz = simd_oprsz(desc) / 8;
350
- unsigned scale = simd_data(desc);
351
ARMVectorReg scratch = { };
352
353
set_helper_retaddr(ra);
354
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
355
uint8_t pg = *(uint8_t *)(vg + H1(i));
356
if (likely(pg & 1)) {
357
target_ulong off = off_fn(vm, i * 8);
358
- tlb_fn(env, &scratch, i * 8, base + (off << scale), mmu_idx, ra);
359
+ tlb_fn(env, &scratch, i * 8, base + (off << scale), oi, ra);
360
}
361
}
362
set_helper_retaddr(0);
363
@@ -XXX,XX +XXX,XX @@ typedef bool sve_ld1_nf_fn(CPUARMState *env, void *vd, intptr_t reg_off,
364
#ifdef CONFIG_SOFTMMU
365
#define DO_LD_NF(NAME, H, TYPEE, TYPEM, HOST) \
366
static bool sve_ld##NAME##_nf(CPUARMState *env, void *vd, intptr_t reg_off, \
367
- target_ulong addr, int mmu_idx) \
368
+ target_ulong addr, int mmu_idx) \
369
{ \
370
target_ulong next_page = -(addr | TARGET_PAGE_MASK); \
371
if (likely(next_page - addr >= sizeof(TYPEM))) { \
372
@@ -XXX,XX +XXX,XX @@ static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
373
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn,
374
sve_ld1_nf_fn *nonfault_fn)
375
{
376
- const int mmu_idx = cpu_mmu_index(env, false);
377
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
378
+ const int mmu_idx = get_mmuidx(oi);
379
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
380
intptr_t reg_off, reg_max = simd_oprsz(desc);
381
- unsigned scale = simd_data(desc);
382
target_ulong addr;
383
384
/* Skip to the first true predicate. */
385
@@ -XXX,XX +XXX,XX @@ static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
386
set_helper_retaddr(ra);
387
addr = off_fn(vm, reg_off);
388
addr = base + (addr << scale);
389
- tlb_fn(env, vd, reg_off, addr, mmu_idx, ra);
390
+ tlb_fn(env, vd, reg_off, addr, oi, ra);
391
392
/* The rest of the reads will be non-faulting. */
393
set_helper_retaddr(0);
394
@@ -XXX,XX +XXX,XX @@ static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
395
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn,
396
sve_ld1_nf_fn *nonfault_fn)
397
{
398
- const int mmu_idx = cpu_mmu_index(env, false);
399
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
400
+ const int mmu_idx = get_mmuidx(oi);
401
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
402
intptr_t reg_off, reg_max = simd_oprsz(desc);
403
- unsigned scale = simd_data(desc);
404
target_ulong addr;
405
406
/* Skip to the first true predicate. */
407
@@ -XXX,XX +XXX,XX @@ static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
408
set_helper_retaddr(ra);
409
addr = off_fn(vm, reg_off);
410
addr = base + (addr << scale);
411
- tlb_fn(env, vd, reg_off, addr, mmu_idx, ra);
412
+ tlb_fn(env, vd, reg_off, addr, oi, ra);
413
414
/* The rest of the reads will be non-faulting. */
415
set_helper_retaddr(0);
416
@@ -XXX,XX +XXX,XX @@ static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
417
target_ulong base, uint32_t desc, uintptr_t ra,
418
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
419
{
420
- const int mmu_idx = cpu_mmu_index(env, false);
421
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
422
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
423
intptr_t i, oprsz = simd_oprsz(desc);
424
- unsigned scale = simd_data(desc);
425
426
set_helper_retaddr(ra);
427
for (i = 0; i < oprsz; ) {
428
@@ -XXX,XX +XXX,XX @@ static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
429
do {
430
if (likely(pg & 1)) {
431
target_ulong off = off_fn(vm, i);
432
- tlb_fn(env, vd, i, base + (off << scale), mmu_idx, ra);
433
+ tlb_fn(env, vd, i, base + (off << scale), oi, ra);
434
}
435
i += 4, pg >>= 4;
436
} while (i & 15);
437
@@ -XXX,XX +XXX,XX @@ static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
438
target_ulong base, uint32_t desc, uintptr_t ra,
439
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
440
{
441
- const int mmu_idx = cpu_mmu_index(env, false);
442
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
443
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
444
intptr_t i, oprsz = simd_oprsz(desc) / 8;
445
- unsigned scale = simd_data(desc);
446
447
set_helper_retaddr(ra);
448
for (i = 0; i < oprsz; i++) {
449
uint8_t pg = *(uint8_t *)(vg + H1(i));
450
if (likely(pg & 1)) {
451
target_ulong off = off_fn(vm, i * 8);
452
- tlb_fn(env, vd, i * 8, base + (off << scale), mmu_idx, ra);
453
+ tlb_fn(env, vd, i * 8, base + (off << scale), oi, ra);
454
}
455
}
456
set_helper_retaddr(0);
457
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
458
index XXXXXXX..XXXXXXX 100644
459
--- a/target/arm/translate-sve.c
460
+++ b/target/arm/translate-sve.c
461
@@ -XXX,XX +XXX,XX @@ static const uint8_t dtype_esz[16] = {
462
3, 2, 1, 3
463
};
464
465
+static TCGMemOpIdx sve_memopidx(DisasContext *s, int dtype)
466
+{
467
+ return make_memop_idx(s->be_data | dtype_mop[dtype], get_mem_index(s));
468
+}
57
+}
469
+
58
+
470
static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
59
static void xlnx_zcu102_init(MachineState *machine)
471
- gen_helper_gvec_mem *fn)
472
+ int dtype, gen_helper_gvec_mem *fn)
473
{
60
{
474
unsigned vsz = vec_full_reg_size(s);
61
XlnxZCU102 *s = ZCU102_MACHINE(machine);
475
TCGv_ptr t_pg;
62
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
476
- TCGv_i32 desc;
63
477
+ TCGv_i32 t_desc;
64
s->binfo.ram_size = ram_size;
478
+ int desc;
65
s->binfo.loader_start = 0;
479
66
+ s->binfo.modify_dtb = zcu102_modify_dtb;
480
/* For e.g. LD4, there are not enough arguments to pass all 4
67
arm_load_kernel(s->soc.boot_cpu_ptr, machine, &s->binfo);
481
* registers as pointers, so encode the regno into the data field.
482
* For consistency, do this even for LD1.
483
*/
484
- desc = tcg_const_i32(simd_desc(vsz, vsz, zt));
485
+ desc = sve_memopidx(s, dtype);
486
+ desc |= zt << MEMOPIDX_SHIFT;
487
+ desc = simd_desc(vsz, vsz, desc);
488
+ t_desc = tcg_const_i32(desc);
489
t_pg = tcg_temp_new_ptr();
490
491
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
492
- fn(cpu_env, t_pg, addr, desc);
493
+ fn(cpu_env, t_pg, addr, t_desc);
494
495
tcg_temp_free_ptr(t_pg);
496
- tcg_temp_free_i32(desc);
497
+ tcg_temp_free_i32(t_desc);
498
}
68
}
499
69
500
static void do_ld_zpa(DisasContext *s, int zt, int pg,
501
@@ -XXX,XX +XXX,XX @@ static void do_ld_zpa(DisasContext *s, int zt, int pg,
502
* accessible via the instruction encoding.
503
*/
504
assert(fn != NULL);
505
- do_mem_zpa(s, zt, pg, addr, fn);
506
+ do_mem_zpa(s, zt, pg, addr, dtype, fn);
507
}
508
509
static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
510
@@ -XXX,XX +XXX,XX @@ static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
511
TCGv_i64 addr = new_tmp_a64(s);
512
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
513
tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
514
- do_mem_zpa(s, a->rd, a->pg, addr, fns[s->be_data == MO_BE][a->dtype]);
515
+ do_mem_zpa(s, a->rd, a->pg, addr, a->dtype,
516
+ fns[s->be_data == MO_BE][a->dtype]);
517
}
518
return true;
519
}
520
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
521
TCGv_i64 addr = new_tmp_a64(s);
522
523
tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), off);
524
- do_mem_zpa(s, a->rd, a->pg, addr, fns[s->be_data == MO_BE][a->dtype]);
525
+ do_mem_zpa(s, a->rd, a->pg, addr, a->dtype,
526
+ fns[s->be_data == MO_BE][a->dtype]);
527
}
528
return true;
529
}
530
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
531
};
532
unsigned vsz = vec_full_reg_size(s);
533
TCGv_ptr t_pg;
534
- TCGv_i32 desc;
535
- int poff;
536
+ TCGv_i32 t_desc;
537
+ int desc, poff;
538
539
/* Load the first quadword using the normal predicated load helpers. */
540
- desc = tcg_const_i32(simd_desc(16, 16, zt));
541
+ desc = sve_memopidx(s, msz_dtype(msz));
542
+ desc |= zt << MEMOPIDX_SHIFT;
543
+ desc = simd_desc(16, 16, desc);
544
+ t_desc = tcg_const_i32(desc);
545
546
poff = pred_full_reg_offset(s, pg);
547
if (vsz > 16) {
548
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
549
t_pg = tcg_temp_new_ptr();
550
tcg_gen_addi_ptr(t_pg, cpu_env, poff);
551
552
- fns[s->be_data == MO_BE][msz](cpu_env, t_pg, addr, desc);
553
+ fns[s->be_data == MO_BE][msz](cpu_env, t_pg, addr, t_desc);
554
555
tcg_temp_free_ptr(t_pg);
556
- tcg_temp_free_i32(desc);
557
+ tcg_temp_free_i32(t_desc);
558
559
/* Replicate that first quadword. */
560
if (vsz > 16) {
561
@@ -XXX,XX +XXX,XX @@ static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
562
fn = fn_multiple[be][nreg - 1][msz];
563
}
564
assert(fn != NULL);
565
- do_mem_zpa(s, zt, pg, addr, fn);
566
+ do_mem_zpa(s, zt, pg, addr, msz_dtype(msz), fn);
567
}
568
569
static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a, uint32_t insn)
570
@@ -XXX,XX +XXX,XX @@ static bool trans_ST_zpri(DisasContext *s, arg_rpri_store *a, uint32_t insn)
571
*** SVE gather loads / scatter stores
572
*/
573
574
-static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, int scale,
575
- TCGv_i64 scalar, gen_helper_gvec_mem_scatter *fn)
576
+static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm,
577
+ int scale, TCGv_i64 scalar, int msz,
578
+ gen_helper_gvec_mem_scatter *fn)
579
{
580
unsigned vsz = vec_full_reg_size(s);
581
- TCGv_i32 desc = tcg_const_i32(simd_desc(vsz, vsz, scale));
582
TCGv_ptr t_zm = tcg_temp_new_ptr();
583
TCGv_ptr t_pg = tcg_temp_new_ptr();
584
TCGv_ptr t_zt = tcg_temp_new_ptr();
585
+ TCGv_i32 t_desc;
586
+ int desc;
587
+
588
+ desc = sve_memopidx(s, msz_dtype(msz));
589
+ desc |= scale << MEMOPIDX_SHIFT;
590
+ desc = simd_desc(vsz, vsz, desc);
591
+ t_desc = tcg_const_i32(desc);
592
593
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
594
tcg_gen_addi_ptr(t_zm, cpu_env, vec_full_reg_offset(s, zm));
595
tcg_gen_addi_ptr(t_zt, cpu_env, vec_full_reg_offset(s, zt));
596
- fn(cpu_env, t_zt, t_pg, t_zm, scalar, desc);
597
+ fn(cpu_env, t_zt, t_pg, t_zm, scalar, t_desc);
598
599
tcg_temp_free_ptr(t_zt);
600
tcg_temp_free_ptr(t_zm);
601
tcg_temp_free_ptr(t_pg);
602
- tcg_temp_free_i32(desc);
603
+ tcg_temp_free_i32(t_desc);
604
}
605
606
/* Indexed by [be][ff][xs][u][msz]. */
607
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
608
assert(fn != NULL);
609
610
do_mem_zpz(s, a->rd, a->pg, a->rm, a->scale * a->msz,
611
- cpu_reg_sp(s, a->rn), fn);
612
+ cpu_reg_sp(s, a->rn), a->msz, fn);
613
return true;
614
}
615
616
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
617
* by loading the immediate into the scalar parameter.
618
*/
619
imm = tcg_const_i64(a->imm << a->msz);
620
- do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, fn);
621
+ do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, a->msz, fn);
622
tcg_temp_free_i64(imm);
623
return true;
624
}
625
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
626
g_assert_not_reached();
627
}
628
do_mem_zpz(s, a->rd, a->pg, a->rm, a->scale * a->msz,
629
- cpu_reg_sp(s, a->rn), fn);
630
+ cpu_reg_sp(s, a->rn), a->msz, fn);
631
return true;
632
}
633
634
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn)
635
* by loading the immediate into the scalar parameter.
636
*/
637
imm = tcg_const_i64(a->imm << a->msz);
638
- do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, fn);
639
+ do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, a->msz, fn);
640
tcg_temp_free_i64(imm);
641
return true;
642
}
643
--
70
--
644
2.19.0
71
2.20.1
645
72
646
73
diff view generated by jsdifflib
Deleted patch
1
Define EXCP_STKOF, and arrange for it to cause us to take
2
a UsageFault with CFSR.STKOF set.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20181002163556.10279-3-peter.maydell@linaro.org
8
---
9
target/arm/cpu.h | 2 ++
10
target/arm/helper.c | 5 +++++
11
2 files changed, 7 insertions(+)
12
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
16
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@
18
#define EXCP_SEMIHOST 16 /* semihosting call */
19
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
20
#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
21
+#define EXCP_STKOF 19 /* v8M STKOF UsageFault */
22
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
23
24
#define ARMV7M_EXCP_RESET 1
25
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CFSR, UNDEFINSTR, 16 + 0, 1)
26
FIELD(V7M_CFSR, INVSTATE, 16 + 1, 1)
27
FIELD(V7M_CFSR, INVPC, 16 + 2, 1)
28
FIELD(V7M_CFSR, NOCP, 16 + 3, 1)
29
+FIELD(V7M_CFSR, STKOF, 16 + 4, 1)
30
FIELD(V7M_CFSR, UNALIGNED, 16 + 8, 1)
31
FIELD(V7M_CFSR, DIVBYZERO, 16 + 9, 1)
32
33
diff --git a/target/arm/helper.c b/target/arm/helper.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/helper.c
36
+++ b/target/arm/helper.c
37
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
38
[EXCP_SEMIHOST] = "Semihosting call",
39
[EXCP_NOCP] = "v7M NOCP UsageFault",
40
[EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
41
+ [EXCP_STKOF] = "v8M STKOF UsageFault",
42
};
43
44
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
45
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
46
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
47
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVSTATE_MASK;
48
break;
49
+ case EXCP_STKOF:
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
51
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_STKOF_MASK;
52
+ break;
53
case EXCP_SWI:
54
/* The PC already points to the next instruction. */
55
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC, env->v7m.secure);
56
--
57
2.19.0
58
59
diff view generated by jsdifflib