1
Hi; here's a target-arm pullreq. Mostly this is some decodetree
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
conversion patches from me, plus a scattering of other bug fixes.
3
2
4
thanks
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
5
-- PMM
6
7
The following changes since commit e3660cc1e3cb136af50c0eaaeac27943c2438d1d:
8
9
Merge tag 'pull-loongarch-20230616' of https://gitlab.com/gaosong/qemu into staging (2023-06-16 12:30:16 +0200)
10
4
11
are available in the Git repository at:
5
are available in the Git repository at:
12
6
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230619
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
14
8
15
for you to fetch changes up to 074259c0f2ac40042dce766d870318cc22f388eb:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
16
10
17
hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property (2023-06-19 15:27:21 +0100)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
18
12
19
----------------------------------------------------------------
13
----------------------------------------------------------------
20
target-arm queue:
14
target-arm queue:
21
* Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
15
* Implement FEAT_ECV
22
* Return correct result for LDG when ATA=0
16
* STM32L4x5: Implement GPIO device
23
* Conversion of system insns, loads and stores to decodetree
17
* Fix 32-bit SMOPA
24
* hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
18
* Refactor v7m related code from cpu32.c into its own file
25
* hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
26
* hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
27
* hw/arm/Kconfig: sbsa-ref uses Bochs display
28
* imx_serial: set wake bit when we receive a data byte
29
* docs: sbsa: document board to firmware interface
30
* hw/misc/bcm2835_property: avoid hard-coded constants
31
20
32
----------------------------------------------------------------
21
----------------------------------------------------------------
33
Marcin Juszkiewicz (2):
22
Inès Varhol (3):
34
hw/arm/Kconfig: sbsa-ref uses Bochs display
23
hw/gpio: Implement STM32L4x5 GPIO
35
docs: sbsa: document board to firmware interface
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
36
26
37
Martin Kaiser (1):
27
Peter Maydell (9):
38
imx_serial: set wake bit when we receive a data byte
28
target/arm: Move some register related defines to internals.h
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
30
target/arm: use FIELD macro for CNTHCTL bit definitions
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
32
target/arm: Implement new FEAT_ECV trap bits
33
target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
34
target/arm: Implement FEAT_ECV CNTPOFF_EL2 handling
35
target/arm: Enable FEAT_ECV for 'max' CPU
36
hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
39
37
40
Peter Maydell (26):
38
Richard Henderson (1):
41
target/arm: Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
39
target/arm: Fix 32-bit SMOPA
42
target/arm: Return correct result for LDG when ATA=0
43
target/arm: Pass memop to gen_mte_check1_mmuidx() in reg_imm9 decode
44
target/arm: Consistently use finalize_memop_asimd() for ASIMD loads/stores
45
target/arm: Convert hint instruction space to decodetree
46
target/arm: Convert barrier insns to decodetree
47
target/arm: Convert CFINV, XAFLAG and AXFLAG to decodetree
48
target/arm: Convert MSR (immediate) to decodetree
49
target/arm: Convert MSR (reg), MRS, SYS, SYSL to decodetree
50
target/arm: Convert exception generation instructions to decodetree
51
target/arm: Convert load/store exclusive and ordered to decodetree
52
target/arm: Convert LDXP, STXP, CASP, CAS to decodetree
53
target/arm: Convert load reg (literal) group to decodetree
54
target/arm: Convert load/store-pair to decodetree
55
target/arm: Convert ld/st reg+imm9 insns to decodetree
56
target/arm: Convert LDR/STR with 12-bit immediate to decodetree
57
target/arm: Convert LDR/STR reg+reg to decodetree
58
target/arm: Convert atomic memory ops to decodetree
59
target/arm: Convert load (pointer auth) insns to decodetree
60
target/arm: Convert LDAPR/STLR (imm) to decodetree
61
target/arm: Convert load/store (multiple structures) to decodetree
62
target/arm: Convert load/store single structure to decodetree
63
target/arm: Convert load/store tags insns to decodetree
64
hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
65
hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
66
hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
67
40
68
Sergey Kambalin (4):
41
Thomas Huth (1):
69
hw/arm/raspi: Import Linux raspi definitions as 'raspberrypi-fw-defs.h'
42
target/arm: Move v7m-related code from cpu32.c into a separate file
70
hw/misc/bcm2835_property: Use 'raspberrypi-fw-defs.h' definitions
71
hw/misc/bcm2835_property: Replace magic frequency values by definitions
72
hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property
73
43
74
docs/system/arm/sbsa.rst | 38 +-
44
MAINTAINERS | 1 +
75
include/hw/arm/raspi_platform.h | 10 +
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
76
include/hw/char/imx_serial.h | 1 +
46
docs/system/arm/emulation.rst | 1 +
77
include/hw/misc/raspberrypi-fw-defs.h | 163 ++
47
include/hw/arm/stm32l4x5_soc.h | 2 +
78
target/arm/tcg/a64.decode | 403 ++++
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
79
hw/char/imx_serial.c | 5 +-
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
80
hw/intc/allwinner-a10-pic.c | 2 +-
50
include/hw/rtc/sun4v-rtc.h | 2 +-
81
hw/misc/bcm2835_property.c | 112 +-
51
target/arm/cpu-features.h | 10 +
82
hw/sd/allwinner-sdhost.c | 2 +-
52
target/arm/cpu.h | 129 +--------
83
hw/timer/nrf51_timer.c | 7 +-
53
target/arm/internals.h | 151 ++++++++++
84
target/arm/tcg/translate-a64.c | 3319 +++++++++++++++------------------
54
hw/arm/stm32l4x5_soc.c | 71 ++++-
85
hw/arm/Kconfig | 1 +
55
hw/gpio/stm32l4x5_gpio.c | 477 ++++++++++++++++++++++++++++++++
86
12 files changed, 2157 insertions(+), 1906 deletions(-)
56
hw/misc/stm32l4x5_syscfg.c | 1 +
87
create mode 100644 include/hw/misc/raspberrypi-fw-defs.h
57
hw/rtc/sun4v-rtc.c | 2 +-
58
target/arm/helper.c | 189 ++++++++++++-
59
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++
60
target/arm/tcg/cpu32.c | 261 ------------------
61
target/arm/tcg/cpu64.c | 1 +
62
target/arm/tcg/sme_helper.c | 77 +++---
63
tests/qtest/stm32l4x5_gpio-test.c | 551 +++++++++++++++++++++++++++++++++++++
64
tests/tcg/aarch64/sme-smopa-1.c | 47 ++++
65
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++
66
hw/arm/Kconfig | 3 +-
67
hw/gpio/Kconfig | 3 +
68
hw/gpio/meson.build | 1 +
69
hw/gpio/trace-events | 6 +
70
target/arm/meson.build | 3 +
71
target/arm/tcg/meson.build | 3 +
72
target/arm/trace-events | 1 +
73
tests/qtest/meson.build | 3 +-
74
tests/tcg/aarch64/Makefile.target | 2 +-
75
31 files changed, 1962 insertions(+), 456 deletions(-)
76
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
77
create mode 100644 hw/gpio/stm32l4x5_gpio.c
78
create mode 100644 target/arm/tcg/cpu-v7m.c
79
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
80
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
81
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
82
diff view generated by jsdifflib
Deleted patch
1
The atomic memory operations are supposed to return the old memory
2
data value in the destination register. This value is not
3
sign-extended, even if the operation is the signed minimum or
4
maximum. (In the pseudocode for the instructions the returned data
5
value is passed to ZeroExtend() to create the value in the register.)
6
1
7
We got this wrong because we were doing a 32-to-64 zero extend on the
8
result for 8 and 16 bit data values, rather than the correct amount
9
of zero extension.
10
11
Fix the bug by using ext8u and ext16u for the MO_8 and MO_16 data
12
sizes rather than ext32u.
13
14
Cc: qemu-stable@nongnu.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20230602155223.2040685-2-peter.maydell@linaro.org
18
---
19
target/arm/tcg/translate-a64.c | 18 ++++++++++++++++--
20
1 file changed, 16 insertions(+), 2 deletions(-)
21
22
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/tcg/translate-a64.c
25
+++ b/target/arm/tcg/translate-a64.c
26
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
27
*/
28
fn(tcg_rt, clean_addr, tcg_rs, get_mem_index(s), mop);
29
30
- if ((mop & MO_SIGN) && size != MO_64) {
31
- tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
32
+ if (mop & MO_SIGN) {
33
+ switch (size) {
34
+ case MO_8:
35
+ tcg_gen_ext8u_i64(tcg_rt, tcg_rt);
36
+ break;
37
+ case MO_16:
38
+ tcg_gen_ext16u_i64(tcg_rt, tcg_rt);
39
+ break;
40
+ case MO_32:
41
+ tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
42
+ break;
43
+ case MO_64:
44
+ break;
45
+ default:
46
+ g_assert_not_reached();
47
+ }
48
}
49
}
50
51
--
52
2.34.1
diff view generated by jsdifflib
Deleted patch
1
The LDG instruction loads the tag from a memory address (identified
2
by [Xn + offset]), and then merges that tag into the destination
3
register Xt. We implemented this correctly for the case when
4
allocation tags are enabled, but didn't get it right when ATA=0:
5
instead of merging the tag bits into Xt, we merged them into the
6
memory address [Xn + offset] and then set Xt to that.
7
1
8
Merge the tag bits into the old Xt value, as they should be.
9
10
Cc: qemu-stable@nongnu.org
11
Fixes: c15294c1e36a7dd9b25 ("target/arm: Implement LDG, STG, ST2G instructions")
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
target/arm/tcg/translate-a64.c | 6 +++++-
16
1 file changed, 5 insertions(+), 1 deletion(-)
17
18
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/tcg/translate-a64.c
21
+++ b/target/arm/tcg/translate-a64.c
22
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
23
if (s->ata) {
24
gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
25
} else {
26
+ /*
27
+ * Tag access disabled: we must check for aborts on the load
28
+ * load from [rn+offset], and then insert a 0 tag into rt.
29
+ */
30
clean_addr = clean_data_tbi(s, addr);
31
gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
32
- gen_address_with_allocation_tag0(tcg_rt, addr);
33
+ gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
34
}
35
} else {
36
tcg_rt = cpu_reg_sp(s, rt);
37
--
38
2.34.1
diff view generated by jsdifflib
Deleted patch
1
In disas_ldst_reg_imm9() we missed one place where a call to
2
a gen_mte_check* function should now be passed the memop we
3
have created rather than just being passed the size. Fix this.
4
1
5
Fixes: 0a9091424d ("target/arm: Pass memop to gen_mte_check1*")
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
---
10
target/arm/tcg/translate-a64.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/translate-a64.c
16
+++ b/target/arm/tcg/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
18
19
clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
20
writeback || rn != 31,
21
- size, is_unpriv, memidx);
22
+ memop, is_unpriv, memidx);
23
24
if (is_vector) {
25
if (is_store) {
26
--
27
2.34.1
28
29
diff view generated by jsdifflib
Deleted patch
1
In the recent refactoring we missed a few places which should be
2
calling finalize_memop_asimd() for ASIMD loads and stores but
3
instead are just calling finalize_memop(); fix these.
4
1
5
For the disas_ldst_single_struct() and disas_ldst_multiple_struct()
6
cases, this is not a behaviour change because there the size
7
is never MO_128 and the two finalize functions do the same thing.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
12
target/arm/tcg/translate-a64.c | 10 ++++++----
13
1 file changed, 6 insertions(+), 4 deletions(-)
14
15
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/tcg/translate-a64.c
18
+++ b/target/arm/tcg/translate-a64.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
20
if (!fp_access_check(s)) {
21
return;
22
}
23
+ memop = finalize_memop_asimd(s, size);
24
} else {
25
if (size == 3 && opc == 2) {
26
/* PRFM - prefetch */
27
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
28
is_store = (opc == 0);
29
is_signed = !is_store && extract32(opc, 1, 1);
30
is_extended = (size < 3) && extract32(opc, 0, 1);
31
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
32
}
33
34
if (rn == 31) {
35
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
36
37
tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
38
39
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
40
clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, memop);
41
42
if (is_vector) {
43
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
44
if (!fp_access_check(s)) {
45
return;
46
}
47
+ memop = finalize_memop_asimd(s, size);
48
} else {
49
if (size == 3 && opc == 2) {
50
/* PRFM - prefetch */
51
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
52
is_store = (opc == 0);
53
is_signed = !is_store && extract32(opc, 1, 1);
54
is_extended = (size < 3) && extract32(opc, 0, 1);
55
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
56
}
57
58
if (rn == 31) {
59
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
60
offset = imm12 << size;
61
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
62
63
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
64
clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, memop);
65
66
if (is_vector) {
67
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
68
* promote consecutive little-endian elements below.
69
*/
70
clean_addr = gen_mte_checkN(s, tcg_rn, is_store, is_postidx || rn != 31,
71
- total, finalize_memop(s, size));
72
+ total, finalize_memop_asimd(s, size));
73
74
/*
75
* Consecutive little-endian elements from a single register
76
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
77
total = selem << scale;
78
tcg_rn = cpu_reg_sp(s, rn);
79
80
- mop = finalize_memop(s, scale);
81
+ mop = finalize_memop_asimd(s, scale);
82
83
clean_addr = gen_mte_checkN(s, tcg_rn, !is_load, is_postidx || rn != 31,
84
total, mop);
85
--
86
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the various instructions in the hint instruction space
2
to decodetree.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-3-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 31 ++++
9
target/arm/tcg/translate-a64.c | 277 ++++++++++++++++++---------------
10
2 files changed, 185 insertions(+), 123 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
17
# the processor is in halting debug state (which we don't implement).
18
# The pattern is listed here as documentation.
19
# DRPS 1101011 0101 11111 000000 11111 00000
20
+
21
+# Hint instruction group
22
+{
23
+ [
24
+ YIELD 1101 0101 0000 0011 0010 0000 001 11111
25
+ WFE 1101 0101 0000 0011 0010 0000 010 11111
26
+ WFI 1101 0101 0000 0011 0010 0000 011 11111
27
+ # We implement WFE to never block, so our SEV/SEVL are NOPs
28
+ # SEV 1101 0101 0000 0011 0010 0000 100 11111
29
+ # SEVL 1101 0101 0000 0011 0010 0000 101 11111
30
+ # Our DGL is a NOP because we don't merge memory accesses anyway.
31
+ # DGL 1101 0101 0000 0011 0010 0000 110 11111
32
+ XPACLRI 1101 0101 0000 0011 0010 0000 111 11111
33
+ PACIA1716 1101 0101 0000 0011 0010 0001 000 11111
34
+ PACIB1716 1101 0101 0000 0011 0010 0001 010 11111
35
+ AUTIA1716 1101 0101 0000 0011 0010 0001 100 11111
36
+ AUTIB1716 1101 0101 0000 0011 0010 0001 110 11111
37
+ ESB 1101 0101 0000 0011 0010 0010 000 11111
38
+ PACIAZ 1101 0101 0000 0011 0010 0011 000 11111
39
+ PACIASP 1101 0101 0000 0011 0010 0011 001 11111
40
+ PACIBZ 1101 0101 0000 0011 0010 0011 010 11111
41
+ PACIBSP 1101 0101 0000 0011 0010 0011 011 11111
42
+ AUTIAZ 1101 0101 0000 0011 0010 0011 100 11111
43
+ AUTIASP 1101 0101 0000 0011 0010 0011 101 11111
44
+ AUTIBZ 1101 0101 0000 0011 0010 0011 110 11111
45
+ AUTIBSP 1101 0101 0000 0011 0010 0011 111 11111
46
+ ]
47
+ # The canonical NOP has CRm == op2 == 0, but all of the space
48
+ # that isn't specifically allocated to an instruction must NOP
49
+ NOP 1101 0101 0000 0011 0010 ---- --- 11111
50
+}
51
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/tcg/translate-a64.c
54
+++ b/target/arm/tcg/translate-a64.c
55
@@ -XXX,XX +XXX,XX @@ static bool trans_ERETA(DisasContext *s, arg_reta *a)
56
return true;
57
}
58
59
-/* HINT instruction group, including various allocated HINTs */
60
-static void handle_hint(DisasContext *s, uint32_t insn,
61
- unsigned int op1, unsigned int op2, unsigned int crm)
62
+static bool trans_NOP(DisasContext *s, arg_NOP *a)
63
{
64
- unsigned int selector = crm << 3 | op2;
65
+ return true;
66
+}
67
68
- if (op1 != 3) {
69
- unallocated_encoding(s);
70
- return;
71
+static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
72
+{
73
+ /*
74
+ * When running in MTTCG we don't generate jumps to the yield and
75
+ * WFE helpers as it won't affect the scheduling of other vCPUs.
76
+ * If we wanted to more completely model WFE/SEV so we don't busy
77
+ * spin unnecessarily we would need to do something more involved.
78
+ */
79
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
80
+ s->base.is_jmp = DISAS_YIELD;
81
}
82
+ return true;
83
+}
84
85
- switch (selector) {
86
- case 0b00000: /* NOP */
87
- break;
88
- case 0b00011: /* WFI */
89
- s->base.is_jmp = DISAS_WFI;
90
- break;
91
- case 0b00001: /* YIELD */
92
- /* When running in MTTCG we don't generate jumps to the yield and
93
- * WFE helpers as it won't affect the scheduling of other vCPUs.
94
- * If we wanted to more completely model WFE/SEV so we don't busy
95
- * spin unnecessarily we would need to do something more involved.
96
+static bool trans_WFI(DisasContext *s, arg_WFI *a)
97
+{
98
+ s->base.is_jmp = DISAS_WFI;
99
+ return true;
100
+}
101
+
102
+static bool trans_WFE(DisasContext *s, arg_WFI *a)
103
+{
104
+ /*
105
+ * When running in MTTCG we don't generate jumps to the yield and
106
+ * WFE helpers as it won't affect the scheduling of other vCPUs.
107
+ * If we wanted to more completely model WFE/SEV so we don't busy
108
+ * spin unnecessarily we would need to do something more involved.
109
+ */
110
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
111
+ s->base.is_jmp = DISAS_WFE;
112
+ }
113
+ return true;
114
+}
115
+
116
+static bool trans_XPACLRI(DisasContext *s, arg_XPACLRI *a)
117
+{
118
+ if (s->pauth_active) {
119
+ gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
120
+ }
121
+ return true;
122
+}
123
+
124
+static bool trans_PACIA1716(DisasContext *s, arg_PACIA1716 *a)
125
+{
126
+ if (s->pauth_active) {
127
+ gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
128
+ }
129
+ return true;
130
+}
131
+
132
+static bool trans_PACIB1716(DisasContext *s, arg_PACIB1716 *a)
133
+{
134
+ if (s->pauth_active) {
135
+ gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
136
+ }
137
+ return true;
138
+}
139
+
140
+static bool trans_AUTIA1716(DisasContext *s, arg_AUTIA1716 *a)
141
+{
142
+ if (s->pauth_active) {
143
+ gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
144
+ }
145
+ return true;
146
+}
147
+
148
+static bool trans_AUTIB1716(DisasContext *s, arg_AUTIB1716 *a)
149
+{
150
+ if (s->pauth_active) {
151
+ gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
152
+ }
153
+ return true;
154
+}
155
+
156
+static bool trans_ESB(DisasContext *s, arg_ESB *a)
157
+{
158
+ /* Without RAS, we must implement this as NOP. */
159
+ if (dc_isar_feature(aa64_ras, s)) {
160
+ /*
161
+ * QEMU does not have a source of physical SErrors,
162
+ * so we are only concerned with virtual SErrors.
163
+ * The pseudocode in the ARM for this case is
164
+ * if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
165
+ * AArch64.vESBOperation();
166
+ * Most of the condition can be evaluated at translation time.
167
+ * Test for EL2 present, and defer test for SEL2 to runtime.
168
*/
169
- if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
170
- s->base.is_jmp = DISAS_YIELD;
171
+ if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
172
+ gen_helper_vesb(cpu_env);
173
}
174
- break;
175
- case 0b00010: /* WFE */
176
- if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
177
- s->base.is_jmp = DISAS_WFE;
178
- }
179
- break;
180
- case 0b00100: /* SEV */
181
- case 0b00101: /* SEVL */
182
- case 0b00110: /* DGH */
183
- /* we treat all as NOP at least for now */
184
- break;
185
- case 0b00111: /* XPACLRI */
186
- if (s->pauth_active) {
187
- gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
188
- }
189
- break;
190
- case 0b01000: /* PACIA1716 */
191
- if (s->pauth_active) {
192
- gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
193
- }
194
- break;
195
- case 0b01010: /* PACIB1716 */
196
- if (s->pauth_active) {
197
- gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
198
- }
199
- break;
200
- case 0b01100: /* AUTIA1716 */
201
- if (s->pauth_active) {
202
- gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
203
- }
204
- break;
205
- case 0b01110: /* AUTIB1716 */
206
- if (s->pauth_active) {
207
- gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
208
- }
209
- break;
210
- case 0b10000: /* ESB */
211
- /* Without RAS, we must implement this as NOP. */
212
- if (dc_isar_feature(aa64_ras, s)) {
213
- /*
214
- * QEMU does not have a source of physical SErrors,
215
- * so we are only concerned with virtual SErrors.
216
- * The pseudocode in the ARM for this case is
217
- * if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
218
- * AArch64.vESBOperation();
219
- * Most of the condition can be evaluated at translation time.
220
- * Test for EL2 present, and defer test for SEL2 to runtime.
221
- */
222
- if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
223
- gen_helper_vesb(cpu_env);
224
- }
225
- }
226
- break;
227
- case 0b11000: /* PACIAZ */
228
- if (s->pauth_active) {
229
- gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30],
230
- tcg_constant_i64(0));
231
- }
232
- break;
233
- case 0b11001: /* PACIASP */
234
- if (s->pauth_active) {
235
- gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
236
- }
237
- break;
238
- case 0b11010: /* PACIBZ */
239
- if (s->pauth_active) {
240
- gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30],
241
- tcg_constant_i64(0));
242
- }
243
- break;
244
- case 0b11011: /* PACIBSP */
245
- if (s->pauth_active) {
246
- gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
247
- }
248
- break;
249
- case 0b11100: /* AUTIAZ */
250
- if (s->pauth_active) {
251
- gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30],
252
- tcg_constant_i64(0));
253
- }
254
- break;
255
- case 0b11101: /* AUTIASP */
256
- if (s->pauth_active) {
257
- gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
258
- }
259
- break;
260
- case 0b11110: /* AUTIBZ */
261
- if (s->pauth_active) {
262
- gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30],
263
- tcg_constant_i64(0));
264
- }
265
- break;
266
- case 0b11111: /* AUTIBSP */
267
- if (s->pauth_active) {
268
- gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
269
- }
270
- break;
271
- default:
272
- /* default specified as NOP equivalent */
273
- break;
274
}
275
+ return true;
276
+}
277
+
278
+static bool trans_PACIAZ(DisasContext *s, arg_PACIAZ *a)
279
+{
280
+ if (s->pauth_active) {
281
+ gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
282
+ }
283
+ return true;
284
+}
285
+
286
+static bool trans_PACIASP(DisasContext *s, arg_PACIASP *a)
287
+{
288
+ if (s->pauth_active) {
289
+ gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
290
+ }
291
+ return true;
292
+}
293
+
294
+static bool trans_PACIBZ(DisasContext *s, arg_PACIBZ *a)
295
+{
296
+ if (s->pauth_active) {
297
+ gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
298
+ }
299
+ return true;
300
+}
301
+
302
+static bool trans_PACIBSP(DisasContext *s, arg_PACIBSP *a)
303
+{
304
+ if (s->pauth_active) {
305
+ gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
306
+ }
307
+ return true;
308
+}
309
+
310
+static bool trans_AUTIAZ(DisasContext *s, arg_AUTIAZ *a)
311
+{
312
+ if (s->pauth_active) {
313
+ gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
314
+ }
315
+ return true;
316
+}
317
+
318
+static bool trans_AUTIASP(DisasContext *s, arg_AUTIASP *a)
319
+{
320
+ if (s->pauth_active) {
321
+ gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
322
+ }
323
+ return true;
324
+}
325
+
326
+static bool trans_AUTIBZ(DisasContext *s, arg_AUTIBZ *a)
327
+{
328
+ if (s->pauth_active) {
329
+ gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
330
+ }
331
+ return true;
332
+}
333
+
334
+static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
335
+{
336
+ if (s->pauth_active) {
337
+ gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
338
+ }
339
+ return true;
340
}
341
342
static void gen_clrex(DisasContext *s, uint32_t insn)
343
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
344
return;
345
}
346
switch (crn) {
347
- case 2: /* HINT (including allocated hints like NOP, YIELD, etc) */
348
- handle_hint(s, insn, op1, op2, crm);
349
- break;
350
case 3: /* CLREX, DSB, DMB, ISB */
351
handle_sync(s, insn, op1, op2, crm);
352
break;
353
--
354
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the insns in the "Barriers" instruction class to
2
decodetree: CLREX, DSB, DMB, ISB and SB.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-4-peter.maydell@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
---
9
target/arm/tcg/a64.decode | 7 +++
10
target/arm/tcg/translate-a64.c | 92 ++++++++++++++--------------------
11
2 files changed, 46 insertions(+), 53 deletions(-)
12
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
16
+++ b/target/arm/tcg/a64.decode
17
@@ -XXX,XX +XXX,XX @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
18
# that isn't specifically allocated to an instruction must NOP
19
NOP 1101 0101 0000 0011 0010 ---- --- 11111
20
}
21
+
22
+# Barriers
23
+
24
+CLREX 1101 0101 0000 0011 0011 ---- 010 11111
25
+DSB_DMB 1101 0101 0000 0011 0011 domain:2 types:2 10- 11111
26
+ISB 1101 0101 0000 0011 0011 ---- 110 11111
27
+SB 1101 0101 0000 0011 0011 0000 111 11111
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/tcg/translate-a64.c
31
+++ b/target/arm/tcg/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
33
return true;
34
}
35
36
-static void gen_clrex(DisasContext *s, uint32_t insn)
37
+static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
38
{
39
tcg_gen_movi_i64(cpu_exclusive_addr, -1);
40
+ return true;
41
}
42
43
-/* CLREX, DSB, DMB, ISB */
44
-static void handle_sync(DisasContext *s, uint32_t insn,
45
- unsigned int op1, unsigned int op2, unsigned int crm)
46
+static bool trans_DSB_DMB(DisasContext *s, arg_DSB_DMB *a)
47
{
48
+ /* We handle DSB and DMB the same way */
49
TCGBar bar;
50
51
- if (op1 != 3) {
52
- unallocated_encoding(s);
53
- return;
54
+ switch (a->types) {
55
+ case 1: /* MBReqTypes_Reads */
56
+ bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
57
+ break;
58
+ case 2: /* MBReqTypes_Writes */
59
+ bar = TCG_BAR_SC | TCG_MO_ST_ST;
60
+ break;
61
+ default: /* MBReqTypes_All */
62
+ bar = TCG_BAR_SC | TCG_MO_ALL;
63
+ break;
64
}
65
+ tcg_gen_mb(bar);
66
+ return true;
67
+}
68
69
- switch (op2) {
70
- case 2: /* CLREX */
71
- gen_clrex(s, insn);
72
- return;
73
- case 4: /* DSB */
74
- case 5: /* DMB */
75
- switch (crm & 3) {
76
- case 1: /* MBReqTypes_Reads */
77
- bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
78
- break;
79
- case 2: /* MBReqTypes_Writes */
80
- bar = TCG_BAR_SC | TCG_MO_ST_ST;
81
- break;
82
- default: /* MBReqTypes_All */
83
- bar = TCG_BAR_SC | TCG_MO_ALL;
84
- break;
85
- }
86
- tcg_gen_mb(bar);
87
- return;
88
- case 6: /* ISB */
89
- /* We need to break the TB after this insn to execute
90
- * a self-modified code correctly and also to take
91
- * any pending interrupts immediately.
92
- */
93
- reset_btype(s);
94
- gen_goto_tb(s, 0, 4);
95
- return;
96
+static bool trans_ISB(DisasContext *s, arg_ISB *a)
97
+{
98
+ /*
99
+ * We need to break the TB after this insn to execute
100
+ * self-modifying code correctly and also to take
101
+ * any pending interrupts immediately.
102
+ */
103
+ reset_btype(s);
104
+ gen_goto_tb(s, 0, 4);
105
+ return true;
106
+}
107
108
- case 7: /* SB */
109
- if (crm != 0 || !dc_isar_feature(aa64_sb, s)) {
110
- goto do_unallocated;
111
- }
112
- /*
113
- * TODO: There is no speculation barrier opcode for TCG;
114
- * MB and end the TB instead.
115
- */
116
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
117
- gen_goto_tb(s, 0, 4);
118
- return;
119
-
120
- default:
121
- do_unallocated:
122
- unallocated_encoding(s);
123
- return;
124
+static bool trans_SB(DisasContext *s, arg_SB *a)
125
+{
126
+ if (!dc_isar_feature(aa64_sb, s)) {
127
+ return false;
128
}
129
+ /*
130
+ * TODO: There is no speculation barrier opcode for TCG;
131
+ * MB and end the TB instead.
132
+ */
133
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
134
+ gen_goto_tb(s, 0, 4);
135
+ return true;
136
}
137
138
static void gen_xaflag(void)
139
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
140
return;
141
}
142
switch (crn) {
143
- case 3: /* CLREX, DSB, DMB, ISB */
144
- handle_sync(s, insn, op1, op2, crm);
145
- break;
146
case 4: /* MSR (immediate) */
147
handle_msr_i(s, insn, op1, op2, crm);
148
break;
149
--
150
2.34.1
151
152
diff view generated by jsdifflib
Deleted patch
1
Convert the CFINV, XAFLAG and AXFLAG insns to decodetree.
2
The old decoder handles these in handle_msr_i(), but
3
the architecture defines them as separate instructions
4
from MSR (immediate).
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230602155223.2040685-5-peter.maydell@linaro.org
9
---
10
target/arm/tcg/a64.decode | 6 ++++
11
target/arm/tcg/translate-a64.c | 53 +++++++++++++++++-----------------
12
2 files changed, 32 insertions(+), 27 deletions(-)
13
14
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/tcg/a64.decode
17
+++ b/target/arm/tcg/a64.decode
18
@@ -XXX,XX +XXX,XX @@ CLREX 1101 0101 0000 0011 0011 ---- 010 11111
19
DSB_DMB 1101 0101 0000 0011 0011 domain:2 types:2 10- 11111
20
ISB 1101 0101 0000 0011 0011 ---- 110 11111
21
SB 1101 0101 0000 0011 0011 0000 111 11111
22
+
23
+# PSTATE
24
+
25
+CFINV 1101 0101 0000 0 000 0100 0000 000 11111
26
+XAFLAG 1101 0101 0000 0 000 0100 0000 001 11111
27
+AXFLAG 1101 0101 0000 0 000 0100 0000 010 11111
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/tcg/translate-a64.c
31
+++ b/target/arm/tcg/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_SB(DisasContext *s, arg_SB *a)
33
return true;
34
}
35
36
-static void gen_xaflag(void)
37
+static bool trans_CFINV(DisasContext *s, arg_CFINV *a)
38
{
39
- TCGv_i32 z = tcg_temp_new_i32();
40
+ if (!dc_isar_feature(aa64_condm_4, s)) {
41
+ return false;
42
+ }
43
+ tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
44
+ return true;
45
+}
46
+
47
+static bool trans_XAFLAG(DisasContext *s, arg_XAFLAG *a)
48
+{
49
+ TCGv_i32 z;
50
+
51
+ if (!dc_isar_feature(aa64_condm_5, s)) {
52
+ return false;
53
+ }
54
+
55
+ z = tcg_temp_new_i32();
56
57
tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
58
59
@@ -XXX,XX +XXX,XX @@ static void gen_xaflag(void)
60
61
/* C | Z */
62
tcg_gen_or_i32(cpu_CF, cpu_CF, z);
63
+
64
+ return true;
65
}
66
67
-static void gen_axflag(void)
68
+static bool trans_AXFLAG(DisasContext *s, arg_AXFLAG *a)
69
{
70
+ if (!dc_isar_feature(aa64_condm_5, s)) {
71
+ return false;
72
+ }
73
+
74
tcg_gen_sari_i32(cpu_VF, cpu_VF, 31); /* V ? -1 : 0 */
75
tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF); /* C & !V */
76
77
@@ -XXX,XX +XXX,XX @@ static void gen_axflag(void)
78
79
tcg_gen_movi_i32(cpu_NF, 0);
80
tcg_gen_movi_i32(cpu_VF, 0);
81
+
82
+ return true;
83
}
84
85
/* MSR (immediate) - move immediate to processor state field */
86
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
87
s->base.is_jmp = DISAS_TOO_MANY;
88
89
switch (op) {
90
- case 0x00: /* CFINV */
91
- if (crm != 0 || !dc_isar_feature(aa64_condm_4, s)) {
92
- goto do_unallocated;
93
- }
94
- tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
95
- s->base.is_jmp = DISAS_NEXT;
96
- break;
97
-
98
- case 0x01: /* XAFlag */
99
- if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
100
- goto do_unallocated;
101
- }
102
- gen_xaflag();
103
- s->base.is_jmp = DISAS_NEXT;
104
- break;
105
-
106
- case 0x02: /* AXFlag */
107
- if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
108
- goto do_unallocated;
109
- }
110
- gen_axflag();
111
- s->base.is_jmp = DISAS_NEXT;
112
- break;
113
-
114
case 0x03: /* UAO */
115
if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
116
goto do_unallocated;
117
--
118
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the MSR (immediate) insn to decodetree. Our implementation
2
has basically no commonality between the different destinations,
3
so we decode the destination register in a64.decode.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230602155223.2040685-6-peter.maydell@linaro.org
8
---
9
target/arm/tcg/a64.decode | 13 ++
10
target/arm/tcg/translate-a64.c | 251 ++++++++++++++++-----------------
11
2 files changed, 136 insertions(+), 128 deletions(-)
12
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
16
+++ b/target/arm/tcg/a64.decode
17
@@ -XXX,XX +XXX,XX @@ SB 1101 0101 0000 0011 0011 0000 111 11111
18
CFINV 1101 0101 0000 0 000 0100 0000 000 11111
19
XAFLAG 1101 0101 0000 0 000 0100 0000 001 11111
20
AXFLAG 1101 0101 0000 0 000 0100 0000 010 11111
21
+
22
+# These are architecturally all "MSR (immediate)"; we decode the destination
23
+# register too because there is no commonality in our implementation.
24
+@msr_i .... .... .... . ... .... imm:4 ... .....
25
+MSR_i_UAO 1101 0101 0000 0 000 0100 .... 011 11111 @msr_i
26
+MSR_i_PAN 1101 0101 0000 0 000 0100 .... 100 11111 @msr_i
27
+MSR_i_SPSEL 1101 0101 0000 0 000 0100 .... 101 11111 @msr_i
28
+MSR_i_SBSS 1101 0101 0000 0 011 0100 .... 001 11111 @msr_i
29
+MSR_i_DIT 1101 0101 0000 0 011 0100 .... 010 11111 @msr_i
30
+MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
31
+MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
32
+MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
33
+MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
34
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/tcg/translate-a64.c
37
+++ b/target/arm/tcg/translate-a64.c
38
@@ -XXX,XX +XXX,XX @@ static bool trans_AXFLAG(DisasContext *s, arg_AXFLAG *a)
39
return true;
40
}
41
42
-/* MSR (immediate) - move immediate to processor state field */
43
-static void handle_msr_i(DisasContext *s, uint32_t insn,
44
- unsigned int op1, unsigned int op2, unsigned int crm)
45
+static bool trans_MSR_i_UAO(DisasContext *s, arg_i *a)
46
{
47
- int op = op1 << 3 | op2;
48
-
49
- /* End the TB by default, chaining is ok. */
50
- s->base.is_jmp = DISAS_TOO_MANY;
51
-
52
- switch (op) {
53
- case 0x03: /* UAO */
54
- if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
55
- goto do_unallocated;
56
- }
57
- if (crm & 1) {
58
- set_pstate_bits(PSTATE_UAO);
59
- } else {
60
- clear_pstate_bits(PSTATE_UAO);
61
- }
62
- gen_rebuild_hflags(s);
63
- break;
64
-
65
- case 0x04: /* PAN */
66
- if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
67
- goto do_unallocated;
68
- }
69
- if (crm & 1) {
70
- set_pstate_bits(PSTATE_PAN);
71
- } else {
72
- clear_pstate_bits(PSTATE_PAN);
73
- }
74
- gen_rebuild_hflags(s);
75
- break;
76
-
77
- case 0x05: /* SPSel */
78
- if (s->current_el == 0) {
79
- goto do_unallocated;
80
- }
81
- gen_helper_msr_i_spsel(cpu_env, tcg_constant_i32(crm & PSTATE_SP));
82
- break;
83
-
84
- case 0x19: /* SSBS */
85
- if (!dc_isar_feature(aa64_ssbs, s)) {
86
- goto do_unallocated;
87
- }
88
- if (crm & 1) {
89
- set_pstate_bits(PSTATE_SSBS);
90
- } else {
91
- clear_pstate_bits(PSTATE_SSBS);
92
- }
93
- /* Don't need to rebuild hflags since SSBS is a nop */
94
- break;
95
-
96
- case 0x1a: /* DIT */
97
- if (!dc_isar_feature(aa64_dit, s)) {
98
- goto do_unallocated;
99
- }
100
- if (crm & 1) {
101
- set_pstate_bits(PSTATE_DIT);
102
- } else {
103
- clear_pstate_bits(PSTATE_DIT);
104
- }
105
- /* There's no need to rebuild hflags because DIT is a nop */
106
- break;
107
-
108
- case 0x1e: /* DAIFSet */
109
- gen_helper_msr_i_daifset(cpu_env, tcg_constant_i32(crm));
110
- break;
111
-
112
- case 0x1f: /* DAIFClear */
113
- gen_helper_msr_i_daifclear(cpu_env, tcg_constant_i32(crm));
114
- /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs. */
115
- s->base.is_jmp = DISAS_UPDATE_EXIT;
116
- break;
117
-
118
- case 0x1c: /* TCO */
119
- if (dc_isar_feature(aa64_mte, s)) {
120
- /* Full MTE is enabled -- set the TCO bit as directed. */
121
- if (crm & 1) {
122
- set_pstate_bits(PSTATE_TCO);
123
- } else {
124
- clear_pstate_bits(PSTATE_TCO);
125
- }
126
- gen_rebuild_hflags(s);
127
- /* Many factors, including TCO, go into MTE_ACTIVE. */
128
- s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
129
- } else if (dc_isar_feature(aa64_mte_insn_reg, s)) {
130
- /* Only "instructions accessible at EL0" -- PSTATE.TCO is WI. */
131
- s->base.is_jmp = DISAS_NEXT;
132
- } else {
133
- goto do_unallocated;
134
- }
135
- break;
136
-
137
- case 0x1b: /* SVCR* */
138
- if (!dc_isar_feature(aa64_sme, s) || crm < 2 || crm > 7) {
139
- goto do_unallocated;
140
- }
141
- if (sme_access_check(s)) {
142
- int old = s->pstate_sm | (s->pstate_za << 1);
143
- int new = (crm & 1) * 3;
144
- int msk = (crm >> 1) & 3;
145
-
146
- if ((old ^ new) & msk) {
147
- /* At least one bit changes. */
148
- gen_helper_set_svcr(cpu_env, tcg_constant_i32(new),
149
- tcg_constant_i32(msk));
150
- } else {
151
- s->base.is_jmp = DISAS_NEXT;
152
- }
153
- }
154
- break;
155
-
156
- default:
157
- do_unallocated:
158
- unallocated_encoding(s);
159
- return;
160
+ if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
161
+ return false;
162
}
163
+ if (a->imm & 1) {
164
+ set_pstate_bits(PSTATE_UAO);
165
+ } else {
166
+ clear_pstate_bits(PSTATE_UAO);
167
+ }
168
+ gen_rebuild_hflags(s);
169
+ s->base.is_jmp = DISAS_TOO_MANY;
170
+ return true;
171
+}
172
+
173
+static bool trans_MSR_i_PAN(DisasContext *s, arg_i *a)
174
+{
175
+ if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
176
+ return false;
177
+ }
178
+ if (a->imm & 1) {
179
+ set_pstate_bits(PSTATE_PAN);
180
+ } else {
181
+ clear_pstate_bits(PSTATE_PAN);
182
+ }
183
+ gen_rebuild_hflags(s);
184
+ s->base.is_jmp = DISAS_TOO_MANY;
185
+ return true;
186
+}
187
+
188
+static bool trans_MSR_i_SPSEL(DisasContext *s, arg_i *a)
189
+{
190
+ if (s->current_el == 0) {
191
+ return false;
192
+ }
193
+ gen_helper_msr_i_spsel(cpu_env, tcg_constant_i32(a->imm & PSTATE_SP));
194
+ s->base.is_jmp = DISAS_TOO_MANY;
195
+ return true;
196
+}
197
+
198
+static bool trans_MSR_i_SBSS(DisasContext *s, arg_i *a)
199
+{
200
+ if (!dc_isar_feature(aa64_ssbs, s)) {
201
+ return false;
202
+ }
203
+ if (a->imm & 1) {
204
+ set_pstate_bits(PSTATE_SSBS);
205
+ } else {
206
+ clear_pstate_bits(PSTATE_SSBS);
207
+ }
208
+ /* Don't need to rebuild hflags since SSBS is a nop */
209
+ s->base.is_jmp = DISAS_TOO_MANY;
210
+ return true;
211
+}
212
+
213
+static bool trans_MSR_i_DIT(DisasContext *s, arg_i *a)
214
+{
215
+ if (!dc_isar_feature(aa64_dit, s)) {
216
+ return false;
217
+ }
218
+ if (a->imm & 1) {
219
+ set_pstate_bits(PSTATE_DIT);
220
+ } else {
221
+ clear_pstate_bits(PSTATE_DIT);
222
+ }
223
+ /* There's no need to rebuild hflags because DIT is a nop */
224
+ s->base.is_jmp = DISAS_TOO_MANY;
225
+ return true;
226
+}
227
+
228
+static bool trans_MSR_i_TCO(DisasContext *s, arg_i *a)
229
+{
230
+ if (dc_isar_feature(aa64_mte, s)) {
231
+ /* Full MTE is enabled -- set the TCO bit as directed. */
232
+ if (a->imm & 1) {
233
+ set_pstate_bits(PSTATE_TCO);
234
+ } else {
235
+ clear_pstate_bits(PSTATE_TCO);
236
+ }
237
+ gen_rebuild_hflags(s);
238
+ /* Many factors, including TCO, go into MTE_ACTIVE. */
239
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
240
+ return true;
241
+ } else if (dc_isar_feature(aa64_mte_insn_reg, s)) {
242
+ /* Only "instructions accessible at EL0" -- PSTATE.TCO is WI. */
243
+ return true;
244
+ } else {
245
+ /* Insn not present */
246
+ return false;
247
+ }
248
+}
249
+
250
+static bool trans_MSR_i_DAIFSET(DisasContext *s, arg_i *a)
251
+{
252
+ gen_helper_msr_i_daifset(cpu_env, tcg_constant_i32(a->imm));
253
+ s->base.is_jmp = DISAS_TOO_MANY;
254
+ return true;
255
+}
256
+
257
+static bool trans_MSR_i_DAIFCLEAR(DisasContext *s, arg_i *a)
258
+{
259
+ gen_helper_msr_i_daifclear(cpu_env, tcg_constant_i32(a->imm));
260
+ /* Exit the cpu loop to re-evaluate pending IRQs. */
261
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
262
+ return true;
263
+}
264
+
265
+static bool trans_MSR_i_SVCR(DisasContext *s, arg_MSR_i_SVCR *a)
266
+{
267
+ if (!dc_isar_feature(aa64_sme, s) || a->mask == 0) {
268
+ return false;
269
+ }
270
+ if (sme_access_check(s)) {
271
+ int old = s->pstate_sm | (s->pstate_za << 1);
272
+ int new = a->imm * 3;
273
+
274
+ if ((old ^ new) & a->mask) {
275
+ /* At least one bit changes. */
276
+ gen_helper_set_svcr(cpu_env, tcg_constant_i32(new),
277
+ tcg_constant_i32(a->mask));
278
+ s->base.is_jmp = DISAS_TOO_MANY;
279
+ }
280
+ }
281
+ return true;
282
}
283
284
static void gen_get_nzcv(TCGv_i64 tcg_rt)
285
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
286
rt = extract32(insn, 0, 5);
287
288
if (op0 == 0) {
289
- if (l || rt != 31) {
290
- unallocated_encoding(s);
291
- return;
292
- }
293
- switch (crn) {
294
- case 4: /* MSR (immediate) */
295
- handle_msr_i(s, insn, op1, op2, crm);
296
- break;
297
- default:
298
- unallocated_encoding(s);
299
- break;
300
- }
301
+ unallocated_encoding(s);
302
return;
303
}
304
handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
305
--
306
2.34.1
diff view generated by jsdifflib
1
In commit 2c5fa0778c3b430 we fixed an endianness bug in the Allwinner
1
cpu.h has a lot of #defines relating to CPU register fields.
2
A10 PIC model; however in the process we introduced a regression.
2
Most of these aren't actually used outside target/arm code,
3
This is because the old code was robust against the incoming 'level'
3
so there's no point in cluttering up the cpu.h file with them.
4
argument being something other than 0 or 1, whereas the new code was
4
Move some easy ones to internals.h.
5
not.
6
5
7
In particular, the allwinner-sdhost code treats its IRQ line
8
as 0-vs-non-0 rather than 0-vs-1, so when the SD controller
9
set its IRQ line for any reason other than transmit the
10
interrupt controller would ignore it. The observed effect
11
was a guest timeout when rebooting the guest kernel.
12
13
Handle level values other than 0 or 1, to restore the old
14
behaviour.
15
16
Fixes: 2c5fa0778c3b430 ("hw/intc/allwinner-a10-pic: Don't use set_bit()/clear_bit()")
17
Cc: qemu-stable@nongnu.org
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20230606104609.3692557-2-peter.maydell@linaro.org
9
Message-id: 20240301183219.2424889-2-peter.maydell@linaro.org
22
---
10
---
23
hw/intc/allwinner-a10-pic.c | 2 +-
11
target/arm/cpu.h | 128 -----------------------------------------
24
1 file changed, 1 insertion(+), 1 deletion(-)
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 128 insertions(+), 128 deletions(-)
25
14
26
diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/intc/allwinner-a10-pic.c
17
--- a/target/arm/cpu.h
29
+++ b/hw/intc/allwinner-a10-pic.c
18
+++ b/target/arm/cpu.h
30
@@ -XXX,XX +XXX,XX @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
31
AwA10PICState *s = opaque;
20
uint64_t ctl; /* Timer Control register */
32
uint32_t *pending_reg = &s->irq_pending[irq / 32];
21
} ARMGenericTimer;
33
22
34
- *pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
23
-#define VTCR_NSW (1u << 29)
35
+ *pending_reg = deposit32(*pending_reg, irq % 32, 1, !!level);
24
-#define VTCR_NSA (1u << 30)
36
aw_a10_pic_update(s);
25
-#define VSTCR_SW VTCR_NSW
37
}
26
-#define VSTCR_SA VTCR_NSA
38
27
-
28
/* Define a maximum sized vector register.
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
30
* For 64-bit, this is a 2048-bit SVE register.
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
34
35
-/* Bit definitions for CPACR (AArch32 only) */
36
-FIELD(CPACR, CP10, 20, 2)
37
-FIELD(CPACR, CP11, 22, 2)
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
40
-FIELD(CPACR, ASEDIS, 31, 1)
41
-
42
-/* Bit definitions for CPACR_EL1 (AArch64 only) */
43
-FIELD(CPACR_EL1, ZEN, 16, 2)
44
-FIELD(CPACR_EL1, FPEN, 20, 2)
45
-FIELD(CPACR_EL1, SMEN, 24, 2)
46
-FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
47
-
48
-/* Bit definitions for HCPTR (AArch32 only) */
49
-FIELD(HCPTR, TCP10, 10, 1)
50
-FIELD(HCPTR, TCP11, 11, 1)
51
-FIELD(HCPTR, TASE, 15, 1)
52
-FIELD(HCPTR, TTA, 20, 1)
53
-FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
54
-FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
55
-
56
-/* Bit definitions for CPTR_EL2 (AArch64 only) */
57
-FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
58
-FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
59
-FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
60
-FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
61
-FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
62
-FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
63
-FIELD(CPTR_EL2, TTA, 28, 1)
64
-FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
65
-FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
66
-
67
-/* Bit definitions for CPTR_EL3 (AArch64 only) */
68
-FIELD(CPTR_EL3, EZ, 8, 1)
69
-FIELD(CPTR_EL3, TFP, 10, 1)
70
-FIELD(CPTR_EL3, ESM, 12, 1)
71
-FIELD(CPTR_EL3, TTA, 20, 1)
72
-FIELD(CPTR_EL3, TAM, 30, 1)
73
-FIELD(CPTR_EL3, TCPAC, 31, 1)
74
-
75
-#define MDCR_MTPME (1U << 28)
76
-#define MDCR_TDCC (1U << 27)
77
-#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
78
-#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
79
-#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
80
-#define MDCR_EPMAD (1U << 21)
81
-#define MDCR_EDAD (1U << 20)
82
-#define MDCR_TTRF (1U << 19)
83
-#define MDCR_STE (1U << 18) /* MDCR_EL3 */
84
-#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
85
-#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
86
-#define MDCR_SDD (1U << 16)
87
-#define MDCR_SPD (3U << 14)
88
-#define MDCR_TDRA (1U << 11)
89
-#define MDCR_TDOSA (1U << 10)
90
-#define MDCR_TDA (1U << 9)
91
-#define MDCR_TDE (1U << 8)
92
-#define MDCR_HPME (1U << 7)
93
-#define MDCR_TPM (1U << 6)
94
-#define MDCR_TPMCR (1U << 5)
95
-#define MDCR_HPMN (0x1fU)
96
-
97
-/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
98
-#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
99
- MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
100
- MDCR_STE | MDCR_SPME | MDCR_SPD)
101
-
102
#define CPSR_M (0x1fU)
103
#define CPSR_T (1U << 5)
104
#define CPSR_F (1U << 6)
105
@@ -XXX,XX +XXX,XX @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
106
#define XPSR_NZCV CPSR_NZCV
107
#define XPSR_IT CPSR_IT
108
109
-#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
110
-#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
111
-#define TTBCR_PD0 (1U << 4)
112
-#define TTBCR_PD1 (1U << 5)
113
-#define TTBCR_EPD0 (1U << 7)
114
-#define TTBCR_IRGN0 (3U << 8)
115
-#define TTBCR_ORGN0 (3U << 10)
116
-#define TTBCR_SH0 (3U << 12)
117
-#define TTBCR_T1SZ (3U << 16)
118
-#define TTBCR_A1 (1U << 22)
119
-#define TTBCR_EPD1 (1U << 23)
120
-#define TTBCR_IRGN1 (3U << 24)
121
-#define TTBCR_ORGN1 (3U << 26)
122
-#define TTBCR_SH1 (1U << 28)
123
-#define TTBCR_EAE (1U << 31)
124
-
125
-FIELD(VTCR, T0SZ, 0, 6)
126
-FIELD(VTCR, SL0, 6, 2)
127
-FIELD(VTCR, IRGN0, 8, 2)
128
-FIELD(VTCR, ORGN0, 10, 2)
129
-FIELD(VTCR, SH0, 12, 2)
130
-FIELD(VTCR, TG0, 14, 2)
131
-FIELD(VTCR, PS, 16, 3)
132
-FIELD(VTCR, VS, 19, 1)
133
-FIELD(VTCR, HA, 21, 1)
134
-FIELD(VTCR, HD, 22, 1)
135
-FIELD(VTCR, HWU59, 25, 1)
136
-FIELD(VTCR, HWU60, 26, 1)
137
-FIELD(VTCR, HWU61, 27, 1)
138
-FIELD(VTCR, HWU62, 28, 1)
139
-FIELD(VTCR, NSW, 29, 1)
140
-FIELD(VTCR, NSA, 30, 1)
141
-FIELD(VTCR, DS, 32, 1)
142
-FIELD(VTCR, SL2, 33, 1)
143
-
144
/* Bit definitions for ARMv8 SPSR (PSTATE) format.
145
* Only these are valid when in AArch64 mode; in
146
* AArch32 mode SPSRs are basically CPSR-format.
147
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
148
#define HCR_TWEDEN (1ULL << 59)
149
#define HCR_TWEDEL MAKE_64BIT_MASK(60, 4)
150
151
-#define HCRX_ENAS0 (1ULL << 0)
152
-#define HCRX_ENALS (1ULL << 1)
153
-#define HCRX_ENASR (1ULL << 2)
154
-#define HCRX_FNXS (1ULL << 3)
155
-#define HCRX_FGTNXS (1ULL << 4)
156
-#define HCRX_SMPME (1ULL << 5)
157
-#define HCRX_TALLINT (1ULL << 6)
158
-#define HCRX_VINMI (1ULL << 7)
159
-#define HCRX_VFNMI (1ULL << 8)
160
-#define HCRX_CMOW (1ULL << 9)
161
-#define HCRX_MCE2 (1ULL << 10)
162
-#define HCRX_MSCEN (1ULL << 11)
163
-
164
-#define HPFAR_NS (1ULL << 63)
165
-
166
#define SCR_NS (1ULL << 0)
167
#define SCR_IRQ (1ULL << 1)
168
#define SCR_FIQ (1ULL << 2)
169
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
170
#define SCR_GPF (1ULL << 48)
171
#define SCR_NSE (1ULL << 62)
172
173
-#define HSTR_TTEE (1 << 16)
174
-#define HSTR_TJDBX (1 << 17)
175
-
176
-#define CNTHCTL_CNTVMASK (1 << 18)
177
-#define CNTHCTL_CNTPMASK (1 << 19)
178
-
179
/* Return the current FPSCR value. */
180
uint32_t vfp_get_fpscr(CPUARMState *env);
181
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
182
diff --git a/target/arm/internals.h b/target/arm/internals.h
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/internals.h
185
+++ b/target/arm/internals.h
186
@@ -XXX,XX +XXX,XX @@ FIELD(DBGWCR, WT, 20, 1)
187
FIELD(DBGWCR, MASK, 24, 5)
188
FIELD(DBGWCR, SSCE, 29, 1)
189
190
+#define VTCR_NSW (1u << 29)
191
+#define VTCR_NSA (1u << 30)
192
+#define VSTCR_SW VTCR_NSW
193
+#define VSTCR_SA VTCR_NSA
194
+
195
+/* Bit definitions for CPACR (AArch32 only) */
196
+FIELD(CPACR, CP10, 20, 2)
197
+FIELD(CPACR, CP11, 22, 2)
198
+FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
199
+FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
200
+FIELD(CPACR, ASEDIS, 31, 1)
201
+
202
+/* Bit definitions for CPACR_EL1 (AArch64 only) */
203
+FIELD(CPACR_EL1, ZEN, 16, 2)
204
+FIELD(CPACR_EL1, FPEN, 20, 2)
205
+FIELD(CPACR_EL1, SMEN, 24, 2)
206
+FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
207
+
208
+/* Bit definitions for HCPTR (AArch32 only) */
209
+FIELD(HCPTR, TCP10, 10, 1)
210
+FIELD(HCPTR, TCP11, 11, 1)
211
+FIELD(HCPTR, TASE, 15, 1)
212
+FIELD(HCPTR, TTA, 20, 1)
213
+FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
214
+FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
215
+
216
+/* Bit definitions for CPTR_EL2 (AArch64 only) */
217
+FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
218
+FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
219
+FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
220
+FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
221
+FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
222
+FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
223
+FIELD(CPTR_EL2, TTA, 28, 1)
224
+FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
225
+FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
226
+
227
+/* Bit definitions for CPTR_EL3 (AArch64 only) */
228
+FIELD(CPTR_EL3, EZ, 8, 1)
229
+FIELD(CPTR_EL3, TFP, 10, 1)
230
+FIELD(CPTR_EL3, ESM, 12, 1)
231
+FIELD(CPTR_EL3, TTA, 20, 1)
232
+FIELD(CPTR_EL3, TAM, 30, 1)
233
+FIELD(CPTR_EL3, TCPAC, 31, 1)
234
+
235
+#define MDCR_MTPME (1U << 28)
236
+#define MDCR_TDCC (1U << 27)
237
+#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
238
+#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
239
+#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
240
+#define MDCR_EPMAD (1U << 21)
241
+#define MDCR_EDAD (1U << 20)
242
+#define MDCR_TTRF (1U << 19)
243
+#define MDCR_STE (1U << 18) /* MDCR_EL3 */
244
+#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
245
+#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
246
+#define MDCR_SDD (1U << 16)
247
+#define MDCR_SPD (3U << 14)
248
+#define MDCR_TDRA (1U << 11)
249
+#define MDCR_TDOSA (1U << 10)
250
+#define MDCR_TDA (1U << 9)
251
+#define MDCR_TDE (1U << 8)
252
+#define MDCR_HPME (1U << 7)
253
+#define MDCR_TPM (1U << 6)
254
+#define MDCR_TPMCR (1U << 5)
255
+#define MDCR_HPMN (0x1fU)
256
+
257
+/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
258
+#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
259
+ MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
260
+ MDCR_STE | MDCR_SPME | MDCR_SPD)
261
+
262
+#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
263
+#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
264
+#define TTBCR_PD0 (1U << 4)
265
+#define TTBCR_PD1 (1U << 5)
266
+#define TTBCR_EPD0 (1U << 7)
267
+#define TTBCR_IRGN0 (3U << 8)
268
+#define TTBCR_ORGN0 (3U << 10)
269
+#define TTBCR_SH0 (3U << 12)
270
+#define TTBCR_T1SZ (3U << 16)
271
+#define TTBCR_A1 (1U << 22)
272
+#define TTBCR_EPD1 (1U << 23)
273
+#define TTBCR_IRGN1 (3U << 24)
274
+#define TTBCR_ORGN1 (3U << 26)
275
+#define TTBCR_SH1 (1U << 28)
276
+#define TTBCR_EAE (1U << 31)
277
+
278
+FIELD(VTCR, T0SZ, 0, 6)
279
+FIELD(VTCR, SL0, 6, 2)
280
+FIELD(VTCR, IRGN0, 8, 2)
281
+FIELD(VTCR, ORGN0, 10, 2)
282
+FIELD(VTCR, SH0, 12, 2)
283
+FIELD(VTCR, TG0, 14, 2)
284
+FIELD(VTCR, PS, 16, 3)
285
+FIELD(VTCR, VS, 19, 1)
286
+FIELD(VTCR, HA, 21, 1)
287
+FIELD(VTCR, HD, 22, 1)
288
+FIELD(VTCR, HWU59, 25, 1)
289
+FIELD(VTCR, HWU60, 26, 1)
290
+FIELD(VTCR, HWU61, 27, 1)
291
+FIELD(VTCR, HWU62, 28, 1)
292
+FIELD(VTCR, NSW, 29, 1)
293
+FIELD(VTCR, NSA, 30, 1)
294
+FIELD(VTCR, DS, 32, 1)
295
+FIELD(VTCR, SL2, 33, 1)
296
+
297
+#define HCRX_ENAS0 (1ULL << 0)
298
+#define HCRX_ENALS (1ULL << 1)
299
+#define HCRX_ENASR (1ULL << 2)
300
+#define HCRX_FNXS (1ULL << 3)
301
+#define HCRX_FGTNXS (1ULL << 4)
302
+#define HCRX_SMPME (1ULL << 5)
303
+#define HCRX_TALLINT (1ULL << 6)
304
+#define HCRX_VINMI (1ULL << 7)
305
+#define HCRX_VFNMI (1ULL << 8)
306
+#define HCRX_CMOW (1ULL << 9)
307
+#define HCRX_MCE2 (1ULL << 10)
308
+#define HCRX_MSCEN (1ULL << 11)
309
+
310
+#define HPFAR_NS (1ULL << 63)
311
+
312
+#define HSTR_TTEE (1 << 16)
313
+#define HSTR_TJDBX (1 << 17)
314
+
315
+#define CNTHCTL_CNTVMASK (1 << 18)
316
+#define CNTHCTL_CNTPMASK (1 << 19)
317
+
318
/* We use a few fake FSR values for internal purposes in M profile.
319
* M profile cores don't have A/R format FSRs, but currently our
320
* get_phys_addr() code assumes A/R profile and reports failures via
39
--
321
--
40
2.34.1
322
2.34.1
41
323
42
324
diff view generated by jsdifflib
1
Convert the instructions in the load/store exclusive (STXR,
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
STLXR, LDXR, LDAXR) and load/store ordered (STLR, STLLR,
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
LDAR, LDLAR) to decodetree.
3
delivering the exception to EL2 with the wrong syndrome.
4
5
Note that for STLR, STLLR, LDAR, LDLAR this fixes an under-decoding
6
in the legacy decoder where we were not checking that the RES1 bits
7
in the Rs and Rt2 fields were set.
8
9
The new function ldst_iss_sf() is equivalent to the existing
10
disas_ldst_compute_iss_sf(), but it takes the pre-decoded 'ext' field
11
rather than taking an undecoded two-bit opc field and extracting
12
'ext' from it. Once all the loads and stores have been converted
13
to decodetree disas_ldst_compute_iss_sf() will be unused and
14
can be deleted.
15
4
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20230602155223.2040685-9-peter.maydell@linaro.org
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
19
---
8
---
20
target/arm/tcg/a64.decode | 11 +++
9
target/arm/helper.c | 2 +-
21
target/arm/tcg/translate-a64.c | 154 ++++++++++++++++++++-------------
10
1 file changed, 1 insertion(+), 1 deletion(-)
22
2 files changed, 103 insertions(+), 62 deletions(-)
23
11
24
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
25
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/tcg/a64.decode
14
--- a/target/arm/helper.c
27
+++ b/target/arm/tcg/a64.decode
15
+++ b/target/arm/helper.c
28
@@ -XXX,XX +XXX,XX @@ HLT 1101 0100 010 ................ 000 00 @i16
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
29
# DCPS1 1101 0100 101 ................ 000 01 @i16
17
return CP_ACCESS_OK;
30
# DCPS2 1101 0100 101 ................ 000 10 @i16
31
# DCPS3 1101 0100 101 ................ 000 11 @i16
32
+
33
+# Loads and stores
34
+
35
+&stxr rn rt rt2 rs sz lasr
36
+&stlr rn rt sz lasr
37
+@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
38
+@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
39
+STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
40
+LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
41
+STLR .. 001000 100 11111 . 11111 ..... ..... @stlr # inc STLLR
42
+LDAR .. 001000 110 11111 . 11111 ..... ..... @stlr # inc LDLAR
43
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/tcg/translate-a64.c
46
+++ b/target/arm/tcg/translate-a64.c
47
@@ -XXX,XX +XXX,XX @@ static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
48
return regsize == 64;
49
}
50
51
+static bool ldst_iss_sf(int size, bool sign, bool ext)
52
+{
53
+
54
+ if (sign) {
55
+ /*
56
+ * Signed loads are 64 bit results if we are not going to
57
+ * do a zero-extend from 32 to 64 after the load.
58
+ * (For a store, sign and ext are always false.)
59
+ */
60
+ return !ext;
61
+ } else {
62
+ /* Unsigned loads/stores work at the specified size */
63
+ return size == MO_64;
64
+ }
65
+}
66
+
67
+static bool trans_STXR(DisasContext *s, arg_stxr *a)
68
+{
69
+ if (a->rn == 31) {
70
+ gen_check_sp_alignment(s);
71
+ }
72
+ if (a->lasr) {
73
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
74
+ }
75
+ gen_store_exclusive(s, a->rs, a->rt, a->rt2, a->rn, a->sz, false);
76
+ return true;
77
+}
78
+
79
+static bool trans_LDXR(DisasContext *s, arg_stxr *a)
80
+{
81
+ if (a->rn == 31) {
82
+ gen_check_sp_alignment(s);
83
+ }
84
+ gen_load_exclusive(s, a->rt, a->rt2, a->rn, a->sz, false);
85
+ if (a->lasr) {
86
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
87
+ }
88
+ return true;
89
+}
90
+
91
+static bool trans_STLR(DisasContext *s, arg_stlr *a)
92
+{
93
+ TCGv_i64 clean_addr;
94
+ MemOp memop;
95
+ bool iss_sf = ldst_iss_sf(a->sz, false, false);
96
+
97
+ /*
98
+ * StoreLORelease is the same as Store-Release for QEMU, but
99
+ * needs the feature-test.
100
+ */
101
+ if (!a->lasr && !dc_isar_feature(aa64_lor, s)) {
102
+ return false;
103
+ }
104
+ /* Generate ISS for non-exclusive accesses including LASR. */
105
+ if (a->rn == 31) {
106
+ gen_check_sp_alignment(s);
107
+ }
108
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
109
+ memop = check_ordered_align(s, a->rn, 0, true, a->sz);
110
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, a->rn),
111
+ true, a->rn != 31, memop);
112
+ do_gpr_st(s, cpu_reg(s, a->rt), clean_addr, memop, true, a->rt,
113
+ iss_sf, a->lasr);
114
+ return true;
115
+}
116
+
117
+static bool trans_LDAR(DisasContext *s, arg_stlr *a)
118
+{
119
+ TCGv_i64 clean_addr;
120
+ MemOp memop;
121
+ bool iss_sf = ldst_iss_sf(a->sz, false, false);
122
+
123
+ /* LoadLOAcquire is the same as Load-Acquire for QEMU. */
124
+ if (!a->lasr && !dc_isar_feature(aa64_lor, s)) {
125
+ return false;
126
+ }
127
+ /* Generate ISS for non-exclusive accesses including LASR. */
128
+ if (a->rn == 31) {
129
+ gen_check_sp_alignment(s);
130
+ }
131
+ memop = check_ordered_align(s, a->rn, 0, false, a->sz);
132
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, a->rn),
133
+ false, a->rn != 31, memop);
134
+ do_gpr_ld(s, cpu_reg(s, a->rt), clean_addr, memop, false, true,
135
+ a->rt, iss_sf, a->lasr);
136
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
137
+ return true;
138
+}
139
+
140
/* Load/store exclusive
141
*
142
* 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
143
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
144
int is_lasr = extract32(insn, 15, 1);
145
int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
146
int size = extract32(insn, 30, 2);
147
- TCGv_i64 clean_addr;
148
- MemOp memop;
149
150
switch (o2_L_o1_o0) {
151
- case 0x0: /* STXR */
152
- case 0x1: /* STLXR */
153
- if (rn == 31) {
154
- gen_check_sp_alignment(s);
155
- }
156
- if (is_lasr) {
157
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
158
- }
159
- gen_store_exclusive(s, rs, rt, rt2, rn, size, false);
160
- return;
161
-
162
- case 0x4: /* LDXR */
163
- case 0x5: /* LDAXR */
164
- if (rn == 31) {
165
- gen_check_sp_alignment(s);
166
- }
167
- gen_load_exclusive(s, rt, rt2, rn, size, false);
168
- if (is_lasr) {
169
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
170
- }
171
- return;
172
-
173
- case 0x8: /* STLLR */
174
- if (!dc_isar_feature(aa64_lor, s)) {
175
- break;
176
- }
177
- /* StoreLORelease is the same as Store-Release for QEMU. */
178
- /* fall through */
179
- case 0x9: /* STLR */
180
- /* Generate ISS for non-exclusive accesses including LASR. */
181
- if (rn == 31) {
182
- gen_check_sp_alignment(s);
183
- }
184
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
185
- memop = check_ordered_align(s, rn, 0, true, size);
186
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
187
- true, rn != 31, memop);
188
- do_gpr_st(s, cpu_reg(s, rt), clean_addr, memop, true, rt,
189
- disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
190
- return;
191
-
192
- case 0xc: /* LDLAR */
193
- if (!dc_isar_feature(aa64_lor, s)) {
194
- break;
195
- }
196
- /* LoadLOAcquire is the same as Load-Acquire for QEMU. */
197
- /* fall through */
198
- case 0xd: /* LDAR */
199
- /* Generate ISS for non-exclusive accesses including LASR. */
200
- if (rn == 31) {
201
- gen_check_sp_alignment(s);
202
- }
203
- memop = check_ordered_align(s, rn, 0, false, size);
204
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
205
- false, rn != 31, memop);
206
- do_gpr_ld(s, cpu_reg(s, rt), clean_addr, memop, false, true,
207
- rt, disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
208
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
209
- return;
210
-
211
case 0x2: case 0x3: /* CASP / STXP */
212
if (size & 2) { /* STXP / STLXP */
213
if (rn == 31) {
214
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
215
return;
216
}
217
break;
218
+ default:
219
+ /* Handled in decodetree */
220
+ break;
221
}
18
}
222
unallocated_encoding(s);
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
20
- return CP_ACCESS_TRAP;
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
22
}
23
return CP_ACCESS_OK;
223
}
24
}
224
--
25
--
225
2.34.1
26
2.34.1
diff view generated by jsdifflib
1
QEMU allows qemu_irq lines to transfer arbitrary integers. However
1
We prefer the FIELD macro over ad-hoc #defines for register bits;
2
the convention is that for a simple IRQ line the values transferred
2
switch CNTHCTL to that style before we add any more bits.
3
are always 0 and 1. The A10 SD controller device instead assumes a
4
0-vs-non-0 convention, which happens to work with the interrupt
5
controller it is wired up to.
6
7
Coerce the value to boolean to follow our usual convention.
8
3
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Tested-by: Guenter Roeck <linux@roeck-us.net>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20230606104609.3692557-3-peter.maydell@linaro.org
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
13
---
8
---
14
hw/sd/allwinner-sdhost.c | 2 +-
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
15
1 file changed, 1 insertion(+), 1 deletion(-)
10
target/arm/helper.c | 9 ++++-----
11
2 files changed, 29 insertions(+), 7 deletions(-)
16
12
17
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/sd/allwinner-sdhost.c
15
--- a/target/arm/internals.h
20
+++ b/hw/sd/allwinner-sdhost.c
16
+++ b/target/arm/internals.h
21
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_update_irq(AwSdHostState *s)
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
18
#define HSTR_TTEE (1 << 16)
19
#define HSTR_TJDBX (1 << 17)
20
21
-#define CNTHCTL_CNTVMASK (1 << 18)
22
-#define CNTHCTL_CNTPMASK (1 << 19)
23
+/*
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
25
+ * have different bit definitions, and EL1PCTEN might be
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
27
+ * disambiguate if necessary.
28
+ */
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
40
+FIELD(CNTHCTL, ECV, 12, 1)
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
46
+FIELD(CNTHCTL, CNTVMASK, 18, 1)
47
+FIELD(CNTHCTL, CNTPMASK, 19, 1)
48
49
/* We use a few fake FSR values for internal purposes in M profile.
50
* M profile cores don't have A/R format FSRs, but currently our
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/helper.c
54
+++ b/target/arm/helper.c
55
@@ -XXX,XX +XXX,XX @@ static void gt_update_irq(ARMCPU *cpu, int timeridx)
56
* It is RES0 in Secure and NonSecure state.
57
*/
58
if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
59
- ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
60
- (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
61
+ ((timeridx == GTIMER_VIRT && (cnthctl & R_CNTHCTL_CNTVMASK_MASK)) ||
62
+ (timeridx == GTIMER_PHYS && (cnthctl & R_CNTHCTL_CNTPMASK_MASK)))) {
63
irqstate = 0;
22
}
64
}
23
65
24
trace_allwinner_sdhost_update_irq(irq);
66
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
25
- qemu_set_irq(s->irq, irq);
67
{
26
+ qemu_set_irq(s->irq, !!irq);
68
ARMCPU *cpu = env_archcpu(env);
69
uint32_t oldval = env->cp15.cnthctl_el2;
70
-
71
raw_write(env, ri, value);
72
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
75
gt_update_irq(cpu, GTIMER_VIRT);
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
78
gt_update_irq(cpu, GTIMER_PHYS);
79
}
27
}
80
}
28
29
static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,
30
--
81
--
31
2.34.1
82
2.34.1
32
83
33
84
diff view generated by jsdifflib
1
Convert the instructions in the LDAPR/STLR (unscaled immediate)
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
group to decodetree.
2
This is not strictly architecturally required, but it is how we've
3
tended to implement registers more recently.
4
5
In particular, bits [19:18] are only present with FEAT_RME,
6
and bits [17:12] will only be present with FEAT_ECV.
3
7
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-18-peter.maydell@linaro.org
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
7
---
11
---
8
target/arm/tcg/a64.decode | 10 +++
12
target/arm/helper.c | 18 ++++++++++++++++++
9
target/arm/tcg/translate-a64.c | 132 ++++++++++++---------------------
13
1 file changed, 18 insertions(+)
10
2 files changed, 56 insertions(+), 86 deletions(-)
11
14
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
17
--- a/target/arm/helper.c
15
+++ b/target/arm/tcg/a64.decode
18
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@ LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
17
%ldra_imm 22:s1 12:9 !function=times_2
20
{
18
21
ARMCPU *cpu = env_archcpu(env);
19
LDRA 11 111 0 00 m:1 . 1 ......... w:1 1 rn:5 rt:5 imm=%ldra_imm
22
uint32_t oldval = env->cp15.cnthctl_el2;
23
+ uint32_t valid_mask =
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
26
+ R_CNTHCTL_EVNTEN_MASK |
27
+ R_CNTHCTL_EVNTDIR_MASK |
28
+ R_CNTHCTL_EVNTI_MASK |
29
+ R_CNTHCTL_EL0VTEN_MASK |
30
+ R_CNTHCTL_EL0PTEN_MASK |
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
32
+ R_CNTHCTL_EL1PTEN_MASK;
20
+
33
+
21
+&ldapr_stlr_i rn rt imm sz sign ext
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
22
+@ldapr_stlr_i .. ...... .. . imm:9 .. rn:5 rt:5 &ldapr_stlr_i
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
23
+STLR_i sz:2 011001 00 0 ......... 00 ..... ..... @ldapr_stlr_i sign=0 ext=0
24
+LDAPR_i sz:2 011001 01 0 ......... 00 ..... ..... @ldapr_stlr_i sign=0 ext=0
25
+LDAPR_i 00 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=0
26
+LDAPR_i 01 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=1
27
+LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=2
28
+LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
29
+LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
30
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/tcg/translate-a64.c
33
+++ b/target/arm/tcg/translate-a64.c
34
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
35
}
36
}
37
38
-/* Update the Sixty-Four bit (SF) registersize. This logic is derived
39
+/*
40
+ * Compute the ISS.SF bit for syndrome information if an exception
41
+ * is taken on a load or store. This indicates whether the instruction
42
+ * is accessing a 32-bit or 64-bit register. This logic is derived
43
* from the ARMv8 specs for LDR (Shared decode for all encodings).
44
*/
45
-static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
46
-{
47
- int opc0 = extract32(opc, 0, 1);
48
- int regsize;
49
-
50
- if (is_signed) {
51
- regsize = opc0 ? 32 : 64;
52
- } else {
53
- regsize = size == 3 ? 64 : 32;
54
- }
55
- return regsize == 64;
56
-}
57
-
58
static bool ldst_iss_sf(int size, bool sign, bool ext)
59
{
60
61
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRA(DisasContext *s, arg_LDRA *a)
62
return true;
63
}
64
65
-/*
66
- * LDAPR/STLR (unscaled immediate)
67
- *
68
- * 31 30 24 22 21 12 10 5 0
69
- * +------+-------------+-----+---+--------+-----+----+-----+
70
- * | size | 0 1 1 0 0 1 | opc | 0 | imm9 | 0 0 | Rn | Rt |
71
- * +------+-------------+-----+---+--------+-----+----+-----+
72
- *
73
- * Rt: source or destination register
74
- * Rn: base register
75
- * imm9: unscaled immediate offset
76
- * opc: 00: STLUR*, 01/10/11: various LDAPUR*
77
- * size: size of load/store
78
- */
79
-static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
80
+static bool trans_LDAPR_i(DisasContext *s, arg_ldapr_stlr_i *a)
81
{
82
- int rt = extract32(insn, 0, 5);
83
- int rn = extract32(insn, 5, 5);
84
- int offset = sextract32(insn, 12, 9);
85
- int opc = extract32(insn, 22, 2);
86
- int size = extract32(insn, 30, 2);
87
TCGv_i64 clean_addr, dirty_addr;
88
- bool is_store = false;
89
- bool extend = false;
90
- bool iss_sf;
91
- MemOp mop = size;
92
+ MemOp mop = a->sz | (a->sign ? MO_SIGN : 0);
93
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
94
95
if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
96
- unallocated_encoding(s);
97
- return;
98
+ return false;
99
}
100
101
- switch (opc) {
102
- case 0: /* STLURB */
103
- is_store = true;
104
- break;
105
- case 1: /* LDAPUR* */
106
- break;
107
- case 2: /* LDAPURS* 64-bit variant */
108
- if (size == 3) {
109
- unallocated_encoding(s);
110
- return;
111
- }
112
- mop |= MO_SIGN;
113
- break;
114
- case 3: /* LDAPURS* 32-bit variant */
115
- if (size > 1) {
116
- unallocated_encoding(s);
117
- return;
118
- }
119
- mop |= MO_SIGN;
120
- extend = true; /* zero-extend 32->64 after signed load */
121
- break;
122
- default:
123
- g_assert_not_reached();
124
- }
125
-
126
- iss_sf = disas_ldst_compute_iss_sf(size, (mop & MO_SIGN) != 0, opc);
127
-
128
- if (rn == 31) {
129
+ if (a->rn == 31) {
130
gen_check_sp_alignment(s);
131
}
132
133
- mop = check_ordered_align(s, rn, offset, is_store, mop);
134
-
135
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
136
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
137
+ mop = check_ordered_align(s, a->rn, a->imm, false, mop);
138
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
139
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, a->imm);
140
clean_addr = clean_data_tbi(s, dirty_addr);
141
142
- if (is_store) {
143
- /* Store-Release semantics */
144
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
145
- do_gpr_st(s, cpu_reg(s, rt), clean_addr, mop, true, rt, iss_sf, true);
146
- } else {
147
- /*
148
- * Load-AcquirePC semantics; we implement as the slightly more
149
- * restrictive Load-Acquire.
150
- */
151
- do_gpr_ld(s, cpu_reg(s, rt), clean_addr, mop,
152
- extend, true, rt, iss_sf, true);
153
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
154
+ /*
155
+ * Load-AcquirePC semantics; we implement as the slightly more
156
+ * restrictive Load-Acquire.
157
+ */
158
+ do_gpr_ld(s, cpu_reg(s, a->rt), clean_addr, mop, a->ext, true,
159
+ a->rt, iss_sf, true);
160
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
161
+ return true;
162
+}
163
+
164
+static bool trans_STLR_i(DisasContext *s, arg_ldapr_stlr_i *a)
165
+{
166
+ TCGv_i64 clean_addr, dirty_addr;
167
+ MemOp mop = a->sz;
168
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
169
+
170
+ if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
171
+ return false;
172
}
173
+
174
+ /* TODO: ARMv8.4-LSE SCTLR.nAA */
175
+
176
+ if (a->rn == 31) {
177
+ gen_check_sp_alignment(s);
178
+ }
36
+ }
179
+
37
+
180
+ mop = check_ordered_align(s, a->rn, a->imm, true, mop);
38
+ /* Clear RES0 bits */
181
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
39
+ value &= valid_mask;
182
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, a->imm);
183
+ clean_addr = clean_data_tbi(s, dirty_addr);
184
+
40
+
185
+ /* Store-Release semantics */
41
raw_write(env, ri, value);
186
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
42
187
+ do_gpr_st(s, cpu_reg(s, a->rt), clean_addr, mop, true, a->rt, iss_sf, true);
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
188
+ return true;
189
}
190
191
/* AdvSIMD load/store multiple structures
192
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
193
case 0x19:
194
if (extract32(insn, 21, 1) != 0) {
195
disas_ldst_tag(s, insn);
196
- } else if (extract32(insn, 10, 2) == 0) {
197
- disas_ldst_ldapr_stlr(s, insn);
198
} else {
199
unallocated_encoding(s);
200
}
201
--
44
--
202
2.34.1
45
2.34.1
diff view generated by jsdifflib
1
Convert the ASIMD load/store single structure insns to decodetree.
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
* four new trap bits for various counter and timer registers
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
scaling of the event stream. This is a no-op for us, because we don't
5
implement the event stream (our WFE is a NOP): all we need to do is
6
allow CNTHCTL_EL2.ENVTIS to be read and written.
7
* extensions to PMSCR_EL1.PCT, PMSCR_EL2.PCT, TRFCR_EL1.TS and
8
TRFCR_EL2.TS: these are all no-ops for us, because we don't implement
9
FEAT_SPE or FEAT_TRF.
10
* new registers CNTPCTSS_EL0 and NCTVCTSS_EL0 which are
11
"self-sychronizing" views of the CNTPCT_EL0 and CNTVCT_EL0, meaning
12
that no barriers are needed around their accesses. For us these
13
are just the same as the normal views, because all our sysregs are
14
inherently self-sychronizing.
15
16
In this commit we implement the trap handling and permit the new
17
CNTHCTL_EL2 bits to be written.
2
18
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Message-id: 20230602155223.2040685-20-peter.maydell@linaro.org
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
6
---
22
---
7
target/arm/tcg/a64.decode | 34 +++++
23
target/arm/cpu-features.h | 5 ++++
8
target/arm/tcg/translate-a64.c | 219 +++++++++++++++------------------
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
9
2 files changed, 136 insertions(+), 117 deletions(-)
25
2 files changed, 51 insertions(+), 5 deletions(-)
10
26
11
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
12
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/tcg/a64.decode
29
--- a/target/arm/cpu-features.h
14
+++ b/target/arm/tcg/a64.decode
30
+++ b/target/arm/cpu-features.h
15
@@ -XXX,XX +XXX,XX @@ LD_mult 0 . 001100 . 1 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 sele
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
16
LD_mult 0 . 001100 . 1 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
17
LD_mult 0 . 001100 . 1 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
18
LD_mult 0 . 001100 . 1 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
19
+
20
+# Load/store single structure
21
+&ldst_single rm rn rt p selem index scale
22
+
23
+%ldst_single_selem 13:1 21:1 !function=plus_1
24
+
25
+%ldst_single_index_b 30:1 10:3
26
+%ldst_single_index_h 30:1 11:2
27
+%ldst_single_index_s 30:1 12:1
28
+
29
+@ldst_single_b .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
30
+ &ldst_single scale=0 selem=%ldst_single_selem \
31
+ index=%ldst_single_index_b
32
+@ldst_single_h .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
33
+ &ldst_single scale=1 selem=%ldst_single_selem \
34
+ index=%ldst_single_index_h
35
+@ldst_single_s .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
36
+ &ldst_single scale=2 selem=%ldst_single_selem \
37
+ index=%ldst_single_index_s
38
+@ldst_single_d . index:1 ...... p:1 .. rm:5 ...... rn:5 rt:5 \
39
+ &ldst_single scale=3 selem=%ldst_single_selem
40
+
41
+ST_single 0 . 001101 . 0 . ..... 00 . ... ..... ..... @ldst_single_b
42
+ST_single 0 . 001101 . 0 . ..... 01 . ..0 ..... ..... @ldst_single_h
43
+ST_single 0 . 001101 . 0 . ..... 10 . .00 ..... ..... @ldst_single_s
44
+ST_single 0 . 001101 . 0 . ..... 10 . 001 ..... ..... @ldst_single_d
45
+
46
+LD_single 0 . 001101 . 1 . ..... 00 . ... ..... ..... @ldst_single_b
47
+LD_single 0 . 001101 . 1 . ..... 01 . ..0 ..... ..... @ldst_single_h
48
+LD_single 0 . 001101 . 1 . ..... 10 . .00 ..... ..... @ldst_single_s
49
+LD_single 0 . 001101 . 1 . ..... 10 . 001 ..... ..... @ldst_single_d
50
+
51
+# Replicating load case
52
+LD_single_repl 0 q:1 001101 p:1 1 . rm:5 11 . 0 scale:2 rn:5 rt:5 selem=%ldst_single_selem
53
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/tcg/translate-a64.c
56
+++ b/target/arm/tcg/translate-a64.c
57
@@ -XXX,XX +XXX,XX @@ static bool trans_ST_mult(DisasContext *s, arg_ldst_mult *a)
58
return true;
59
}
33
}
60
34
61
-/* AdvSIMD load/store single structure
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
62
- *
36
+{
63
- * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
64
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
65
- * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size | Rn | Rt |
66
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
67
- *
68
- * AdvSIMD load/store single structure (post-indexed)
69
- *
70
- * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
71
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
72
- * | 0 | Q | 0 0 1 1 0 1 1 | L R | Rm | opc | S | size | Rn | Rt |
73
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
74
- *
75
- * Rt: first (or only) SIMD&FP register to be transferred
76
- * Rn: base address or SP
77
- * Rm (post-index only): post-index register (when !31) or size dependent #imm
78
- * index = encoded in Q:S:size dependent on size
79
- *
80
- * lane_size = encoded in R, opc
81
- * transfer width = encoded in opc, S, size
82
- */
83
-static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
84
+static bool trans_ST_single(DisasContext *s, arg_ldst_single *a)
85
{
86
- int rt = extract32(insn, 0, 5);
87
- int rn = extract32(insn, 5, 5);
88
- int rm = extract32(insn, 16, 5);
89
- int size = extract32(insn, 10, 2);
90
- int S = extract32(insn, 12, 1);
91
- int opc = extract32(insn, 13, 3);
92
- int R = extract32(insn, 21, 1);
93
- int is_load = extract32(insn, 22, 1);
94
- int is_postidx = extract32(insn, 23, 1);
95
- int is_q = extract32(insn, 30, 1);
96
-
97
- int scale = extract32(opc, 1, 2);
98
- int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
99
- bool replicate = false;
100
- int index = is_q << 3 | S << 2 | size;
101
- int xs, total;
102
+ int xs, total, rt;
103
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
104
MemOp mop;
105
106
- if (extract32(insn, 31, 1)) {
107
- unallocated_encoding(s);
108
- return;
109
+ if (!a->p && a->rm != 0) {
110
+ return false;
111
}
112
- if (!is_postidx && rm != 0) {
113
- unallocated_encoding(s);
114
- return;
115
- }
116
-
117
- switch (scale) {
118
- case 3:
119
- if (!is_load || S) {
120
- unallocated_encoding(s);
121
- return;
122
- }
123
- scale = size;
124
- replicate = true;
125
- break;
126
- case 0:
127
- break;
128
- case 1:
129
- if (extract32(size, 0, 1)) {
130
- unallocated_encoding(s);
131
- return;
132
- }
133
- index >>= 1;
134
- break;
135
- case 2:
136
- if (extract32(size, 1, 1)) {
137
- unallocated_encoding(s);
138
- return;
139
- }
140
- if (!extract32(size, 0, 1)) {
141
- index >>= 2;
142
- } else {
143
- if (S) {
144
- unallocated_encoding(s);
145
- return;
146
- }
147
- index >>= 3;
148
- scale = 3;
149
- }
150
- break;
151
- default:
152
- g_assert_not_reached();
153
- }
154
-
155
if (!fp_access_check(s)) {
156
- return;
157
+ return true;
158
}
159
160
- if (rn == 31) {
161
+ if (a->rn == 31) {
162
gen_check_sp_alignment(s);
163
}
164
165
- total = selem << scale;
166
- tcg_rn = cpu_reg_sp(s, rn);
167
+ total = a->selem << a->scale;
168
+ tcg_rn = cpu_reg_sp(s, a->rn);
169
170
- mop = finalize_memop_asimd(s, scale);
171
-
172
- clean_addr = gen_mte_checkN(s, tcg_rn, !is_load, is_postidx || rn != 31,
173
+ mop = finalize_memop_asimd(s, a->scale);
174
+ clean_addr = gen_mte_checkN(s, tcg_rn, true, a->p || a->rn != 31,
175
total, mop);
176
177
- tcg_ebytes = tcg_constant_i64(1 << scale);
178
- for (xs = 0; xs < selem; xs++) {
179
- if (replicate) {
180
- /* Load and replicate to all elements */
181
- TCGv_i64 tcg_tmp = tcg_temp_new_i64();
182
-
183
- tcg_gen_qemu_ld_i64(tcg_tmp, clean_addr, get_mem_index(s), mop);
184
- tcg_gen_gvec_dup_i64(scale, vec_full_reg_offset(s, rt),
185
- (is_q + 1) * 8, vec_full_reg_size(s),
186
- tcg_tmp);
187
- } else {
188
- /* Load/store one element per register */
189
- if (is_load) {
190
- do_vec_ld(s, rt, index, clean_addr, mop);
191
- } else {
192
- do_vec_st(s, rt, index, clean_addr, mop);
193
- }
194
- }
195
+ tcg_ebytes = tcg_constant_i64(1 << a->scale);
196
+ for (xs = 0, rt = a->rt; xs < a->selem; xs++, rt = (rt + 1) % 32) {
197
+ do_vec_st(s, rt, a->index, clean_addr, mop);
198
tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
199
- rt = (rt + 1) % 32;
200
}
201
202
- if (is_postidx) {
203
- if (rm == 31) {
204
+ if (a->p) {
205
+ if (a->rm == 31) {
206
tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
207
} else {
208
- tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
209
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
210
}
211
}
212
+ return true;
213
+}
38
+}
214
+
39
+
215
+static bool trans_LD_single(DisasContext *s, arg_ldst_single *a)
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
41
{
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
48
: !extract32(env->cp15.cnthctl_el2, 0, 1))) {
49
return CP_ACCESS_TRAP_EL2;
50
}
51
+ if (has_el2 && timeridx == GTIMER_VIRT) {
52
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVCT)) {
53
+ return CP_ACCESS_TRAP_EL2;
54
+ }
55
+ }
56
break;
57
}
58
return CP_ACCESS_OK;
59
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
60
}
61
}
62
}
63
+ if (has_el2 && timeridx == GTIMER_VIRT) {
64
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVT)) {
65
+ return CP_ACCESS_TRAP_EL2;
66
+ }
67
+ }
68
break;
69
}
70
return CP_ACCESS_OK;
71
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
if (cpu_isar_feature(aa64_rme, cpu)) {
73
valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
74
}
75
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
76
+ valid_mask |=
77
+ R_CNTHCTL_EL1TVT_MASK |
78
+ R_CNTHCTL_EL1TVCT_MASK |
79
+ R_CNTHCTL_EL1NVPCT_MASK |
80
+ R_CNTHCTL_EL1NVVCT_MASK |
81
+ R_CNTHCTL_EVNTIS_MASK;
82
+ }
83
84
/* Clear RES0 bits */
85
value &= valid_mask;
86
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
87
{
88
if (arm_current_el(env) == 1) {
89
/* This must be a FEAT_NV access */
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
91
return CP_ACCESS_OK;
92
}
93
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
95
return CP_ACCESS_OK;
96
}
97
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
216
+{
100
+{
217
+ int xs, total, rt;
101
+ if (arm_current_el(env) == 1) {
218
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
102
+ /* This must be a FEAT_NV access with NVx == 101 */
219
+ MemOp mop;
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
220
+
104
+ return CP_ACCESS_TRAP_EL2;
221
+ if (!a->p && a->rm != 0) {
222
+ return false;
223
+ }
224
+ if (!fp_access_check(s)) {
225
+ return true;
226
+ }
227
+
228
+ if (a->rn == 31) {
229
+ gen_check_sp_alignment(s);
230
+ }
231
+
232
+ total = a->selem << a->scale;
233
+ tcg_rn = cpu_reg_sp(s, a->rn);
234
+
235
+ mop = finalize_memop_asimd(s, a->scale);
236
+ clean_addr = gen_mte_checkN(s, tcg_rn, false, a->p || a->rn != 31,
237
+ total, mop);
238
+
239
+ tcg_ebytes = tcg_constant_i64(1 << a->scale);
240
+ for (xs = 0, rt = a->rt; xs < a->selem; xs++, rt = (rt + 1) % 32) {
241
+ do_vec_ld(s, rt, a->index, clean_addr, mop);
242
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
243
+ }
244
+
245
+ if (a->p) {
246
+ if (a->rm == 31) {
247
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
248
+ } else {
249
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
250
+ }
105
+ }
251
+ }
106
+ }
252
+ return true;
107
+ return e2h_access(env, ri, isread);
253
+}
108
+}
254
+
109
+
255
+static bool trans_LD_single_repl(DisasContext *s, arg_LD_single_repl *a)
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
111
+ bool isread)
256
+{
112
+{
257
+ int xs, total, rt;
113
+ if (arm_current_el(env) == 1) {
258
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
114
+ /* This must be a FEAT_NV access with NVx == 101 */
259
+ MemOp mop;
115
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVVCT)) {
260
+
116
+ return CP_ACCESS_TRAP_EL2;
261
+ if (!a->p && a->rm != 0) {
262
+ return false;
263
+ }
264
+ if (!fp_access_check(s)) {
265
+ return true;
266
+ }
267
+
268
+ if (a->rn == 31) {
269
+ gen_check_sp_alignment(s);
270
+ }
271
+
272
+ total = a->selem << a->scale;
273
+ tcg_rn = cpu_reg_sp(s, a->rn);
274
+
275
+ mop = finalize_memop_asimd(s, a->scale);
276
+ clean_addr = gen_mte_checkN(s, tcg_rn, false, a->p || a->rn != 31,
277
+ total, mop);
278
+
279
+ tcg_ebytes = tcg_constant_i64(1 << a->scale);
280
+ for (xs = 0, rt = a->rt; xs < a->selem; xs++, rt = (rt + 1) % 32) {
281
+ /* Load and replicate to all elements */
282
+ TCGv_i64 tcg_tmp = tcg_temp_new_i64();
283
+
284
+ tcg_gen_qemu_ld_i64(tcg_tmp, clean_addr, get_mem_index(s), mop);
285
+ tcg_gen_gvec_dup_i64(a->scale, vec_full_reg_offset(s, rt),
286
+ (a->q + 1) * 8, vec_full_reg_size(s), tcg_tmp);
287
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
288
+ }
289
+
290
+ if (a->p) {
291
+ if (a->rm == 31) {
292
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
293
+ } else {
294
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
295
+ }
117
+ }
296
+ }
118
+ }
297
+ return true;
119
+ return e2h_access(env, ri, isread);
298
}
120
+}
299
121
+
300
/*
122
/* Test if system register redirection is to occur in the current state. */
301
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
123
static bool redirect_for_e2h(CPUARMState *env)
302
static void disas_ldst(DisasContext *s, uint32_t insn)
303
{
124
{
304
switch (extract32(insn, 24, 6)) {
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
305
- case 0x0d: /* AdvSIMD load/store single structure */
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
306
- disas_ldst_single_struct(s, insn);
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
307
- break;
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
308
case 0x19:
129
- .access = PL2_RW, .accessfn = e2h_access,
309
if (extract32(insn, 21, 1) != 0) {
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
310
disas_ldst_tag(s, insn);
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
134
{ .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
135
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
136
.type = ARM_CP_IO | ARM_CP_ALIAS,
137
- .access = PL2_RW, .accessfn = e2h_access,
138
+ .access = PL2_RW, .accessfn = access_el1nvvct,
139
.nv2_redirect_offset = 0x170 | NV2_REDIR_NO_NV1,
140
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
141
.writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
142
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
143
.type = ARM_CP_IO | ARM_CP_ALIAS,
144
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
145
.nv2_redirect_offset = 0x178 | NV2_REDIR_NO_NV1,
146
- .access = PL2_RW, .accessfn = e2h_access,
147
+ .access = PL2_RW, .accessfn = access_el1nvpct,
148
.writefn = gt_phys_cval_write, .raw_writefn = raw_write },
149
{ .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
150
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
151
.type = ARM_CP_IO | ARM_CP_ALIAS,
152
.nv2_redirect_offset = 0x168 | NV2_REDIR_NO_NV1,
153
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
154
- .access = PL2_RW, .accessfn = e2h_access,
155
+ .access = PL2_RW, .accessfn = access_el1nvvct,
156
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
157
#endif
158
};
311
--
159
--
312
2.34.1
160
2.34.1
diff view generated by jsdifflib
1
Convert the instructions in the ASIMD load/store multiple structures
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
instruction classes to decodetree.
2
defined, which are "self-synchronized" views of the physical and
3
virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers
4
(meaning that no barriers are needed around accesses to them to
5
ensure that reads of them do not occur speculatively and out-of-order
6
with other instructions).
7
8
For QEMU, all our system registers are self-synchronized, so we can
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
10
to the new register encodings.
11
12
This means we now implement all the functionality required for
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
3
14
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-19-peter.maydell@linaro.org
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
7
---
18
---
8
target/arm/tcg/a64.decode | 20 +++
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
9
target/arm/tcg/translate-a64.c | 222 ++++++++++++++++-----------------
20
1 file changed, 43 insertions(+)
10
2 files changed, 131 insertions(+), 111 deletions(-)
11
21
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
24
--- a/target/arm/helper.c
15
+++ b/target/arm/tcg/a64.decode
25
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@ LDAPR_i 01 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
17
LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=2
27
},
18
LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
28
};
19
LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
29
30
+/*
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
33
+ * so our implementations here are identical to the normal registers.
34
+ */
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
38
+ .accessfn = gt_vct_access,
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
40
+ },
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
43
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
44
+ .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
45
+ },
46
+ { .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
47
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
48
+ .accessfn = gt_pct_access,
49
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
50
+ },
51
+ { .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
52
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
53
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
54
+ .accessfn = gt_pct_access, .readfn = gt_cnt_read,
55
+ },
56
+};
20
+
57
+
21
+# Load/store multiple structures
58
#else
22
+# The 4-bit opcode in [15:12] encodes repeat count and structure elements
59
23
+&ldst_mult rm rn rt sz q p rpt selem
60
/*
24
+@ldst_mult . q:1 ...... p:1 . . rm:5 .... sz:2 rn:5 rt:5 &ldst_mult
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
25
+ST_mult 0 . 001100 . 0 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
62
},
26
+ST_mult 0 . 001100 . 0 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
63
};
27
+ST_mult 0 . 001100 . 0 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
64
28
+ST_mult 0 . 001100 . 0 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
65
+/*
29
+ST_mult 0 . 001100 . 0 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
30
+ST_mult 0 . 001100 . 0 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
67
+ * is exposed to userspace by Linux.
31
+ST_mult 0 . 001100 . 0 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
68
+ */
69
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
70
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
71
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
72
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
73
+ .readfn = gt_virt_cnt_read,
74
+ },
75
+};
32
+
76
+
33
+LD_mult 0 . 001100 . 1 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
77
#endif
34
+LD_mult 0 . 001100 . 1 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
78
35
+LD_mult 0 . 001100 . 1 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
36
+LD_mult 0 . 001100 . 1 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
37
+LD_mult 0 . 001100 . 1 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
38
+LD_mult 0 . 001100 . 1 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
39
+LD_mult 0 . 001100 . 1 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
40
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/tcg/translate-a64.c
43
+++ b/target/arm/tcg/translate-a64.c
44
@@ -XXX,XX +XXX,XX @@ static bool trans_STLR_i(DisasContext *s, arg_ldapr_stlr_i *a)
45
return true;
46
}
47
48
-/* AdvSIMD load/store multiple structures
49
- *
50
- * 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
51
- * +---+---+---------------+---+-------------+--------+------+------+------+
52
- * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size | Rn | Rt |
53
- * +---+---+---------------+---+-------------+--------+------+------+------+
54
- *
55
- * AdvSIMD load/store multiple structures (post-indexed)
56
- *
57
- * 31 30 29 23 22 21 20 16 15 12 11 10 9 5 4 0
58
- * +---+---+---------------+---+---+---------+--------+------+------+------+
59
- * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 | Rm | opcode | size | Rn | Rt |
60
- * +---+---+---------------+---+---+---------+--------+------+------+------+
61
- *
62
- * Rt: first (or only) SIMD&FP register to be transferred
63
- * Rn: base address or SP
64
- * Rm (post-index only): post-index register (when !31) or size dependent #imm
65
- */
66
-static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
67
+static bool trans_LD_mult(DisasContext *s, arg_ldst_mult *a)
68
{
69
- int rt = extract32(insn, 0, 5);
70
- int rn = extract32(insn, 5, 5);
71
- int rm = extract32(insn, 16, 5);
72
- int size = extract32(insn, 10, 2);
73
- int opcode = extract32(insn, 12, 4);
74
- bool is_store = !extract32(insn, 22, 1);
75
- bool is_postidx = extract32(insn, 23, 1);
76
- bool is_q = extract32(insn, 30, 1);
77
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
78
MemOp endian, align, mop;
79
80
int total; /* total bytes */
81
int elements; /* elements per vector */
82
- int rpt; /* num iterations */
83
- int selem; /* structure elements */
84
int r;
85
+ int size = a->sz;
86
87
- if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
88
- unallocated_encoding(s);
89
- return;
90
+ if (!a->p && a->rm != 0) {
91
+ /* For non-postindexed accesses the Rm field must be 0 */
92
+ return false;
93
}
83
}
94
-
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
95
- if (!is_postidx && rm != 0) {
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
96
- unallocated_encoding(s);
97
- return;
98
+ if (size == 3 && !a->q && a->selem != 1) {
99
+ return false;
100
}
101
-
102
- /* From the shared decode logic */
103
- switch (opcode) {
104
- case 0x0:
105
- rpt = 1;
106
- selem = 4;
107
- break;
108
- case 0x2:
109
- rpt = 4;
110
- selem = 1;
111
- break;
112
- case 0x4:
113
- rpt = 1;
114
- selem = 3;
115
- break;
116
- case 0x6:
117
- rpt = 3;
118
- selem = 1;
119
- break;
120
- case 0x7:
121
- rpt = 1;
122
- selem = 1;
123
- break;
124
- case 0x8:
125
- rpt = 1;
126
- selem = 2;
127
- break;
128
- case 0xa:
129
- rpt = 2;
130
- selem = 1;
131
- break;
132
- default:
133
- unallocated_encoding(s);
134
- return;
135
- }
136
-
137
- if (size == 3 && !is_q && selem != 1) {
138
- /* reserved */
139
- unallocated_encoding(s);
140
- return;
141
- }
142
-
143
if (!fp_access_check(s)) {
144
- return;
145
+ return true;
146
}
147
148
- if (rn == 31) {
149
+ if (a->rn == 31) {
150
gen_check_sp_alignment(s);
151
}
152
153
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
154
endian = MO_LE;
155
}
156
157
- total = rpt * selem * (is_q ? 16 : 8);
158
- tcg_rn = cpu_reg_sp(s, rn);
159
+ total = a->rpt * a->selem * (a->q ? 16 : 8);
160
+ tcg_rn = cpu_reg_sp(s, a->rn);
161
162
/*
163
* Issue the MTE check vs the logical repeat count, before we
164
* promote consecutive little-endian elements below.
165
*/
166
- clean_addr = gen_mte_checkN(s, tcg_rn, is_store, is_postidx || rn != 31,
167
- total, finalize_memop_asimd(s, size));
168
+ clean_addr = gen_mte_checkN(s, tcg_rn, false, a->p || a->rn != 31, total,
169
+ finalize_memop_asimd(s, size));
170
171
/*
172
* Consecutive little-endian elements from a single register
173
* can be promoted to a larger little-endian operation.
174
*/
175
align = MO_ALIGN;
176
- if (selem == 1 && endian == MO_LE) {
177
+ if (a->selem == 1 && endian == MO_LE) {
178
align = pow2_align(size);
179
size = 3;
180
}
181
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
182
}
183
mop = endian | size | align;
184
185
- elements = (is_q ? 16 : 8) >> size;
186
+ elements = (a->q ? 16 : 8) >> size;
187
tcg_ebytes = tcg_constant_i64(1 << size);
188
- for (r = 0; r < rpt; r++) {
189
+ for (r = 0; r < a->rpt; r++) {
190
int e;
191
for (e = 0; e < elements; e++) {
192
int xs;
193
- for (xs = 0; xs < selem; xs++) {
194
- int tt = (rt + r + xs) % 32;
195
- if (is_store) {
196
- do_vec_st(s, tt, e, clean_addr, mop);
197
- } else {
198
- do_vec_ld(s, tt, e, clean_addr, mop);
199
- }
200
+ for (xs = 0; xs < a->selem; xs++) {
201
+ int tt = (a->rt + r + xs) % 32;
202
+ do_vec_ld(s, tt, e, clean_addr, mop);
203
tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
204
}
205
}
206
}
207
208
- if (!is_store) {
209
- /* For non-quad operations, setting a slice of the low
210
- * 64 bits of the register clears the high 64 bits (in
211
- * the ARM ARM pseudocode this is implicit in the fact
212
- * that 'rval' is a 64 bit wide variable).
213
- * For quad operations, we might still need to zero the
214
- * high bits of SVE.
215
- */
216
- for (r = 0; r < rpt * selem; r++) {
217
- int tt = (rt + r) % 32;
218
- clear_vec_high(s, is_q, tt);
219
+ /*
220
+ * For non-quad operations, setting a slice of the low 64 bits of
221
+ * the register clears the high 64 bits (in the ARM ARM pseudocode
222
+ * this is implicit in the fact that 'rval' is a 64 bit wide
223
+ * variable). For quad operations, we might still need to zero
224
+ * the high bits of SVE.
225
+ */
226
+ for (r = 0; r < a->rpt * a->selem; r++) {
227
+ int tt = (a->rt + r) % 32;
228
+ clear_vec_high(s, a->q, tt);
229
+ }
86
+ }
230
+
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
231
+ if (a->p) {
88
ARMCPRegInfo vapa_cp_reginfo[] = {
232
+ if (a->rm == 31) {
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
233
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
234
+ } else {
235
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
236
+ }
237
+ }
238
+ return true;
239
+}
240
+
241
+static bool trans_ST_mult(DisasContext *s, arg_ldst_mult *a)
242
+{
243
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
244
+ MemOp endian, align, mop;
245
+
246
+ int total; /* total bytes */
247
+ int elements; /* elements per vector */
248
+ int r;
249
+ int size = a->sz;
250
+
251
+ if (!a->p && a->rm != 0) {
252
+ /* For non-postindexed accesses the Rm field must be 0 */
253
+ return false;
254
+ }
255
+ if (size == 3 && !a->q && a->selem != 1) {
256
+ return false;
257
+ }
258
+ if (!fp_access_check(s)) {
259
+ return true;
260
+ }
261
+
262
+ if (a->rn == 31) {
263
+ gen_check_sp_alignment(s);
264
+ }
265
+
266
+ /* For our purposes, bytes are always little-endian. */
267
+ endian = s->be_data;
268
+ if (size == 0) {
269
+ endian = MO_LE;
270
+ }
271
+
272
+ total = a->rpt * a->selem * (a->q ? 16 : 8);
273
+ tcg_rn = cpu_reg_sp(s, a->rn);
274
+
275
+ /*
276
+ * Issue the MTE check vs the logical repeat count, before we
277
+ * promote consecutive little-endian elements below.
278
+ */
279
+ clean_addr = gen_mte_checkN(s, tcg_rn, true, a->p || a->rn != 31, total,
280
+ finalize_memop_asimd(s, size));
281
+
282
+ /*
283
+ * Consecutive little-endian elements from a single register
284
+ * can be promoted to a larger little-endian operation.
285
+ */
286
+ align = MO_ALIGN;
287
+ if (a->selem == 1 && endian == MO_LE) {
288
+ align = pow2_align(size);
289
+ size = 3;
290
+ }
291
+ if (!s->align_mem) {
292
+ align = 0;
293
+ }
294
+ mop = endian | size | align;
295
+
296
+ elements = (a->q ? 16 : 8) >> size;
297
+ tcg_ebytes = tcg_constant_i64(1 << size);
298
+ for (r = 0; r < a->rpt; r++) {
299
+ int e;
300
+ for (e = 0; e < elements; e++) {
301
+ int xs;
302
+ for (xs = 0; xs < a->selem; xs++) {
303
+ int tt = (a->rt + r + xs) % 32;
304
+ do_vec_st(s, tt, e, clean_addr, mop);
305
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
306
+ }
307
}
308
}
309
310
- if (is_postidx) {
311
- if (rm == 31) {
312
+ if (a->p) {
313
+ if (a->rm == 31) {
314
tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
315
} else {
316
- tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
317
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
318
}
319
}
320
+ return true;
321
}
322
323
/* AdvSIMD load/store single structure
324
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
325
static void disas_ldst(DisasContext *s, uint32_t insn)
326
{
327
switch (extract32(insn, 24, 6)) {
328
- case 0x0c: /* AdvSIMD load/store multiple structures */
329
- disas_ldst_multiple_struct(s, insn);
330
- break;
331
case 0x0d: /* AdvSIMD load/store single structure */
332
disas_ldst_single_struct(s, insn);
333
break;
334
--
90
--
335
2.34.1
91
2.34.1
diff view generated by jsdifflib
1
Convert the instructions in the load/store memory tags instruction
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
group to decodetree.
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
that it controls a hypervisor-adjustable offset made to the physical
4
counter and timer.
5
6
Implement the handling for this register, which includes control/trap
7
bits in SCR_EL3 and CNTHCTL_EL2.
3
8
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-21-peter.maydell@linaro.org
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
7
---
12
---
8
target/arm/tcg/a64.decode | 25 +++
13
target/arm/cpu-features.h | 5 +++
9
target/arm/tcg/translate-a64.c | 360 ++++++++++++++++-----------------
14
target/arm/cpu.h | 1 +
10
2 files changed, 199 insertions(+), 186 deletions(-)
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
11
18
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
19
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
13
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
21
--- a/target/arm/cpu-features.h
15
+++ b/target/arm/tcg/a64.decode
22
+++ b/target/arm/cpu-features.h
16
@@ -XXX,XX +XXX,XX @@ LD_single 0 . 001101 . 1 . ..... 10 . 001 ..... ..... @ldst_single_d
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
17
24
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
18
# Replicating load case
19
LD_single_repl 0 q:1 001101 p:1 1 . rm:5 11 . 0 scale:2 rn:5 rt:5 selem=%ldst_single_selem
20
+
21
+%tag_offset 12:s9 !function=scale_by_log2_tag_granule
22
+&ldst_tag rn rt imm p w
23
+@ldst_tag ........ .. . ......... .. rn:5 rt:5 &ldst_tag imm=%tag_offset
24
+@ldst_tag_mult ........ .. . 000000000 .. rn:5 rt:5 &ldst_tag imm=0
25
+
26
+STZGM 11011001 00 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
27
+STG 11011001 00 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
28
+STG 11011001 00 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
29
+STG 11011001 00 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
30
+
31
+LDG 11011001 01 1 ......... 00 ..... ..... @ldst_tag p=0 w=0
32
+STZG 11011001 01 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
33
+STZG 11011001 01 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
34
+STZG 11011001 01 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
35
+
36
+STGM 11011001 10 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
37
+ST2G 11011001 10 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
38
+ST2G 11011001 10 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
39
+ST2G 11011001 10 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
40
+
41
+LDGM 11011001 11 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
42
+STZ2G 11011001 11 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
43
+STZ2G 11011001 11 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
44
+STZ2G 11011001 11 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
45
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/tcg/translate-a64.c
48
+++ b/target/arm/tcg/translate-a64.c
49
@@ -XXX,XX +XXX,XX @@ static int uimm_scaled(DisasContext *s, int x)
50
return imm << scale;
51
}
25
}
52
26
53
+/* For load/store memory tags: scale offset by LOG2_TAG_GRANULE */
27
+static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
54
+static int scale_by_log2_tag_granule(DisasContext *s, int x)
55
+{
28
+{
56
+ return x << LOG2_TAG_GRANULE;
29
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
57
+}
30
+}
58
+
31
+
59
/*
32
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
60
* Include the generated decoders.
33
{
61
*/
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
62
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_single_repl(DisasContext *s, arg_LD_single_repl *a)
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
63
return true;
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
40
uint64_t c14_cntkctl; /* Timer Control register */
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
50
+++ b/target/arm/helper.c
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
52
if (cpu_isar_feature(aa64_rme, cpu)) {
53
valid_mask |= SCR_NSE | SCR_GPF;
54
}
55
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
56
+ valid_mask |= SCR_ECVEN;
57
+ }
58
} else {
59
valid_mask &= ~(SCR_RW | SCR_ST);
60
if (cpu_isar_feature(aa32_ras, cpu)) {
61
@@ -XXX,XX +XXX,XX @@ void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
62
gt_update_irq(cpu, GTIMER_PHYS);
64
}
63
}
65
64
66
-/*
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
67
- * Load/Store memory tags
66
+{
68
- *
67
+ if ((env->cp15.scr_el3 & SCR_ECVEN) &&
69
- * 31 30 29 24 22 21 12 10 5 0
68
+ FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, ECV) &&
70
- * +-----+-------------+-----+---+------+-----+------+------+
69
+ arm_is_el2_enabled(env) &&
71
- * | 1 1 | 0 1 1 0 0 1 | op1 | 1 | imm9 | op2 | Rn | Rt |
70
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
72
- * +-----+-------------+-----+---+------+-----+------+------+
71
+ return env->cp15.cntpoff_el2;
73
- */
74
-static void disas_ldst_tag(DisasContext *s, uint32_t insn)
75
+static bool trans_STZGM(DisasContext *s, arg_ldst_tag *a)
76
{
77
- int rt = extract32(insn, 0, 5);
78
- int rn = extract32(insn, 5, 5);
79
- uint64_t offset = sextract64(insn, 12, 9) << LOG2_TAG_GRANULE;
80
- int op2 = extract32(insn, 10, 2);
81
- int op1 = extract32(insn, 22, 2);
82
- bool is_load = false, is_pair = false, is_zero = false, is_mult = false;
83
- int index = 0;
84
TCGv_i64 addr, clean_addr, tcg_rt;
85
+ int size = 4 << s->dcz_blocksize;
86
87
- /* We checked insn bits [29:24,21] in the caller. */
88
- if (extract32(insn, 30, 2) != 3) {
89
- goto do_unallocated;
90
+ if (!dc_isar_feature(aa64_mte, s)) {
91
+ return false;
92
+ }
72
+ }
93
+ if (s->current_el == 0) {
73
+ return 0;
94
+ return false;
95
}
96
97
- /*
98
- * @index is a tri-state variable which has 3 states:
99
- * < 0 : post-index, writeback
100
- * = 0 : signed offset
101
- * > 0 : pre-index, writeback
102
- */
103
- switch (op1) {
104
- case 0:
105
- if (op2 != 0) {
106
- /* STG */
107
- index = op2 - 2;
108
- } else {
109
- /* STZGM */
110
- if (s->current_el == 0 || offset != 0) {
111
- goto do_unallocated;
112
- }
113
- is_mult = is_zero = true;
114
- }
115
- break;
116
- case 1:
117
- if (op2 != 0) {
118
- /* STZG */
119
- is_zero = true;
120
- index = op2 - 2;
121
- } else {
122
- /* LDG */
123
- is_load = true;
124
- }
125
- break;
126
- case 2:
127
- if (op2 != 0) {
128
- /* ST2G */
129
- is_pair = true;
130
- index = op2 - 2;
131
- } else {
132
- /* STGM */
133
- if (s->current_el == 0 || offset != 0) {
134
- goto do_unallocated;
135
- }
136
- is_mult = true;
137
- }
138
- break;
139
- case 3:
140
- if (op2 != 0) {
141
- /* STZ2G */
142
- is_pair = is_zero = true;
143
- index = op2 - 2;
144
- } else {
145
- /* LDGM */
146
- if (s->current_el == 0 || offset != 0) {
147
- goto do_unallocated;
148
- }
149
- is_mult = is_load = true;
150
- }
151
- break;
152
-
153
- default:
154
- do_unallocated:
155
- unallocated_encoding(s);
156
- return;
157
- }
158
-
159
- if (is_mult
160
- ? !dc_isar_feature(aa64_mte, s)
161
- : !dc_isar_feature(aa64_mte_insn_reg, s)) {
162
- goto do_unallocated;
163
- }
164
-
165
- if (rn == 31) {
166
+ if (a->rn == 31) {
167
gen_check_sp_alignment(s);
168
}
169
170
- addr = read_cpu_reg_sp(s, rn, true);
171
- if (index >= 0) {
172
+ addr = read_cpu_reg_sp(s, a->rn, true);
173
+ tcg_gen_addi_i64(addr, addr, a->imm);
174
+ tcg_rt = cpu_reg(s, a->rt);
175
+
176
+ if (s->ata) {
177
+ gen_helper_stzgm_tags(cpu_env, addr, tcg_rt);
178
+ }
179
+ /*
180
+ * The non-tags portion of STZGM is mostly like DC_ZVA,
181
+ * except the alignment happens before the access.
182
+ */
183
+ clean_addr = clean_data_tbi(s, addr);
184
+ tcg_gen_andi_i64(clean_addr, clean_addr, -size);
185
+ gen_helper_dc_zva(cpu_env, clean_addr);
186
+ return true;
187
+}
74
+}
188
+
75
+
189
+static bool trans_STGM(DisasContext *s, arg_ldst_tag *a)
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
190
+{
77
+{
191
+ TCGv_i64 addr, clean_addr, tcg_rt;
78
+ if (arm_current_el(env) >= 2) {
192
+
79
+ return 0;
193
+ if (!dc_isar_feature(aa64_mte, s)) {
194
+ return false;
195
+ }
80
+ }
196
+ if (s->current_el == 0) {
81
+ return gt_phys_raw_cnt_offset(env);
197
+ return false;
198
+ }
199
+
200
+ if (a->rn == 31) {
201
+ gen_check_sp_alignment(s);
202
+ }
203
+
204
+ addr = read_cpu_reg_sp(s, a->rn, true);
205
+ tcg_gen_addi_i64(addr, addr, a->imm);
206
+ tcg_rt = cpu_reg(s, a->rt);
207
+
208
+ if (s->ata) {
209
+ gen_helper_stgm(cpu_env, addr, tcg_rt);
210
+ } else {
211
+ MMUAccessType acc = MMU_DATA_STORE;
212
+ int size = 4 << GMID_EL1_BS;
213
+
214
+ clean_addr = clean_data_tbi(s, addr);
215
+ tcg_gen_andi_i64(clean_addr, clean_addr, -size);
216
+ gen_probe_access(s, clean_addr, acc, size);
217
+ }
218
+ return true;
219
+}
82
+}
220
+
83
+
221
+static bool trans_LDGM(DisasContext *s, arg_ldst_tag *a)
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
85
{
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
88
* reset timer to when ISTATUS next has to change
89
*/
90
uint64_t offset = timeridx == GTIMER_VIRT ?
91
- cpu->env.cp15.cntvoff_el2 : 0;
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
93
uint64_t count = gt_get_countervalue(&cpu->env);
94
/* Note that this must be unsigned 64 bit arithmetic: */
95
int istatus = count - offset >= gt->cval;
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
97
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
{
100
- return gt_get_countervalue(env);
101
+ return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
102
}
103
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
106
case GTIMER_HYPVIRT:
107
offset = gt_virt_cnt_offset(env);
108
break;
109
+ case GTIMER_PHYS:
110
+ offset = gt_phys_cnt_offset(env);
111
+ break;
112
}
113
114
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
115
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
case GTIMER_HYPVIRT:
117
offset = gt_virt_cnt_offset(env);
118
break;
119
+ case GTIMER_PHYS:
120
+ offset = gt_phys_cnt_offset(env);
121
+ break;
122
}
123
124
trace_arm_gt_tval_write(timeridx, value);
125
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
R_CNTHCTL_EL1NVVCT_MASK |
127
R_CNTHCTL_EVNTIS_MASK;
128
}
129
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
130
+ valid_mask |= R_CNTHCTL_ECV_MASK;
131
+ }
132
133
/* Clear RES0 bits */
134
value &= valid_mask;
135
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
136
},
137
};
138
139
+static CPAccessResult gt_cntpoff_access(CPUARMState *env,
140
+ const ARMCPRegInfo *ri,
141
+ bool isread)
222
+{
142
+{
223
+ TCGv_i64 addr, clean_addr, tcg_rt;
143
+ if (arm_current_el(env) == 2 && !(env->cp15.scr_el3 & SCR_ECVEN)) {
224
+
144
+ return CP_ACCESS_TRAP_EL3;
225
+ if (!dc_isar_feature(aa64_mte, s)) {
226
+ return false;
227
+ }
145
+ }
228
+ if (s->current_el == 0) {
146
+ return CP_ACCESS_OK;
229
+ return false;
230
+ }
231
+
232
+ if (a->rn == 31) {
233
+ gen_check_sp_alignment(s);
234
+ }
235
+
236
+ addr = read_cpu_reg_sp(s, a->rn, true);
237
+ tcg_gen_addi_i64(addr, addr, a->imm);
238
+ tcg_rt = cpu_reg(s, a->rt);
239
+
240
+ if (s->ata) {
241
+ gen_helper_ldgm(tcg_rt, cpu_env, addr);
242
+ } else {
243
+ MMUAccessType acc = MMU_DATA_LOAD;
244
+ int size = 4 << GMID_EL1_BS;
245
+
246
+ clean_addr = clean_data_tbi(s, addr);
247
+ tcg_gen_andi_i64(clean_addr, clean_addr, -size);
248
+ gen_probe_access(s, clean_addr, acc, size);
249
+ /* The result tags are zeros. */
250
+ tcg_gen_movi_i64(tcg_rt, 0);
251
+ }
252
+ return true;
253
+}
147
+}
254
+
148
+
255
+static bool trans_LDG(DisasContext *s, arg_ldst_tag *a)
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
150
+ uint64_t value)
256
+{
151
+{
257
+ TCGv_i64 addr, clean_addr, tcg_rt;
152
+ ARMCPU *cpu = env_archcpu(env);
258
+
153
+
259
+ if (!dc_isar_feature(aa64_mte_insn_reg, s)) {
154
+ trace_arm_gt_cntpoff_write(value);
260
+ return false;
155
+ raw_write(env, ri, value);
261
+ }
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
262
+
263
+ if (a->rn == 31) {
264
+ gen_check_sp_alignment(s);
265
+ }
266
+
267
+ addr = read_cpu_reg_sp(s, a->rn, true);
268
+ if (!a->p) {
269
/* pre-index or signed offset */
270
- tcg_gen_addi_i64(addr, addr, offset);
271
+ tcg_gen_addi_i64(addr, addr, a->imm);
272
}
273
274
- if (is_mult) {
275
- tcg_rt = cpu_reg(s, rt);
276
+ tcg_gen_andi_i64(addr, addr, -TAG_GRANULE);
277
+ tcg_rt = cpu_reg(s, a->rt);
278
+ if (s->ata) {
279
+ gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
280
+ } else {
281
+ /*
282
+ * Tag access disabled: we must check for aborts on the load
283
+ * load from [rn+offset], and then insert a 0 tag into rt.
284
+ */
285
+ clean_addr = clean_data_tbi(s, addr);
286
+ gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
287
+ gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
288
+ }
289
290
- if (is_zero) {
291
- int size = 4 << s->dcz_blocksize;
292
-
293
- if (s->ata) {
294
- gen_helper_stzgm_tags(cpu_env, addr, tcg_rt);
295
- }
296
- /*
297
- * The non-tags portion of STZGM is mostly like DC_ZVA,
298
- * except the alignment happens before the access.
299
- */
300
- clean_addr = clean_data_tbi(s, addr);
301
- tcg_gen_andi_i64(clean_addr, clean_addr, -size);
302
- gen_helper_dc_zva(cpu_env, clean_addr);
303
- } else if (s->ata) {
304
- if (is_load) {
305
- gen_helper_ldgm(tcg_rt, cpu_env, addr);
306
- } else {
307
- gen_helper_stgm(cpu_env, addr, tcg_rt);
308
- }
309
- } else {
310
- MMUAccessType acc = is_load ? MMU_DATA_LOAD : MMU_DATA_STORE;
311
- int size = 4 << GMID_EL1_BS;
312
-
313
- clean_addr = clean_data_tbi(s, addr);
314
- tcg_gen_andi_i64(clean_addr, clean_addr, -size);
315
- gen_probe_access(s, clean_addr, acc, size);
316
-
317
- if (is_load) {
318
- /* The result tags are zeros. */
319
- tcg_gen_movi_i64(tcg_rt, 0);
320
- }
321
+ if (a->w) {
322
+ /* pre-index or post-index */
323
+ if (a->p) {
324
+ /* post-index */
325
+ tcg_gen_addi_i64(addr, addr, a->imm);
326
}
327
- return;
328
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), addr);
329
+ }
330
+ return true;
331
+}
157
+}
332
+
158
+
333
+static bool do_STG(DisasContext *s, arg_ldst_tag *a, bool is_zero, bool is_pair)
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
334
+{
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
335
+ TCGv_i64 addr, tcg_rt;
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
336
+
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
337
+ if (a->rn == 31) {
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
338
+ gen_check_sp_alignment(s);
164
+ .nv2_redirect_offset = 0x1a8,
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
166
+};
167
#else
168
169
/*
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
171
if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
172
define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
339
}
173
}
340
174
+#ifndef CONFIG_USER_ONLY
341
- if (is_load) {
175
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
342
- tcg_gen_andi_i64(addr, addr, -TAG_GRANULE);
176
+ define_one_arm_cp_reg(cpu, &gen_timer_cntpoff_reginfo);
343
- tcg_rt = cpu_reg(s, rt);
344
- if (s->ata) {
345
- gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
346
+ addr = read_cpu_reg_sp(s, a->rn, true);
347
+ if (!a->p) {
348
+ /* pre-index or signed offset */
349
+ tcg_gen_addi_i64(addr, addr, a->imm);
350
+ }
177
+ }
351
+ tcg_rt = cpu_reg_sp(s, a->rt);
178
+#endif
352
+ if (!s->ata) {
179
if (arm_feature(env, ARM_FEATURE_VAPA)) {
353
+ /*
180
ARMCPRegInfo vapa_cp_reginfo[] = {
354
+ * For STG and ST2G, we need to check alignment and probe memory.
181
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
355
+ * TODO: For STZG and STZ2G, we could rely on the stores below,
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
356
+ * at least for system mode; user-only won't enforce alignment.
183
index XXXXXXX..XXXXXXX 100644
357
+ */
184
--- a/target/arm/trace-events
358
+ if (is_pair) {
185
+++ b/target/arm/trace-events
359
+ gen_helper_st2g_stub(cpu_env, addr);
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
360
} else {
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
361
- /*
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
362
- * Tag access disabled: we must check for aborts on the load
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
363
- * load from [rn+offset], and then insert a 0 tag into rt.
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
364
- */
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
365
- clean_addr = clean_data_tbi(s, addr);
192
366
- gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
193
# kvm.c
367
- gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
368
+ gen_helper_stg_stub(cpu_env, addr);
369
+ }
370
+ } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
371
+ if (is_pair) {
372
+ gen_helper_st2g_parallel(cpu_env, addr, tcg_rt);
373
+ } else {
374
+ gen_helper_stg_parallel(cpu_env, addr, tcg_rt);
375
}
376
} else {
377
- tcg_rt = cpu_reg_sp(s, rt);
378
- if (!s->ata) {
379
- /*
380
- * For STG and ST2G, we need to check alignment and probe memory.
381
- * TODO: For STZG and STZ2G, we could rely on the stores below,
382
- * at least for system mode; user-only won't enforce alignment.
383
- */
384
- if (is_pair) {
385
- gen_helper_st2g_stub(cpu_env, addr);
386
- } else {
387
- gen_helper_stg_stub(cpu_env, addr);
388
- }
389
- } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
390
- if (is_pair) {
391
- gen_helper_st2g_parallel(cpu_env, addr, tcg_rt);
392
- } else {
393
- gen_helper_stg_parallel(cpu_env, addr, tcg_rt);
394
- }
395
+ if (is_pair) {
396
+ gen_helper_st2g(cpu_env, addr, tcg_rt);
397
} else {
398
- if (is_pair) {
399
- gen_helper_st2g(cpu_env, addr, tcg_rt);
400
- } else {
401
- gen_helper_stg(cpu_env, addr, tcg_rt);
402
- }
403
+ gen_helper_stg(cpu_env, addr, tcg_rt);
404
}
405
}
406
407
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
408
}
409
}
410
411
- if (index != 0) {
412
+ if (a->w) {
413
/* pre-index or post-index */
414
- if (index < 0) {
415
+ if (a->p) {
416
/* post-index */
417
- tcg_gen_addi_i64(addr, addr, offset);
418
+ tcg_gen_addi_i64(addr, addr, a->imm);
419
}
420
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), addr);
421
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), addr);
422
}
423
+ return true;
424
}
425
426
-/* Loads and stores */
427
-static void disas_ldst(DisasContext *s, uint32_t insn)
428
-{
429
- switch (extract32(insn, 24, 6)) {
430
- case 0x19:
431
- if (extract32(insn, 21, 1) != 0) {
432
- disas_ldst_tag(s, insn);
433
- } else {
434
- unallocated_encoding(s);
435
- }
436
- break;
437
- default:
438
- unallocated_encoding(s);
439
- break;
440
- }
441
-}
442
+TRANS_FEAT(STG, aa64_mte_insn_reg, do_STG, a, false, false)
443
+TRANS_FEAT(STZG, aa64_mte_insn_reg, do_STG, a, true, false)
444
+TRANS_FEAT(ST2G, aa64_mte_insn_reg, do_STG, a, false, true)
445
+TRANS_FEAT(STZ2G, aa64_mte_insn_reg, do_STG, a, true, true)
446
447
typedef void ArithTwoOp(TCGv_i64, TCGv_i64, TCGv_i64);
448
449
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
450
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
451
{
452
switch (extract32(insn, 25, 4)) {
453
- case 0x4:
454
- case 0x6:
455
- case 0xc:
456
- case 0xe: /* Loads and stores */
457
- disas_ldst(s, insn);
458
- break;
459
case 0x5:
460
case 0xd: /* Data processing - register */
461
disas_data_proc_reg(s, insn);
462
--
194
--
463
2.34.1
195
2.34.1
diff view generated by jsdifflib
1
Convert the instructions in the load/store register (pointer
1
Enable all FEAT_ECV features on the 'max' CPU.
2
authentication) group ot decodetree: LDRAA, LDRAB.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230602155223.2040685-17-peter.maydell@linaro.org
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
8
---
7
---
9
target/arm/tcg/a64.decode | 7 +++
8
docs/system/arm/emulation.rst | 1 +
10
target/arm/tcg/translate-a64.c | 83 +++++++---------------------------
9
target/arm/tcg/cpu64.c | 1 +
11
2 files changed, 23 insertions(+), 67 deletions(-)
10
2 files changed, 2 insertions(+)
12
11
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
14
--- a/docs/system/arm/emulation.rst
16
+++ b/target/arm/tcg/a64.decode
15
+++ b/docs/system/arm/emulation.rst
17
@@ -XXX,XX +XXX,XX @@ LDUMIN .. 111 0 00 . . 1 ..... 0111 00 ..... ..... @atomic
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
18
SWP .. 111 0 00 . . 1 ..... 1000 00 ..... ..... @atomic
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
19
18
- FEAT_DoubleFault (Double Fault Extension)
20
LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
21
+
20
+- FEAT_ECV (Enhanced Counter Virtualization)
22
+# Load/store register (pointer authentication)
21
- FEAT_EPAC (Enhanced pointer authentication)
23
+
22
- FEAT_ETS (Enhanced Translation Synchronization)
24
+# LDRA immediate is 10 bits signed and scaled, but the bits aren't all contiguous
23
- FEAT_EVT (Enhanced Virtualization Traps)
25
+%ldra_imm 22:s1 12:9 !function=times_2
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
26
+
27
+LDRA 11 111 0 00 m:1 . 1 ......... w:1 1 rn:5 rt:5 imm=%ldra_imm
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
29
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/tcg/translate-a64.c
26
--- a/target/arm/tcg/cpu64.c
31
+++ b/target/arm/tcg/translate-a64.c
27
+++ b/target/arm/tcg/cpu64.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_LDAPR(DisasContext *s, arg_LDAPR *a)
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
33
return true;
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
34
}
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
35
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
36
-/*
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
37
- * PAC memory operations
33
cpu->isar.id_aa64mmfr0 = t;
38
- *
34
39
- * 31 30 27 26 24 22 21 12 11 10 5 0
35
t = cpu->isar.id_aa64mmfr1;
40
- * +------+-------+---+-----+-----+---+--------+---+---+----+-----+
41
- * | size | 1 1 1 | V | 0 0 | M S | 1 | imm9 | W | 1 | Rn | Rt |
42
- * +------+-------+---+-----+-----+---+--------+---+---+----+-----+
43
- *
44
- * Rt: the result register
45
- * Rn: base address or SP
46
- * V: vector flag (always 0 as of v8.3)
47
- * M: clear for key DA, set for key DB
48
- * W: pre-indexing flag
49
- * S: sign for imm9.
50
- */
51
-static void disas_ldst_pac(DisasContext *s, uint32_t insn,
52
- int size, int rt, bool is_vector)
53
+static bool trans_LDRA(DisasContext *s, arg_LDRA *a)
54
{
55
- int rn = extract32(insn, 5, 5);
56
- bool is_wback = extract32(insn, 11, 1);
57
- bool use_key_a = !extract32(insn, 23, 1);
58
- int offset;
59
TCGv_i64 clean_addr, dirty_addr, tcg_rt;
60
MemOp memop;
61
62
- if (size != 3 || is_vector || !dc_isar_feature(aa64_pauth, s)) {
63
- unallocated_encoding(s);
64
- return;
65
+ /* Load with pointer authentication */
66
+ if (!dc_isar_feature(aa64_pauth, s)) {
67
+ return false;
68
}
69
70
- if (rn == 31) {
71
+ if (a->rn == 31) {
72
gen_check_sp_alignment(s);
73
}
74
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
75
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
76
77
if (s->pauth_active) {
78
- if (use_key_a) {
79
+ if (!a->m) {
80
gen_helper_autda(dirty_addr, cpu_env, dirty_addr,
81
tcg_constant_i64(0));
82
} else {
83
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn,
84
}
85
}
86
87
- /* Form the 10-bit signed, scaled offset. */
88
- offset = (extract32(insn, 22, 1) << 9) | extract32(insn, 12, 9);
89
- offset = sextract32(offset << size, 0, 10 + size);
90
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
91
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, a->imm);
92
93
- memop = finalize_memop(s, size);
94
+ memop = finalize_memop(s, MO_64);
95
96
/* Note that "clean" and "dirty" here refer to TBI not PAC. */
97
clean_addr = gen_mte_check1(s, dirty_addr, false,
98
- is_wback || rn != 31, memop);
99
+ a->w || a->rn != 31, memop);
100
101
- tcg_rt = cpu_reg(s, rt);
102
+ tcg_rt = cpu_reg(s, a->rt);
103
do_gpr_ld(s, tcg_rt, clean_addr, memop,
104
- /* extend */ false, /* iss_valid */ !is_wback,
105
- /* iss_srt */ rt, /* iss_sf */ true, /* iss_ar */ false);
106
+ /* extend */ false, /* iss_valid */ !a->w,
107
+ /* iss_srt */ a->rt, /* iss_sf */ true, /* iss_ar */ false);
108
109
- if (is_wback) {
110
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
111
+ if (a->w) {
112
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
113
}
114
+ return true;
115
}
116
117
/*
118
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
119
}
120
}
121
122
-/* Load/store register (all forms) */
123
-static void disas_ldst_reg(DisasContext *s, uint32_t insn)
124
-{
125
- int rt = extract32(insn, 0, 5);
126
- bool is_vector = extract32(insn, 26, 1);
127
- int size = extract32(insn, 30, 2);
128
-
129
- switch (extract32(insn, 24, 2)) {
130
- case 0:
131
- if (extract32(insn, 21, 1) == 0) {
132
- break;
133
- }
134
- switch (extract32(insn, 10, 2)) {
135
- case 0:
136
- case 2:
137
- break;
138
- default:
139
- disas_ldst_pac(s, insn, size, rt, is_vector);
140
- return;
141
- }
142
- break;
143
- }
144
- unallocated_encoding(s);
145
-}
146
-
147
/* AdvSIMD load/store multiple structures
148
*
149
* 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
150
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
151
static void disas_ldst(DisasContext *s, uint32_t insn)
152
{
153
switch (extract32(insn, 24, 6)) {
154
- case 0x38: case 0x39:
155
- case 0x3c: case 0x3d: /* Load/store register (all forms) */
156
- disas_ldst_reg(s, insn);
157
- break;
158
case 0x0c: /* AdvSIMD load/store multiple structures */
159
disas_ldst_multiple_struct(s, insn);
160
break;
161
--
36
--
162
2.34.1
37
2.34.1
163
38
164
39
diff view generated by jsdifflib
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
3
Features supported :
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
- the 8 STM32L4x5 GPIOs are initialized with their reset values
5
Acked-by: Richard Henderson <richard.henderson@linaro.org>
5
(except IDR, see below)
6
Message-id: 20230612223456.33824-2-philmd@linaro.org
6
- input mode : setting a pin in input mode "externally" (using input
7
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
7
irqs) results in an out irq (transmitted to SYSCFG)
8
[PMD: Split from bigger patch: 1/4]
8
- output mode : setting a bit in ODR sets the corresponding out irq
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
(if this line is configured in output mode)
10
- pull-up, pull-down
11
- push-pull, open-drain
12
13
Difference with the real GPIOs :
14
- Alternate Function and Analog mode aren't implemented :
15
pins in AF/Analog behave like pins in input mode
16
- floating pins stay at their last value
17
- register IDR reset values differ from the real one :
18
values are coherent with the other registers reset values
19
and the fact that AF/Analog modes aren't implemented
20
- setting I/O output speed isn't supported
21
- locking port bits isn't supported
22
- ADC function isn't supported
23
- GPIOH has 16 pins instead of 2 pins
24
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective
25
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
29
Acked-by: Alistair Francis <alistair.francis@wdc.com>
30
Message-id: 20240305210444.310665-2-ines.varhol@telecom-paris.fr
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
32
---
12
include/hw/misc/raspberrypi-fw-defs.h | 163 ++++++++++++++++++++++++++
33
MAINTAINERS | 1 +
13
1 file changed, 163 insertions(+)
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
14
create mode 100644 include/hw/misc/raspberrypi-fw-defs.h
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
37
hw/gpio/Kconfig | 3 +
38
hw/gpio/meson.build | 1 +
39
hw/gpio/trace-events | 6 +
40
7 files changed, 559 insertions(+), 1 deletion(-)
41
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
42
create mode 100644 hw/gpio/stm32l4x5_gpio.c
15
43
16
diff --git a/include/hw/misc/raspberrypi-fw-defs.h b/include/hw/misc/raspberrypi-fw-defs.h
44
diff --git a/MAINTAINERS b/MAINTAINERS
45
index XXXXXXX..XXXXXXX 100644
46
--- a/MAINTAINERS
47
+++ b/MAINTAINERS
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
49
F: hw/misc/stm32l4x5_exti.c
50
F: hw/misc/stm32l4x5_syscfg.c
51
F: hw/misc/stm32l4x5_rcc.c
52
+F: hw/gpio/stm32l4x5_gpio.c
53
F: include/hw/*/stm32l4x5_*.h
54
55
B-L475E-IOT01A IoT Node
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
57
index XXXXXXX..XXXXXXX 100644
58
--- a/docs/system/arm/b-l475e-iot01a.rst
59
+++ b/docs/system/arm/b-l475e-iot01a.rst
60
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
61
- STM32L4x5 EXTI (Extended interrupts and events controller)
62
- STM32L4x5 SYSCFG (System configuration controller)
63
- STM32L4x5 RCC (Reset and clock control)
64
+- STM32L4x5 GPIOs (General-purpose I/Os)
65
66
Missing devices
67
"""""""""""""""
68
@@ -XXX,XX +XXX,XX @@ Missing devices
69
The B-L475E-IOT01A does *not* support the following devices:
70
71
- Serial ports (UART)
72
-- General-purpose I/Os (GPIO)
73
- Analog to Digital Converter (ADC)
74
- SPI controller
75
- Timer controller (TIMER)
76
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
17
new file mode 100644
77
new file mode 100644
18
index XXXXXXX..XXXXXXX
78
index XXXXXXX..XXXXXXX
19
--- /dev/null
79
--- /dev/null
20
+++ b/include/hw/misc/raspberrypi-fw-defs.h
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
21
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
22
+/*
82
+/*
23
+ * Raspberry Pi firmware definitions
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
24
+ *
84
+ *
25
+ * Copyright (C) 2022 Auriga LLC, based on Linux kernel
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
26
+ * `include/soc/bcm2835/raspberrypi-firmware.h` (Copyright © 2015 Broadcom)
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
27
+ *
87
+ *
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
29
+ */
92
+ */
30
+
93
+
31
+#ifndef INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
94
+/*
32
+#define INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
98
+ */
99
+
100
+#ifndef HW_STM32L4X5_GPIO_H
101
+#define HW_STM32L4X5_GPIO_H
102
+
103
+#include "hw/sysbus.h"
104
+#include "qom/object.h"
105
+
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
108
+
109
+#define GPIO_NUM_PINS 16
110
+
111
+struct Stm32l4x5GpioState {
112
+ SysBusDevice parent_obj;
113
+
114
+ MemoryRegion mmio;
115
+
116
+ /* GPIO registers */
117
+ uint32_t moder;
118
+ uint32_t otyper;
119
+ uint32_t ospeedr;
120
+ uint32_t pupdr;
121
+ uint32_t idr;
122
+ uint32_t odr;
123
+ uint32_t lckr;
124
+ uint32_t afrl;
125
+ uint32_t afrh;
126
+ uint32_t ascr;
127
+
128
+ /* GPIO registers reset values */
129
+ uint32_t moder_reset;
130
+ uint32_t ospeedr_reset;
131
+ uint32_t pupdr_reset;
132
+
133
+ /*
134
+ * External driving of pins.
135
+ * The pins can be set externally through the device
136
+ * anonymous input GPIOs lines under certain conditions.
137
+ * The pin must not be in push-pull output mode,
138
+ * and can't be set high in open-drain mode.
139
+ * Pins driven externally and configured to
140
+ * output mode will in general be "disconnected"
141
+ * (see `get_gpio_pinmask_to_disconnect()`)
142
+ */
143
+ uint16_t disconnected_pins;
144
+ uint16_t pins_connected_high;
145
+
146
+ char *name;
147
+ Clock *clk;
148
+ qemu_irq pin[GPIO_NUM_PINS];
149
+};
150
+
151
+#endif
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
153
new file mode 100644
154
index XXXXXXX..XXXXXXX
155
--- /dev/null
156
+++ b/hw/gpio/stm32l4x5_gpio.c
157
@@ -XXX,XX +XXX,XX @@
158
+/*
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
160
+ *
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
163
+ *
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
165
+ *
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
167
+ * See the COPYING file in the top-level directory.
168
+ */
169
+
170
+/*
171
+ * The reference used is the STMicroElectronics RM0351 Reference manual
172
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
173
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
174
+ */
33
+
175
+
34
+#include "qemu/osdep.h"
176
+#include "qemu/osdep.h"
35
+
177
+#include "qemu/log.h"
36
+enum rpi_firmware_property_tag {
178
+#include "hw/gpio/stm32l4x5_gpio.h"
37
+ RPI_FWREQ_PROPERTY_END = 0,
179
+#include "hw/irq.h"
38
+ RPI_FWREQ_GET_FIRMWARE_REVISION = 0x00000001,
180
+#include "hw/qdev-clock.h"
39
+ RPI_FWREQ_GET_FIRMWARE_VARIANT = 0x00000002,
181
+#include "hw/qdev-properties.h"
40
+ RPI_FWREQ_GET_FIRMWARE_HASH = 0x00000003,
182
+#include "qapi/visitor.h"
41
+
183
+#include "qapi/error.h"
42
+ RPI_FWREQ_SET_CURSOR_INFO = 0x00008010,
184
+#include "migration/vmstate.h"
43
+ RPI_FWREQ_SET_CURSOR_STATE = 0x00008011,
185
+#include "trace.h"
44
+
186
+
45
+ RPI_FWREQ_GET_BOARD_MODEL = 0x00010001,
187
+#define GPIO_MODER 0x00
46
+ RPI_FWREQ_GET_BOARD_REVISION = 0x00010002,
188
+#define GPIO_OTYPER 0x04
47
+ RPI_FWREQ_GET_BOARD_MAC_ADDRESS = 0x00010003,
189
+#define GPIO_OSPEEDR 0x08
48
+ RPI_FWREQ_GET_BOARD_SERIAL = 0x00010004,
190
+#define GPIO_PUPDR 0x0C
49
+ RPI_FWREQ_GET_ARM_MEMORY = 0x00010005,
191
+#define GPIO_IDR 0x10
50
+ RPI_FWREQ_GET_VC_MEMORY = 0x00010006,
192
+#define GPIO_ODR 0x14
51
+ RPI_FWREQ_GET_CLOCKS = 0x00010007,
193
+#define GPIO_BSRR 0x18
52
+ RPI_FWREQ_GET_POWER_STATE = 0x00020001,
194
+#define GPIO_LCKR 0x1C
53
+ RPI_FWREQ_GET_TIMING = 0x00020002,
195
+#define GPIO_AFRL 0x20
54
+ RPI_FWREQ_SET_POWER_STATE = 0x00028001,
196
+#define GPIO_AFRH 0x24
55
+ RPI_FWREQ_GET_CLOCK_STATE = 0x00030001,
197
+#define GPIO_BRR 0x28
56
+ RPI_FWREQ_GET_CLOCK_RATE = 0x00030002,
198
+#define GPIO_ASCR 0x2C
57
+ RPI_FWREQ_GET_VOLTAGE = 0x00030003,
199
+
58
+ RPI_FWREQ_GET_MAX_CLOCK_RATE = 0x00030004,
200
+/* 0b11111111_11111111_00000000_00000000 */
59
+ RPI_FWREQ_GET_MAX_VOLTAGE = 0x00030005,
201
+#define RESERVED_BITS_MASK 0xFFFF0000
60
+ RPI_FWREQ_GET_TEMPERATURE = 0x00030006,
202
+
61
+ RPI_FWREQ_GET_MIN_CLOCK_RATE = 0x00030007,
203
+static void update_gpio_idr(Stm32l4x5GpioState *s);
62
+ RPI_FWREQ_GET_MIN_VOLTAGE = 0x00030008,
204
+
63
+ RPI_FWREQ_GET_TURBO = 0x00030009,
205
+static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
64
+ RPI_FWREQ_GET_MAX_TEMPERATURE = 0x0003000a,
206
+{
65
+ RPI_FWREQ_GET_STC = 0x0003000b,
207
+ return extract32(s->pupdr, 2 * pin, 2) == 1;
66
+ RPI_FWREQ_ALLOCATE_MEMORY = 0x0003000c,
208
+}
67
+ RPI_FWREQ_LOCK_MEMORY = 0x0003000d,
209
+
68
+ RPI_FWREQ_UNLOCK_MEMORY = 0x0003000e,
210
+static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
69
+ RPI_FWREQ_RELEASE_MEMORY = 0x0003000f,
211
+{
70
+ RPI_FWREQ_EXECUTE_CODE = 0x00030010,
212
+ return extract32(s->pupdr, 2 * pin, 2) == 2;
71
+ RPI_FWREQ_EXECUTE_QPU = 0x00030011,
213
+}
72
+ RPI_FWREQ_SET_ENABLE_QPU = 0x00030012,
214
+
73
+ RPI_FWREQ_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
215
+static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
74
+ RPI_FWREQ_GET_EDID_BLOCK = 0x00030020,
216
+{
75
+ RPI_FWREQ_GET_CUSTOMER_OTP = 0x00030021,
217
+ return extract32(s->moder, 2 * pin, 2) == 1;
76
+ RPI_FWREQ_GET_EDID_BLOCK_DISPLAY = 0x00030023,
218
+}
77
+ RPI_FWREQ_GET_DOMAIN_STATE = 0x00030030,
219
+
78
+ RPI_FWREQ_GET_THROTTLED = 0x00030046,
220
+static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
79
+ RPI_FWREQ_GET_CLOCK_MEASURED = 0x00030047,
221
+{
80
+ RPI_FWREQ_NOTIFY_REBOOT = 0x00030048,
222
+ return extract32(s->otyper, pin, 1) == 1;
81
+ RPI_FWREQ_SET_CLOCK_STATE = 0x00038001,
223
+}
82
+ RPI_FWREQ_SET_CLOCK_RATE = 0x00038002,
224
+
83
+ RPI_FWREQ_SET_VOLTAGE = 0x00038003,
225
+static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
84
+ RPI_FWREQ_SET_MAX_CLOCK_RATE = 0x00038004,
226
+{
85
+ RPI_FWREQ_SET_MIN_CLOCK_RATE = 0x00038007,
227
+ return extract32(s->otyper, pin, 1) == 0;
86
+ RPI_FWREQ_SET_TURBO = 0x00038009,
228
+}
87
+ RPI_FWREQ_SET_CUSTOMER_OTP = 0x00038021,
229
+
88
+ RPI_FWREQ_SET_DOMAIN_STATE = 0x00038030,
230
+static void stm32l4x5_gpio_reset_hold(Object *obj)
89
+ RPI_FWREQ_GET_GPIO_STATE = 0x00030041,
231
+{
90
+ RPI_FWREQ_SET_GPIO_STATE = 0x00038041,
232
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
91
+ RPI_FWREQ_SET_SDHOST_CLOCK = 0x00038042,
233
+
92
+ RPI_FWREQ_GET_GPIO_CONFIG = 0x00030043,
234
+ s->moder = s->moder_reset;
93
+ RPI_FWREQ_SET_GPIO_CONFIG = 0x00038043,
235
+ s->otyper = 0x00000000;
94
+ RPI_FWREQ_GET_PERIPH_REG = 0x00030045,
236
+ s->ospeedr = s->ospeedr_reset;
95
+ RPI_FWREQ_SET_PERIPH_REG = 0x00038045,
237
+ s->pupdr = s->pupdr_reset;
96
+ RPI_FWREQ_GET_POE_HAT_VAL = 0x00030049,
238
+ s->idr = 0x00000000;
97
+ RPI_FWREQ_SET_POE_HAT_VAL = 0x00038049,
239
+ s->odr = 0x00000000;
98
+ RPI_FWREQ_SET_POE_HAT_VAL_OLD = 0x00030050,
240
+ s->lckr = 0x00000000;
99
+ RPI_FWREQ_NOTIFY_XHCI_RESET = 0x00030058,
241
+ s->afrl = 0x00000000;
100
+ RPI_FWREQ_GET_REBOOT_FLAGS = 0x00030064,
242
+ s->afrh = 0x00000000;
101
+ RPI_FWREQ_SET_REBOOT_FLAGS = 0x00038064,
243
+ s->ascr = 0x00000000;
102
+ RPI_FWREQ_NOTIFY_DISPLAY_DONE = 0x00030066,
244
+
103
+
245
+ s->disconnected_pins = 0xFFFF;
104
+ /* Dispmanx TAGS */
246
+ s->pins_connected_high = 0x0000;
105
+ RPI_FWREQ_FRAMEBUFFER_ALLOCATE = 0x00040001,
247
+ update_gpio_idr(s);
106
+ RPI_FWREQ_FRAMEBUFFER_BLANK = 0x00040002,
248
+}
107
+ RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003,
249
+
108
+ RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004,
250
+static void stm32l4x5_gpio_set(void *opaque, int line, int level)
109
+ RPI_FWREQ_FRAMEBUFFER_GET_DEPTH = 0x00040005,
251
+{
110
+ RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006,
252
+ Stm32l4x5GpioState *s = opaque;
111
+ RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007,
253
+ /*
112
+ RPI_FWREQ_FRAMEBUFFER_GET_PITCH = 0x00040008,
254
+ * The pin isn't set if line is configured in output mode
113
+ RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
255
+ * except if level is 0 and the output is open-drain.
114
+ RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
256
+ * This way there will be no short-circuit prone situations.
115
+ RPI_FWREQ_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
257
+ */
116
+ RPI_FWREQ_FRAMEBUFFER_GET_LAYER = 0x0004000c,
258
+ if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
117
+ RPI_FWREQ_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
259
+ qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
118
+ RPI_FWREQ_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
260
+ line);
119
+ RPI_FWREQ_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
261
+ return;
120
+ RPI_FWREQ_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
262
+ }
121
+ RPI_FWREQ_FRAMEBUFFER_RELEASE = 0x00048001,
263
+
122
+ RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
264
+ s->disconnected_pins &= ~(1 << line);
123
+ RPI_FWREQ_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
265
+ if (level) {
124
+ RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
266
+ s->pins_connected_high |= (1 << line);
125
+ RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
267
+ } else {
126
+ RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
268
+ s->pins_connected_high &= ~(1 << line);
127
+ RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
269
+ }
128
+ RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
270
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
129
+ RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006,
271
+ s->pins_connected_high);
130
+ RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007,
272
+ update_gpio_idr(s);
131
+ RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
273
+}
132
+ RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
274
+
133
+ RPI_FWREQ_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
275
+
134
+ RPI_FWREQ_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
276
+static void update_gpio_idr(Stm32l4x5GpioState *s)
135
+ RPI_FWREQ_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
277
+{
136
+ RPI_FWREQ_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
278
+ uint32_t new_idr_mask = 0;
137
+ RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
279
+ uint32_t new_idr = s->odr;
138
+ RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
280
+ uint32_t old_idr = s->idr;
139
+ RPI_FWREQ_FRAMEBUFFER_SET_DEPTH = 0x00048005,
281
+ int new_pin_state, old_pin_state;
140
+ RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
282
+
141
+ RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
283
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
142
+ RPI_FWREQ_FRAMEBUFFER_SET_PITCH = 0x00048008,
284
+ if (is_output(s, i)) {
143
+ RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
285
+ if (is_push_pull(s, i)) {
144
+ RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
286
+ new_idr_mask |= (1 << i);
145
+ RPI_FWREQ_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
287
+ } else if (!(s->odr & (1 << i))) {
146
+
288
+ /* open-drain ODR 0 */
147
+ RPI_FWREQ_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
289
+ new_idr_mask |= (1 << i);
148
+ RPI_FWREQ_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
290
+ /* open-drain ODR 1 */
149
+ RPI_FWREQ_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
291
+ } else if (!(s->disconnected_pins & (1 << i)) &&
150
+ RPI_FWREQ_FRAMEBUFFER_SET_LAYER = 0x0004800c,
292
+ !(s->pins_connected_high & (1 << i))) {
151
+ RPI_FWREQ_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
293
+ /* open-drain ODR 1 with pin connected low */
152
+ RPI_FWREQ_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
294
+ new_idr_mask |= (1 << i);
153
+
295
+ new_idr &= ~(1 << i);
154
+ RPI_FWREQ_VCHIQ_INIT = 0x00048010,
296
+ /* open-drain ODR 1 with unactive pin */
155
+
297
+ } else if (is_pull_up(s, i)) {
156
+ RPI_FWREQ_SET_PLANE = 0x00048015,
298
+ new_idr_mask |= (1 << i);
157
+ RPI_FWREQ_GET_DISPLAY_TIMING = 0x00040017,
299
+ } else if (is_pull_down(s, i)) {
158
+ RPI_FWREQ_SET_TIMING = 0x00048017,
300
+ new_idr_mask |= (1 << i);
159
+ RPI_FWREQ_GET_DISPLAY_CFG = 0x00040018,
301
+ new_idr &= ~(1 << i);
160
+ RPI_FWREQ_SET_DISPLAY_POWER = 0x00048019,
302
+ }
161
+ RPI_FWREQ_GET_COMMAND_LINE = 0x00050001,
303
+ /*
162
+ RPI_FWREQ_GET_DMA_CHANNELS = 0x00060001,
304
+ * The only case left is for open-drain ODR 1
305
+ * with unactive pin without pull-up or pull-down :
306
+ * the value is floating.
307
+ */
308
+ /* input or analog mode with connected pin */
309
+ } else if (!(s->disconnected_pins & (1 << i))) {
310
+ if (s->pins_connected_high & (1 << i)) {
311
+ /* pin high */
312
+ new_idr_mask |= (1 << i);
313
+ new_idr |= (1 << i);
314
+ } else {
315
+ /* pin low */
316
+ new_idr_mask |= (1 << i);
317
+ new_idr &= ~(1 << i);
318
+ }
319
+ /* input or analog mode with disconnected pin */
320
+ } else {
321
+ if (is_pull_up(s, i)) {
322
+ /* pull-up */
323
+ new_idr_mask |= (1 << i);
324
+ new_idr |= (1 << i);
325
+ } else if (is_pull_down(s, i)) {
326
+ /* pull-down */
327
+ new_idr_mask |= (1 << i);
328
+ new_idr &= ~(1 << i);
329
+ }
330
+ /*
331
+ * The only case left is for a disconnected pin
332
+ * without pull-up or pull-down :
333
+ * the value is floating.
334
+ */
335
+ }
336
+ }
337
+
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
340
+
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
342
+ if (new_idr_mask & (1 << i)) {
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
345
+ if (new_pin_state > old_pin_state) {
346
+ qemu_irq_raise(s->pin[i]);
347
+ } else if (new_pin_state < old_pin_state) {
348
+ qemu_irq_lower(s->pin[i]);
349
+ }
350
+ }
351
+ }
352
+}
353
+
354
+/*
355
+ * Return mask of pins that are both configured in output
356
+ * mode and externally driven (except pins in open-drain
357
+ * mode externally set to 0).
358
+ */
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
360
+{
361
+ uint32_t pins_to_disconnect = 0;
362
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
363
+ /* for each connected pin in output mode */
364
+ if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
365
+ /* if either push-pull or high level */
366
+ if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
367
+ pins_to_disconnect |= (1 << i);
368
+ qemu_log_mask(LOG_GUEST_ERROR,
369
+ "Line %d can't be driven externally\n",
370
+ i);
371
+ }
372
+ }
373
+ }
374
+ return pins_to_disconnect;
375
+}
376
+
377
+/*
378
+ * Set field `disconnected_pins` and call `update_gpio_idr()`
379
+ */
380
+static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
381
+{
382
+ s->disconnected_pins |= lines;
383
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
384
+ s->pins_connected_high);
385
+ update_gpio_idr(s);
386
+}
387
+
388
+static void disconnected_pins_set(Object *obj, Visitor *v,
389
+ const char *name, void *opaque, Error **errp)
390
+{
391
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
392
+ uint16_t value;
393
+ if (!visit_type_uint16(v, name, &value, errp)) {
394
+ return;
395
+ }
396
+ disconnect_gpio_pins(s, value);
397
+}
398
+
399
+static void disconnected_pins_get(Object *obj, Visitor *v,
400
+ const char *name, void *opaque, Error **errp)
401
+{
402
+ visit_type_uint16(v, name, (uint16_t *)opaque, errp);
403
+}
404
+
405
+static void clock_freq_get(Object *obj, Visitor *v,
406
+ const char *name, void *opaque, Error **errp)
407
+{
408
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
409
+ uint32_t clock_freq_hz = clock_get_hz(s->clk);
410
+ visit_type_uint32(v, name, &clock_freq_hz, errp);
411
+}
412
+
413
+static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
414
+ uint64_t val64, unsigned int size)
415
+{
416
+ Stm32l4x5GpioState *s = opaque;
417
+
418
+ uint32_t value = val64;
419
+ trace_stm32l4x5_gpio_write(s->name, addr, val64);
420
+
421
+ switch (addr) {
422
+ case GPIO_MODER:
423
+ s->moder = value;
424
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
425
+ qemu_log_mask(LOG_UNIMP,
426
+ "%s: Analog and AF modes aren't supported\n\
427
+ Analog and AF mode behave like input mode\n",
428
+ __func__);
429
+ return;
430
+ case GPIO_OTYPER:
431
+ s->otyper = value & ~RESERVED_BITS_MASK;
432
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
433
+ return;
434
+ case GPIO_OSPEEDR:
435
+ qemu_log_mask(LOG_UNIMP,
436
+ "%s: Changing I/O output speed isn't supported\n\
437
+ I/O speed is already maximal\n",
438
+ __func__);
439
+ s->ospeedr = value;
440
+ return;
441
+ case GPIO_PUPDR:
442
+ s->pupdr = value;
443
+ update_gpio_idr(s);
444
+ return;
445
+ case GPIO_IDR:
446
+ qemu_log_mask(LOG_UNIMP,
447
+ "%s: GPIO->IDR is read-only\n",
448
+ __func__);
449
+ return;
450
+ case GPIO_ODR:
451
+ s->odr = value & ~RESERVED_BITS_MASK;
452
+ update_gpio_idr(s);
453
+ return;
454
+ case GPIO_BSRR: {
455
+ uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
456
+ uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
457
+ /* If both BSx and BRx are set, BSx has priority.*/
458
+ s->odr &= ~bits_to_reset;
459
+ s->odr |= bits_to_set;
460
+ update_gpio_idr(s);
461
+ return;
462
+ }
463
+ case GPIO_LCKR:
464
+ qemu_log_mask(LOG_UNIMP,
465
+ "%s: Locking port bits configuration isn't supported\n",
466
+ __func__);
467
+ s->lckr = value & ~RESERVED_BITS_MASK;
468
+ return;
469
+ case GPIO_AFRL:
470
+ qemu_log_mask(LOG_UNIMP,
471
+ "%s: Alternate functions aren't supported\n",
472
+ __func__);
473
+ s->afrl = value;
474
+ return;
475
+ case GPIO_AFRH:
476
+ qemu_log_mask(LOG_UNIMP,
477
+ "%s: Alternate functions aren't supported\n",
478
+ __func__);
479
+ s->afrh = value;
480
+ return;
481
+ case GPIO_BRR: {
482
+ uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
483
+ s->odr &= ~bits_to_reset;
484
+ update_gpio_idr(s);
485
+ return;
486
+ }
487
+ case GPIO_ASCR:
488
+ qemu_log_mask(LOG_UNIMP,
489
+ "%s: ADC function isn't supported\n",
490
+ __func__);
491
+ s->ascr = value & ~RESERVED_BITS_MASK;
492
+ return;
493
+ default:
494
+ qemu_log_mask(LOG_GUEST_ERROR,
495
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
496
+ }
497
+}
498
+
499
+static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
500
+ unsigned int size)
501
+{
502
+ Stm32l4x5GpioState *s = opaque;
503
+
504
+ trace_stm32l4x5_gpio_read(s->name, addr);
505
+
506
+ switch (addr) {
507
+ case GPIO_MODER:
508
+ return s->moder;
509
+ case GPIO_OTYPER:
510
+ return s->otyper;
511
+ case GPIO_OSPEEDR:
512
+ return s->ospeedr;
513
+ case GPIO_PUPDR:
514
+ return s->pupdr;
515
+ case GPIO_IDR:
516
+ return s->idr;
517
+ case GPIO_ODR:
518
+ return s->odr;
519
+ case GPIO_BSRR:
520
+ return 0;
521
+ case GPIO_LCKR:
522
+ return s->lckr;
523
+ case GPIO_AFRL:
524
+ return s->afrl;
525
+ case GPIO_AFRH:
526
+ return s->afrh;
527
+ case GPIO_BRR:
528
+ return 0;
529
+ case GPIO_ASCR:
530
+ return s->ascr;
531
+ default:
532
+ qemu_log_mask(LOG_GUEST_ERROR,
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
534
+ return 0;
535
+ }
536
+}
537
+
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
539
+ .read = stm32l4x5_gpio_read,
540
+ .write = stm32l4x5_gpio_write,
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
542
+ .impl = {
543
+ .min_access_size = 4,
544
+ .max_access_size = 4,
545
+ .unaligned = false,
546
+ },
547
+ .valid = {
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
551
+ },
163
+};
552
+};
164
+
553
+
165
+enum rpi_firmware_clk_id {
554
+static void stm32l4x5_gpio_init(Object *obj)
166
+ RPI_FIRMWARE_EMMC_CLK_ID = 1,
555
+{
167
+ RPI_FIRMWARE_UART_CLK_ID,
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
168
+ RPI_FIRMWARE_ARM_CLK_ID,
557
+
169
+ RPI_FIRMWARE_CORE_CLK_ID,
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
170
+ RPI_FIRMWARE_V3D_CLK_ID,
559
+ TYPE_STM32L4X5_GPIO, 0x400);
171
+ RPI_FIRMWARE_H264_CLK_ID,
560
+
172
+ RPI_FIRMWARE_ISP_CLK_ID,
561
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
173
+ RPI_FIRMWARE_SDRAM_CLK_ID,
562
+
174
+ RPI_FIRMWARE_PIXEL_CLK_ID,
563
+ qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
175
+ RPI_FIRMWARE_PWM_CLK_ID,
564
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
176
+ RPI_FIRMWARE_HEVC_CLK_ID,
565
+
177
+ RPI_FIRMWARE_EMMC2_CLK_ID,
566
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
178
+ RPI_FIRMWARE_M2MC_CLK_ID,
567
+
179
+ RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
568
+ object_property_add(obj, "disconnected-pins", "uint16",
180
+ RPI_FIRMWARE_VEC_CLK_ID,
569
+ disconnected_pins_get, disconnected_pins_set,
181
+ RPI_FIRMWARE_NUM_CLK_ID,
570
+ NULL, &s->disconnected_pins);
571
+ object_property_add(obj, "clock-freq-hz", "uint32",
572
+ clock_freq_get, NULL, NULL, NULL);
573
+}
574
+
575
+static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
576
+{
577
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
578
+ if (!clock_has_source(s->clk)) {
579
+ error_setg(errp, "GPIO: clk input must be connected");
580
+ return;
581
+ }
582
+}
583
+
584
+static const VMStateDescription vmstate_stm32l4x5_gpio = {
585
+ .name = TYPE_STM32L4X5_GPIO,
586
+ .version_id = 1,
587
+ .minimum_version_id = 1,
588
+ .fields = (VMStateField[]){
589
+ VMSTATE_UINT32(moder, Stm32l4x5GpioState),
590
+ VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
591
+ VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
592
+ VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
593
+ VMSTATE_UINT32(idr, Stm32l4x5GpioState),
594
+ VMSTATE_UINT32(odr, Stm32l4x5GpioState),
595
+ VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
596
+ VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
597
+ VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
598
+ VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
599
+ VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
600
+ VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
601
+ VMSTATE_END_OF_LIST()
602
+ }
182
+};
603
+};
183
+
604
+
184
+#endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */
605
+static Property stm32l4x5_gpio_properties[] = {
606
+ DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
607
+ DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
608
+ DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
609
+ DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
610
+ DEFINE_PROP_END_OF_LIST(),
611
+};
612
+
613
+static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
614
+{
615
+ DeviceClass *dc = DEVICE_CLASS(klass);
616
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
617
+
618
+ device_class_set_props(dc, stm32l4x5_gpio_properties);
619
+ dc->vmsd = &vmstate_stm32l4x5_gpio;
620
+ dc->realize = stm32l4x5_gpio_realize;
621
+ rc->phases.hold = stm32l4x5_gpio_reset_hold;
622
+}
623
+
624
+static const TypeInfo stm32l4x5_gpio_types[] = {
625
+ {
626
+ .name = TYPE_STM32L4X5_GPIO,
627
+ .parent = TYPE_SYS_BUS_DEVICE,
628
+ .instance_size = sizeof(Stm32l4x5GpioState),
629
+ .instance_init = stm32l4x5_gpio_init,
630
+ .class_init = stm32l4x5_gpio_class_init,
631
+ },
632
+};
633
+
634
+DEFINE_TYPES(stm32l4x5_gpio_types)
635
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
636
index XXXXXXX..XXXXXXX 100644
637
--- a/hw/gpio/Kconfig
638
+++ b/hw/gpio/Kconfig
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
640
641
config SIFIVE_GPIO
642
bool
643
+
644
+config STM32L4X5_GPIO
645
+ bool
646
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
647
index XXXXXXX..XXXXXXX 100644
648
--- a/hw/gpio/meson.build
649
+++ b/hw/gpio/meson.build
650
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
651
'bcm2835_gpio.c',
652
'bcm2838_gpio.c'
653
))
654
+system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
655
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
656
system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
657
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
658
index XXXXXXX..XXXXXXX 100644
659
--- a/hw/gpio/trace-events
660
+++ b/hw/gpio/trace-events
661
@@ -XXX,XX +XXX,XX @@ sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " val
662
# aspeed_gpio.c
663
aspeed_gpio_read(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
664
aspeed_gpio_write(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
665
+
666
+# stm32l4x5_gpio.c
667
+stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
668
+stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
669
+stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
670
+stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
185
--
671
--
186
2.34.1
672
2.34.1
187
673
188
674
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
Message-id: 20230607092112.655098-1-marcin.juszkiewicz@linaro.org
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
hw/arm/Kconfig | 1 +
10
include/hw/arm/stm32l4x5_soc.h | 2 +
9
1 file changed, 1 insertion(+)
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
10
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
14
hw/misc/stm32l4x5_syscfg.c | 1 +
15
hw/arm/Kconfig | 3 +-
16
6 files changed, 63 insertions(+), 18 deletions(-)
17
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/stm32l4x5_soc.h
21
+++ b/include/hw/arm/stm32l4x5_soc.h
22
@@ -XXX,XX +XXX,XX @@
23
#include "hw/misc/stm32l4x5_syscfg.h"
24
#include "hw/misc/stm32l4x5_exti.h"
25
#include "hw/misc/stm32l4x5_rcc.h"
26
+#include "hw/gpio/stm32l4x5_gpio.h"
27
#include "qom/object.h"
28
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
32
Stm32l4x5SyscfgState syscfg;
33
Stm32l4x5RccState rcc;
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
35
36
MemoryRegion sram1;
37
MemoryRegion sram2;
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
42
@@ -XXX,XX +XXX,XX @@
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
45
46
+#define NUM_GPIOS 8
47
#define GPIO_NUM_PINS 16
48
49
struct Stm32l4x5GpioState {
50
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/hw/misc/stm32l4x5_syscfg.h
53
+++ b/include/hw/misc/stm32l4x5_syscfg.h
54
@@ -XXX,XX +XXX,XX @@
55
56
#include "hw/sysbus.h"
57
#include "qom/object.h"
58
+#include "hw/gpio/stm32l4x5_gpio.h"
59
60
#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
61
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
62
63
-#define NUM_GPIOS 8
64
-#define GPIO_NUM_PINS 16
65
#define SYSCFG_NUM_EXTICR 4
66
67
struct Stm32l4x5SyscfgState {
68
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/arm/stm32l4x5_soc.c
71
+++ b/hw/arm/stm32l4x5_soc.c
72
@@ -XXX,XX +XXX,XX @@
73
#include "sysemu/sysemu.h"
74
#include "hw/or-irq.h"
75
#include "hw/arm/stm32l4x5_soc.h"
76
+#include "hw/gpio/stm32l4x5_gpio.h"
77
#include "hw/qdev-clock.h"
78
#include "hw/misc/unimp.h"
79
80
@@ -XXX,XX +XXX,XX @@ static const int exti_or_gate1_lines_in[EXTI_OR_GATE1_NUM_LINES_IN] = {
81
16, 35, 36, 37, 38,
82
};
83
84
+static const struct {
85
+ uint32_t addr;
86
+ uint32_t moder_reset;
87
+ uint32_t ospeedr_reset;
88
+ uint32_t pupdr_reset;
89
+} stm32l4x5_gpio_cfg[NUM_GPIOS] = {
90
+ { 0x48000000, 0xABFFFFFF, 0x0C000000, 0x64000000 },
91
+ { 0x48000400, 0xFFFFFEBF, 0x00000000, 0x00000100 },
92
+ { 0x48000800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
93
+ { 0x48000C00, 0xFFFFFFFF, 0x00000000, 0x00000000 },
94
+ { 0x48001000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
95
+ { 0x48001400, 0xFFFFFFFF, 0x00000000, 0x00000000 },
96
+ { 0x48001800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
97
+ { 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
98
+};
99
+
100
static void stm32l4x5_soc_initfn(Object *obj)
101
{
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
104
}
105
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
106
object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
107
+
108
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
109
+ g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
110
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
111
+ }
112
}
113
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
118
MemoryRegion *system_memory = get_system_memory();
119
- DeviceState *armv7m;
120
+ DeviceState *armv7m, *dev;
121
SysBusDevice *busdev;
122
+ uint32_t pin_index;
123
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
125
sc->flash_size, errp)) {
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
127
return;
128
}
129
130
+ /* GPIOs */
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
133
+ dev = DEVICE(&s->gpio[i]);
134
+ qdev_prop_set_string(dev, "name", name);
135
+ qdev_prop_set_uint32(dev, "mode-reset",
136
+ stm32l4x5_gpio_cfg[i].moder_reset);
137
+ qdev_prop_set_uint32(dev, "ospeed-reset",
138
+ stm32l4x5_gpio_cfg[i].ospeedr_reset);
139
+ qdev_prop_set_uint32(dev, "pupd-reset",
140
+ stm32l4x5_gpio_cfg[i].pupdr_reset);
141
+ busdev = SYS_BUS_DEVICE(&s->gpio[i]);
142
+ g_free(name);
143
+ name = g_strdup_printf("gpio%c-out", 'a' + i);
144
+ qdev_connect_clock_in(DEVICE(&s->gpio[i]), "clk",
145
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
146
+ if (!sysbus_realize(busdev, errp)) {
147
+ return;
148
+ }
149
+ sysbus_mmio_map(busdev, 0, stm32l4x5_gpio_cfg[i].addr);
150
+ }
151
+
152
/* System configuration controller */
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
154
if (!sysbus_realize(busdev, errp)) {
155
return;
156
}
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
158
- /*
159
- * TODO: when the GPIO device is implemented, connect it
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
161
- * GPIO_NUM_PINS.
162
- */
163
+
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
166
+ pin_index = GPIO_NUM_PINS * i + j;
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
169
+ pin_index));
170
+ }
171
+ }
172
173
/* EXTI device */
174
busdev = SYS_BUS_DEVICE(&s->exti);
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
176
}
177
}
178
179
- for (unsigned i = 0; i < 16; i++) {
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
183
}
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
186
187
/* AHB2 BUS */
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/misc/stm32l4x5_syscfg.c
202
+++ b/hw/misc/stm32l4x5_syscfg.c
203
@@ -XXX,XX +XXX,XX @@
204
#include "hw/irq.h"
205
#include "migration/vmstate.h"
206
#include "hw/misc/stm32l4x5_syscfg.h"
207
+#include "hw/gpio/stm32l4x5_gpio.h"
208
209
#define SYSCFG_MEMRMP 0x00
210
#define SYSCFG_CFGR1 0x04
11
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
12
index XXXXXXX..XXXXXXX 100644
212
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/Kconfig
213
--- a/hw/arm/Kconfig
14
+++ b/hw/arm/Kconfig
214
+++ b/hw/arm/Kconfig
15
@@ -XXX,XX +XXX,XX @@ config SBSA_REF
215
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
16
select PL061 # GPIO
216
bool
17
select USB_EHCI_SYSBUS
217
select ARM_V7M
18
select WDT_SBSA
218
select OR_IRQ
19
+ select BOCHS_DISPLAY
219
- select STM32L4X5_SYSCFG
20
220
select STM32L4X5_EXTI
21
config SABRELITE
221
+ select STM32L4X5_SYSCFG
222
select STM32L4X5_RCC
223
+ select STM32L4X5_GPIO
224
225
config XLNX_ZYNQMP_ARM
22
bool
226
bool
23
--
227
--
24
2.34.1
228
2.34.1
229
230
diff view generated by jsdifflib
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
3
The testcase contains :
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
- `test_idr_reset_value()` :
5
Message-id: 20230612223456.33824-5-philmd@linaro.org
5
Checks the reset values of MODER, OTYPER, PUPDR, ODR and IDR.
6
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
6
- `test_gpio_output_mode()` :
7
[PMD: Split from bigger patch: 3/4]
7
Checks that writing a bit in register ODR results in the corresponding
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
pin rising or lowering, if this pin is configured in output mode.
9
[PMM: added a comment about RPI_FIRMWARE_CORE_CLK_RATE
9
- `test_gpio_input_mode()` :
10
really being SoC-specific]
10
Checks that a input pin set high or low externally results
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
in the pin rising and lowering.
12
- `test_pull_up_pull_down()` :
13
Checks that a floating pin in pull-up/down mode is actually high/down.
14
- `test_push_pull()` :
15
Checks that a pin set externally is disconnected when configured in
16
push-pull output mode, and can't be set externally while in this mode.
17
- `test_open_drain()` :
18
Checks that a pin set externally high is disconnected when configured
19
in open-drain output mode, and can't be set high while in this mode.
20
- `test_bsrr_brr()` :
21
Checks that writing to BSRR and BRR has the desired result in ODR.
22
- `test_clock_enable()` :
23
Checks that GPIO clock is at the right frequency after enabling it.
24
25
Acked-by: Thomas Huth <thuth@redhat.com>
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
30
---
14
include/hw/arm/raspi_platform.h | 5 +++++
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
15
hw/misc/bcm2835_property.c | 3 +++
32
tests/qtest/meson.build | 3 +-
16
2 files changed, 8 insertions(+)
33
2 files changed, 553 insertions(+), 1 deletion(-)
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
17
35
18
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
37
new file mode 100644
38
index XXXXXXX..XXXXXXX
39
--- /dev/null
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
41
@@ -XXX,XX +XXX,XX @@
42
+/*
43
+ * QTest testcase for STM32L4x5_GPIO
44
+ *
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
47
+ *
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
49
+ * See the COPYING file in the top-level directory.
50
+ */
51
+
52
+#include "qemu/osdep.h"
53
+#include "libqtest-single.h"
54
+
55
+#define GPIO_BASE_ADDR 0x48000000
56
+#define GPIO_SIZE 0x400
57
+#define NUM_GPIOS 8
58
+#define NUM_GPIO_PINS 16
59
+
60
+#define GPIO_A 0x48000000
61
+#define GPIO_B 0x48000400
62
+#define GPIO_C 0x48000800
63
+#define GPIO_D 0x48000C00
64
+#define GPIO_E 0x48001000
65
+#define GPIO_F 0x48001400
66
+#define GPIO_G 0x48001800
67
+#define GPIO_H 0x48001C00
68
+
69
+#define MODER 0x00
70
+#define OTYPER 0x04
71
+#define PUPDR 0x0C
72
+#define IDR 0x10
73
+#define ODR 0x14
74
+#define BSRR 0x18
75
+#define BRR 0x28
76
+
77
+#define MODER_INPUT 0
78
+#define MODER_OUTPUT 1
79
+
80
+#define PUPDR_NONE 0
81
+#define PUPDR_PULLUP 1
82
+#define PUPDR_PULLDOWN 2
83
+
84
+#define OTYPER_PUSH_PULL 0
85
+#define OTYPER_OPEN_DRAIN 1
86
+
87
+const uint32_t moder_reset[NUM_GPIOS] = {
88
+ 0xABFFFFFF,
89
+ 0xFFFFFEBF,
90
+ 0xFFFFFFFF,
91
+ 0xFFFFFFFF,
92
+ 0xFFFFFFFF,
93
+ 0xFFFFFFFF,
94
+ 0xFFFFFFFF,
95
+ 0x0000000F
96
+};
97
+
98
+const uint32_t pupdr_reset[NUM_GPIOS] = {
99
+ 0x64000000,
100
+ 0x00000100,
101
+ 0x00000000,
102
+ 0x00000000,
103
+ 0x00000000,
104
+ 0x00000000,
105
+ 0x00000000,
106
+ 0x00000000
107
+};
108
+
109
+const uint32_t idr_reset[NUM_GPIOS] = {
110
+ 0x0000A000,
111
+ 0x00000010,
112
+ 0x00000000,
113
+ 0x00000000,
114
+ 0x00000000,
115
+ 0x00000000,
116
+ 0x00000000,
117
+ 0x00000000
118
+};
119
+
120
+static uint32_t gpio_readl(unsigned int gpio, unsigned int offset)
121
+{
122
+ return readl(gpio + offset);
123
+}
124
+
125
+static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value)
126
+{
127
+ writel(gpio + offset, value);
128
+}
129
+
130
+static void gpio_set_bit(unsigned int gpio, unsigned int reg,
131
+ unsigned int pin, uint32_t value)
132
+{
133
+ uint32_t mask = 0xFFFFFFFF & ~(0x1 << pin);
134
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin);
135
+}
136
+
137
+static void gpio_set_2bits(unsigned int gpio, unsigned int reg,
138
+ unsigned int pin, uint32_t value)
139
+{
140
+ uint32_t offset = 2 * pin;
141
+ uint32_t mask = 0xFFFFFFFF & ~(0x3 << offset);
142
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset);
143
+}
144
+
145
+static unsigned int get_gpio_id(uint32_t gpio_addr)
146
+{
147
+ return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE;
148
+}
149
+
150
+static void gpio_set_irq(unsigned int gpio, int num, int level)
151
+{
152
+ g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c",
153
+ get_gpio_id(gpio) + 'a');
154
+ qtest_set_irq_in(global_qtest, name, NULL, num, level);
155
+}
156
+
157
+static void disconnect_all_pins(unsigned int gpio)
158
+{
159
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
160
+ get_gpio_id(gpio) + 'a');
161
+ QDict *r;
162
+
163
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': "
164
+ "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }",
165
+ path, 0xFFFF);
166
+ g_assert_false(qdict_haskey(r, "error"));
167
+ qobject_unref(r);
168
+}
169
+
170
+static uint32_t get_disconnected_pins(unsigned int gpio)
171
+{
172
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
173
+ get_gpio_id(gpio) + 'a');
174
+ uint32_t disconnected_pins = 0;
175
+ QDict *r;
176
+
177
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':"
178
+ " { 'path': %s, 'property': 'disconnected-pins'} }", path);
179
+ g_assert_false(qdict_haskey(r, "error"));
180
+ disconnected_pins = qdict_get_int(r, "return");
181
+ qobject_unref(r);
182
+ return disconnected_pins;
183
+}
184
+
185
+static uint32_t reset(uint32_t gpio, unsigned int offset)
186
+{
187
+ switch (offset) {
188
+ case MODER:
189
+ return moder_reset[get_gpio_id(gpio)];
190
+ case PUPDR:
191
+ return pupdr_reset[get_gpio_id(gpio)];
192
+ case IDR:
193
+ return idr_reset[get_gpio_id(gpio)];
194
+ }
195
+ return 0x0;
196
+}
197
+
198
+static void system_reset(void)
199
+{
200
+ QDict *r;
201
+ r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
202
+ g_assert_false(qdict_haskey(r, "error"));
203
+ qobject_unref(r);
204
+}
205
+
206
+static void test_idr_reset_value(void)
207
+{
208
+ /*
209
+ * Checks that the values in MODER, OTYPER, PUPDR and ODR
210
+ * after reset are correct, and that the value in IDR is
211
+ * coherent.
212
+ * Since AF and analog modes aren't implemented, IDR reset
213
+ * values aren't the same as with a real board.
214
+ *
215
+ * Register IDR contains the actual values of all GPIO pins.
216
+ * Its value depends on the pins' configuration
217
+ * (intput/output/analog : register MODER, push-pull/open-drain :
218
+ * register OTYPER, pull-up/pull-down/none : register PUPDR)
219
+ * and on the values stored in register ODR
220
+ * (in case the pin is in output mode).
221
+ */
222
+
223
+ gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
224
+ gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
225
+ gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
226
+ gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
227
+
228
+ gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
229
+ gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
230
+ gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
231
+ gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
232
+
233
+ gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
234
+ gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
235
+ gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
236
+ gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
237
+
238
+ gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
239
+ gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
240
+ gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
241
+ gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
242
+
243
+ system_reset();
244
+
245
+ uint32_t moder = gpio_readl(GPIO_A, MODER);
246
+ uint32_t odr = gpio_readl(GPIO_A, ODR);
247
+ uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
248
+ uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
249
+ uint32_t idr = gpio_readl(GPIO_A, IDR);
250
+ /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
251
+ /* here AF is the same as Analog and Input mode */
252
+ g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
253
+ g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
254
+ g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
255
+ /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
256
+ g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
257
+ /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
258
+ g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
259
+
260
+ moder = gpio_readl(GPIO_B, MODER);
261
+ odr = gpio_readl(GPIO_B, ODR);
262
+ otyper = gpio_readl(GPIO_B, OTYPER);
263
+ pupdr = gpio_readl(GPIO_B, PUPDR);
264
+ idr = gpio_readl(GPIO_B, IDR);
265
+ /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
266
+ /* here AF is the same as Analog and Input mode */
267
+ g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
268
+ g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
269
+ g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
270
+ /* ... 5: neither, 4: pull-up, 3: neither ... */
271
+ g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
272
+ /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
273
+ g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
274
+
275
+ moder = gpio_readl(GPIO_C, MODER);
276
+ odr = gpio_readl(GPIO_C, ODR);
277
+ otyper = gpio_readl(GPIO_C, OTYPER);
278
+ pupdr = gpio_readl(GPIO_C, PUPDR);
279
+ idr = gpio_readl(GPIO_C, IDR);
280
+ /* Analog, same as Input mode*/
281
+ g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
282
+ g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
283
+ g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
284
+ /* no pull-up or pull-down */
285
+ g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
286
+ /* reset value */
287
+ g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
288
+
289
+ moder = gpio_readl(GPIO_H, MODER);
290
+ odr = gpio_readl(GPIO_H, ODR);
291
+ otyper = gpio_readl(GPIO_H, OTYPER);
292
+ pupdr = gpio_readl(GPIO_H, PUPDR);
293
+ idr = gpio_readl(GPIO_H, IDR);
294
+ /* Analog, same as Input mode */
295
+ g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
296
+ g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
297
+ g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
298
+ /* no pull-up or pull-down */
299
+ g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
300
+ /* reset value */
301
+ g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
302
+}
303
+
304
+static void test_gpio_output_mode(const void *data)
305
+{
306
+ /*
307
+ * Checks that setting a bit in ODR sets the corresponding
308
+ * GPIO line high : it should set the right bit in IDR
309
+ * and send an irq to syscfg.
310
+ * Additionally, it checks that values written to ODR
311
+ * when not in output mode are stored and not discarded.
312
+ */
313
+ unsigned int pin = ((uint64_t)data) & 0xF;
314
+ uint32_t gpio = ((uint64_t)data) >> 32;
315
+ unsigned int gpio_id = get_gpio_id(gpio);
316
+
317
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
318
+
319
+ /* Set a bit in ODR and check nothing happens */
320
+ gpio_set_bit(gpio, ODR, pin, 1);
321
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
322
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
323
+
324
+ /* Configure the relevant line as output and check the pin is high */
325
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
326
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
327
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
328
+
329
+ /* Reset the bit in ODR and check the pin is low */
330
+ gpio_set_bit(gpio, ODR, pin, 0);
331
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
332
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
333
+
334
+ /* Clean the test */
335
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
336
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
337
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
338
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
339
+}
340
+
341
+static void test_gpio_input_mode(const void *data)
342
+{
343
+ /*
344
+ * Test that setting a line high/low externally sets the
345
+ * corresponding GPIO line high/low : it should set the
346
+ * right bit in IDR and send an irq to syscfg.
347
+ */
348
+ unsigned int pin = ((uint64_t)data) & 0xF;
349
+ uint32_t gpio = ((uint64_t)data) >> 32;
350
+ unsigned int gpio_id = get_gpio_id(gpio);
351
+
352
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
353
+
354
+ /* Configure a line as input, raise it, and check that the pin is high */
355
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
356
+ gpio_set_irq(gpio, pin, 1);
357
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
358
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
359
+
360
+ /* Lower the line and check that the pin is low */
361
+ gpio_set_irq(gpio, pin, 0);
362
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
363
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
364
+
365
+ /* Clean the test */
366
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
367
+ disconnect_all_pins(gpio);
368
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
369
+}
370
+
371
+static void test_pull_up_pull_down(const void *data)
372
+{
373
+ /*
374
+ * Test that a floating pin with pull-up sets the pin
375
+ * high and vice-versa.
376
+ */
377
+ unsigned int pin = ((uint64_t)data) & 0xF;
378
+ uint32_t gpio = ((uint64_t)data) >> 32;
379
+ unsigned int gpio_id = get_gpio_id(gpio);
380
+
381
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
382
+
383
+ /* Configure a line as input with pull-up, check the line is set high */
384
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
385
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
386
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
387
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
388
+
389
+ /* Configure the line with pull-down, check the line is low */
390
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
391
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
392
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
393
+
394
+ /* Clean the test */
395
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
396
+ gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
397
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
398
+}
399
+
400
+static void test_push_pull(const void *data)
401
+{
402
+ /*
403
+ * Test that configuring a line in push-pull output mode
404
+ * disconnects the pin, that the pin can't be set or reset
405
+ * externally afterwards.
406
+ */
407
+ unsigned int pin = ((uint64_t)data) & 0xF;
408
+ uint32_t gpio = ((uint64_t)data) >> 32;
409
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
410
+
411
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
412
+
413
+ /* Setting a line high externally, configuring it in push-pull output */
414
+ /* And checking the pin was disconnected */
415
+ gpio_set_irq(gpio, pin, 1);
416
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
417
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
418
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
419
+
420
+ /* Setting a line low externally, configuring it in push-pull output */
421
+ /* And checking the pin was disconnected */
422
+ gpio_set_irq(gpio2, pin, 0);
423
+ gpio_set_bit(gpio2, ODR, pin, 1);
424
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
425
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
426
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
427
+
428
+ /* Trying to set a push-pull output pin, checking it doesn't work */
429
+ gpio_set_irq(gpio, pin, 1);
430
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
431
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
432
+
433
+ /* Trying to reset a push-pull output pin, checking it doesn't work */
434
+ gpio_set_irq(gpio2, pin, 0);
435
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
436
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
437
+
438
+ /* Clean the test */
439
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
440
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
441
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
442
+}
443
+
444
+static void test_open_drain(const void *data)
445
+{
446
+ /*
447
+ * Test that configuring a line in open-drain output mode
448
+ * disconnects a pin set high externally and that the pin
449
+ * can't be set high externally while configured in open-drain.
450
+ *
451
+ * However a pin set low externally shouldn't be disconnected,
452
+ * and it can be set low externally when in open-drain mode.
453
+ */
454
+ unsigned int pin = ((uint64_t)data) & 0xF;
455
+ uint32_t gpio = ((uint64_t)data) >> 32;
456
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
457
+
458
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
459
+
460
+ /* Setting a line high externally, configuring it in open-drain output */
461
+ /* And checking the pin was disconnected */
462
+ gpio_set_irq(gpio, pin, 1);
463
+ gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN);
464
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
465
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
466
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
467
+
468
+ /* Setting a line low externally, configuring it in open-drain output */
469
+ /* And checking the pin wasn't disconnected */
470
+ gpio_set_irq(gpio2, pin, 0);
471
+ gpio_set_bit(gpio2, ODR, pin, 1);
472
+ gpio_set_bit(gpio2, OTYPER, pin, OTYPER_OPEN_DRAIN);
473
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
474
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
475
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
476
+ reset(gpio2, IDR) & ~(1 << pin));
477
+
478
+ /* Trying to set a open-drain output pin, checking it doesn't work */
479
+ gpio_set_irq(gpio, pin, 1);
480
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
481
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
482
+
483
+ /* Trying to reset a open-drain output pin, checking it works */
484
+ gpio_set_bit(gpio, ODR, pin, 1);
485
+ gpio_set_irq(gpio, pin, 0);
486
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
487
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
488
+ reset(gpio2, IDR) & ~(1 << pin));
489
+
490
+ /* Clean the test */
491
+ disconnect_all_pins(gpio2);
492
+ gpio_writel(gpio2, OTYPER, reset(gpio2, OTYPER));
493
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
494
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
495
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR));
496
+ disconnect_all_pins(gpio);
497
+ gpio_writel(gpio, OTYPER, reset(gpio, OTYPER));
498
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
499
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
500
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
501
+}
502
+
503
+static void test_bsrr_brr(const void *data)
504
+{
505
+ /*
506
+ * Test that writing a '1' in BSS and BSRR
507
+ * has the desired effect on ODR.
508
+ * In BSRR, BSx has priority over BRx.
509
+ */
510
+ unsigned int pin = ((uint64_t)data) & 0xF;
511
+ uint32_t gpio = ((uint64_t)data) >> 32;
512
+
513
+ gpio_writel(gpio, BSRR, (1 << pin));
514
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
515
+
516
+ gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS)));
517
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
518
+
519
+ gpio_writel(gpio, BSRR, (1 << pin));
520
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
521
+
522
+ gpio_writel(gpio, BRR, (1 << pin));
523
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
524
+
525
+ /* BSx should have priority over BRx */
526
+ gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS)));
527
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
528
+
529
+ gpio_writel(gpio, BRR, (1 << pin));
530
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
531
+
532
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
533
+}
534
+
535
+int main(int argc, char **argv)
536
+{
537
+ int ret;
538
+
539
+ g_test_init(&argc, &argv, NULL);
540
+ g_test_set_nonfatal_assertions();
541
+ qtest_add_func("stm32l4x5/gpio/test_idr_reset_value",
542
+ test_idr_reset_value);
543
+ /*
544
+ * The inputs for the tests (gpio and pin) can be changed,
545
+ * but the tests don't work for pins that are high at reset
546
+ * (GPIOA15, GPIO13 and GPIOB5).
547
+ * Specifically, rising the pin then checking `get_irq()`
548
+ * is problematic since the pin was already high.
549
+ */
550
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode",
551
+ (void *)((uint64_t)GPIO_C << 32 | 5),
552
+ test_gpio_output_mode);
553
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode",
554
+ (void *)((uint64_t)GPIO_H << 32 | 3),
555
+ test_gpio_output_mode);
556
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1",
557
+ (void *)((uint64_t)GPIO_D << 32 | 6),
558
+ test_gpio_input_mode);
559
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2",
560
+ (void *)((uint64_t)GPIO_C << 32 | 10),
561
+ test_gpio_input_mode);
562
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1",
563
+ (void *)((uint64_t)GPIO_B << 32 | 5),
564
+ test_pull_up_pull_down);
565
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down2",
566
+ (void *)((uint64_t)GPIO_F << 32 | 1),
567
+ test_pull_up_pull_down);
568
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull1",
569
+ (void *)((uint64_t)GPIO_G << 32 | 6),
570
+ test_push_pull);
571
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull2",
572
+ (void *)((uint64_t)GPIO_H << 32 | 3),
573
+ test_push_pull);
574
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain1",
575
+ (void *)((uint64_t)GPIO_C << 32 | 4),
576
+ test_open_drain);
577
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain2",
578
+ (void *)((uint64_t)GPIO_E << 32 | 11),
579
+ test_open_drain);
580
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr1",
581
+ (void *)((uint64_t)GPIO_A << 32 | 12),
582
+ test_bsrr_brr);
583
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
584
+ (void *)((uint64_t)GPIO_D << 32 | 0),
585
+ test_bsrr_brr);
586
+
587
+ qtest_start("-machine b-l475e-iot01a");
588
+ ret = g_test_run();
589
+ qtest_end();
590
+
591
+ return ret;
592
+}
593
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
19
index XXXXXXX..XXXXXXX 100644
594
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/raspi_platform.h
595
--- a/tests/qtest/meson.build
21
+++ b/include/hw/arm/raspi_platform.h
596
+++ b/tests/qtest/meson.build
22
@@ -XXX,XX +XXX,XX @@
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
23
/* Clock rates */
598
qtests_stm32l4x5 = \
24
#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
599
['stm32l4x5_exti-test',
25
#define RPI_FIRMWARE_UART_CLK_RATE 3000000
600
'stm32l4x5_syscfg-test',
26
+/*
601
- 'stm32l4x5_rcc-test']
27
+ * TODO: this is really SoC-specific; we might want to
602
+ 'stm32l4x5_rcc-test',
28
+ * set it per-SoC if it turns out any guests care.
603
+ 'stm32l4x5_gpio-test']
29
+ */
604
30
+#define RPI_FIRMWARE_CORE_CLK_RATE 350000000
605
qtests_arm = \
31
#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
32
33
#endif
34
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/misc/bcm2835_property.c
37
+++ b/hw/misc/bcm2835_property.c
38
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
39
case RPI_FIRMWARE_UART_CLK_ID:
40
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE);
41
break;
42
+ case RPI_FIRMWARE_CORE_CLK_ID:
43
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_CORE_CLK_RATE);
44
+ break;
45
default:
46
stl_le_phys(&s->dma_as, value + 16,
47
RPI_FIRMWARE_DEFAULT_CLK_RATE);
48
--
607
--
49
2.34.1
608
2.34.1
50
609
51
610
diff view generated by jsdifflib
1
Convert MSR (reg), MRS, SYS, SYSL to decodetree. For QEMU these are
1
From: Richard Henderson <richard.henderson@linaro.org>
2
all essentially the same instruction (system register access).
2
3
3
While the 8-bit input elements are sequential in the input vector,
4
the 32-bit output elements are not sequential in the output matrix.
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
7
Cc: qemu-stable@nongnu.org
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-7-peter.maydell@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
---
14
---
9
target/arm/tcg/a64.decode | 8 ++++++++
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
10
target/arm/tcg/translate-a64.c | 32 +++++---------------------------
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
11
2 files changed, 13 insertions(+), 27 deletions(-)
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
12
18
tests/tcg/aarch64/Makefile.target | 2 +-
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
19
4 files changed, 147 insertions(+), 33 deletions(-)
20
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
21
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
22
23
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
14
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
25
--- a/target/arm/tcg/sme_helper.c
16
+++ b/target/arm/tcg/a64.decode
26
+++ b/target/arm/tcg/sme_helper.c
17
@@ -XXX,XX +XXX,XX @@ MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
18
MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
19
MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
20
MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
21
+
22
+# MRS, MSR (register), SYS, SYSL. These are all essentially the
23
+# same instruction as far as QEMU is concerned.
24
+# NB: op0 is bits [20:19], but op0=0b00 is other insns, so we have
25
+# to hand-decode it.
26
+SYS 1101 0101 00 l:1 01 op1:3 crn:4 crm:4 op2:3 rt:5 op0=1
27
+SYS 1101 0101 00 l:1 10 op1:3 crn:4 crm:4 op2:3 rt:5 op0=2
28
+SYS 1101 0101 00 l:1 11 op1:3 crn:4 crm:4 op2:3 rt:5 op0=3
29
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/tcg/translate-a64.c
32
+++ b/target/arm/tcg/translate-a64.c
33
@@ -XXX,XX +XXX,XX @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
34
* These are all essentially the same insn in 'read' and 'write'
35
* versions, with varying op0 fields.
36
*/
37
-static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
38
+static void handle_sys(DisasContext *s, bool isread,
39
unsigned int op0, unsigned int op1, unsigned int op2,
40
unsigned int crn, unsigned int crm, unsigned int rt)
41
{
42
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
43
}
28
}
44
}
29
}
45
30
46
-/* System
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
47
- * 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
48
- * +---------------------+---+-----+-----+-------+-------+-----+------+
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
49
- * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 | CRn | CRm | op2 | Rt |
34
+ uint8_t *pn, uint8_t *pm,
50
- * +---------------------+---+-----+-----+-------+-------+-----+------+
35
+ uint32_t desc, IMOPFn32 *fn)
51
- */
36
+{
52
-static void disas_system(DisasContext *s, uint32_t insn)
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
53
+static bool trans_SYS(DisasContext *s, arg_SYS *a)
38
+ bool neg = simd_data(desc);
39
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
41
- uint8_t *pn, uint8_t *pm,
42
- uint32_t desc, IMOPFn *fn)
43
+ for (row = 0; row < oprsz; ++row) {
44
+ uint8_t pa = (pn[H1(row >> 1)] >> ((row & 1) * 4)) & 0xf;
45
+ uint32_t *za_row = &za[tile_vslice_index(row)];
46
+ uint32_t n = zn[H4(row)];
47
+
48
+ for (col = 0; col < oprsz; ++col) {
49
+ uint8_t pb = pm[H1(col >> 1)] >> ((col & 1) * 4);
50
+ uint32_t *a = &za_row[H4(col)];
51
+
52
+ *a = fn(n, zm[H4(col)], *a, pa & pb, neg);
53
+ }
54
+ }
55
+}
56
+
57
+typedef uint64_t IMOPFn64(uint64_t, uint64_t, uint64_t, uint8_t, bool);
58
+static inline void do_imopa_d(uint64_t *za, uint64_t *zn, uint64_t *zm,
59
+ uint8_t *pn, uint8_t *pm,
60
+ uint32_t desc, IMOPFn64 *fn)
54
{
61
{
55
- unsigned int l, op0, op1, crn, crm, op2, rt;
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
56
- l = extract32(insn, 21, 1);
63
bool neg = simd_data(desc);
57
- op0 = extract32(insn, 19, 2);
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
58
- op1 = extract32(insn, 16, 3);
59
- crn = extract32(insn, 12, 4);
60
- crm = extract32(insn, 8, 4);
61
- op2 = extract32(insn, 5, 3);
62
- rt = extract32(insn, 0, 5);
63
-
64
- if (op0 == 0) {
65
- unallocated_encoding(s);
66
- return;
67
- }
68
- handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
69
+ handle_sys(s, a->l, a->op0, a->op1, a->op2, a->crn, a->crm, a->rt);
70
+ return true;
71
}
65
}
72
66
73
/* Exception generation
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
74
@@ -XXX,XX +XXX,XX @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
75
switch (extract32(insn, 25, 7)) {
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
76
case 0x6a: /* Exception generation / System */
70
{ \
77
if (insn & (1 << 24)) {
71
- uint32_t sum0 = 0, sum1 = 0; \
78
- if (extract32(insn, 22, 2) == 0) {
72
+ uint32_t sum = 0; \
79
- disas_system(s, insn);
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
80
- } else {
74
n &= expand_pred_b(p); \
81
- unallocated_encoding(s);
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
82
- }
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
83
+ unallocated_encoding(s);
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
84
} else {
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
85
disas_exc(s, insn);
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
86
}
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
83
- if (neg) { \
84
- sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
85
- } else { \
86
- sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
87
- } \
88
- return ((uint64_t)sum1 << 32) | sum0; \
89
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
90
+ sum += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
91
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
92
+ sum += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
93
+ return neg ? a - sum : a + sum; \
94
}
95
96
#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
97
@@ -XXX,XX +XXX,XX @@ DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
98
DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
99
DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
100
101
-#define DEF_IMOPH(NAME) \
102
- void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
103
- void *vpm, uint32_t desc) \
104
- { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
105
+#define DEF_IMOPH(NAME, S) \
106
+ void HELPER(sme_##NAME##_##S)(void *vza, void *vzn, void *vzm, \
107
+ void *vpn, void *vpm, uint32_t desc) \
108
+ { do_imopa_##S(vza, vzn, vzm, vpn, vpm, desc, NAME##_##S); }
109
110
-DEF_IMOPH(smopa_s)
111
-DEF_IMOPH(umopa_s)
112
-DEF_IMOPH(sumopa_s)
113
-DEF_IMOPH(usmopa_s)
114
-DEF_IMOPH(smopa_d)
115
-DEF_IMOPH(umopa_d)
116
-DEF_IMOPH(sumopa_d)
117
-DEF_IMOPH(usmopa_d)
118
+DEF_IMOPH(smopa, s)
119
+DEF_IMOPH(umopa, s)
120
+DEF_IMOPH(sumopa, s)
121
+DEF_IMOPH(usmopa, s)
122
+
123
+DEF_IMOPH(smopa, d)
124
+DEF_IMOPH(umopa, d)
125
+DEF_IMOPH(sumopa, d)
126
+DEF_IMOPH(usmopa, d)
127
diff --git a/tests/tcg/aarch64/sme-smopa-1.c b/tests/tcg/aarch64/sme-smopa-1.c
128
new file mode 100644
129
index XXXXXXX..XXXXXXX
130
--- /dev/null
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
132
@@ -XXX,XX +XXX,XX @@
133
+#include <stdio.h>
134
+#include <string.h>
135
+
136
+int main()
137
+{
138
+ static const int cmp[4][4] = {
139
+ { 110, 134, 158, 182 },
140
+ { 390, 478, 566, 654 },
141
+ { 670, 822, 974, 1126 },
142
+ { 950, 1166, 1382, 1598 }
143
+ };
144
+ int dst[4][4];
145
+ int *tmp = &dst[0][0];
146
+
147
+ asm volatile(
148
+ ".arch armv8-r+sme\n\t"
149
+ "smstart\n\t"
150
+ "index z0.b, #0, #1\n\t"
151
+ "movprfx z1, z0\n\t"
152
+ "add z1.b, z1.b, #16\n\t"
153
+ "ptrue p0.b\n\t"
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
155
+ "ptrue p0.s, vl4\n\t"
156
+ "mov w12, #0\n\t"
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
158
+ "add %0, %0, #16\n\t"
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
160
+ "add %0, %0, #16\n\t"
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
162
+ "add %0, %0, #16\n\t"
163
+ "st1w { za0h.s[w12, #3] }, p0, [%0]\n\t"
164
+ "smstop"
165
+ : "+r"(tmp) : : "memory");
166
+
167
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
168
+ return 0;
169
+ }
170
+
171
+ /* See above for correct results. */
172
+ for (int i = 0; i < 4; ++i) {
173
+ for (int j = 0; j < 4; ++j) {
174
+ printf("%6d", dst[i][j]);
175
+ }
176
+ printf("\n");
177
+ }
178
+ return 1;
179
+}
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
181
new file mode 100644
182
index XXXXXXX..XXXXXXX
183
--- /dev/null
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
185
@@ -XXX,XX +XXX,XX @@
186
+#include <stdio.h>
187
+#include <string.h>
188
+
189
+int main()
190
+{
191
+ static const long cmp[4][4] = {
192
+ { 110, 134, 158, 182 },
193
+ { 390, 478, 566, 654 },
194
+ { 670, 822, 974, 1126 },
195
+ { 950, 1166, 1382, 1598 }
196
+ };
197
+ long dst[4][4];
198
+ long *tmp = &dst[0][0];
199
+ long svl;
200
+
201
+ /* Validate that we have a wide enough vector for 4 elements. */
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
203
+ if (svl < 32) {
204
+ return 0;
205
+ }
206
+
207
+ asm volatile(
208
+ "smstart\n\t"
209
+ "index z0.h, #0, #1\n\t"
210
+ "movprfx z1, z0\n\t"
211
+ "add z1.h, z1.h, #16\n\t"
212
+ "ptrue p0.b\n\t"
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
214
+ "ptrue p0.d, vl4\n\t"
215
+ "mov w12, #0\n\t"
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
217
+ "add %0, %0, #32\n\t"
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
219
+ "mov w12, #2\n\t"
220
+ "add %0, %0, #32\n\t"
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
222
+ "add %0, %0, #32\n\t"
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
224
+ "smstop"
225
+ : "+r"(tmp) : : "memory");
226
+
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
228
+ return 0;
229
+ }
230
+
231
+ /* See above for correct results. */
232
+ for (int i = 0; i < 4; ++i) {
233
+ for (int j = 0; j < 4; ++j) {
234
+ printf("%6ld", dst[i][j]);
235
+ }
236
+ printf("\n");
237
+ }
238
+ return 1;
239
+}
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
241
index XXXXXXX..XXXXXXX 100644
242
--- a/tests/tcg/aarch64/Makefile.target
243
+++ b/tests/tcg/aarch64/Makefile.target
244
@@ -XXX,XX +XXX,XX @@ endif
245
246
# SME Tests
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
248
-AARCH64_TESTS += sme-outprod1
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
250
endif
251
252
# System Registers Tests
87
--
253
--
88
2.34.1
254
2.34.1
89
255
90
256
diff view generated by jsdifflib
Deleted patch
1
Convert the exception generation instructions SVC, HVC, SMC, BRK and
2
HLT to decodetree.
3
1
4
The old decoder decoded the halting-debug insnns DCPS1, DCPS2 and
5
DCPS3 just in order to then make them UNDEF; as with DRPS, we don't
6
bother to decode them, but document the patterns in a64.decode.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20230602155223.2040685-8-peter.maydell@linaro.org
11
---
12
target/arm/tcg/a64.decode | 15 +++
13
target/arm/tcg/translate-a64.c | 173 ++++++++++++---------------------
14
2 files changed, 79 insertions(+), 109 deletions(-)
15
16
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/tcg/a64.decode
19
+++ b/target/arm/tcg/a64.decode
20
@@ -XXX,XX +XXX,XX @@ MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
21
SYS 1101 0101 00 l:1 01 op1:3 crn:4 crm:4 op2:3 rt:5 op0=1
22
SYS 1101 0101 00 l:1 10 op1:3 crn:4 crm:4 op2:3 rt:5 op0=2
23
SYS 1101 0101 00 l:1 11 op1:3 crn:4 crm:4 op2:3 rt:5 op0=3
24
+
25
+# Exception generation
26
+
27
+@i16 .... .... ... imm:16 ... .. &i
28
+SVC 1101 0100 000 ................ 000 01 @i16
29
+HVC 1101 0100 000 ................ 000 10 @i16
30
+SMC 1101 0100 000 ................ 000 11 @i16
31
+BRK 1101 0100 001 ................ 000 00 @i16
32
+HLT 1101 0100 010 ................ 000 00 @i16
33
+# These insns always UNDEF unless in halting debug state, which
34
+# we don't implement. So we don't need to decode them. The patterns
35
+# are listed here as documentation.
36
+# DCPS1 1101 0100 101 ................ 000 01 @i16
37
+# DCPS2 1101 0100 101 ................ 000 10 @i16
38
+# DCPS3 1101 0100 101 ................ 000 11 @i16
39
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/tcg/translate-a64.c
42
+++ b/target/arm/tcg/translate-a64.c
43
@@ -XXX,XX +XXX,XX @@ static bool trans_SYS(DisasContext *s, arg_SYS *a)
44
return true;
45
}
46
47
-/* Exception generation
48
- *
49
- * 31 24 23 21 20 5 4 2 1 0
50
- * +-----------------+-----+------------------------+-----+----+
51
- * | 1 1 0 1 0 1 0 0 | opc | imm16 | op2 | LL |
52
- * +-----------------------+------------------------+----------+
53
- */
54
-static void disas_exc(DisasContext *s, uint32_t insn)
55
+static bool trans_SVC(DisasContext *s, arg_i *a)
56
{
57
- int opc = extract32(insn, 21, 3);
58
- int op2_ll = extract32(insn, 0, 5);
59
- int imm16 = extract32(insn, 5, 16);
60
- uint32_t syndrome;
61
-
62
- switch (opc) {
63
- case 0:
64
- /* For SVC, HVC and SMC we advance the single-step state
65
- * machine before taking the exception. This is architecturally
66
- * mandated, to ensure that single-stepping a system call
67
- * instruction works properly.
68
- */
69
- switch (op2_ll) {
70
- case 1: /* SVC */
71
- syndrome = syn_aa64_svc(imm16);
72
- if (s->fgt_svc) {
73
- gen_exception_insn_el(s, 0, EXCP_UDEF, syndrome, 2);
74
- break;
75
- }
76
- gen_ss_advance(s);
77
- gen_exception_insn(s, 4, EXCP_SWI, syndrome);
78
- break;
79
- case 2: /* HVC */
80
- if (s->current_el == 0) {
81
- unallocated_encoding(s);
82
- break;
83
- }
84
- /* The pre HVC helper handles cases when HVC gets trapped
85
- * as an undefined insn by runtime configuration.
86
- */
87
- gen_a64_update_pc(s, 0);
88
- gen_helper_pre_hvc(cpu_env);
89
- gen_ss_advance(s);
90
- gen_exception_insn_el(s, 4, EXCP_HVC, syn_aa64_hvc(imm16), 2);
91
- break;
92
- case 3: /* SMC */
93
- if (s->current_el == 0) {
94
- unallocated_encoding(s);
95
- break;
96
- }
97
- gen_a64_update_pc(s, 0);
98
- gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
99
- gen_ss_advance(s);
100
- gen_exception_insn_el(s, 4, EXCP_SMC, syn_aa64_smc(imm16), 3);
101
- break;
102
- default:
103
- unallocated_encoding(s);
104
- break;
105
- }
106
- break;
107
- case 1:
108
- if (op2_ll != 0) {
109
- unallocated_encoding(s);
110
- break;
111
- }
112
- /* BRK */
113
- gen_exception_bkpt_insn(s, syn_aa64_bkpt(imm16));
114
- break;
115
- case 2:
116
- if (op2_ll != 0) {
117
- unallocated_encoding(s);
118
- break;
119
- }
120
- /* HLT. This has two purposes.
121
- * Architecturally, it is an external halting debug instruction.
122
- * Since QEMU doesn't implement external debug, we treat this as
123
- * it is required for halting debug disabled: it will UNDEF.
124
- * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
125
- */
126
- if (semihosting_enabled(s->current_el == 0) && imm16 == 0xf000) {
127
- gen_exception_internal_insn(s, EXCP_SEMIHOST);
128
- } else {
129
- unallocated_encoding(s);
130
- }
131
- break;
132
- case 5:
133
- if (op2_ll < 1 || op2_ll > 3) {
134
- unallocated_encoding(s);
135
- break;
136
- }
137
- /* DCPS1, DCPS2, DCPS3 */
138
- unallocated_encoding(s);
139
- break;
140
- default:
141
- unallocated_encoding(s);
142
- break;
143
+ /*
144
+ * For SVC, HVC and SMC we advance the single-step state
145
+ * machine before taking the exception. This is architecturally
146
+ * mandated, to ensure that single-stepping a system call
147
+ * instruction works properly.
148
+ */
149
+ uint32_t syndrome = syn_aa64_svc(a->imm);
150
+ if (s->fgt_svc) {
151
+ gen_exception_insn_el(s, 0, EXCP_UDEF, syndrome, 2);
152
+ return true;
153
}
154
+ gen_ss_advance(s);
155
+ gen_exception_insn(s, 4, EXCP_SWI, syndrome);
156
+ return true;
157
}
158
159
-/* Branches, exception generating and system instructions */
160
-static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
161
+static bool trans_HVC(DisasContext *s, arg_i *a)
162
{
163
- switch (extract32(insn, 25, 7)) {
164
- case 0x6a: /* Exception generation / System */
165
- if (insn & (1 << 24)) {
166
- unallocated_encoding(s);
167
- } else {
168
- disas_exc(s, insn);
169
- }
170
- break;
171
- default:
172
+ if (s->current_el == 0) {
173
unallocated_encoding(s);
174
- break;
175
+ return true;
176
}
177
+ /*
178
+ * The pre HVC helper handles cases when HVC gets trapped
179
+ * as an undefined insn by runtime configuration.
180
+ */
181
+ gen_a64_update_pc(s, 0);
182
+ gen_helper_pre_hvc(cpu_env);
183
+ /* Architecture requires ss advance before we do the actual work */
184
+ gen_ss_advance(s);
185
+ gen_exception_insn_el(s, 4, EXCP_HVC, syn_aa64_hvc(a->imm), 2);
186
+ return true;
187
+}
188
+
189
+static bool trans_SMC(DisasContext *s, arg_i *a)
190
+{
191
+ if (s->current_el == 0) {
192
+ unallocated_encoding(s);
193
+ return true;
194
+ }
195
+ gen_a64_update_pc(s, 0);
196
+ gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(a->imm)));
197
+ /* Architecture requires ss advance before we do the actual work */
198
+ gen_ss_advance(s);
199
+ gen_exception_insn_el(s, 4, EXCP_SMC, syn_aa64_smc(a->imm), 3);
200
+ return true;
201
+}
202
+
203
+static bool trans_BRK(DisasContext *s, arg_i *a)
204
+{
205
+ gen_exception_bkpt_insn(s, syn_aa64_bkpt(a->imm));
206
+ return true;
207
+}
208
+
209
+static bool trans_HLT(DisasContext *s, arg_i *a)
210
+{
211
+ /*
212
+ * HLT. This has two purposes.
213
+ * Architecturally, it is an external halting debug instruction.
214
+ * Since QEMU doesn't implement external debug, we treat this as
215
+ * it is required for halting debug disabled: it will UNDEF.
216
+ * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
217
+ */
218
+ if (semihosting_enabled(s->current_el == 0) && a->imm == 0xf000) {
219
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
220
+ } else {
221
+ unallocated_encoding(s);
222
+ }
223
+ return true;
224
}
225
226
/*
227
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
228
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
229
{
230
switch (extract32(insn, 25, 4)) {
231
- case 0xa: case 0xb: /* Branch, exception generation and system insns */
232
- disas_b_exc_sys(s, insn);
233
- break;
234
case 0x4:
235
case 0x6:
236
case 0xc:
237
--
238
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the load/store exclusive pair (LDXP, STXP, LDAXP, STLXP),
2
compare-and-swap pair (CASP, CASPA, CASPAL, CASPL), and compare-and
3
swap (CAS, CASA, CASAL, CASL) instructions to decodetree.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230602155223.2040685-10-peter.maydell@linaro.org
8
---
9
target/arm/tcg/a64.decode | 11 +++
10
target/arm/tcg/translate-a64.c | 121 ++++++++++++---------------------
11
2 files changed, 53 insertions(+), 79 deletions(-)
12
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
16
+++ b/target/arm/tcg/a64.decode
17
@@ -XXX,XX +XXX,XX @@ HLT 1101 0100 010 ................ 000 00 @i16
18
&stlr rn rt sz lasr
19
@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
20
@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
21
+%imm1_30_p2 30:1 !function=plus_2
22
+@stxp .. ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=%imm1_30_p2
23
STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
24
LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
25
STLR .. 001000 100 11111 . 11111 ..... ..... @stlr # inc STLLR
26
LDAR .. 001000 110 11111 . 11111 ..... ..... @stlr # inc LDLAR
27
+
28
+STXP 1 . 001000 001 ..... . ..... ..... ..... @stxp # inc STLXP
29
+LDXP 1 . 001000 011 ..... . ..... ..... ..... @stxp # inc LDAXP
30
+
31
+# CASP, CASPA, CASPAL, CASPL (we don't decode the bits that determine
32
+# acquire/release semantics because QEMU's cmpxchg always has those)
33
+CASP 0 . 001000 0 - 1 rs:5 - 11111 rn:5 rt:5 sz=%imm1_30_p2
34
+# CAS, CASA, CASAL, CASL
35
+CAS sz:2 001000 1 - 1 rs:5 - 11111 rn:5 rt:5
36
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/tcg/translate-a64.c
39
+++ b/target/arm/tcg/translate-a64.c
40
@@ -XXX,XX +XXX,XX @@ static bool trans_LDAR(DisasContext *s, arg_stlr *a)
41
return true;
42
}
43
44
-/* Load/store exclusive
45
- *
46
- * 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
47
- * +-----+-------------+----+---+----+------+----+-------+------+------+
48
- * | sz | 0 0 1 0 0 0 | o2 | L | o1 | Rs | o0 | Rt2 | Rn | Rt |
49
- * +-----+-------------+----+---+----+------+----+-------+------+------+
50
- *
51
- * sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
52
- * L: 0 -> store, 1 -> load
53
- * o2: 0 -> exclusive, 1 -> not
54
- * o1: 0 -> single register, 1 -> register pair
55
- * o0: 1 -> load-acquire/store-release, 0 -> not
56
- */
57
-static void disas_ldst_excl(DisasContext *s, uint32_t insn)
58
+static bool trans_STXP(DisasContext *s, arg_stxr *a)
59
{
60
- int rt = extract32(insn, 0, 5);
61
- int rn = extract32(insn, 5, 5);
62
- int rt2 = extract32(insn, 10, 5);
63
- int rs = extract32(insn, 16, 5);
64
- int is_lasr = extract32(insn, 15, 1);
65
- int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
66
- int size = extract32(insn, 30, 2);
67
-
68
- switch (o2_L_o1_o0) {
69
- case 0x2: case 0x3: /* CASP / STXP */
70
- if (size & 2) { /* STXP / STLXP */
71
- if (rn == 31) {
72
- gen_check_sp_alignment(s);
73
- }
74
- if (is_lasr) {
75
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
76
- }
77
- gen_store_exclusive(s, rs, rt, rt2, rn, size, true);
78
- return;
79
- }
80
- if (rt2 == 31
81
- && ((rt | rs) & 1) == 0
82
- && dc_isar_feature(aa64_atomics, s)) {
83
- /* CASP / CASPL */
84
- gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
85
- return;
86
- }
87
- break;
88
-
89
- case 0x6: case 0x7: /* CASPA / LDXP */
90
- if (size & 2) { /* LDXP / LDAXP */
91
- if (rn == 31) {
92
- gen_check_sp_alignment(s);
93
- }
94
- gen_load_exclusive(s, rt, rt2, rn, size, true);
95
- if (is_lasr) {
96
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
97
- }
98
- return;
99
- }
100
- if (rt2 == 31
101
- && ((rt | rs) & 1) == 0
102
- && dc_isar_feature(aa64_atomics, s)) {
103
- /* CASPA / CASPAL */
104
- gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
105
- return;
106
- }
107
- break;
108
-
109
- case 0xa: /* CAS */
110
- case 0xb: /* CASL */
111
- case 0xe: /* CASA */
112
- case 0xf: /* CASAL */
113
- if (rt2 == 31 && dc_isar_feature(aa64_atomics, s)) {
114
- gen_compare_and_swap(s, rs, rt, rn, size);
115
- return;
116
- }
117
- break;
118
- default:
119
- /* Handled in decodetree */
120
- break;
121
+ if (a->rn == 31) {
122
+ gen_check_sp_alignment(s);
123
}
124
- unallocated_encoding(s);
125
+ if (a->lasr) {
126
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
127
+ }
128
+ gen_store_exclusive(s, a->rs, a->rt, a->rt2, a->rn, a->sz, true);
129
+ return true;
130
+}
131
+
132
+static bool trans_LDXP(DisasContext *s, arg_stxr *a)
133
+{
134
+ if (a->rn == 31) {
135
+ gen_check_sp_alignment(s);
136
+ }
137
+ gen_load_exclusive(s, a->rt, a->rt2, a->rn, a->sz, true);
138
+ if (a->lasr) {
139
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
140
+ }
141
+ return true;
142
+}
143
+
144
+static bool trans_CASP(DisasContext *s, arg_CASP *a)
145
+{
146
+ if (!dc_isar_feature(aa64_atomics, s)) {
147
+ return false;
148
+ }
149
+ if (((a->rt | a->rs) & 1) != 0) {
150
+ return false;
151
+ }
152
+
153
+ gen_compare_and_swap_pair(s, a->rs, a->rt, a->rn, a->sz);
154
+ return true;
155
+}
156
+
157
+static bool trans_CAS(DisasContext *s, arg_CAS *a)
158
+{
159
+ if (!dc_isar_feature(aa64_atomics, s)) {
160
+ return false;
161
+ }
162
+ gen_compare_and_swap(s, a->rs, a->rt, a->rn, a->sz);
163
+ return true;
164
}
165
166
/*
167
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
168
static void disas_ldst(DisasContext *s, uint32_t insn)
169
{
170
switch (extract32(insn, 24, 6)) {
171
- case 0x08: /* Load/store exclusive */
172
- disas_ldst_excl(s, insn);
173
- break;
174
case 0x18: case 0x1c: /* Load register (literal) */
175
disas_ld_lit(s, insn);
176
break;
177
--
178
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the "Load register (literal)" instruction class to
2
decodetree.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-11-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 13 ++++++
9
target/arm/tcg/translate-a64.c | 76 ++++++++++------------------------
10
2 files changed, 35 insertions(+), 54 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ LDXP 1 . 001000 011 ..... . ..... ..... ..... @stxp # inc LDAXP
17
CASP 0 . 001000 0 - 1 rs:5 - 11111 rn:5 rt:5 sz=%imm1_30_p2
18
# CAS, CASA, CASAL, CASL
19
CAS sz:2 001000 1 - 1 rs:5 - 11111 rn:5 rt:5
20
+
21
+&ldlit rt imm sz sign
22
+@ldlit .. ... . .. ................... rt:5 &ldlit imm=%imm19
23
+
24
+LD_lit 00 011 0 00 ................... ..... @ldlit sz=2 sign=0
25
+LD_lit 01 011 0 00 ................... ..... @ldlit sz=3 sign=0
26
+LD_lit 10 011 0 00 ................... ..... @ldlit sz=2 sign=1
27
+LD_lit_v 00 011 1 00 ................... ..... @ldlit sz=2 sign=0
28
+LD_lit_v 01 011 1 00 ................... ..... @ldlit sz=3 sign=0
29
+LD_lit_v 10 011 1 00 ................... ..... @ldlit sz=4 sign=0
30
+
31
+# PRFM
32
+NOP 11 011 0 00 ------------------- -----
33
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/tcg/translate-a64.c
36
+++ b/target/arm/tcg/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ static bool trans_CAS(DisasContext *s, arg_CAS *a)
38
return true;
39
}
40
41
-/*
42
- * Load register (literal)
43
- *
44
- * 31 30 29 27 26 25 24 23 5 4 0
45
- * +-----+-------+---+-----+-------------------+-------+
46
- * | opc | 0 1 1 | V | 0 0 | imm19 | Rt |
47
- * +-----+-------+---+-----+-------------------+-------+
48
- *
49
- * V: 1 -> vector (simd/fp)
50
- * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
51
- * 10-> 32 bit signed, 11 -> prefetch
52
- * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
53
- */
54
-static void disas_ld_lit(DisasContext *s, uint32_t insn)
55
+static bool trans_LD_lit(DisasContext *s, arg_ldlit *a)
56
{
57
- int rt = extract32(insn, 0, 5);
58
- int64_t imm = sextract32(insn, 5, 19) << 2;
59
- bool is_vector = extract32(insn, 26, 1);
60
- int opc = extract32(insn, 30, 2);
61
- bool is_signed = false;
62
- int size = 2;
63
- TCGv_i64 tcg_rt, clean_addr;
64
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, false);
65
+ TCGv_i64 tcg_rt = cpu_reg(s, a->rt);
66
+ TCGv_i64 clean_addr = tcg_temp_new_i64();
67
+ MemOp memop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
68
+
69
+ gen_pc_plus_diff(s, clean_addr, a->imm);
70
+ do_gpr_ld(s, tcg_rt, clean_addr, memop,
71
+ false, true, a->rt, iss_sf, false);
72
+ return true;
73
+}
74
+
75
+static bool trans_LD_lit_v(DisasContext *s, arg_ldlit *a)
76
+{
77
+ /* Load register (literal), vector version */
78
+ TCGv_i64 clean_addr;
79
MemOp memop;
80
81
- if (is_vector) {
82
- if (opc == 3) {
83
- unallocated_encoding(s);
84
- return;
85
- }
86
- size = 2 + opc;
87
- if (!fp_access_check(s)) {
88
- return;
89
- }
90
- memop = finalize_memop_asimd(s, size);
91
- } else {
92
- if (opc == 3) {
93
- /* PRFM (literal) : prefetch */
94
- return;
95
- }
96
- size = 2 + extract32(opc, 0, 1);
97
- is_signed = extract32(opc, 1, 1);
98
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
99
+ if (!fp_access_check(s)) {
100
+ return true;
101
}
102
-
103
- tcg_rt = cpu_reg(s, rt);
104
-
105
+ memop = finalize_memop_asimd(s, a->sz);
106
clean_addr = tcg_temp_new_i64();
107
- gen_pc_plus_diff(s, clean_addr, imm);
108
-
109
- if (is_vector) {
110
- do_fp_ld(s, rt, clean_addr, memop);
111
- } else {
112
- /* Only unsigned 32bit loads target 32bit registers. */
113
- bool iss_sf = opc != 0;
114
- do_gpr_ld(s, tcg_rt, clean_addr, memop, false, true, rt, iss_sf, false);
115
- }
116
+ gen_pc_plus_diff(s, clean_addr, a->imm);
117
+ do_fp_ld(s, a->rt, clean_addr, memop);
118
+ return true;
119
}
120
121
/*
122
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
123
static void disas_ldst(DisasContext *s, uint32_t insn)
124
{
125
switch (extract32(insn, 24, 6)) {
126
- case 0x18: case 0x1c: /* Load register (literal) */
127
- disas_ld_lit(s, insn);
128
- break;
129
case 0x28: case 0x29:
130
case 0x2c: case 0x2d: /* Load/store pair (all forms) */
131
disas_ldst_pair(s, insn);
132
--
133
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the load/store register pair insns (LDP, STP,
2
LDNP, STNP, LDPSW, STGP) to decodetree.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20230602155223.2040685-12-peter.maydell@linaro.org
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
target/arm/tcg/a64.decode | 61 +++++
9
target/arm/tcg/translate-a64.c | 422 ++++++++++++++++-----------------
10
2 files changed, 268 insertions(+), 215 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ LD_lit_v 10 011 1 00 ................... ..... @ldlit sz=4 sign=0
17
18
# PRFM
19
NOP 11 011 0 00 ------------------- -----
20
+
21
+&ldstpair rt2 rt rn imm sz sign w p
22
+@ldstpair .. ... . ... . imm:s7 rt2:5 rn:5 rt:5 &ldstpair
23
+
24
+# STNP, LDNP: Signed offset, non-temporal hint. We don't emulate caches
25
+# so we ignore hints about data access patterns, and handle these like
26
+# plain signed offset.
27
+STP 00 101 0 000 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
28
+LDP 00 101 0 000 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
29
+STP 10 101 0 000 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
30
+LDP 10 101 0 000 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
31
+STP_v 00 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
32
+LDP_v 00 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
33
+STP_v 01 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
34
+LDP_v 01 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
35
+STP_v 10 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
36
+LDP_v 10 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
37
+
38
+# STP and LDP: post-indexed
39
+STP 00 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
40
+LDP 00 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
41
+LDP 01 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=1 w=1
42
+STP 10 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
43
+LDP 10 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
44
+STP_v 00 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
45
+LDP_v 00 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
46
+STP_v 01 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
47
+LDP_v 01 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
48
+STP_v 10 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=1 w=1
49
+LDP_v 10 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=1 w=1
50
+
51
+# STP and LDP: offset
52
+STP 00 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
53
+LDP 00 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
54
+LDP 01 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=0 w=0
55
+STP 10 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
56
+LDP 10 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
57
+STP_v 00 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
58
+LDP_v 00 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
59
+STP_v 01 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
60
+LDP_v 01 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
61
+STP_v 10 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
62
+LDP_v 10 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
63
+
64
+# STP and LDP: pre-indexed
65
+STP 00 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
66
+LDP 00 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
67
+LDP 01 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=0 w=1
68
+STP 10 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
69
+LDP 10 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
70
+STP_v 00 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
71
+LDP_v 00 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
72
+STP_v 01 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
73
+LDP_v 01 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
74
+STP_v 10 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=1
75
+LDP_v 10 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=1
76
+
77
+# STGP: store tag and pair
78
+STGP 01 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
79
+STGP 01 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
80
+STGP 01 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
81
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/tcg/translate-a64.c
84
+++ b/target/arm/tcg/translate-a64.c
85
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_lit_v(DisasContext *s, arg_ldlit *a)
86
return true;
87
}
88
89
-/*
90
- * LDNP (Load Pair - non-temporal hint)
91
- * LDP (Load Pair - non vector)
92
- * LDPSW (Load Pair Signed Word - non vector)
93
- * STNP (Store Pair - non-temporal hint)
94
- * STP (Store Pair - non vector)
95
- * LDNP (Load Pair of SIMD&FP - non-temporal hint)
96
- * LDP (Load Pair of SIMD&FP)
97
- * STNP (Store Pair of SIMD&FP - non-temporal hint)
98
- * STP (Store Pair of SIMD&FP)
99
- *
100
- * 31 30 29 27 26 25 24 23 22 21 15 14 10 9 5 4 0
101
- * +-----+-------+---+---+-------+---+-----------------------------+
102
- * | opc | 1 0 1 | V | 0 | index | L | imm7 | Rt2 | Rn | Rt |
103
- * +-----+-------+---+---+-------+---+-------+-------+------+------+
104
- *
105
- * opc: LDP/STP/LDNP/STNP 00 -> 32 bit, 10 -> 64 bit
106
- * LDPSW/STGP 01
107
- * LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
108
- * V: 0 -> GPR, 1 -> Vector
109
- * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
110
- * 10 -> signed offset, 11 -> pre-index
111
- * L: 0 -> Store 1 -> Load
112
- *
113
- * Rt, Rt2 = GPR or SIMD registers to be stored
114
- * Rn = general purpose register containing address
115
- * imm7 = signed offset (multiple of 4 or 8 depending on size)
116
- */
117
-static void disas_ldst_pair(DisasContext *s, uint32_t insn)
118
+static void op_addr_ldstpair_pre(DisasContext *s, arg_ldstpair *a,
119
+ TCGv_i64 *clean_addr, TCGv_i64 *dirty_addr,
120
+ uint64_t offset, bool is_store, MemOp mop)
121
{
122
- int rt = extract32(insn, 0, 5);
123
- int rn = extract32(insn, 5, 5);
124
- int rt2 = extract32(insn, 10, 5);
125
- uint64_t offset = sextract64(insn, 15, 7);
126
- int index = extract32(insn, 23, 2);
127
- bool is_vector = extract32(insn, 26, 1);
128
- bool is_load = extract32(insn, 22, 1);
129
- int opc = extract32(insn, 30, 2);
130
- bool is_signed = false;
131
- bool postindex = false;
132
- bool wback = false;
133
- bool set_tag = false;
134
- TCGv_i64 clean_addr, dirty_addr;
135
- MemOp mop;
136
- int size;
137
-
138
- if (opc == 3) {
139
- unallocated_encoding(s);
140
- return;
141
- }
142
-
143
- if (is_vector) {
144
- size = 2 + opc;
145
- } else if (opc == 1 && !is_load) {
146
- /* STGP */
147
- if (!dc_isar_feature(aa64_mte_insn_reg, s) || index == 0) {
148
- unallocated_encoding(s);
149
- return;
150
- }
151
- size = 3;
152
- set_tag = true;
153
- } else {
154
- size = 2 + extract32(opc, 1, 1);
155
- is_signed = extract32(opc, 0, 1);
156
- if (!is_load && is_signed) {
157
- unallocated_encoding(s);
158
- return;
159
- }
160
- }
161
-
162
- switch (index) {
163
- case 1: /* post-index */
164
- postindex = true;
165
- wback = true;
166
- break;
167
- case 0:
168
- /* signed offset with "non-temporal" hint. Since we don't emulate
169
- * caches we don't care about hints to the cache system about
170
- * data access patterns, and handle this identically to plain
171
- * signed offset.
172
- */
173
- if (is_signed) {
174
- /* There is no non-temporal-hint version of LDPSW */
175
- unallocated_encoding(s);
176
- return;
177
- }
178
- postindex = false;
179
- break;
180
- case 2: /* signed offset, rn not updated */
181
- postindex = false;
182
- break;
183
- case 3: /* pre-index */
184
- postindex = false;
185
- wback = true;
186
- break;
187
- }
188
-
189
- if (is_vector && !fp_access_check(s)) {
190
- return;
191
- }
192
-
193
- offset <<= (set_tag ? LOG2_TAG_GRANULE : size);
194
-
195
- if (rn == 31) {
196
+ if (a->rn == 31) {
197
gen_check_sp_alignment(s);
198
}
199
200
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
201
- if (!postindex) {
202
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
203
+ if (!a->p) {
204
+ tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
205
+ }
206
+
207
+ *clean_addr = gen_mte_checkN(s, *dirty_addr, is_store,
208
+ (a->w || a->rn != 31), 2 << a->sz, mop);
209
+}
210
+
211
+static void op_addr_ldstpair_post(DisasContext *s, arg_ldstpair *a,
212
+ TCGv_i64 dirty_addr, uint64_t offset)
213
+{
214
+ if (a->w) {
215
+ if (a->p) {
216
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
217
+ }
218
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
219
+ }
220
+}
221
+
222
+static bool trans_STP(DisasContext *s, arg_ldstpair *a)
223
+{
224
+ uint64_t offset = a->imm << a->sz;
225
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt, tcg_rt2;
226
+ MemOp mop = finalize_memop(s, a->sz);
227
+
228
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, true, mop);
229
+ tcg_rt = cpu_reg(s, a->rt);
230
+ tcg_rt2 = cpu_reg(s, a->rt2);
231
+ /*
232
+ * We built mop above for the single logical access -- rebuild it
233
+ * now for the paired operation.
234
+ *
235
+ * With LSE2, non-sign-extending pairs are treated atomically if
236
+ * aligned, and if unaligned one of the pair will be completely
237
+ * within a 16-byte block and that element will be atomic.
238
+ * Otherwise each element is separately atomic.
239
+ * In all cases, issue one operation with the correct atomicity.
240
+ */
241
+ mop = a->sz + 1;
242
+ if (s->align_mem) {
243
+ mop |= (a->sz == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
244
+ }
245
+ mop = finalize_memop_pair(s, mop);
246
+ if (a->sz == 2) {
247
+ TCGv_i64 tmp = tcg_temp_new_i64();
248
+
249
+ if (s->be_data == MO_LE) {
250
+ tcg_gen_concat32_i64(tmp, tcg_rt, tcg_rt2);
251
+ } else {
252
+ tcg_gen_concat32_i64(tmp, tcg_rt2, tcg_rt);
253
+ }
254
+ tcg_gen_qemu_st_i64(tmp, clean_addr, get_mem_index(s), mop);
255
+ } else {
256
+ TCGv_i128 tmp = tcg_temp_new_i128();
257
+
258
+ if (s->be_data == MO_LE) {
259
+ tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
260
+ } else {
261
+ tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
262
+ }
263
+ tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
264
+ }
265
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
266
+ return true;
267
+}
268
+
269
+static bool trans_LDP(DisasContext *s, arg_ldstpair *a)
270
+{
271
+ uint64_t offset = a->imm << a->sz;
272
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt, tcg_rt2;
273
+ MemOp mop = finalize_memop(s, a->sz);
274
+
275
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, false, mop);
276
+ tcg_rt = cpu_reg(s, a->rt);
277
+ tcg_rt2 = cpu_reg(s, a->rt2);
278
+
279
+ /*
280
+ * We built mop above for the single logical access -- rebuild it
281
+ * now for the paired operation.
282
+ *
283
+ * With LSE2, non-sign-extending pairs are treated atomically if
284
+ * aligned, and if unaligned one of the pair will be completely
285
+ * within a 16-byte block and that element will be atomic.
286
+ * Otherwise each element is separately atomic.
287
+ * In all cases, issue one operation with the correct atomicity.
288
+ *
289
+ * This treats sign-extending loads like zero-extending loads,
290
+ * since that reuses the most code below.
291
+ */
292
+ mop = a->sz + 1;
293
+ if (s->align_mem) {
294
+ mop |= (a->sz == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
295
+ }
296
+ mop = finalize_memop_pair(s, mop);
297
+ if (a->sz == 2) {
298
+ int o2 = s->be_data == MO_LE ? 32 : 0;
299
+ int o1 = o2 ^ 32;
300
+
301
+ tcg_gen_qemu_ld_i64(tcg_rt, clean_addr, get_mem_index(s), mop);
302
+ if (a->sign) {
303
+ tcg_gen_sextract_i64(tcg_rt2, tcg_rt, o2, 32);
304
+ tcg_gen_sextract_i64(tcg_rt, tcg_rt, o1, 32);
305
+ } else {
306
+ tcg_gen_extract_i64(tcg_rt2, tcg_rt, o2, 32);
307
+ tcg_gen_extract_i64(tcg_rt, tcg_rt, o1, 32);
308
+ }
309
+ } else {
310
+ TCGv_i128 tmp = tcg_temp_new_i128();
311
+
312
+ tcg_gen_qemu_ld_i128(tmp, clean_addr, get_mem_index(s), mop);
313
+ if (s->be_data == MO_LE) {
314
+ tcg_gen_extr_i128_i64(tcg_rt, tcg_rt2, tmp);
315
+ } else {
316
+ tcg_gen_extr_i128_i64(tcg_rt2, tcg_rt, tmp);
317
+ }
318
+ }
319
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
320
+ return true;
321
+}
322
+
323
+static bool trans_STP_v(DisasContext *s, arg_ldstpair *a)
324
+{
325
+ uint64_t offset = a->imm << a->sz;
326
+ TCGv_i64 clean_addr, dirty_addr;
327
+ MemOp mop;
328
+
329
+ if (!fp_access_check(s)) {
330
+ return true;
331
+ }
332
+
333
+ /* LSE2 does not merge FP pairs; leave these as separate operations. */
334
+ mop = finalize_memop_asimd(s, a->sz);
335
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, true, mop);
336
+ do_fp_st(s, a->rt, clean_addr, mop);
337
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << a->sz);
338
+ do_fp_st(s, a->rt2, clean_addr, mop);
339
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
340
+ return true;
341
+}
342
+
343
+static bool trans_LDP_v(DisasContext *s, arg_ldstpair *a)
344
+{
345
+ uint64_t offset = a->imm << a->sz;
346
+ TCGv_i64 clean_addr, dirty_addr;
347
+ MemOp mop;
348
+
349
+ if (!fp_access_check(s)) {
350
+ return true;
351
+ }
352
+
353
+ /* LSE2 does not merge FP pairs; leave these as separate operations. */
354
+ mop = finalize_memop_asimd(s, a->sz);
355
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, false, mop);
356
+ do_fp_ld(s, a->rt, clean_addr, mop);
357
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << a->sz);
358
+ do_fp_ld(s, a->rt2, clean_addr, mop);
359
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
360
+ return true;
361
+}
362
+
363
+static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
364
+{
365
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt, tcg_rt2;
366
+ uint64_t offset = a->imm << LOG2_TAG_GRANULE;
367
+ MemOp mop;
368
+ TCGv_i128 tmp;
369
+
370
+ if (!dc_isar_feature(aa64_mte_insn_reg, s)) {
371
+ return false;
372
+ }
373
+
374
+ if (a->rn == 31) {
375
+ gen_check_sp_alignment(s);
376
+ }
377
+
378
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
379
+ if (!a->p) {
380
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
381
}
382
383
- if (set_tag) {
384
- if (!s->ata) {
385
- /*
386
- * TODO: We could rely on the stores below, at least for
387
- * system mode, if we arrange to add MO_ALIGN_16.
388
- */
389
- gen_helper_stg_stub(cpu_env, dirty_addr);
390
- } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
391
- gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
392
- } else {
393
- gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
394
- }
395
- }
396
-
397
- if (is_vector) {
398
- mop = finalize_memop_asimd(s, size);
399
- } else {
400
- mop = finalize_memop(s, size);
401
- }
402
- clean_addr = gen_mte_checkN(s, dirty_addr, !is_load,
403
- (wback || rn != 31) && !set_tag,
404
- 2 << size, mop);
405
-
406
- if (is_vector) {
407
- /* LSE2 does not merge FP pairs; leave these as separate operations. */
408
- if (is_load) {
409
- do_fp_ld(s, rt, clean_addr, mop);
410
- } else {
411
- do_fp_st(s, rt, clean_addr, mop);
412
- }
413
- tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
414
- if (is_load) {
415
- do_fp_ld(s, rt2, clean_addr, mop);
416
- } else {
417
- do_fp_st(s, rt2, clean_addr, mop);
418
- }
419
- } else {
420
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
421
- TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
422
-
423
+ if (!s->ata) {
424
/*
425
- * We built mop above for the single logical access -- rebuild it
426
- * now for the paired operation.
427
- *
428
- * With LSE2, non-sign-extending pairs are treated atomically if
429
- * aligned, and if unaligned one of the pair will be completely
430
- * within a 16-byte block and that element will be atomic.
431
- * Otherwise each element is separately atomic.
432
- * In all cases, issue one operation with the correct atomicity.
433
- *
434
- * This treats sign-extending loads like zero-extending loads,
435
- * since that reuses the most code below.
436
+ * TODO: We could rely on the stores below, at least for
437
+ * system mode, if we arrange to add MO_ALIGN_16.
438
*/
439
- mop = size + 1;
440
- if (s->align_mem) {
441
- mop |= (size == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
442
- }
443
- mop = finalize_memop_pair(s, mop);
444
-
445
- if (is_load) {
446
- if (size == 2) {
447
- int o2 = s->be_data == MO_LE ? 32 : 0;
448
- int o1 = o2 ^ 32;
449
-
450
- tcg_gen_qemu_ld_i64(tcg_rt, clean_addr, get_mem_index(s), mop);
451
- if (is_signed) {
452
- tcg_gen_sextract_i64(tcg_rt2, tcg_rt, o2, 32);
453
- tcg_gen_sextract_i64(tcg_rt, tcg_rt, o1, 32);
454
- } else {
455
- tcg_gen_extract_i64(tcg_rt2, tcg_rt, o2, 32);
456
- tcg_gen_extract_i64(tcg_rt, tcg_rt, o1, 32);
457
- }
458
- } else {
459
- TCGv_i128 tmp = tcg_temp_new_i128();
460
-
461
- tcg_gen_qemu_ld_i128(tmp, clean_addr, get_mem_index(s), mop);
462
- if (s->be_data == MO_LE) {
463
- tcg_gen_extr_i128_i64(tcg_rt, tcg_rt2, tmp);
464
- } else {
465
- tcg_gen_extr_i128_i64(tcg_rt2, tcg_rt, tmp);
466
- }
467
- }
468
- } else {
469
- if (size == 2) {
470
- TCGv_i64 tmp = tcg_temp_new_i64();
471
-
472
- if (s->be_data == MO_LE) {
473
- tcg_gen_concat32_i64(tmp, tcg_rt, tcg_rt2);
474
- } else {
475
- tcg_gen_concat32_i64(tmp, tcg_rt2, tcg_rt);
476
- }
477
- tcg_gen_qemu_st_i64(tmp, clean_addr, get_mem_index(s), mop);
478
- } else {
479
- TCGv_i128 tmp = tcg_temp_new_i128();
480
-
481
- if (s->be_data == MO_LE) {
482
- tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
483
- } else {
484
- tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
485
- }
486
- tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
487
- }
488
- }
489
+ gen_helper_stg_stub(cpu_env, dirty_addr);
490
+ } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
491
+ gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
492
+ } else {
493
+ gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
494
}
495
496
- if (wback) {
497
- if (postindex) {
498
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
499
- }
500
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
501
+ mop = finalize_memop(s, a->sz);
502
+ clean_addr = gen_mte_checkN(s, dirty_addr, true, false, 2 << a->sz, mop);
503
+
504
+ tcg_rt = cpu_reg(s, a->rt);
505
+ tcg_rt2 = cpu_reg(s, a->rt2);
506
+
507
+ assert(a->sz == 3);
508
+
509
+ tmp = tcg_temp_new_i128();
510
+ if (s->be_data == MO_LE) {
511
+ tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
512
+ } else {
513
+ tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
514
}
515
+ tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
516
+
517
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
518
+ return true;
519
}
520
521
/*
522
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
523
static void disas_ldst(DisasContext *s, uint32_t insn)
524
{
525
switch (extract32(insn, 24, 6)) {
526
- case 0x28: case 0x29:
527
- case 0x2c: case 0x2d: /* Load/store pair (all forms) */
528
- disas_ldst_pair(s, insn);
529
- break;
530
case 0x38: case 0x39:
531
case 0x3c: case 0x3d: /* Load/store register (all forms) */
532
disas_ldst_reg(s, insn);
533
--
534
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the load and store instructions which use a 9-bit
2
immediate offset to decodetree.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-13-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 69 +++++++++++
9
target/arm/tcg/translate-a64.c | 206 ++++++++++++++-------------------
10
2 files changed, 153 insertions(+), 122 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ LDP_v 10 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p
17
STGP 01 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
18
STGP 01 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
19
STGP 01 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
20
+
21
+# Load/store register (unscaled immediate)
22
+&ldst_imm rt rn imm sz sign w p unpriv ext
23
+@ldst_imm .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=0
24
+@ldst_imm_pre .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=1
25
+@ldst_imm_post .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=1 w=1
26
+@ldst_imm_user .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=1 p=0 w=0
27
+
28
+STR_i sz:2 111 0 00 00 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
29
+LDR_i 00 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=0
30
+LDR_i 01 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=1
31
+LDR_i 10 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=2
32
+LDR_i 11 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=3
33
+LDR_i 00 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=0
34
+LDR_i 01 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=1
35
+LDR_i 10 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=2
36
+LDR_i 00 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=1 sz=0
37
+LDR_i 01 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=1 sz=1
38
+
39
+STR_i sz:2 111 0 00 00 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
40
+LDR_i 00 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=0
41
+LDR_i 01 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=1
42
+LDR_i 10 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=2
43
+LDR_i 11 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=3
44
+LDR_i 00 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=0
45
+LDR_i 01 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=1
46
+LDR_i 10 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=2
47
+LDR_i 00 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=1 sz=0
48
+LDR_i 01 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=1 sz=1
49
+
50
+STR_i sz:2 111 0 00 00 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=0
51
+LDR_i 00 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=0
52
+LDR_i 01 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=1
53
+LDR_i 10 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=2
54
+LDR_i 11 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=0 sz=3
55
+LDR_i 00 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=0
56
+LDR_i 01 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=1
57
+LDR_i 10 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=2
58
+LDR_i 00 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=1 sz=0
59
+LDR_i 01 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=1 sz=1
60
+
61
+STR_i sz:2 111 0 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
62
+LDR_i 00 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=0
63
+LDR_i 01 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=1
64
+LDR_i 10 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=2
65
+LDR_i 11 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=3
66
+LDR_i 00 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=0
67
+LDR_i 01 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=1
68
+LDR_i 10 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=2
69
+LDR_i 00 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=1 sz=0
70
+LDR_i 01 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=1 sz=1
71
+
72
+# PRFM : prefetch memory: a no-op for QEMU
73
+NOP 11 111 0 00 10 0 --------- 00 ----- -----
74
+
75
+STR_v_i sz:2 111 1 00 00 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
76
+STR_v_i 00 111 1 00 10 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=4
77
+LDR_v_i sz:2 111 1 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
78
+LDR_v_i 00 111 1 00 11 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=4
79
+
80
+STR_v_i sz:2 111 1 00 00 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
81
+STR_v_i 00 111 1 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=4
82
+LDR_v_i sz:2 111 1 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
83
+LDR_v_i 00 111 1 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=4
84
+
85
+STR_v_i sz:2 111 1 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
86
+STR_v_i 00 111 1 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
87
+LDR_v_i sz:2 111 1 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
88
+LDR_v_i 00 111 1 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
89
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/tcg/translate-a64.c
92
+++ b/target/arm/tcg/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
94
return true;
95
}
96
97
-/*
98
- * Load/store (immediate post-indexed)
99
- * Load/store (immediate pre-indexed)
100
- * Load/store (unscaled immediate)
101
- *
102
- * 31 30 29 27 26 25 24 23 22 21 20 12 11 10 9 5 4 0
103
- * +----+-------+---+-----+-----+---+--------+-----+------+------+
104
- * |size| 1 1 1 | V | 0 0 | opc | 0 | imm9 | idx | Rn | Rt |
105
- * +----+-------+---+-----+-----+---+--------+-----+------+------+
106
- *
107
- * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
108
- 10 -> unprivileged
109
- * V = 0 -> non-vector
110
- * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
111
- * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
112
- */
113
-static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
114
- int opc,
115
- int size,
116
- int rt,
117
- bool is_vector)
118
+static void op_addr_ldst_imm_pre(DisasContext *s, arg_ldst_imm *a,
119
+ TCGv_i64 *clean_addr, TCGv_i64 *dirty_addr,
120
+ uint64_t offset, bool is_store, MemOp mop)
121
{
122
- int rn = extract32(insn, 5, 5);
123
- int imm9 = sextract32(insn, 12, 9);
124
- int idx = extract32(insn, 10, 2);
125
- bool is_signed = false;
126
- bool is_store = false;
127
- bool is_extended = false;
128
- bool is_unpriv = (idx == 2);
129
- bool iss_valid;
130
- bool post_index;
131
- bool writeback;
132
int memidx;
133
- MemOp memop;
134
- TCGv_i64 clean_addr, dirty_addr;
135
136
- if (is_vector) {
137
- size |= (opc & 2) << 1;
138
- if (size > 4 || is_unpriv) {
139
- unallocated_encoding(s);
140
- return;
141
- }
142
- is_store = ((opc & 1) == 0);
143
- if (!fp_access_check(s)) {
144
- return;
145
- }
146
- memop = finalize_memop_asimd(s, size);
147
- } else {
148
- if (size == 3 && opc == 2) {
149
- /* PRFM - prefetch */
150
- if (idx != 0) {
151
- unallocated_encoding(s);
152
- return;
153
- }
154
- return;
155
- }
156
- if (opc == 3 && size > 1) {
157
- unallocated_encoding(s);
158
- return;
159
- }
160
- is_store = (opc == 0);
161
- is_signed = !is_store && extract32(opc, 1, 1);
162
- is_extended = (size < 3) && extract32(opc, 0, 1);
163
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
164
- }
165
-
166
- switch (idx) {
167
- case 0:
168
- case 2:
169
- post_index = false;
170
- writeback = false;
171
- break;
172
- case 1:
173
- post_index = true;
174
- writeback = true;
175
- break;
176
- case 3:
177
- post_index = false;
178
- writeback = true;
179
- break;
180
- default:
181
- g_assert_not_reached();
182
- }
183
-
184
- iss_valid = !is_vector && !writeback;
185
-
186
- if (rn == 31) {
187
+ if (a->rn == 31) {
188
gen_check_sp_alignment(s);
189
}
190
191
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
192
- if (!post_index) {
193
- tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
194
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
195
+ if (!a->p) {
196
+ tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
197
}
198
+ memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
199
+ *clean_addr = gen_mte_check1_mmuidx(s, *dirty_addr, is_store,
200
+ a->w || a->rn != 31,
201
+ mop, a->unpriv, memidx);
202
+}
203
204
- memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
205
-
206
- clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
207
- writeback || rn != 31,
208
- memop, is_unpriv, memidx);
209
-
210
- if (is_vector) {
211
- if (is_store) {
212
- do_fp_st(s, rt, clean_addr, memop);
213
- } else {
214
- do_fp_ld(s, rt, clean_addr, memop);
215
- }
216
- } else {
217
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
218
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
219
-
220
- if (is_store) {
221
- do_gpr_st_memidx(s, tcg_rt, clean_addr, memop, memidx,
222
- iss_valid, rt, iss_sf, false);
223
- } else {
224
- do_gpr_ld_memidx(s, tcg_rt, clean_addr, memop,
225
- is_extended, memidx,
226
- iss_valid, rt, iss_sf, false);
227
+static void op_addr_ldst_imm_post(DisasContext *s, arg_ldst_imm *a,
228
+ TCGv_i64 dirty_addr, uint64_t offset)
229
+{
230
+ if (a->w) {
231
+ if (a->p) {
232
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
233
}
234
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
235
}
236
+}
237
238
- if (writeback) {
239
- TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
240
- if (post_index) {
241
- tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
242
- }
243
- tcg_gen_mov_i64(tcg_rn, dirty_addr);
244
+static bool trans_STR_i(DisasContext *s, arg_ldst_imm *a)
245
+{
246
+ bool iss_sf, iss_valid = !a->w;
247
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
248
+ int memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
249
+ MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
250
+
251
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, true, mop);
252
+
253
+ tcg_rt = cpu_reg(s, a->rt);
254
+ iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
255
+
256
+ do_gpr_st_memidx(s, tcg_rt, clean_addr, mop, memidx,
257
+ iss_valid, a->rt, iss_sf, false);
258
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
259
+ return true;
260
+}
261
+
262
+static bool trans_LDR_i(DisasContext *s, arg_ldst_imm *a)
263
+{
264
+ bool iss_sf, iss_valid = !a->w;
265
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
266
+ int memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
267
+ MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
268
+
269
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, false, mop);
270
+
271
+ tcg_rt = cpu_reg(s, a->rt);
272
+ iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
273
+
274
+ do_gpr_ld_memidx(s, tcg_rt, clean_addr, mop,
275
+ a->ext, memidx, iss_valid, a->rt, iss_sf, false);
276
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
277
+ return true;
278
+}
279
+
280
+static bool trans_STR_v_i(DisasContext *s, arg_ldst_imm *a)
281
+{
282
+ TCGv_i64 clean_addr, dirty_addr;
283
+ MemOp mop;
284
+
285
+ if (!fp_access_check(s)) {
286
+ return true;
287
}
288
+ mop = finalize_memop_asimd(s, a->sz);
289
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, true, mop);
290
+ do_fp_st(s, a->rt, clean_addr, mop);
291
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
292
+ return true;
293
+}
294
+
295
+static bool trans_LDR_v_i(DisasContext *s, arg_ldst_imm *a)
296
+{
297
+ TCGv_i64 clean_addr, dirty_addr;
298
+ MemOp mop;
299
+
300
+ if (!fp_access_check(s)) {
301
+ return true;
302
+ }
303
+ mop = finalize_memop_asimd(s, a->sz);
304
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, false, mop);
305
+ do_fp_ld(s, a->rt, clean_addr, mop);
306
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
307
+ return true;
308
}
309
310
/*
311
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
312
switch (extract32(insn, 24, 2)) {
313
case 0:
314
if (extract32(insn, 21, 1) == 0) {
315
- /* Load/store register (unscaled immediate)
316
- * Load/store immediate pre/post-indexed
317
- * Load/store register unprivileged
318
- */
319
- disas_ldst_reg_imm9(s, insn, opc, size, rt, is_vector);
320
- return;
321
+ break;
322
}
323
switch (extract32(insn, 10, 2)) {
324
case 0:
325
--
326
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the LDR and STR instructions which use a 12-bit immediate
2
offset to decodetree. We can reuse the existing LDR and STR
3
trans functions for these.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230602155223.2040685-14-peter.maydell@linaro.org
8
---
9
target/arm/tcg/a64.decode | 25 ++++++++
10
target/arm/tcg/translate-a64.c | 104 +++++----------------------------
11
2 files changed, 41 insertions(+), 88 deletions(-)
12
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
16
+++ b/target/arm/tcg/a64.decode
17
@@ -XXX,XX +XXX,XX @@ STR_v_i sz:2 111 1 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0
18
STR_v_i 00 111 1 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
19
LDR_v_i sz:2 111 1 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
20
LDR_v_i 00 111 1 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
21
+
22
+# Load/store with an unsigned 12 bit immediate, which is scaled by the
23
+# element size. The function gets the sz:imm and returns the scaled immediate.
24
+%uimm_scaled 10:12 sz:3 !function=uimm_scaled
25
+
26
+@ldst_uimm .. ... . .. .. ............ rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=0 imm=%uimm_scaled
27
+
28
+STR_i sz:2 111 0 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=0
29
+LDR_i 00 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=0
30
+LDR_i 01 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=1
31
+LDR_i 10 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=2
32
+LDR_i 11 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=3
33
+LDR_i 00 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=0
34
+LDR_i 01 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=1
35
+LDR_i 10 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=2
36
+LDR_i 00 111 0 01 11 ............ ..... ..... @ldst_uimm sign=1 ext=1 sz=0
37
+LDR_i 01 111 0 01 11 ............ ..... ..... @ldst_uimm sign=1 ext=1 sz=1
38
+
39
+# PRFM
40
+NOP 11 111 0 01 10 ------------ ----- -----
41
+
42
+STR_v_i sz:2 111 1 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=0
43
+STR_v_i 00 111 1 01 10 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
44
+LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0
45
+LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
46
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/tcg/translate-a64.c
49
+++ b/target/arm/tcg/translate-a64.c
50
@@ -XXX,XX +XXX,XX @@ enum a64_shift_type {
51
A64_SHIFT_TYPE_ROR = 3
52
};
53
54
+/*
55
+ * Helpers for extracting complex instruction fields
56
+ */
57
+
58
+/*
59
+ * For load/store with an unsigned 12 bit immediate scaled by the element
60
+ * size. The input has the immediate field in bits [14:3] and the element
61
+ * size in [2:0].
62
+ */
63
+static int uimm_scaled(DisasContext *s, int x)
64
+{
65
+ unsigned imm = x >> 3;
66
+ unsigned scale = extract32(x, 0, 3);
67
+ return imm << scale;
68
+}
69
+
70
/*
71
* Include the generated decoders.
72
*/
73
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
74
}
75
}
76
77
-/*
78
- * Load/store (unsigned immediate)
79
- *
80
- * 31 30 29 27 26 25 24 23 22 21 10 9 5
81
- * +----+-------+---+-----+-----+------------+-------+------+
82
- * |size| 1 1 1 | V | 0 1 | opc | imm12 | Rn | Rt |
83
- * +----+-------+---+-----+-----+------------+-------+------+
84
- *
85
- * For non-vector:
86
- * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
87
- * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
88
- * For vector:
89
- * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
90
- * opc<0>: 0 -> store, 1 -> load
91
- * Rn: base address register (inc SP)
92
- * Rt: target register
93
- */
94
-static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
95
- int opc,
96
- int size,
97
- int rt,
98
- bool is_vector)
99
-{
100
- int rn = extract32(insn, 5, 5);
101
- unsigned int imm12 = extract32(insn, 10, 12);
102
- unsigned int offset;
103
- TCGv_i64 clean_addr, dirty_addr;
104
- bool is_store;
105
- bool is_signed = false;
106
- bool is_extended = false;
107
- MemOp memop;
108
-
109
- if (is_vector) {
110
- size |= (opc & 2) << 1;
111
- if (size > 4) {
112
- unallocated_encoding(s);
113
- return;
114
- }
115
- is_store = !extract32(opc, 0, 1);
116
- if (!fp_access_check(s)) {
117
- return;
118
- }
119
- memop = finalize_memop_asimd(s, size);
120
- } else {
121
- if (size == 3 && opc == 2) {
122
- /* PRFM - prefetch */
123
- return;
124
- }
125
- if (opc == 3 && size > 1) {
126
- unallocated_encoding(s);
127
- return;
128
- }
129
- is_store = (opc == 0);
130
- is_signed = !is_store && extract32(opc, 1, 1);
131
- is_extended = (size < 3) && extract32(opc, 0, 1);
132
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
133
- }
134
-
135
- if (rn == 31) {
136
- gen_check_sp_alignment(s);
137
- }
138
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
139
- offset = imm12 << size;
140
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
141
-
142
- clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, memop);
143
-
144
- if (is_vector) {
145
- if (is_store) {
146
- do_fp_st(s, rt, clean_addr, memop);
147
- } else {
148
- do_fp_ld(s, rt, clean_addr, memop);
149
- }
150
- } else {
151
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
152
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
153
- if (is_store) {
154
- do_gpr_st(s, tcg_rt, clean_addr, memop, true, rt, iss_sf, false);
155
- } else {
156
- do_gpr_ld(s, tcg_rt, clean_addr, memop,
157
- is_extended, true, rt, iss_sf, false);
158
- }
159
- }
160
-}
161
-
162
/* Atomic memory operations
163
*
164
* 31 30 27 26 24 22 21 16 15 12 10 5 0
165
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
166
return;
167
}
168
break;
169
- case 1:
170
- disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector);
171
- return;
172
}
173
unallocated_encoding(s);
174
}
175
--
176
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the LDR and STR instructions which take a register
2
plus register offset to decodetree.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-15-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 22 +++++
9
target/arm/tcg/translate-a64.c | 173 +++++++++++++++------------------
10
2 files changed, 103 insertions(+), 92 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ STR_v_i sz:2 111 1 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=
17
STR_v_i 00 111 1 01 10 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
18
LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0
19
LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
20
+
21
+# Load/store with register offset
22
+&ldst rm rn rt sign ext sz opt s
23
+@ldst .. ... . .. .. . rm:5 opt:3 s:1 .. rn:5 rt:5 &ldst
24
+STR sz:2 111 0 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
25
+LDR 00 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=0
26
+LDR 01 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=1
27
+LDR 10 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=2
28
+LDR 11 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=3
29
+LDR 00 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=0
30
+LDR 01 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=1
31
+LDR 10 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=2
32
+LDR 00 111 0 00 11 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=1 sz=0
33
+LDR 01 111 0 00 11 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=1 sz=1
34
+
35
+# PRFM
36
+NOP 11 111 0 00 10 1 ----- -1- - 10 ----- -----
37
+
38
+STR_v sz:2 111 1 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
39
+STR_v 00 111 1 00 10 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
40
+LDR_v sz:2 111 1 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
41
+LDR_v 00 111 1 00 11 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
42
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/tcg/translate-a64.c
45
+++ b/target/arm/tcg/translate-a64.c
46
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_v_i(DisasContext *s, arg_ldst_imm *a)
47
return true;
48
}
49
50
-/*
51
- * Load/store (register offset)
52
- *
53
- * 31 30 29 27 26 25 24 23 22 21 20 16 15 13 12 11 10 9 5 4 0
54
- * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
55
- * |size| 1 1 1 | V | 0 0 | opc | 1 | Rm | opt | S| 1 0 | Rn | Rt |
56
- * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
57
- *
58
- * For non-vector:
59
- * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
60
- * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
61
- * For vector:
62
- * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
63
- * opc<0>: 0 -> store, 1 -> load
64
- * V: 1 -> vector/simd
65
- * opt: extend encoding (see DecodeRegExtend)
66
- * S: if S=1 then scale (essentially index by sizeof(size))
67
- * Rt: register to transfer into/out of
68
- * Rn: address register or SP for base
69
- * Rm: offset register or ZR for offset
70
- */
71
-static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
72
- int opc,
73
- int size,
74
- int rt,
75
- bool is_vector)
76
+static void op_addr_ldst_pre(DisasContext *s, arg_ldst *a,
77
+ TCGv_i64 *clean_addr, TCGv_i64 *dirty_addr,
78
+ bool is_store, MemOp memop)
79
{
80
- int rn = extract32(insn, 5, 5);
81
- int shift = extract32(insn, 12, 1);
82
- int rm = extract32(insn, 16, 5);
83
- int opt = extract32(insn, 13, 3);
84
- bool is_signed = false;
85
- bool is_store = false;
86
- bool is_extended = false;
87
- TCGv_i64 tcg_rm, clean_addr, dirty_addr;
88
- MemOp memop;
89
+ TCGv_i64 tcg_rm;
90
91
- if (extract32(opt, 1, 1) == 0) {
92
- unallocated_encoding(s);
93
- return;
94
- }
95
-
96
- if (is_vector) {
97
- size |= (opc & 2) << 1;
98
- if (size > 4) {
99
- unallocated_encoding(s);
100
- return;
101
- }
102
- is_store = !extract32(opc, 0, 1);
103
- if (!fp_access_check(s)) {
104
- return;
105
- }
106
- memop = finalize_memop_asimd(s, size);
107
- } else {
108
- if (size == 3 && opc == 2) {
109
- /* PRFM - prefetch */
110
- return;
111
- }
112
- if (opc == 3 && size > 1) {
113
- unallocated_encoding(s);
114
- return;
115
- }
116
- is_store = (opc == 0);
117
- is_signed = !is_store && extract32(opc, 1, 1);
118
- is_extended = (size < 3) && extract32(opc, 0, 1);
119
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
120
- }
121
-
122
- if (rn == 31) {
123
+ if (a->rn == 31) {
124
gen_check_sp_alignment(s);
125
}
126
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
127
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
128
129
- tcg_rm = read_cpu_reg(s, rm, 1);
130
- ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
131
+ tcg_rm = read_cpu_reg(s, a->rm, 1);
132
+ ext_and_shift_reg(tcg_rm, tcg_rm, a->opt, a->s ? a->sz : 0);
133
134
- tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
135
+ tcg_gen_add_i64(*dirty_addr, *dirty_addr, tcg_rm);
136
+ *clean_addr = gen_mte_check1(s, *dirty_addr, is_store, true, memop);
137
+}
138
139
- clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, memop);
140
+static bool trans_LDR(DisasContext *s, arg_ldst *a)
141
+{
142
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
143
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
144
+ MemOp memop;
145
146
- if (is_vector) {
147
- if (is_store) {
148
- do_fp_st(s, rt, clean_addr, memop);
149
- } else {
150
- do_fp_ld(s, rt, clean_addr, memop);
151
- }
152
- } else {
153
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
154
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
155
-
156
- if (is_store) {
157
- do_gpr_st(s, tcg_rt, clean_addr, memop,
158
- true, rt, iss_sf, false);
159
- } else {
160
- do_gpr_ld(s, tcg_rt, clean_addr, memop,
161
- is_extended, true, rt, iss_sf, false);
162
- }
163
+ if (extract32(a->opt, 1, 1) == 0) {
164
+ return false;
165
}
166
+
167
+ memop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
168
+ op_addr_ldst_pre(s, a, &clean_addr, &dirty_addr, false, memop);
169
+ tcg_rt = cpu_reg(s, a->rt);
170
+ do_gpr_ld(s, tcg_rt, clean_addr, memop,
171
+ a->ext, true, a->rt, iss_sf, false);
172
+ return true;
173
+}
174
+
175
+static bool trans_STR(DisasContext *s, arg_ldst *a)
176
+{
177
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
178
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
179
+ MemOp memop;
180
+
181
+ if (extract32(a->opt, 1, 1) == 0) {
182
+ return false;
183
+ }
184
+
185
+ memop = finalize_memop(s, a->sz);
186
+ op_addr_ldst_pre(s, a, &clean_addr, &dirty_addr, true, memop);
187
+ tcg_rt = cpu_reg(s, a->rt);
188
+ do_gpr_st(s, tcg_rt, clean_addr, memop, true, a->rt, iss_sf, false);
189
+ return true;
190
+}
191
+
192
+static bool trans_LDR_v(DisasContext *s, arg_ldst *a)
193
+{
194
+ TCGv_i64 clean_addr, dirty_addr;
195
+ MemOp memop;
196
+
197
+ if (extract32(a->opt, 1, 1) == 0) {
198
+ return false;
199
+ }
200
+
201
+ if (!fp_access_check(s)) {
202
+ return true;
203
+ }
204
+
205
+ memop = finalize_memop_asimd(s, a->sz);
206
+ op_addr_ldst_pre(s, a, &clean_addr, &dirty_addr, false, memop);
207
+ do_fp_ld(s, a->rt, clean_addr, memop);
208
+ return true;
209
+}
210
+
211
+static bool trans_STR_v(DisasContext *s, arg_ldst *a)
212
+{
213
+ TCGv_i64 clean_addr, dirty_addr;
214
+ MemOp memop;
215
+
216
+ if (extract32(a->opt, 1, 1) == 0) {
217
+ return false;
218
+ }
219
+
220
+ if (!fp_access_check(s)) {
221
+ return true;
222
+ }
223
+
224
+ memop = finalize_memop_asimd(s, a->sz);
225
+ op_addr_ldst_pre(s, a, &clean_addr, &dirty_addr, true, memop);
226
+ do_fp_st(s, a->rt, clean_addr, memop);
227
+ return true;
228
}
229
230
/* Atomic memory operations
231
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
232
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
233
{
234
int rt = extract32(insn, 0, 5);
235
- int opc = extract32(insn, 22, 2);
236
bool is_vector = extract32(insn, 26, 1);
237
int size = extract32(insn, 30, 2);
238
239
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
240
disas_ldst_atomic(s, insn, size, rt, is_vector);
241
return;
242
case 2:
243
- disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector);
244
- return;
245
+ break;
246
default:
247
disas_ldst_pac(s, insn, size, rt, is_vector);
248
return;
249
--
250
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Convert the insns in the atomic memory operations group to
2
decodetree.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-16-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 15 ++++
9
target/arm/tcg/translate-a64.c | 153 ++++++++++++---------------------
10
2 files changed, 70 insertions(+), 98 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ STR_v sz:2 111 1 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
17
STR_v 00 111 1 00 10 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
18
LDR_v sz:2 111 1 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
19
LDR_v 00 111 1 00 11 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
20
+
21
+# Atomic memory operations
22
+&atomic rs rn rt a r sz
23
+@atomic sz:2 ... . .. a:1 r:1 . rs:5 . ... .. rn:5 rt:5 &atomic
24
+LDADD .. 111 0 00 . . 1 ..... 0000 00 ..... ..... @atomic
25
+LDCLR .. 111 0 00 . . 1 ..... 0001 00 ..... ..... @atomic
26
+LDEOR .. 111 0 00 . . 1 ..... 0010 00 ..... ..... @atomic
27
+LDSET .. 111 0 00 . . 1 ..... 0011 00 ..... ..... @atomic
28
+LDSMAX .. 111 0 00 . . 1 ..... 0100 00 ..... ..... @atomic
29
+LDSMIN .. 111 0 00 . . 1 ..... 0101 00 ..... ..... @atomic
30
+LDUMAX .. 111 0 00 . . 1 ..... 0110 00 ..... ..... @atomic
31
+LDUMIN .. 111 0 00 . . 1 ..... 0111 00 ..... ..... @atomic
32
+SWP .. 111 0 00 . . 1 ..... 1000 00 ..... ..... @atomic
33
+
34
+LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
35
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/tcg/translate-a64.c
38
+++ b/target/arm/tcg/translate-a64.c
39
@@ -XXX,XX +XXX,XX @@ static bool trans_STR_v(DisasContext *s, arg_ldst *a)
40
return true;
41
}
42
43
-/* Atomic memory operations
44
- *
45
- * 31 30 27 26 24 22 21 16 15 12 10 5 0
46
- * +------+-------+---+-----+-----+---+----+----+-----+-----+----+-----+
47
- * | size | 1 1 1 | V | 0 0 | A R | 1 | Rs | o3 | opc | 0 0 | Rn | Rt |
48
- * +------+-------+---+-----+-----+--------+----+-----+-----+----+-----+
49
- *
50
- * Rt: the result register
51
- * Rn: base address or SP
52
- * Rs: the source register for the operation
53
- * V: vector flag (always 0 as of v8.3)
54
- * A: acquire flag
55
- * R: release flag
56
- */
57
-static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
58
- int size, int rt, bool is_vector)
59
+
60
+static bool do_atomic_ld(DisasContext *s, arg_atomic *a, AtomicThreeOpFn *fn,
61
+ int sign, bool invert)
62
{
63
- int rs = extract32(insn, 16, 5);
64
- int rn = extract32(insn, 5, 5);
65
- int o3_opc = extract32(insn, 12, 4);
66
- bool r = extract32(insn, 22, 1);
67
- bool a = extract32(insn, 23, 1);
68
- TCGv_i64 tcg_rs, tcg_rt, clean_addr;
69
- AtomicThreeOpFn *fn = NULL;
70
- MemOp mop = size;
71
+ MemOp mop = a->sz | sign;
72
+ TCGv_i64 clean_addr, tcg_rs, tcg_rt;
73
74
- if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
75
- unallocated_encoding(s);
76
- return;
77
- }
78
- switch (o3_opc) {
79
- case 000: /* LDADD */
80
- fn = tcg_gen_atomic_fetch_add_i64;
81
- break;
82
- case 001: /* LDCLR */
83
- fn = tcg_gen_atomic_fetch_and_i64;
84
- break;
85
- case 002: /* LDEOR */
86
- fn = tcg_gen_atomic_fetch_xor_i64;
87
- break;
88
- case 003: /* LDSET */
89
- fn = tcg_gen_atomic_fetch_or_i64;
90
- break;
91
- case 004: /* LDSMAX */
92
- fn = tcg_gen_atomic_fetch_smax_i64;
93
- mop |= MO_SIGN;
94
- break;
95
- case 005: /* LDSMIN */
96
- fn = tcg_gen_atomic_fetch_smin_i64;
97
- mop |= MO_SIGN;
98
- break;
99
- case 006: /* LDUMAX */
100
- fn = tcg_gen_atomic_fetch_umax_i64;
101
- break;
102
- case 007: /* LDUMIN */
103
- fn = tcg_gen_atomic_fetch_umin_i64;
104
- break;
105
- case 010: /* SWP */
106
- fn = tcg_gen_atomic_xchg_i64;
107
- break;
108
- case 014: /* LDAPR, LDAPRH, LDAPRB */
109
- if (!dc_isar_feature(aa64_rcpc_8_3, s) ||
110
- rs != 31 || a != 1 || r != 0) {
111
- unallocated_encoding(s);
112
- return;
113
- }
114
- break;
115
- default:
116
- unallocated_encoding(s);
117
- return;
118
- }
119
-
120
- if (rn == 31) {
121
+ if (a->rn == 31) {
122
gen_check_sp_alignment(s);
123
}
124
-
125
- mop = check_atomic_align(s, rn, mop);
126
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), false, rn != 31, mop);
127
-
128
- if (o3_opc == 014) {
129
- /*
130
- * LDAPR* are a special case because they are a simple load, not a
131
- * fetch-and-do-something op.
132
- * The architectural consistency requirements here are weaker than
133
- * full load-acquire (we only need "load-acquire processor consistent"),
134
- * but we choose to implement them as full LDAQ.
135
- */
136
- do_gpr_ld(s, cpu_reg(s, rt), clean_addr, mop, false,
137
- true, rt, disas_ldst_compute_iss_sf(size, false, 0), true);
138
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
139
- return;
140
- }
141
-
142
- tcg_rs = read_cpu_reg(s, rs, true);
143
- tcg_rt = cpu_reg(s, rt);
144
-
145
- if (o3_opc == 1) { /* LDCLR */
146
+ mop = check_atomic_align(s, a->rn, mop);
147
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, a->rn), false,
148
+ a->rn != 31, mop);
149
+ tcg_rs = read_cpu_reg(s, a->rs, true);
150
+ tcg_rt = cpu_reg(s, a->rt);
151
+ if (invert) {
152
tcg_gen_not_i64(tcg_rs, tcg_rs);
153
}
154
-
155
- /* The tcg atomic primitives are all full barriers. Therefore we
156
+ /*
157
+ * The tcg atomic primitives are all full barriers. Therefore we
158
* can ignore the Acquire and Release bits of this instruction.
159
*/
160
fn(tcg_rt, clean_addr, tcg_rs, get_mem_index(s), mop);
161
162
if (mop & MO_SIGN) {
163
- switch (size) {
164
+ switch (a->sz) {
165
case MO_8:
166
tcg_gen_ext8u_i64(tcg_rt, tcg_rt);
167
break;
168
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
169
g_assert_not_reached();
170
}
171
}
172
+ return true;
173
+}
174
+
175
+TRANS_FEAT(LDADD, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_add_i64, 0, false)
176
+TRANS_FEAT(LDCLR, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_and_i64, 0, true)
177
+TRANS_FEAT(LDEOR, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_xor_i64, 0, false)
178
+TRANS_FEAT(LDSET, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_or_i64, 0, false)
179
+TRANS_FEAT(LDSMAX, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_smax_i64, MO_SIGN, false)
180
+TRANS_FEAT(LDSMIN, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_smin_i64, MO_SIGN, false)
181
+TRANS_FEAT(LDUMAX, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_umax_i64, 0, false)
182
+TRANS_FEAT(LDUMIN, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_umin_i64, 0, false)
183
+TRANS_FEAT(SWP, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_xchg_i64, 0, false)
184
+
185
+static bool trans_LDAPR(DisasContext *s, arg_LDAPR *a)
186
+{
187
+ bool iss_sf = ldst_iss_sf(a->sz, false, false);
188
+ TCGv_i64 clean_addr;
189
+ MemOp mop;
190
+
191
+ if (!dc_isar_feature(aa64_atomics, s) ||
192
+ !dc_isar_feature(aa64_rcpc_8_3, s)) {
193
+ return false;
194
+ }
195
+ if (a->rn == 31) {
196
+ gen_check_sp_alignment(s);
197
+ }
198
+ mop = check_atomic_align(s, a->rn, a->sz);
199
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, a->rn), false,
200
+ a->rn != 31, mop);
201
+ /*
202
+ * LDAPR* are a special case because they are a simple load, not a
203
+ * fetch-and-do-something op.
204
+ * The architectural consistency requirements here are weaker than
205
+ * full load-acquire (we only need "load-acquire processor consistent"),
206
+ * but we choose to implement them as full LDAQ.
207
+ */
208
+ do_gpr_ld(s, cpu_reg(s, a->rt), clean_addr, mop, false,
209
+ true, a->rt, iss_sf, true);
210
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
211
+ return true;
212
}
213
214
/*
215
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
216
}
217
switch (extract32(insn, 10, 2)) {
218
case 0:
219
- disas_ldst_atomic(s, insn, size, rt, is_vector);
220
- return;
221
case 2:
222
break;
223
default:
224
--
225
2.34.1
diff view generated by jsdifflib
Deleted patch
1
The nrf51_timer has a free-running counter which we implement using
2
the pattern of using two fields (update_counter_ns, counter) to track
3
the last point at which we calculated the counter value, and the
4
counter value at that time. Then we can find the current counter
5
value by converting the difference in wall-clock time between then
6
and now to a tick count that we need to add to the counter value.
7
1
8
Unfortunately the nrf51_timer's implementation of this has a bug
9
which means it loses time every time update_counter() is called.
10
After updating s->counter it always sets s->update_counter_ns to
11
'now', even though the actual point when s->counter hit the new value
12
will be some point in the past (half a tick, say). In the worst case
13
(guest code in a tight loop reading the counter, icount mode) the
14
counter is continually queried less than a tick after it was last
15
read, so s->counter never advances but s->update_counter_ns does, and
16
the guest never makes forward progress.
17
18
The fix for this is to only advance update_counter_ns to the
19
timestamp of the last tick, not all the way to 'now'. (This is the
20
pattern used in hw/misc/mps2-fpgaio.c's counter.)
21
22
Cc: qemu-stable@nongnu.org
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Joel Stanley <joel@jms.id.au>
25
Message-id: 20230606134917.3782215-1-peter.maydell@linaro.org
26
---
27
hw/timer/nrf51_timer.c | 7 ++++++-
28
1 file changed, 6 insertions(+), 1 deletion(-)
29
30
diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/nrf51_timer.c
33
+++ b/hw/timer/nrf51_timer.c
34
@@ -XXX,XX +XXX,XX @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now)
35
uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
36
37
s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
38
- s->update_counter_ns = now;
39
+ /*
40
+ * Only advance the sync time to the timestamp of the last tick,
41
+ * not all the way to 'now', so we don't lose time if we do
42
+ * multiple resyncs in a single tick.
43
+ */
44
+ s->update_counter_ns += ticks_to_ns(s, ticks);
45
return ticks;
46
}
47
48
--
49
2.34.1
diff view generated by jsdifflib
1
From: Martin Kaiser <martin@kaiser.cx>
1
The sun4v RTC device model added under commit a0e893039cf2ce0 in 2016
2
was unfortunately added with a license of GPL-v3-or-later, which is
3
not compatible with other QEMU code which has a GPL-v2-only license.
2
4
3
The Linux kernel added a flood check for RX data recently in commit
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
4
496a4471b7c3 ("serial: imx: work-around for hardware RX flood"). This
6
to make it compatible with the rest of QEMU.
5
check uses the wake bit in the UART status register 2. The wake bit
6
indicates that the receiver detected a start bit on the RX line. If the
7
kernel sees a number of RX interrupts without the wake bit being set, it
8
treats this as spurious data and resets the UART port. imx_serial does
9
never set the wake bit and triggers the kernel's flood check.
10
7
11
This patch adds support for the wake bit. wake is set when we receive a
8
Cc: qemu-stable@nongnu.org
12
new character (it's not set for break events). It seems that wake is
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
cleared by the kernel driver, the hardware does not have to clear it
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
14
automatically after data was read.
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
15
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
16
The wake bit can be configured as an interrupt source. Support this
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
17
mechanism as well.
18
19
Co-developed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
21
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
22
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
15
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
16
Acked-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20240223161300.938542-1-peter.maydell@linaro.org
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
19
---
25
include/hw/char/imx_serial.h | 1 +
20
include/hw/rtc/sun4v-rtc.h | 2 +-
26
hw/char/imx_serial.c | 5 ++++-
21
hw/rtc/sun4v-rtc.c | 2 +-
27
2 files changed, 5 insertions(+), 1 deletion(-)
22
2 files changed, 2 insertions(+), 2 deletions(-)
28
23
29
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
30
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/char/imx_serial.h
26
--- a/include/hw/rtc/sun4v-rtc.h
32
+++ b/include/hw/char/imx_serial.h
27
+++ b/include/hw/rtc/sun4v-rtc.h
33
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXSerialState, IMX_SERIAL)
28
@@ -XXX,XX +XXX,XX @@
34
29
*
35
#define UCR4_DREN BIT(0) /* Receive Data Ready interrupt enable */
30
* Copyright (c) 2016 Artyom Tarasenko
36
#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
31
*
37
+#define UCR4_WKEN BIT(7) /* WAKE interrupt enable */
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
38
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
39
#define UTS1_TXEMPTY (1<<6)
34
* version.
40
#define UTS1_RXEMPTY (1<<5)
35
*/
41
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
36
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
42
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/char/imx_serial.c
39
--- a/hw/rtc/sun4v-rtc.c
44
+++ b/hw/char/imx_serial.c
40
+++ b/hw/rtc/sun4v-rtc.c
45
@@ -XXX,XX +XXX,XX @@ static void imx_update(IMXSerialState *s)
41
@@ -XXX,XX +XXX,XX @@
46
* TCEN and TXDC are both bit 3
42
*
47
* RDR and DREN are both bit 0
43
* Copyright (c) 2016 Artyom Tarasenko
48
*/
44
*
49
- mask |= s->ucr4 & (UCR4_TCEN | UCR4_DREN);
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
50
+ mask |= s->ucr4 & (UCR4_WKEN | UCR4_TCEN | UCR4_DREN);
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
51
47
* version.
52
usr2 = s->usr2 & mask;
48
*/
53
54
@@ -XXX,XX +XXX,XX @@ static void imx_put_data(void *opaque, uint32_t value)
55
56
static void imx_receive(void *opaque, const uint8_t *buf, int size)
57
{
58
+ IMXSerialState *s = (IMXSerialState *)opaque;
59
+
60
+ s->usr2 |= USR2_WAKE;
61
imx_put_data(opaque, *buf);
62
}
63
49
64
--
50
--
65
2.34.1
51
2.34.1
66
52
67
53
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
We plan to add more hardware information into DeviceTree to limit amount
3
Move the code to a separate file so that we do not have to compile
4
of hardcoded values in firmware.
4
it anymore if CONFIG_ARM_V7M is not set.
5
5
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Message-id: 20230531171834.236569-1-marcin.juszkiewicz@linaro.org
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
8
[PMM: fix format nits, add text about platform version fields from
9
a comment in the C source file]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
docs/system/arm/sbsa.rst | 38 +++++++++++++++++++++++++++++++-------
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
14
1 file changed, 31 insertions(+), 7 deletions(-)
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
13
target/arm/meson.build | 3 +
14
target/arm/tcg/meson.build | 3 +
15
4 files changed, 296 insertions(+), 261 deletions(-)
16
create mode 100644 target/arm/tcg/cpu-v7m.c
15
17
16
diff --git a/docs/system/arm/sbsa.rst b/docs/system/arm/sbsa.rst
18
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/target/arm/tcg/cpu-v7m.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QEMU ARMv7-M TCG-only CPUs.
26
+ *
27
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
28
+ *
29
+ * This code is licensed under the GNU GPL v2 or later.
30
+ *
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
32
+ */
33
+
34
+#include "qemu/osdep.h"
35
+#include "cpu.h"
36
+#include "hw/core/tcg-cpu-ops.h"
37
+#include "internals.h"
38
+
39
+#if !defined(CONFIG_USER_ONLY)
40
+
41
+#include "hw/intc/armv7m_nvic.h"
42
+
43
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
44
+{
45
+ CPUClass *cc = CPU_GET_CLASS(cs);
46
+ ARMCPU *cpu = ARM_CPU(cs);
47
+ CPUARMState *env = &cpu->env;
48
+ bool ret = false;
49
+
50
+ /*
51
+ * ARMv7-M interrupt masking works differently than -A or -R.
52
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
53
+ * masking FIQ and IRQ interrupts, an exception is taken only
54
+ * if it is higher priority than the current execution priority
55
+ * (which depends on state like BASEPRI, FAULTMASK and the
56
+ * currently active exception).
57
+ */
58
+ if (interrupt_request & CPU_INTERRUPT_HARD
59
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
60
+ cs->exception_index = EXCP_IRQ;
61
+ cc->tcg_ops->do_interrupt(cs);
62
+ ret = true;
63
+ }
64
+ return ret;
65
+}
66
+
67
+#endif /* !CONFIG_USER_ONLY */
68
+
69
+static void cortex_m0_initfn(Object *obj)
70
+{
71
+ ARMCPU *cpu = ARM_CPU(obj);
72
+ set_feature(&cpu->env, ARM_FEATURE_V6);
73
+ set_feature(&cpu->env, ARM_FEATURE_M);
74
+
75
+ cpu->midr = 0x410cc200;
76
+
77
+ /*
78
+ * These ID register values are not guest visible, because
79
+ * we do not implement the Main Extension. They must be set
80
+ * to values corresponding to the Cortex-M0's implemented
81
+ * features, because QEMU generally controls its emulation
82
+ * by looking at ID register fields. We use the same values as
83
+ * for the M3.
84
+ */
85
+ cpu->isar.id_pfr0 = 0x00000030;
86
+ cpu->isar.id_pfr1 = 0x00000200;
87
+ cpu->isar.id_dfr0 = 0x00100000;
88
+ cpu->id_afr0 = 0x00000000;
89
+ cpu->isar.id_mmfr0 = 0x00000030;
90
+ cpu->isar.id_mmfr1 = 0x00000000;
91
+ cpu->isar.id_mmfr2 = 0x00000000;
92
+ cpu->isar.id_mmfr3 = 0x00000000;
93
+ cpu->isar.id_isar0 = 0x01141110;
94
+ cpu->isar.id_isar1 = 0x02111000;
95
+ cpu->isar.id_isar2 = 0x21112231;
96
+ cpu->isar.id_isar3 = 0x01111110;
97
+ cpu->isar.id_isar4 = 0x01310102;
98
+ cpu->isar.id_isar5 = 0x00000000;
99
+ cpu->isar.id_isar6 = 0x00000000;
100
+}
101
+
102
+static void cortex_m3_initfn(Object *obj)
103
+{
104
+ ARMCPU *cpu = ARM_CPU(obj);
105
+ set_feature(&cpu->env, ARM_FEATURE_V7);
106
+ set_feature(&cpu->env, ARM_FEATURE_M);
107
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
108
+ cpu->midr = 0x410fc231;
109
+ cpu->pmsav7_dregion = 8;
110
+ cpu->isar.id_pfr0 = 0x00000030;
111
+ cpu->isar.id_pfr1 = 0x00000200;
112
+ cpu->isar.id_dfr0 = 0x00100000;
113
+ cpu->id_afr0 = 0x00000000;
114
+ cpu->isar.id_mmfr0 = 0x00000030;
115
+ cpu->isar.id_mmfr1 = 0x00000000;
116
+ cpu->isar.id_mmfr2 = 0x00000000;
117
+ cpu->isar.id_mmfr3 = 0x00000000;
118
+ cpu->isar.id_isar0 = 0x01141110;
119
+ cpu->isar.id_isar1 = 0x02111000;
120
+ cpu->isar.id_isar2 = 0x21112231;
121
+ cpu->isar.id_isar3 = 0x01111110;
122
+ cpu->isar.id_isar4 = 0x01310102;
123
+ cpu->isar.id_isar5 = 0x00000000;
124
+ cpu->isar.id_isar6 = 0x00000000;
125
+}
126
+
127
+static void cortex_m4_initfn(Object *obj)
128
+{
129
+ ARMCPU *cpu = ARM_CPU(obj);
130
+
131
+ set_feature(&cpu->env, ARM_FEATURE_V7);
132
+ set_feature(&cpu->env, ARM_FEATURE_M);
133
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
134
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
135
+ cpu->midr = 0x410fc240; /* r0p0 */
136
+ cpu->pmsav7_dregion = 8;
137
+ cpu->isar.mvfr0 = 0x10110021;
138
+ cpu->isar.mvfr1 = 0x11000011;
139
+ cpu->isar.mvfr2 = 0x00000000;
140
+ cpu->isar.id_pfr0 = 0x00000030;
141
+ cpu->isar.id_pfr1 = 0x00000200;
142
+ cpu->isar.id_dfr0 = 0x00100000;
143
+ cpu->id_afr0 = 0x00000000;
144
+ cpu->isar.id_mmfr0 = 0x00000030;
145
+ cpu->isar.id_mmfr1 = 0x00000000;
146
+ cpu->isar.id_mmfr2 = 0x00000000;
147
+ cpu->isar.id_mmfr3 = 0x00000000;
148
+ cpu->isar.id_isar0 = 0x01141110;
149
+ cpu->isar.id_isar1 = 0x02111000;
150
+ cpu->isar.id_isar2 = 0x21112231;
151
+ cpu->isar.id_isar3 = 0x01111110;
152
+ cpu->isar.id_isar4 = 0x01310102;
153
+ cpu->isar.id_isar5 = 0x00000000;
154
+ cpu->isar.id_isar6 = 0x00000000;
155
+}
156
+
157
+static void cortex_m7_initfn(Object *obj)
158
+{
159
+ ARMCPU *cpu = ARM_CPU(obj);
160
+
161
+ set_feature(&cpu->env, ARM_FEATURE_V7);
162
+ set_feature(&cpu->env, ARM_FEATURE_M);
163
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
164
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
165
+ cpu->midr = 0x411fc272; /* r1p2 */
166
+ cpu->pmsav7_dregion = 8;
167
+ cpu->isar.mvfr0 = 0x10110221;
168
+ cpu->isar.mvfr1 = 0x12000011;
169
+ cpu->isar.mvfr2 = 0x00000040;
170
+ cpu->isar.id_pfr0 = 0x00000030;
171
+ cpu->isar.id_pfr1 = 0x00000200;
172
+ cpu->isar.id_dfr0 = 0x00100000;
173
+ cpu->id_afr0 = 0x00000000;
174
+ cpu->isar.id_mmfr0 = 0x00100030;
175
+ cpu->isar.id_mmfr1 = 0x00000000;
176
+ cpu->isar.id_mmfr2 = 0x01000000;
177
+ cpu->isar.id_mmfr3 = 0x00000000;
178
+ cpu->isar.id_isar0 = 0x01101110;
179
+ cpu->isar.id_isar1 = 0x02112000;
180
+ cpu->isar.id_isar2 = 0x20232231;
181
+ cpu->isar.id_isar3 = 0x01111131;
182
+ cpu->isar.id_isar4 = 0x01310132;
183
+ cpu->isar.id_isar5 = 0x00000000;
184
+ cpu->isar.id_isar6 = 0x00000000;
185
+}
186
+
187
+static void cortex_m33_initfn(Object *obj)
188
+{
189
+ ARMCPU *cpu = ARM_CPU(obj);
190
+
191
+ set_feature(&cpu->env, ARM_FEATURE_V8);
192
+ set_feature(&cpu->env, ARM_FEATURE_M);
193
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
194
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
195
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
196
+ cpu->midr = 0x410fd213; /* r0p3 */
197
+ cpu->pmsav7_dregion = 16;
198
+ cpu->sau_sregion = 8;
199
+ cpu->isar.mvfr0 = 0x10110021;
200
+ cpu->isar.mvfr1 = 0x11000011;
201
+ cpu->isar.mvfr2 = 0x00000040;
202
+ cpu->isar.id_pfr0 = 0x00000030;
203
+ cpu->isar.id_pfr1 = 0x00000210;
204
+ cpu->isar.id_dfr0 = 0x00200000;
205
+ cpu->id_afr0 = 0x00000000;
206
+ cpu->isar.id_mmfr0 = 0x00101F40;
207
+ cpu->isar.id_mmfr1 = 0x00000000;
208
+ cpu->isar.id_mmfr2 = 0x01000000;
209
+ cpu->isar.id_mmfr3 = 0x00000000;
210
+ cpu->isar.id_isar0 = 0x01101110;
211
+ cpu->isar.id_isar1 = 0x02212000;
212
+ cpu->isar.id_isar2 = 0x20232232;
213
+ cpu->isar.id_isar3 = 0x01111131;
214
+ cpu->isar.id_isar4 = 0x01310132;
215
+ cpu->isar.id_isar5 = 0x00000000;
216
+ cpu->isar.id_isar6 = 0x00000000;
217
+ cpu->clidr = 0x00000000;
218
+ cpu->ctr = 0x8000c000;
219
+}
220
+
221
+static void cortex_m55_initfn(Object *obj)
222
+{
223
+ ARMCPU *cpu = ARM_CPU(obj);
224
+
225
+ set_feature(&cpu->env, ARM_FEATURE_V8);
226
+ set_feature(&cpu->env, ARM_FEATURE_V8_1M);
227
+ set_feature(&cpu->env, ARM_FEATURE_M);
228
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
229
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
230
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
231
+ cpu->midr = 0x410fd221; /* r0p1 */
232
+ cpu->revidr = 0;
233
+ cpu->pmsav7_dregion = 16;
234
+ cpu->sau_sregion = 8;
235
+ /* These are the MVFR* values for the FPU + full MVE configuration */
236
+ cpu->isar.mvfr0 = 0x10110221;
237
+ cpu->isar.mvfr1 = 0x12100211;
238
+ cpu->isar.mvfr2 = 0x00000040;
239
+ cpu->isar.id_pfr0 = 0x20000030;
240
+ cpu->isar.id_pfr1 = 0x00000230;
241
+ cpu->isar.id_dfr0 = 0x10200000;
242
+ cpu->id_afr0 = 0x00000000;
243
+ cpu->isar.id_mmfr0 = 0x00111040;
244
+ cpu->isar.id_mmfr1 = 0x00000000;
245
+ cpu->isar.id_mmfr2 = 0x01000000;
246
+ cpu->isar.id_mmfr3 = 0x00000011;
247
+ cpu->isar.id_isar0 = 0x01103110;
248
+ cpu->isar.id_isar1 = 0x02212000;
249
+ cpu->isar.id_isar2 = 0x20232232;
250
+ cpu->isar.id_isar3 = 0x01111131;
251
+ cpu->isar.id_isar4 = 0x01310132;
252
+ cpu->isar.id_isar5 = 0x00000000;
253
+ cpu->isar.id_isar6 = 0x00000000;
254
+ cpu->clidr = 0x00000000; /* caches not implemented */
255
+ cpu->ctr = 0x8303c003;
256
+}
257
+
258
+static const TCGCPUOps arm_v7m_tcg_ops = {
259
+ .initialize = arm_translate_init,
260
+ .synchronize_from_tb = arm_cpu_synchronize_from_tb,
261
+ .debug_excp_handler = arm_debug_excp_handler,
262
+ .restore_state_to_opc = arm_restore_state_to_opc,
263
+
264
+#ifdef CONFIG_USER_ONLY
265
+ .record_sigsegv = arm_cpu_record_sigsegv,
266
+ .record_sigbus = arm_cpu_record_sigbus,
267
+#else
268
+ .tlb_fill = arm_cpu_tlb_fill,
269
+ .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
270
+ .do_interrupt = arm_v7m_cpu_do_interrupt,
271
+ .do_transaction_failed = arm_cpu_do_transaction_failed,
272
+ .do_unaligned_access = arm_cpu_do_unaligned_access,
273
+ .adjust_watchpoint_address = arm_adjust_watchpoint_address,
274
+ .debug_check_watchpoint = arm_debug_check_watchpoint,
275
+ .debug_check_breakpoint = arm_debug_check_breakpoint,
276
+#endif /* !CONFIG_USER_ONLY */
277
+};
278
+
279
+static void arm_v7m_class_init(ObjectClass *oc, void *data)
280
+{
281
+ ARMCPUClass *acc = ARM_CPU_CLASS(oc);
282
+ CPUClass *cc = CPU_CLASS(oc);
283
+
284
+ acc->info = data;
285
+ cc->tcg_ops = &arm_v7m_tcg_ops;
286
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
287
+}
288
+
289
+static const ARMCPUInfo arm_v7m_cpus[] = {
290
+ { .name = "cortex-m0", .initfn = cortex_m0_initfn,
291
+ .class_init = arm_v7m_class_init },
292
+ { .name = "cortex-m3", .initfn = cortex_m3_initfn,
293
+ .class_init = arm_v7m_class_init },
294
+ { .name = "cortex-m4", .initfn = cortex_m4_initfn,
295
+ .class_init = arm_v7m_class_init },
296
+ { .name = "cortex-m7", .initfn = cortex_m7_initfn,
297
+ .class_init = arm_v7m_class_init },
298
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
299
+ .class_init = arm_v7m_class_init },
300
+ { .name = "cortex-m55", .initfn = cortex_m55_initfn,
301
+ .class_init = arm_v7m_class_init },
302
+};
303
+
304
+static void arm_v7m_cpu_register_types(void)
305
+{
306
+ size_t i;
307
+
308
+ for (i = 0; i < ARRAY_SIZE(arm_v7m_cpus); ++i) {
309
+ arm_cpu_register(&arm_v7m_cpus[i]);
310
+ }
311
+}
312
+
313
+type_init(arm_v7m_cpu_register_types)
314
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
17
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/system/arm/sbsa.rst
316
--- a/target/arm/tcg/cpu32.c
19
+++ b/docs/system/arm/sbsa.rst
317
+++ b/target/arm/tcg/cpu32.c
20
@@ -XXX,XX +XXX,XX @@ any real hardware the ``sbsa-ref`` board intends to look like real
318
@@ -XXX,XX +XXX,XX @@
21
hardware. The `Server Base System Architecture
319
#include "hw/boards.h"
22
<https://developer.arm.com/documentation/den0029/latest>`_ defines a
320
#endif
23
minimum base line of hardware support and importantly how the firmware
321
#include "cpregs.h"
24
-reports that to any operating system. It is a static system that
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
25
-reports a very minimal DT to the firmware for non-discoverable
323
-#include "hw/intc/armv7m_nvic.h"
26
-information about components affected by the qemu command line (i.e.
324
-#endif
27
-cpus and memory). As a result it must have a firmware specifically
325
28
-built to expect a certain hardware layout (as you would in a real
326
29
-machine).
327
/* Share AArch32 -cpu max features with AArch64. */
30
+reports that to any operating system.
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
31
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
32
It is intended to be a machine for developing firmware and testing
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
33
standards compliance with operating systems.
331
34
@@ -XXX,XX +XXX,XX @@ standards compliance with operating systems.
332
-#if !defined(CONFIG_USER_ONLY)
35
Supported devices
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
36
"""""""""""""""""
334
-{
37
335
- CPUClass *cc = CPU_GET_CLASS(cs);
38
-The sbsa-ref board supports:
336
- ARMCPU *cpu = ARM_CPU(cs);
39
+The ``sbsa-ref`` board supports:
337
- CPUARMState *env = &cpu->env;
40
338
- bool ret = false;
41
- A configurable number of AArch64 CPUs
339
-
42
- GIC version 3
340
- /*
43
@@ -XXX,XX +XXX,XX @@ The sbsa-ref board supports:
341
- * ARMv7-M interrupt masking works differently than -A or -R.
44
- Bochs display adapter on PCIe bus
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
45
- A generic SBSA watchdog device
343
- * masking FIQ and IRQ interrupts, an exception is taken only
46
344
- * if it is higher priority than the current execution priority
47
+
345
- * (which depends on state like BASEPRI, FAULTMASK and the
48
+Board to firmware interface
346
- * currently active exception).
49
+"""""""""""""""""""""""""""
347
- */
50
+
348
- if (interrupt_request & CPU_INTERRUPT_HARD
51
+``sbsa-ref`` is a static system that reports a very minimal devicetree to the
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
52
+firmware for non-discoverable information about system components. This
350
- cs->exception_index = EXCP_IRQ;
53
+includes both internal hardware and parts affected by the qemu command line
351
- cc->tcg_ops->do_interrupt(cs);
54
+(i.e. CPUs and memory). As a result it must have a firmware specifically built
352
- ret = true;
55
+to expect a certain hardware layout (as you would in a real machine).
353
- }
56
+
354
- return ret;
57
+DeviceTree information
355
-}
58
+''''''''''''''''''''''
356
-#endif /* !CONFIG_USER_ONLY */
59
+
357
-
60
+The devicetree provided by the board model to the firmware is not intended
358
static void arm926_initfn(Object *obj)
61
+to be a complete compliant DT. It currently reports:
359
{
62
+
360
ARMCPU *cpu = ARM_CPU(obj);
63
+ - CPUs
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
64
+ - memory
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
65
+ - platform version
363
}
66
+ - GIC addresses
364
67
+
365
-static void cortex_m0_initfn(Object *obj)
68
+The platform version is only for informing platform firmware about
366
-{
69
+what kind of ``sbsa-ref`` board it is running on. It is neither
367
- ARMCPU *cpu = ARM_CPU(obj);
70
+a QEMU versioned machine type nor a reflection of the level of the
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
71
+SBSA/SystemReady SR support provided.
369
- set_feature(&cpu->env, ARM_FEATURE_M);
72
+
370
-
73
+The ``machine-version-major`` value is updated when changes breaking
371
- cpu->midr = 0x410cc200;
74
+fw compatibility are introduced. The ``machine-version-minor`` value
372
-
75
+is updated when features are added that don't break fw compatibility.
373
- /*
374
- * These ID register values are not guest visible, because
375
- * we do not implement the Main Extension. They must be set
376
- * to values corresponding to the Cortex-M0's implemented
377
- * features, because QEMU generally controls its emulation
378
- * by looking at ID register fields. We use the same values as
379
- * for the M3.
380
- */
381
- cpu->isar.id_pfr0 = 0x00000030;
382
- cpu->isar.id_pfr1 = 0x00000200;
383
- cpu->isar.id_dfr0 = 0x00100000;
384
- cpu->id_afr0 = 0x00000000;
385
- cpu->isar.id_mmfr0 = 0x00000030;
386
- cpu->isar.id_mmfr1 = 0x00000000;
387
- cpu->isar.id_mmfr2 = 0x00000000;
388
- cpu->isar.id_mmfr3 = 0x00000000;
389
- cpu->isar.id_isar0 = 0x01141110;
390
- cpu->isar.id_isar1 = 0x02111000;
391
- cpu->isar.id_isar2 = 0x21112231;
392
- cpu->isar.id_isar3 = 0x01111110;
393
- cpu->isar.id_isar4 = 0x01310102;
394
- cpu->isar.id_isar5 = 0x00000000;
395
- cpu->isar.id_isar6 = 0x00000000;
396
-}
397
-
398
-static void cortex_m3_initfn(Object *obj)
399
-{
400
- ARMCPU *cpu = ARM_CPU(obj);
401
- set_feature(&cpu->env, ARM_FEATURE_V7);
402
- set_feature(&cpu->env, ARM_FEATURE_M);
403
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
404
- cpu->midr = 0x410fc231;
405
- cpu->pmsav7_dregion = 8;
406
- cpu->isar.id_pfr0 = 0x00000030;
407
- cpu->isar.id_pfr1 = 0x00000200;
408
- cpu->isar.id_dfr0 = 0x00100000;
409
- cpu->id_afr0 = 0x00000000;
410
- cpu->isar.id_mmfr0 = 0x00000030;
411
- cpu->isar.id_mmfr1 = 0x00000000;
412
- cpu->isar.id_mmfr2 = 0x00000000;
413
- cpu->isar.id_mmfr3 = 0x00000000;
414
- cpu->isar.id_isar0 = 0x01141110;
415
- cpu->isar.id_isar1 = 0x02111000;
416
- cpu->isar.id_isar2 = 0x21112231;
417
- cpu->isar.id_isar3 = 0x01111110;
418
- cpu->isar.id_isar4 = 0x01310102;
419
- cpu->isar.id_isar5 = 0x00000000;
420
- cpu->isar.id_isar6 = 0x00000000;
421
-}
422
-
423
-static void cortex_m4_initfn(Object *obj)
424
-{
425
- ARMCPU *cpu = ARM_CPU(obj);
426
-
427
- set_feature(&cpu->env, ARM_FEATURE_V7);
428
- set_feature(&cpu->env, ARM_FEATURE_M);
429
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
430
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
431
- cpu->midr = 0x410fc240; /* r0p0 */
432
- cpu->pmsav7_dregion = 8;
433
- cpu->isar.mvfr0 = 0x10110021;
434
- cpu->isar.mvfr1 = 0x11000011;
435
- cpu->isar.mvfr2 = 0x00000000;
436
- cpu->isar.id_pfr0 = 0x00000030;
437
- cpu->isar.id_pfr1 = 0x00000200;
438
- cpu->isar.id_dfr0 = 0x00100000;
439
- cpu->id_afr0 = 0x00000000;
440
- cpu->isar.id_mmfr0 = 0x00000030;
441
- cpu->isar.id_mmfr1 = 0x00000000;
442
- cpu->isar.id_mmfr2 = 0x00000000;
443
- cpu->isar.id_mmfr3 = 0x00000000;
444
- cpu->isar.id_isar0 = 0x01141110;
445
- cpu->isar.id_isar1 = 0x02111000;
446
- cpu->isar.id_isar2 = 0x21112231;
447
- cpu->isar.id_isar3 = 0x01111110;
448
- cpu->isar.id_isar4 = 0x01310102;
449
- cpu->isar.id_isar5 = 0x00000000;
450
- cpu->isar.id_isar6 = 0x00000000;
451
-}
452
-
453
-static void cortex_m7_initfn(Object *obj)
454
-{
455
- ARMCPU *cpu = ARM_CPU(obj);
456
-
457
- set_feature(&cpu->env, ARM_FEATURE_V7);
458
- set_feature(&cpu->env, ARM_FEATURE_M);
459
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
460
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
461
- cpu->midr = 0x411fc272; /* r1p2 */
462
- cpu->pmsav7_dregion = 8;
463
- cpu->isar.mvfr0 = 0x10110221;
464
- cpu->isar.mvfr1 = 0x12000011;
465
- cpu->isar.mvfr2 = 0x00000040;
466
- cpu->isar.id_pfr0 = 0x00000030;
467
- cpu->isar.id_pfr1 = 0x00000200;
468
- cpu->isar.id_dfr0 = 0x00100000;
469
- cpu->id_afr0 = 0x00000000;
470
- cpu->isar.id_mmfr0 = 0x00100030;
471
- cpu->isar.id_mmfr1 = 0x00000000;
472
- cpu->isar.id_mmfr2 = 0x01000000;
473
- cpu->isar.id_mmfr3 = 0x00000000;
474
- cpu->isar.id_isar0 = 0x01101110;
475
- cpu->isar.id_isar1 = 0x02112000;
476
- cpu->isar.id_isar2 = 0x20232231;
477
- cpu->isar.id_isar3 = 0x01111131;
478
- cpu->isar.id_isar4 = 0x01310132;
479
- cpu->isar.id_isar5 = 0x00000000;
480
- cpu->isar.id_isar6 = 0x00000000;
481
-}
482
-
483
-static void cortex_m33_initfn(Object *obj)
484
-{
485
- ARMCPU *cpu = ARM_CPU(obj);
486
-
487
- set_feature(&cpu->env, ARM_FEATURE_V8);
488
- set_feature(&cpu->env, ARM_FEATURE_M);
489
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
490
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
491
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
492
- cpu->midr = 0x410fd213; /* r0p3 */
493
- cpu->pmsav7_dregion = 16;
494
- cpu->sau_sregion = 8;
495
- cpu->isar.mvfr0 = 0x10110021;
496
- cpu->isar.mvfr1 = 0x11000011;
497
- cpu->isar.mvfr2 = 0x00000040;
498
- cpu->isar.id_pfr0 = 0x00000030;
499
- cpu->isar.id_pfr1 = 0x00000210;
500
- cpu->isar.id_dfr0 = 0x00200000;
501
- cpu->id_afr0 = 0x00000000;
502
- cpu->isar.id_mmfr0 = 0x00101F40;
503
- cpu->isar.id_mmfr1 = 0x00000000;
504
- cpu->isar.id_mmfr2 = 0x01000000;
505
- cpu->isar.id_mmfr3 = 0x00000000;
506
- cpu->isar.id_isar0 = 0x01101110;
507
- cpu->isar.id_isar1 = 0x02212000;
508
- cpu->isar.id_isar2 = 0x20232232;
509
- cpu->isar.id_isar3 = 0x01111131;
510
- cpu->isar.id_isar4 = 0x01310132;
511
- cpu->isar.id_isar5 = 0x00000000;
512
- cpu->isar.id_isar6 = 0x00000000;
513
- cpu->clidr = 0x00000000;
514
- cpu->ctr = 0x8000c000;
515
-}
516
-
517
-static void cortex_m55_initfn(Object *obj)
518
-{
519
- ARMCPU *cpu = ARM_CPU(obj);
520
-
521
- set_feature(&cpu->env, ARM_FEATURE_V8);
522
- set_feature(&cpu->env, ARM_FEATURE_V8_1M);
523
- set_feature(&cpu->env, ARM_FEATURE_M);
524
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
525
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
526
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
527
- cpu->midr = 0x410fd221; /* r0p1 */
528
- cpu->revidr = 0;
529
- cpu->pmsav7_dregion = 16;
530
- cpu->sau_sregion = 8;
531
- /* These are the MVFR* values for the FPU + full MVE configuration */
532
- cpu->isar.mvfr0 = 0x10110221;
533
- cpu->isar.mvfr1 = 0x12100211;
534
- cpu->isar.mvfr2 = 0x00000040;
535
- cpu->isar.id_pfr0 = 0x20000030;
536
- cpu->isar.id_pfr1 = 0x00000230;
537
- cpu->isar.id_dfr0 = 0x10200000;
538
- cpu->id_afr0 = 0x00000000;
539
- cpu->isar.id_mmfr0 = 0x00111040;
540
- cpu->isar.id_mmfr1 = 0x00000000;
541
- cpu->isar.id_mmfr2 = 0x01000000;
542
- cpu->isar.id_mmfr3 = 0x00000011;
543
- cpu->isar.id_isar0 = 0x01103110;
544
- cpu->isar.id_isar1 = 0x02212000;
545
- cpu->isar.id_isar2 = 0x20232232;
546
- cpu->isar.id_isar3 = 0x01111131;
547
- cpu->isar.id_isar4 = 0x01310132;
548
- cpu->isar.id_isar5 = 0x00000000;
549
- cpu->isar.id_isar6 = 0x00000000;
550
- cpu->clidr = 0x00000000; /* caches not implemented */
551
- cpu->ctr = 0x8303c003;
552
-}
553
-
554
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
555
/* Dummy the TCM region regs for the moment */
556
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
557
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
558
cpu->reset_sctlr = 0x00000078;
559
}
560
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
562
- .initialize = arm_translate_init,
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
564
- .debug_excp_handler = arm_debug_excp_handler,
565
- .restore_state_to_opc = arm_restore_state_to_opc,
566
-
567
-#ifdef CONFIG_USER_ONLY
568
- .record_sigsegv = arm_cpu_record_sigsegv,
569
- .record_sigbus = arm_cpu_record_sigbus,
570
-#else
571
- .tlb_fill = arm_cpu_tlb_fill,
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
579
-#endif /* !CONFIG_USER_ONLY */
580
-};
581
-
582
-static void arm_v7m_class_init(ObjectClass *oc, void *data)
583
-{
584
- ARMCPUClass *acc = ARM_CPU_CLASS(oc);
585
- CPUClass *cc = CPU_CLASS(oc);
586
-
587
- acc->info = data;
588
- cc->tcg_ops = &arm_v7m_tcg_ops;
589
- cc->gdb_core_xml_file = "arm-m-profile.xml";
590
-}
591
-
592
#ifndef TARGET_AARCH64
593
/*
594
* -cpu max: a CPU with as many features enabled as our emulation supports.
595
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
596
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
597
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
598
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
599
- { .name = "cortex-m0", .initfn = cortex_m0_initfn,
600
- .class_init = arm_v7m_class_init },
601
- { .name = "cortex-m3", .initfn = cortex_m3_initfn,
602
- .class_init = arm_v7m_class_init },
603
- { .name = "cortex-m4", .initfn = cortex_m4_initfn,
604
- .class_init = arm_v7m_class_init },
605
- { .name = "cortex-m7", .initfn = cortex_m7_initfn,
606
- .class_init = arm_v7m_class_init },
607
- { .name = "cortex-m33", .initfn = cortex_m33_initfn,
608
- .class_init = arm_v7m_class_init },
609
- { .name = "cortex-m55", .initfn = cortex_m55_initfn,
610
- .class_init = arm_v7m_class_init },
611
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
612
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
613
{ .name = "cortex-r52", .initfn = cortex_r52_initfn },
614
diff --git a/target/arm/meson.build b/target/arm/meson.build
615
index XXXXXXX..XXXXXXX 100644
616
--- a/target/arm/meson.build
617
+++ b/target/arm/meson.build
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
619
'ptw.c',
620
))
621
622
+arm_user_ss = ss.source_set()
623
+
624
subdir('hvf')
625
626
if 'CONFIG_TCG' in config_all_accel
627
@@ -XXX,XX +XXX,XX @@ endif
628
629
target_arch += {'arm': arm_ss}
630
target_system_arch += {'arm': arm_system_ss}
631
+target_user_arch += {'arm': arm_user_ss}
632
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
633
index XXXXXXX..XXXXXXX 100644
634
--- a/target/arm/tcg/meson.build
635
+++ b/target/arm/tcg/meson.build
636
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
637
arm_system_ss.add(files(
638
'psci.c',
639
))
640
+
641
+arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
642
+arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
76
--
643
--
77
2.34.1
644
2.34.1
diff view generated by jsdifflib
Deleted patch
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
1
3
Replace magic property values by a proper definition,
4
removing redundant comments.
5
6
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230612223456.33824-3-philmd@linaro.org
10
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
11
[PMD: Split from bigger patch: 2/4]
12
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/misc/bcm2835_property.c | 101 +++++++++++++++++++------------------
16
1 file changed, 51 insertions(+), 50 deletions(-)
17
18
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/bcm2835_property.c
21
+++ b/hw/misc/bcm2835_property.c
22
@@ -XXX,XX +XXX,XX @@
23
#include "migration/vmstate.h"
24
#include "hw/irq.h"
25
#include "hw/misc/bcm2835_mbox_defs.h"
26
+#include "hw/misc/raspberrypi-fw-defs.h"
27
#include "sysemu/dma.h"
28
#include "qemu/log.h"
29
#include "qemu/module.h"
30
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
31
/* @(value + 8) : Request/response indicator */
32
resplen = 0;
33
switch (tag) {
34
- case 0x00000000: /* End tag */
35
+ case RPI_FWREQ_PROPERTY_END:
36
break;
37
- case 0x00000001: /* Get firmware revision */
38
+ case RPI_FWREQ_GET_FIRMWARE_REVISION:
39
stl_le_phys(&s->dma_as, value + 12, 346337);
40
resplen = 4;
41
break;
42
- case 0x00010001: /* Get board model */
43
+ case RPI_FWREQ_GET_BOARD_MODEL:
44
qemu_log_mask(LOG_UNIMP,
45
"bcm2835_property: 0x%08x get board model NYI\n",
46
tag);
47
resplen = 4;
48
break;
49
- case 0x00010002: /* Get board revision */
50
+ case RPI_FWREQ_GET_BOARD_REVISION:
51
stl_le_phys(&s->dma_as, value + 12, s->board_rev);
52
resplen = 4;
53
break;
54
- case 0x00010003: /* Get board MAC address */
55
+ case RPI_FWREQ_GET_BOARD_MAC_ADDRESS:
56
resplen = sizeof(s->macaddr.a);
57
dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen,
58
MEMTXATTRS_UNSPECIFIED);
59
break;
60
- case 0x00010004: /* Get board serial */
61
+ case RPI_FWREQ_GET_BOARD_SERIAL:
62
qemu_log_mask(LOG_UNIMP,
63
"bcm2835_property: 0x%08x get board serial NYI\n",
64
tag);
65
resplen = 8;
66
break;
67
- case 0x00010005: /* Get ARM memory */
68
+ case RPI_FWREQ_GET_ARM_MEMORY:
69
/* base */
70
stl_le_phys(&s->dma_as, value + 12, 0);
71
/* size */
72
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_base);
73
resplen = 8;
74
break;
75
- case 0x00010006: /* Get VC memory */
76
+ case RPI_FWREQ_GET_VC_MEMORY:
77
/* base */
78
stl_le_phys(&s->dma_as, value + 12, s->fbdev->vcram_base);
79
/* size */
80
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_size);
81
resplen = 8;
82
break;
83
- case 0x00028001: /* Set power state */
84
+ case RPI_FWREQ_SET_POWER_STATE:
85
/* Assume that whatever device they asked for exists,
86
* and we'll just claim we set it to the desired state
87
*/
88
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
89
90
/* Clocks */
91
92
- case 0x00030001: /* Get clock state */
93
+ case RPI_FWREQ_GET_CLOCK_STATE:
94
stl_le_phys(&s->dma_as, value + 16, 0x1);
95
resplen = 8;
96
break;
97
98
- case 0x00038001: /* Set clock state */
99
+ case RPI_FWREQ_SET_CLOCK_STATE:
100
qemu_log_mask(LOG_UNIMP,
101
"bcm2835_property: 0x%08x set clock state NYI\n",
102
tag);
103
resplen = 8;
104
break;
105
106
- case 0x00030002: /* Get clock rate */
107
- case 0x00030004: /* Get max clock rate */
108
- case 0x00030007: /* Get min clock rate */
109
+ case RPI_FWREQ_GET_CLOCK_RATE:
110
+ case RPI_FWREQ_GET_MAX_CLOCK_RATE:
111
+ case RPI_FWREQ_GET_MIN_CLOCK_RATE:
112
switch (ldl_le_phys(&s->dma_as, value + 12)) {
113
- case 1: /* EMMC */
114
+ case RPI_FIRMWARE_EMMC_CLK_ID:
115
stl_le_phys(&s->dma_as, value + 16, 50000000);
116
break;
117
- case 2: /* UART */
118
+ case RPI_FIRMWARE_UART_CLK_ID:
119
stl_le_phys(&s->dma_as, value + 16, 3000000);
120
break;
121
default:
122
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
123
resplen = 8;
124
break;
125
126
- case 0x00038002: /* Set clock rate */
127
- case 0x00038004: /* Set max clock rate */
128
- case 0x00038007: /* Set min clock rate */
129
+ case RPI_FWREQ_SET_CLOCK_RATE:
130
+ case RPI_FWREQ_SET_MAX_CLOCK_RATE:
131
+ case RPI_FWREQ_SET_MIN_CLOCK_RATE:
132
qemu_log_mask(LOG_UNIMP,
133
"bcm2835_property: 0x%08x set clock rate NYI\n",
134
tag);
135
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
136
137
/* Temperature */
138
139
- case 0x00030006: /* Get temperature */
140
+ case RPI_FWREQ_GET_TEMPERATURE:
141
stl_le_phys(&s->dma_as, value + 16, 25000);
142
resplen = 8;
143
break;
144
145
- case 0x0003000A: /* Get max temperature */
146
+ case RPI_FWREQ_GET_MAX_TEMPERATURE:
147
stl_le_phys(&s->dma_as, value + 16, 99000);
148
resplen = 8;
149
break;
150
151
/* Frame buffer */
152
153
- case 0x00040001: /* Allocate buffer */
154
+ case RPI_FWREQ_FRAMEBUFFER_ALLOCATE:
155
stl_le_phys(&s->dma_as, value + 12, fbconfig.base);
156
stl_le_phys(&s->dma_as, value + 16,
157
bcm2835_fb_get_size(&fbconfig));
158
resplen = 8;
159
break;
160
- case 0x00048001: /* Release buffer */
161
+ case RPI_FWREQ_FRAMEBUFFER_RELEASE:
162
resplen = 0;
163
break;
164
- case 0x00040002: /* Blank screen */
165
+ case RPI_FWREQ_FRAMEBUFFER_BLANK:
166
resplen = 4;
167
break;
168
- case 0x00044003: /* Test physical display width/height */
169
- case 0x00044004: /* Test virtual display width/height */
170
+ case RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT:
171
+ case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT:
172
resplen = 8;
173
break;
174
- case 0x00048003: /* Set physical display width/height */
175
+ case RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT:
176
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
177
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
178
bcm2835_fb_validate_config(&fbconfig);
179
fbconfig_updated = true;
180
/* fall through */
181
- case 0x00040003: /* Get physical display width/height */
182
+ case RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT:
183
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
184
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
185
resplen = 8;
186
break;
187
- case 0x00048004: /* Set virtual display width/height */
188
+ case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT:
189
fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
190
fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
191
bcm2835_fb_validate_config(&fbconfig);
192
fbconfig_updated = true;
193
/* fall through */
194
- case 0x00040004: /* Get virtual display width/height */
195
+ case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT:
196
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
197
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
198
resplen = 8;
199
break;
200
- case 0x00044005: /* Test depth */
201
+ case RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH:
202
resplen = 4;
203
break;
204
- case 0x00048005: /* Set depth */
205
+ case RPI_FWREQ_FRAMEBUFFER_SET_DEPTH:
206
fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12);
207
bcm2835_fb_validate_config(&fbconfig);
208
fbconfig_updated = true;
209
/* fall through */
210
- case 0x00040005: /* Get depth */
211
+ case RPI_FWREQ_FRAMEBUFFER_GET_DEPTH:
212
stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
213
resplen = 4;
214
break;
215
- case 0x00044006: /* Test pixel order */
216
+ case RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER:
217
resplen = 4;
218
break;
219
- case 0x00048006: /* Set pixel order */
220
+ case RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER:
221
fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12);
222
bcm2835_fb_validate_config(&fbconfig);
223
fbconfig_updated = true;
224
/* fall through */
225
- case 0x00040006: /* Get pixel order */
226
+ case RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER:
227
stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
228
resplen = 4;
229
break;
230
- case 0x00044007: /* Test pixel alpha */
231
+ case RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE:
232
resplen = 4;
233
break;
234
- case 0x00048007: /* Set alpha */
235
+ case RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE:
236
fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12);
237
bcm2835_fb_validate_config(&fbconfig);
238
fbconfig_updated = true;
239
/* fall through */
240
- case 0x00040007: /* Get alpha */
241
+ case RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE:
242
stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
243
resplen = 4;
244
break;
245
- case 0x00040008: /* Get pitch */
246
+ case RPI_FWREQ_FRAMEBUFFER_GET_PITCH:
247
stl_le_phys(&s->dma_as, value + 12,
248
bcm2835_fb_get_pitch(&fbconfig));
249
resplen = 4;
250
break;
251
- case 0x00044009: /* Test virtual offset */
252
+ case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET:
253
resplen = 8;
254
break;
255
- case 0x00048009: /* Set virtual offset */
256
+ case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET:
257
fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12);
258
fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16);
259
bcm2835_fb_validate_config(&fbconfig);
260
fbconfig_updated = true;
261
/* fall through */
262
- case 0x00040009: /* Get virtual offset */
263
+ case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET:
264
stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
265
stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
266
resplen = 8;
267
break;
268
- case 0x0004000a: /* Get/Test/Set overscan */
269
- case 0x0004400a:
270
- case 0x0004800a:
271
+ case RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN:
272
+ case RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN:
273
+ case RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN:
274
stl_le_phys(&s->dma_as, value + 12, 0);
275
stl_le_phys(&s->dma_as, value + 16, 0);
276
stl_le_phys(&s->dma_as, value + 20, 0);
277
stl_le_phys(&s->dma_as, value + 24, 0);
278
resplen = 16;
279
break;
280
- case 0x0004800b: /* Set palette */
281
+ case RPI_FWREQ_FRAMEBUFFER_SET_PALETTE:
282
offset = ldl_le_phys(&s->dma_as, value + 12);
283
length = ldl_le_phys(&s->dma_as, value + 16);
284
n = 0;
285
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
286
stl_le_phys(&s->dma_as, value + 12, 0);
287
resplen = 4;
288
break;
289
- case 0x00040013: /* Get number of displays */
290
+ case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
291
stl_le_phys(&s->dma_as, value + 12, 1);
292
resplen = 4;
293
break;
294
295
- case 0x00060001: /* Get DMA channels */
296
+ case RPI_FWREQ_GET_DMA_CHANNELS:
297
/* channels 2-5 */
298
stl_le_phys(&s->dma_as, value + 12, 0x003C);
299
resplen = 4;
300
break;
301
302
- case 0x00050001: /* Get command line */
303
+ case RPI_FWREQ_GET_COMMAND_LINE:
304
/*
305
* We follow the firmware behaviour: no NUL terminator is
306
* written to the buffer, and if the buffer is too short
307
--
308
2.34.1
309
310
diff view generated by jsdifflib
Deleted patch
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
1
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230612223456.33824-4-philmd@linaro.org
7
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
8
[PMD: Split from bigger patch: 4/4]
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/raspi_platform.h | 5 +++++
13
hw/misc/bcm2835_property.c | 8 +++++---
14
2 files changed, 10 insertions(+), 3 deletions(-)
15
16
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/raspi_platform.h
19
+++ b/include/hw/arm/raspi_platform.h
20
@@ -XXX,XX +XXX,XX @@
21
#define INTERRUPT_ILLEGAL_TYPE0 6
22
#define INTERRUPT_ILLEGAL_TYPE1 7
23
24
+/* Clock rates */
25
+#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
26
+#define RPI_FIRMWARE_UART_CLK_RATE 3000000
27
+#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
28
+
29
#endif
30
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/bcm2835_property.c
33
+++ b/hw/misc/bcm2835_property.c
34
@@ -XXX,XX +XXX,XX @@
35
#include "qemu/log.h"
36
#include "qemu/module.h"
37
#include "trace.h"
38
+#include "hw/arm/raspi_platform.h"
39
40
/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
41
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
43
case RPI_FWREQ_GET_MIN_CLOCK_RATE:
44
switch (ldl_le_phys(&s->dma_as, value + 12)) {
45
case RPI_FIRMWARE_EMMC_CLK_ID:
46
- stl_le_phys(&s->dma_as, value + 16, 50000000);
47
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_EMMC_CLK_RATE);
48
break;
49
case RPI_FIRMWARE_UART_CLK_ID:
50
- stl_le_phys(&s->dma_as, value + 16, 3000000);
51
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE);
52
break;
53
default:
54
- stl_le_phys(&s->dma_as, value + 16, 700000000);
55
+ stl_le_phys(&s->dma_as, value + 16,
56
+ RPI_FIRMWARE_DEFAULT_CLK_RATE);
57
break;
58
}
59
resplen = 8;
60
--
61
2.34.1
62
63
diff view generated by jsdifflib