1
The following changes since commit 003ba52a8b327180e284630b289c6ece5a3e08b9:
1
Hi; here's a target-arm pullreq. Mostly this is some decodetree
2
conversion patches from me, plus a scattering of other bug fixes.
2
3
3
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2023-02-16 11:16:39 +0000)
4
thanks
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)
4
10
5
are available in the Git repository at:
11
are available in the Git repository at:
6
12
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230216
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230619
8
14
9
for you to fetch changes up to caf01d6a435d9f4a95aeae2f9fc6cb8b889b1fb8:
15
for you to fetch changes up to 074259c0f2ac40042dce766d870318cc22f388eb:
10
16
11
tests/qtest: Restrict tpm-tis-devices-{swtpm}-test to CONFIG_TCG (2023-02-16 16:28:53 +0000)
17
hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property (2023-06-19 15:27:21 +0100)
12
18
13
----------------------------------------------------------------
19
----------------------------------------------------------------
14
target-arm queue:
20
target-arm queue:
15
* Some mostly M-profile-related code cleanups
21
* Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
16
* avocado: Retire the boot_linux.py AArch64 TCG tests
22
* Return correct result for LDG when ATA=0
17
* hw/arm/smmuv3: Add GBPA register
23
* Conversion of system insns, loads and stores to decodetree
18
* arm/virt: don't try to spell out the accelerator
24
* hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
19
* hw/arm: Attach PSPI module to NPCM7XX SoC
25
* hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
20
* Some cleanup/refactoring patches aiming towards
26
* hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
21
allowing building Arm targets without CONFIG_TCG
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
22
31
23
----------------------------------------------------------------
32
----------------------------------------------------------------
24
Alex Bennée (1):
33
Marcin Juszkiewicz (2):
25
tests/avocado: retire the Aarch64 TCG tests from boot_linux.py
34
hw/arm/Kconfig: sbsa-ref uses Bochs display
35
docs: sbsa: document board to firmware interface
26
36
27
Claudio Fontana (3):
37
Martin Kaiser (1):
28
target/arm: rename handle_semihosting to tcg_handle_semihosting
38
imx_serial: set wake bit when we receive a data byte
29
target/arm: wrap psci call with tcg_enabled
30
target/arm: wrap call to aarch64_sve_change_el in tcg_enabled()
31
39
32
Cornelia Huck (1):
40
Peter Maydell (26):
33
arm/virt: don't try to spell out the accelerator
41
target/arm: Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
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
34
67
35
Fabiano Rosas (7):
68
Sergey Kambalin (4):
36
target/arm: Move PC alignment check
69
hw/arm/raspi: Import Linux raspi definitions as 'raspberrypi-fw-defs.h'
37
target/arm: Move cpregs code out of cpu.h
70
hw/misc/bcm2835_property: Use 'raspberrypi-fw-defs.h' definitions
38
tests/avocado: Skip tests that require a missing accelerator
71
hw/misc/bcm2835_property: Replace magic frequency values by definitions
39
tests/avocado: Tag TCG tests with accel:tcg
72
hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property
40
target/arm: Use "max" as default cpu for the virt machine with KVM
41
tests/qtest: arm-cpu-features: Match tests to required accelerators
42
tests/qtest: Restrict tpm-tis-devices-{swtpm}-test to CONFIG_TCG
43
73
44
Hao Wu (3):
74
docs/system/arm/sbsa.rst | 38 +-
45
MAINTAINERS: Add myself to maintainers and remove Havard
75
include/hw/arm/raspi_platform.h | 10 +
46
hw/ssi: Add Nuvoton PSPI Module
76
include/hw/char/imx_serial.h | 1 +
47
hw/arm: Attach PSPI module to NPCM7XX SoC
77
include/hw/misc/raspberrypi-fw-defs.h | 163 ++
48
78
target/arm/tcg/a64.decode | 403 ++++
49
Jean-Philippe Brucker (2):
79
hw/char/imx_serial.c | 5 +-
50
hw/arm/smmu-common: Support 64-bit addresses
80
hw/intc/allwinner-a10-pic.c | 2 +-
51
hw/arm/smmu-common: Fix TTB1 handling
81
hw/misc/bcm2835_property.c | 112 +-
52
82
hw/sd/allwinner-sdhost.c | 2 +-
53
Mostafa Saleh (1):
83
hw/timer/nrf51_timer.c | 7 +-
54
hw/arm/smmuv3: Add GBPA register
84
target/arm/tcg/translate-a64.c | 3319 +++++++++++++++------------------
55
85
hw/arm/Kconfig | 1 +
56
Philippe Mathieu-Daudé (12):
86
12 files changed, 2157 insertions(+), 1906 deletions(-)
57
hw/intc/armv7m_nvic: Use OBJECT_DECLARE_SIMPLE_TYPE() macro
87
create mode 100644 include/hw/misc/raspberrypi-fw-defs.h
58
target/arm: Simplify arm_v7m_mmu_idx_for_secstate() for user emulation
59
target/arm: Reduce arm_v7m_mmu_idx_[all/for_secstate_and_priv]() scope
60
target/arm: Constify ID_PFR1 on user emulation
61
target/arm: Convert CPUARMState::eabi to boolean
62
target/arm: Avoid resetting CPUARMState::eabi field
63
target/arm: Restrict CPUARMState::gicv3state to sysemu
64
target/arm: Restrict CPUARMState::arm_boot_info to sysemu
65
target/arm: Restrict CPUARMState::nvic to sysemu
66
target/arm: Store CPUARMState::nvic as NVICState*
67
target/arm: Declare CPU <-> NVIC helpers in 'hw/intc/armv7m_nvic.h'
68
hw/arm: Add missing XLNX_ZYNQMP_ARM -> USB_DWC3 Kconfig dependency
69
70
MAINTAINERS | 8 +-
71
docs/system/arm/nuvoton.rst | 2 +-
72
hw/arm/smmuv3-internal.h | 7 +
73
include/hw/arm/npcm7xx.h | 2 +
74
include/hw/arm/smmu-common.h | 2 -
75
include/hw/arm/smmuv3.h | 1 +
76
include/hw/intc/armv7m_nvic.h | 128 +++++++++++++++++-
77
include/hw/ssi/npcm_pspi.h | 53 ++++++++
78
linux-user/user-internals.h | 2 +-
79
target/arm/cpregs.h | 98 ++++++++++++++
80
target/arm/cpu.h | 228 ++-------------------------------
81
target/arm/internals.h | 14 --
82
hw/arm/npcm7xx.c | 25 +++-
83
hw/arm/smmu-common.c | 4 +-
84
hw/arm/smmuv3.c | 43 ++++++-
85
hw/arm/virt.c | 10 +-
86
hw/intc/armv7m_nvic.c | 38 ++----
87
hw/ssi/npcm_pspi.c | 221 ++++++++++++++++++++++++++++++++
88
linux-user/arm/cpu_loop.c | 4 +-
89
target/arm/cpu.c | 5 +-
90
target/arm/cpu_tcg.c | 3 +
91
target/arm/helper.c | 31 +++--
92
target/arm/m_helper.c | 86 +++++++------
93
target/arm/machine.c | 18 +--
94
tests/qtest/arm-cpu-features.c | 28 ++--
95
hw/arm/Kconfig | 1 +
96
hw/ssi/meson.build | 2 +-
97
hw/ssi/trace-events | 5 +
98
tests/avocado/avocado_qemu/__init__.py | 4 +
99
tests/avocado/boot_linux.py | 48 ++-----
100
tests/avocado/boot_linux_console.py | 1 +
101
tests/avocado/machine_aarch64_virt.py | 63 ++++++++-
102
tests/avocado/reverse_debugging.py | 8 ++
103
tests/qtest/meson.build | 4 +-
104
34 files changed, 798 insertions(+), 399 deletions(-)
105
create mode 100644 include/hw/ssi/npcm_pspi.h
106
create mode 100644 hw/ssi/npcm_pspi.c
107
diff view generated by jsdifflib
1
From: Fabiano Rosas <farosas@suse.de>
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.)
2
6
3
These tests set -accel tcg, so restrict them to when TCG is present.
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.
4
10
5
Signed-off-by: Fabiano Rosas <farosas@suse.de>
11
Fix the bug by using ext8u and ext16u for the MO_8 and MO_16 data
6
Acked-by: Richard Henderson <richard.henderson@linaro.org>
12
sizes rather than ext32u.
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
13
14
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20230602155223.2040685-2-peter.maydell@linaro.org
9
---
18
---
10
tests/qtest/meson.build | 4 ++--
19
target/arm/tcg/translate-a64.c | 18 ++++++++++++++++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
20
1 file changed, 16 insertions(+), 2 deletions(-)
12
21
13
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
22
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qtest/meson.build
24
--- a/target/arm/tcg/translate-a64.c
16
+++ b/tests/qtest/meson.build
25
+++ b/target/arm/tcg/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
26
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
18
# TODO: once aarch64 TCG is fixed on ARM 32 bit host, make bios-tables-test unconditional
27
*/
19
qtests_aarch64 = \
28
fn(tcg_rt, clean_addr, tcg_rs, get_mem_index(s), mop);
20
(cpu != 'arm' and unpack_edk2_blobs ? ['bios-tables-test'] : []) + \
29
21
- (config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-test'] : []) + \
30
- if ((mop & MO_SIGN) && size != MO_64) {
22
- (config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-swtpm-test'] : []) + \
31
- tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
23
+ (config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? \
32
+ if (mop & MO_SIGN) {
24
+ ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \
33
+ switch (size) {
25
(config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \
34
+ case MO_8:
26
(config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \
35
+ tcg_gen_ext8u_i64(tcg_rt, tcg_rt);
27
['arm-cpu-features',
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
28
--
51
--
29
2.34.1
52
2.34.1
diff view generated by jsdifflib
1
From: Fabiano Rosas <farosas@suse.de>
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.
2
7
3
Now that the cortex-a15 is under CONFIG_TCG, use as default CPU for a
8
Merge the tag bits into the old Xt value, as they should be.
4
KVM-only build the 'max' cpu.
5
9
6
Note that we cannot use 'host' here because the qtests can run without
10
Cc: qemu-stable@nongnu.org
7
any other accelerator (than qtest) and 'host' depends on KVM being
11
Fixes: c15294c1e36a7dd9b25 ("target/arm: Implement LDG, STG, ST2G instructions")
8
enabled.
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
10
Signed-off-by: Fabiano Rosas <farosas@suse.de>
11
Acked-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Thomas Huth <thuth@redhat.com>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
14
---
15
hw/arm/virt.c | 4 ++++
15
target/arm/tcg/translate-a64.c | 6 +++++-
16
1 file changed, 4 insertions(+)
16
1 file changed, 5 insertions(+), 1 deletion(-)
17
17
18
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
18
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/virt.c
20
--- a/target/arm/tcg/translate-a64.c
21
+++ b/hw/arm/virt.c
21
+++ b/target/arm/tcg/translate-a64.c
22
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
22
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
23
mc->minimum_page_bits = 12;
23
if (s->ata) {
24
mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids;
24
gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
25
mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
25
} else {
26
+#ifdef CONFIG_TCG
26
+ /*
27
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
27
+ * Tag access disabled: we must check for aborts on the load
28
+#else
28
+ * load from [rn+offset], and then insert a 0 tag into rt.
29
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("max");
29
+ */
30
+#endif
30
clean_addr = clean_data_tbi(s, addr);
31
mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
31
gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
32
mc->kvm_type = virt_kvm_type;
32
- gen_address_with_allocation_tag0(tcg_rt, addr);
33
assert(!mc->get_hotplug_handler);
33
+ gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
34
}
35
} else {
36
tcg_rt = cpu_reg_sp(s, rt);
34
--
37
--
35
2.34.1
38
2.34.1
diff view generated by jsdifflib
1
From: Claudio Fontana <cfontana@suse.de>
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.
2
4
3
make it clearer from the name that this is a tcg-only function.
5
Fixes: 0a9091424d ("target/arm: Pass memop to gen_mte_check1*")
4
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Claudio Fontana <cfontana@suse.de>
6
Signed-off-by: Fabiano Rosas <farosas@suse.de>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
target/arm/helper.c | 4 ++--
10
target/arm/tcg/translate-a64.c | 2 +-
13
1 file changed, 2 insertions(+), 2 deletions(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
14
12
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
15
--- a/target/arm/tcg/translate-a64.c
18
+++ b/target/arm/helper.c
16
+++ b/target/arm/tcg/translate-a64.c
19
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
17
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
20
* trapped to the hypervisor in KVM.
18
21
*/
19
clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
22
#ifdef CONFIG_TCG
20
writeback || rn != 31,
23
-static void handle_semihosting(CPUState *cs)
21
- size, is_unpriv, memidx);
24
+static void tcg_handle_semihosting(CPUState *cs)
22
+ memop, is_unpriv, memidx);
25
{
23
26
ARMCPU *cpu = ARM_CPU(cs);
24
if (is_vector) {
27
CPUARMState *env = &cpu->env;
25
if (is_store) {
28
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_interrupt(CPUState *cs)
29
*/
30
#ifdef CONFIG_TCG
31
if (cs->exception_index == EXCP_SEMIHOST) {
32
- handle_semihosting(cs);
33
+ tcg_handle_semihosting(cs);
34
return;
35
}
36
#endif
37
--
26
--
38
2.34.1
27
2.34.1
39
28
40
29
diff view generated by jsdifflib
1
From: Fabiano Rosas <farosas@suse.de>
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.
2
4
3
This allows the test to be skipped when TCG is not present in the QEMU
5
For the disas_ldst_single_struct() and disas_ldst_multiple_struct()
4
binary.
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.
5
8
6
Signed-off-by: Fabiano Rosas <farosas@suse.de>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
tests/avocado/boot_linux_console.py | 1 +
12
target/arm/tcg/translate-a64.c | 10 ++++++----
12
tests/avocado/reverse_debugging.py | 8 ++++++++
13
1 file changed, 6 insertions(+), 4 deletions(-)
13
2 files changed, 9 insertions(+)
14
14
15
diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py
15
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/avocado/boot_linux_console.py
17
--- a/target/arm/tcg/translate-a64.c
18
+++ b/tests/avocado/boot_linux_console.py
18
+++ b/target/arm/tcg/translate-a64.c
19
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_uboot_netbsd9(self):
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
20
20
if (!fp_access_check(s)) {
21
def test_aarch64_raspi3_atf(self):
21
return;
22
"""
22
}
23
+ :avocado: tags=accel:tcg
23
+ memop = finalize_memop_asimd(s, size);
24
:avocado: tags=arch:aarch64
24
} else {
25
:avocado: tags=machine:raspi3b
25
if (size == 3 && opc == 2) {
26
:avocado: tags=cpu:cortex-a53
26
/* PRFM - prefetch */
27
diff --git a/tests/avocado/reverse_debugging.py b/tests/avocado/reverse_debugging.py
27
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
28
index XXXXXXX..XXXXXXX 100644
28
is_store = (opc == 0);
29
--- a/tests/avocado/reverse_debugging.py
29
is_signed = !is_store && extract32(opc, 1, 1);
30
+++ b/tests/avocado/reverse_debugging.py
30
is_extended = (size < 3) && extract32(opc, 0, 1);
31
@@ -XXX,XX +XXX,XX @@ def reverse_debugging(self, shift=7, args=None):
31
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
32
vm.shutdown()
32
}
33
33
34
class ReverseDebugging_X86_64(ReverseDebugging):
34
if (rn == 31) {
35
+ """
35
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
36
+ :avocado: tags=accel:tcg
36
37
+ """
37
tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
38
+
38
39
REG_PC = 0x10
39
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
40
REG_CS = 0x12
40
clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, memop);
41
def get_pc(self, g):
41
42
@@ -XXX,XX +XXX,XX @@ def test_x86_64_pc(self):
42
if (is_vector) {
43
self.reverse_debugging()
43
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
44
44
if (!fp_access_check(s)) {
45
class ReverseDebugging_AArch64(ReverseDebugging):
45
return;
46
+ """
46
}
47
+ :avocado: tags=accel:tcg
47
+ memop = finalize_memop_asimd(s, size);
48
+ """
48
} else {
49
+
49
if (size == 3 && opc == 2) {
50
REG_PC = 32
50
/* PRFM - prefetch */
51
51
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
52
# unidentified gitlab timeout problem
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);
53
--
85
--
54
2.34.1
86
2.34.1
55
56
diff view generated by jsdifflib
1
From: Claudio Fontana <cfontana@suse.de>
1
Convert the various instructions in the hint instruction space
2
to decodetree.
2
3
3
Signed-off-by: Claudio Fontana <cfontana@suse.de>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Fabiano Rosas <farosas@suse.de>
6
Message-id: 20230602155223.2040685-3-peter.maydell@linaro.org
6
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
7
---
9
target/arm/helper.c | 12 +++++++-----
8
target/arm/tcg/a64.decode | 31 ++++
10
1 file changed, 7 insertions(+), 5 deletions(-)
9
target/arm/tcg/translate-a64.c | 277 ++++++++++++++++++---------------
10
2 files changed, 185 insertions(+), 123 deletions(-)
11
11
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/helper.c
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
16
@@ -XXX,XX +XXX,XX @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
17
unsigned int cur_el = arm_current_el(env);
17
# the processor is in halting debug state (which we don't implement).
18
int rt;
18
# The pattern is listed here as documentation.
19
19
# DRPS 1101011 0101 11111 000000 11111 00000
20
- /*
20
+
21
- * Note that new_el can never be 0. If cur_el is 0, then
21
+# Hint instruction group
22
- * el0_a64 is is_a64(), else el0_a64 is ignored.
22
+{
23
- */
23
+ [
24
- aarch64_sve_change_el(env, cur_el, new_el, is_a64(env));
24
+ YIELD 1101 0101 0000 0011 0010 0000 001 11111
25
+ if (tcg_enabled()) {
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)) {
26
+ /*
160
+ /*
27
+ * Note that new_el can never be 0. If cur_el is 0, then
161
+ * QEMU does not have a source of physical SErrors,
28
+ * el0_a64 is is_a64(), else el0_a64 is ignored.
162
+ * so we are only concerned with virtual SErrors.
29
+ */
163
+ * The pseudocode in the ARM for this case is
30
+ aarch64_sve_change_el(env, cur_el, new_el, is_a64(env));
164
+ * if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
31
+ }
165
+ * AArch64.vESBOperation();
32
166
+ * Most of the condition can be evaluated at translation time.
33
if (cur_el < new_el) {
167
+ * Test for EL2 present, and defer test for SEL2 to runtime.
34
/*
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;
35
--
353
--
36
2.34.1
354
2.34.1
37
38
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Convert the insns in the "Barriers" instruction class to
2
decodetree: CLREX, DSB, DMB, ISB and SB.
2
3
3
The two TCG tests for GICv2 and GICv3 are very heavy weight distros
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
that take a long time to boot up, especially for an --enable-debug
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
build. The total code coverage they give is:
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(-)
6
12
7
Overall coverage rate:
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
8
lines......: 11.2% (59584 of 530123 lines)
9
functions..: 15.0% (7436 of 49443 functions)
10
branches...: 6.3% (19273 of 303933 branches)
11
12
We already get pretty close to that with the machine_aarch64_virt
13
tests which only does one full boot (~120s vs ~600s) of alpine. We
14
expand the kernel+initrd boot (~8s) to test both GICs and also add an
15
RNG device and a block device to generate a few IRQs and exercise the
16
storage layer. With that we get to a coverage of:
17
18
Overall coverage rate:
19
lines......: 11.0% (58121 of 530123 lines)
20
functions..: 14.9% (7343 of 49443 functions)
21
branches...: 6.0% (18269 of 303933 branches)
22
23
which I feel is close enough given the massive time saving. If we want
24
to target any more sub-systems we can use lighter weight more directed
25
tests.
26
27
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
28
Reviewed-by: Fabiano Rosas <farosas@suse.de>
29
Acked-by: Richard Henderson <richard.henderson@linaro.org>
30
Message-id: 20230203181632.2919715-1-alex.bennee@linaro.org
31
Cc: Peter Maydell <peter.maydell@linaro.org>
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
---
34
tests/avocado/boot_linux.py | 48 ++++----------------
35
tests/avocado/machine_aarch64_virt.py | 63 ++++++++++++++++++++++++---
36
2 files changed, 65 insertions(+), 46 deletions(-)
37
38
diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py
39
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
40
--- a/tests/avocado/boot_linux.py
15
--- a/target/arm/tcg/a64.decode
41
+++ b/tests/avocado/boot_linux.py
16
+++ b/target/arm/tcg/a64.decode
42
@@ -XXX,XX +XXX,XX @@ def test_pc_q35_kvm(self):
17
@@ -XXX,XX +XXX,XX @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
43
self.launch_and_wait(set_up_ssh_connection=False)
18
# that isn't specifically allocated to an instruction must NOP
44
19
NOP 1101 0101 0000 0011 0010 ---- --- 11111
45
20
}
46
-# For Aarch64 we only boot KVM tests in CI as the TCG tests are very
21
+
47
-# heavyweight. There are lighter weight distros which we use in the
22
+# Barriers
48
-# machine_aarch64_virt.py tests.
23
+
49
+# For Aarch64 we only boot KVM tests in CI as booting the current
24
+CLREX 1101 0101 0000 0011 0011 ---- 010 11111
50
+# Fedora OS in TCG tests is very heavyweight. There are lighter weight
25
+DSB_DMB 1101 0101 0000 0011 0011 domain:2 types:2 10- 11111
51
+# distros which we use in the machine_aarch64_virt.py tests.
26
+ISB 1101 0101 0000 0011 0011 ---- 110 11111
52
class BootLinuxAarch64(LinuxTest):
27
+SB 1101 0101 0000 0011 0011 0000 111 11111
53
"""
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
54
:avocado: tags=arch:aarch64
29
index XXXXXXX..XXXXXXX 100644
55
:avocado: tags=machine:virt
30
--- a/target/arm/tcg/translate-a64.c
56
- :avocado: tags=machine:gic-version=2
31
+++ b/target/arm/tcg/translate-a64.c
57
"""
32
@@ -XXX,XX +XXX,XX @@ static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
58
timeout = 720
33
return true;
59
34
}
60
- def add_common_args(self):
35
61
- self.vm.add_args('-bios',
36
-static void gen_clrex(DisasContext *s, uint32_t insn)
62
- os.path.join(BUILD_DIR, 'pc-bios',
37
+static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
63
- 'edk2-aarch64-code.fd'))
38
{
64
- self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0')
39
tcg_gen_movi_i64(cpu_exclusive_addr, -1);
65
- self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom')
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;
66
-
119
-
67
- @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
120
- default:
68
- def test_fedora_cloud_tcg_gicv2(self):
121
- do_unallocated:
69
- """
122
- unallocated_encoding(s);
70
- :avocado: tags=accel:tcg
123
- return;
71
- :avocado: tags=cpu:max
124
+static bool trans_SB(DisasContext *s, arg_SB *a)
72
- :avocado: tags=device:gicv2
125
+{
73
- """
126
+ if (!dc_isar_feature(aa64_sb, s)) {
74
- self.require_accelerator("tcg")
127
+ return false;
75
- self.vm.add_args("-accel", "tcg")
128
}
76
- self.vm.add_args("-cpu", "max,lpa2=off")
129
+ /*
77
- self.vm.add_args("-machine", "virt,gic-version=2")
130
+ * TODO: There is no speculation barrier opcode for TCG;
78
- self.add_common_args()
131
+ * MB and end the TB instead.
79
- self.launch_and_wait(set_up_ssh_connection=False)
132
+ */
80
-
133
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
81
- @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
134
+ gen_goto_tb(s, 0, 4);
82
- def test_fedora_cloud_tcg_gicv3(self):
135
+ return true;
83
- """
136
}
84
- :avocado: tags=accel:tcg
137
85
- :avocado: tags=cpu:max
138
static void gen_xaflag(void)
86
- :avocado: tags=device:gicv3
139
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
87
- """
140
return;
88
- self.require_accelerator("tcg")
141
}
89
- self.vm.add_args("-accel", "tcg")
142
switch (crn) {
90
- self.vm.add_args("-cpu", "max,lpa2=off")
143
- case 3: /* CLREX, DSB, DMB, ISB */
91
- self.vm.add_args("-machine", "virt,gic-version=3")
144
- handle_sync(s, insn, op1, op2, crm);
92
- self.add_common_args()
145
- break;
93
- self.launch_and_wait(set_up_ssh_connection=False)
146
case 4: /* MSR (immediate) */
94
-
147
handle_msr_i(s, insn, op1, op2, crm);
95
def test_virt_kvm(self):
148
break;
96
"""
97
:avocado: tags=accel:kvm
98
@@ -XXX,XX +XXX,XX @@ def test_virt_kvm(self):
99
self.require_accelerator("kvm")
100
self.vm.add_args("-accel", "kvm")
101
self.vm.add_args("-machine", "virt,gic-version=host")
102
- self.add_common_args()
103
+ self.vm.add_args('-bios',
104
+ os.path.join(BUILD_DIR, 'pc-bios',
105
+ 'edk2-aarch64-code.fd'))
106
+ self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0')
107
+ self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom')
108
self.launch_and_wait(set_up_ssh_connection=False)
109
110
111
diff --git a/tests/avocado/machine_aarch64_virt.py b/tests/avocado/machine_aarch64_virt.py
112
index XXXXXXX..XXXXXXX 100644
113
--- a/tests/avocado/machine_aarch64_virt.py
114
+++ b/tests/avocado/machine_aarch64_virt.py
115
@@ -XXX,XX +XXX,XX @@
116
117
import time
118
import os
119
+import logging
120
121
from avocado_qemu import QemuSystemTest
122
from avocado_qemu import wait_for_console_pattern
123
from avocado_qemu import exec_command
124
from avocado_qemu import BUILD_DIR
125
+from avocado.utils import process
126
+from avocado.utils.path import find_command
127
128
class Aarch64VirtMachine(QemuSystemTest):
129
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
130
@@ -XXX,XX +XXX,XX @@ def test_alpine_virt_tcg_gic_max(self):
131
self.wait_for_console_pattern('Welcome to Alpine Linux 3.16')
132
133
134
- def test_aarch64_virt(self):
135
+ def common_aarch64_virt(self, machine):
136
"""
137
- :avocado: tags=arch:aarch64
138
- :avocado: tags=machine:virt
139
- :avocado: tags=accel:tcg
140
- :avocado: tags=cpu:max
141
+ Common code to launch basic virt machine with kernel+initrd
142
+ and a scratch disk.
143
"""
144
+ logger = logging.getLogger('aarch64_virt')
145
+
146
kernel_url = ('https://fileserver.linaro.org/s/'
147
'z6B2ARM7DQT3HWN/download')
148
-
149
kernel_hash = 'ed11daab50c151dde0e1e9c9cb8b2d9bd3215347'
150
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
151
152
@@ -XXX,XX +XXX,XX @@ def test_aarch64_virt(self):
153
'console=ttyAMA0')
154
self.require_accelerator("tcg")
155
self.vm.add_args('-cpu', 'max,pauth-impdef=on',
156
+ '-machine', machine,
157
'-accel', 'tcg',
158
'-kernel', kernel_path,
159
'-append', kernel_command_line)
160
+
161
+ # A RNG offers an easy way to generate a few IRQs
162
+ self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0')
163
+ self.vm.add_args('-object',
164
+ 'rng-random,id=rng0,filename=/dev/urandom')
165
+
166
+ # Also add a scratch block device
167
+ logger.info('creating scratch qcow2 image')
168
+ image_path = os.path.join(self.workdir, 'scratch.qcow2')
169
+ qemu_img = os.path.join(BUILD_DIR, 'qemu-img')
170
+ if not os.path.exists(qemu_img):
171
+ qemu_img = find_command('qemu-img', False)
172
+ if qemu_img is False:
173
+ self.cancel('Could not find "qemu-img", which is required to '
174
+ 'create the temporary qcow2 image')
175
+ cmd = '%s create -f qcow2 %s 8M' % (qemu_img, image_path)
176
+ process.run(cmd)
177
+
178
+ # Add the device
179
+ self.vm.add_args('-blockdev',
180
+ f"driver=qcow2,file.driver=file,file.filename={image_path},node-name=scratch")
181
+ self.vm.add_args('-device',
182
+ 'virtio-blk-device,drive=scratch')
183
+
184
self.vm.launch()
185
self.wait_for_console_pattern('Welcome to Buildroot')
186
time.sleep(0.1)
187
exec_command(self, 'root')
188
time.sleep(0.1)
189
+ exec_command(self, 'dd if=/dev/hwrng of=/dev/vda bs=512 count=4')
190
+ time.sleep(0.1)
191
+ exec_command(self, 'md5sum /dev/vda')
192
+ time.sleep(0.1)
193
+ exec_command(self, 'cat /proc/interrupts')
194
+ time.sleep(0.1)
195
exec_command(self, 'cat /proc/self/maps')
196
time.sleep(0.1)
197
+
198
+ def test_aarch64_virt_gicv3(self):
199
+ """
200
+ :avocado: tags=arch:aarch64
201
+ :avocado: tags=machine:virt
202
+ :avocado: tags=accel:tcg
203
+ :avocado: tags=cpu:max
204
+ """
205
+ self.common_aarch64_virt("virt,gic_version=3")
206
+
207
+ def test_aarch64_virt_gicv2(self):
208
+ """
209
+ :avocado: tags=arch:aarch64
210
+ :avocado: tags=machine:virt
211
+ :avocado: tags=accel:tcg
212
+ :avocado: tags=cpu:max
213
+ """
214
+ self.common_aarch64_virt("virt,gic-version=2")
215
--
149
--
216
2.34.1
150
2.34.1
217
151
218
152
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
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).
2
5
3
Signed-off-by: Hao Wu <wuhaotsh@google.com>
4
Reviewed-by: Titus Rwantare <titusr@google.com>
5
Reviewed-by: Philippe Mathieu-Daude <philmd@linaro.org>
6
Message-id: 20230208235433.3989937-4-wuhaotsh@google.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
8
---
9
---
9
docs/system/arm/nuvoton.rst | 2 +-
10
target/arm/tcg/a64.decode | 6 ++++
10
include/hw/arm/npcm7xx.h | 2 ++
11
target/arm/tcg/translate-a64.c | 53 +++++++++++++++++-----------------
11
hw/arm/npcm7xx.c | 25 +++++++++++++++++++++++--
12
2 files changed, 32 insertions(+), 27 deletions(-)
12
3 files changed, 26 insertions(+), 3 deletions(-)
13
13
14
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
14
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/nuvoton.rst
16
--- a/target/arm/tcg/a64.decode
17
+++ b/docs/system/arm/nuvoton.rst
17
+++ b/target/arm/tcg/a64.decode
18
@@ -XXX,XX +XXX,XX @@ Supported devices
18
@@ -XXX,XX +XXX,XX @@ CLREX 1101 0101 0000 0011 0011 ---- 010 11111
19
* SMBus controller (SMBF)
19
DSB_DMB 1101 0101 0000 0011 0011 domain:2 types:2 10- 11111
20
* Ethernet controller (EMC)
20
ISB 1101 0101 0000 0011 0011 ---- 110 11111
21
* Tachometer
21
SB 1101 0101 0000 0011 0011 0000 111 11111
22
+ * Peripheral SPI controller (PSPI)
22
+
23
23
+# PSTATE
24
Missing devices
24
+
25
---------------
25
+CFINV 1101 0101 0000 0 000 0100 0000 000 11111
26
@@ -XXX,XX +XXX,XX @@ Missing devices
26
+XAFLAG 1101 0101 0000 0 000 0100 0000 001 11111
27
27
+AXFLAG 1101 0101 0000 0 000 0100 0000 010 11111
28
* Ethernet controller (GMAC)
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
29
* USB device (USBD)
30
- * Peripheral SPI controller (PSPI)
31
* SD/MMC host
32
* PECI interface
33
* PCI and PCIe root complex and bridges
34
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
35
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/npcm7xx.h
30
--- a/target/arm/tcg/translate-a64.c
37
+++ b/include/hw/arm/npcm7xx.h
31
+++ b/target/arm/tcg/translate-a64.c
38
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@ static bool trans_SB(DisasContext *s, arg_SB *a)
39
#include "hw/nvram/npcm7xx_otp.h"
33
return true;
40
#include "hw/timer/npcm7xx_timer.h"
34
}
41
#include "hw/ssi/npcm7xx_fiu.h"
35
42
+#include "hw/ssi/npcm_pspi.h"
36
-static void gen_xaflag(void)
43
#include "hw/usb/hcd-ehci.h"
37
+static bool trans_CFINV(DisasContext *s, arg_CFINV *a)
44
#include "hw/usb/hcd-ohci.h"
38
{
45
#include "target/arm/cpu.h"
39
- TCGv_i32 z = tcg_temp_new_i32();
46
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxState {
40
+ if (!dc_isar_feature(aa64_condm_4, s)) {
47
NPCM7xxFIUState fiu[2];
41
+ return false;
48
NPCM7xxEMCState emc[2];
42
+ }
49
NPCM7xxSDHCIState mmc;
43
+ tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
50
+ NPCMPSPIState pspi[2];
44
+ return true;
51
};
45
+}
52
53
#define TYPE_NPCM7XX "npcm7xx"
54
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/npcm7xx.c
57
+++ b/hw/arm/npcm7xx.c
58
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
59
NPCM7XX_EMC1RX_IRQ = 15,
60
NPCM7XX_EMC1TX_IRQ,
61
NPCM7XX_MMC_IRQ = 26,
62
+ NPCM7XX_PSPI2_IRQ = 28,
63
+ NPCM7XX_PSPI1_IRQ = 31,
64
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
65
NPCM7XX_TIMER1_IRQ,
66
NPCM7XX_TIMER2_IRQ,
67
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_emc_addr[] = {
68
0xf0826000,
69
};
70
71
+/* Register base address for each PSPI Module */
72
+static const hwaddr npcm7xx_pspi_addr[] = {
73
+ 0xf0200000,
74
+ 0xf0201000,
75
+};
76
+
46
+
77
static const struct {
47
+static bool trans_XAFLAG(DisasContext *s, arg_XAFLAG *a)
78
hwaddr regs_addr;
48
+{
79
uint32_t unconnected_pins;
49
+ TCGv_i32 z;
80
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
50
+
81
object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
51
+ if (!dc_isar_feature(aa64_condm_5, s)) {
82
}
52
+ return false;
83
84
+ for (i = 0; i < ARRAY_SIZE(s->pspi); i++) {
85
+ object_initialize_child(obj, "pspi[*]", &s->pspi[i], TYPE_NPCM_PSPI);
86
+ }
53
+ }
87
+
54
+
88
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
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;
89
}
65
}
90
66
91
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
67
-static void gen_axflag(void)
92
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0,
68
+static bool trans_AXFLAG(DisasContext *s, arg_AXFLAG *a)
93
npcm7xx_irq(s, NPCM7XX_MMC_IRQ));
69
{
94
70
+ if (!dc_isar_feature(aa64_condm_5, s)) {
95
+ /* PSPI */
71
+ return false;
96
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pspi_addr) != ARRAY_SIZE(s->pspi));
97
+ for (i = 0; i < ARRAY_SIZE(s->pspi); i++) {
98
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pspi[i]);
99
+ int irq = (i == 0) ? NPCM7XX_PSPI1_IRQ : NPCM7XX_PSPI2_IRQ;
100
+
101
+ sysbus_realize(sbd, &error_abort);
102
+ sysbus_mmio_map(sbd, 0, npcm7xx_pspi_addr[i]);
103
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
104
+ }
72
+ }
105
+
73
+
106
create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
74
tcg_gen_sari_i32(cpu_VF, cpu_VF, 31); /* V ? -1 : 0 */
107
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
75
tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF); /* C & !V */
108
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
76
109
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
77
@@ -XXX,XX +XXX,XX @@ static void gen_axflag(void)
110
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
78
111
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
79
tcg_gen_movi_i32(cpu_NF, 0);
112
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
80
tcg_gen_movi_i32(cpu_VF, 0);
113
- create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
81
+
114
- create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
82
+ return true;
115
create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
83
}
116
create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
84
117
create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
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;
118
--
117
--
119
2.34.1
118
2.34.1
diff view generated by jsdifflib
New 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.
1
4
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
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Convert MSR (reg), MRS, SYS, SYSL to decodetree. For QEMU these are
2
all essentially the same instruction (system register access).
2
3
3
There is no point in using a void pointer to access the NVIC.
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Use the real type to avoid casting it while debugging.
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
---
9
target/arm/tcg/a64.decode | 8 ++++++++
10
target/arm/tcg/translate-a64.c | 32 +++++---------------------------
11
2 files changed, 13 insertions(+), 27 deletions(-)
5
12
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230206223502.25122-11-philmd@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/cpu.h | 46 ++++++++++++++++++++++---------------------
12
hw/intc/armv7m_nvic.c | 38 ++++++++++++-----------------------
13
target/arm/cpu.c | 1 +
14
target/arm/m_helper.c | 2 +-
15
4 files changed, 39 insertions(+), 48 deletions(-)
16
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
15
--- a/target/arm/tcg/a64.decode
20
+++ b/target/arm/cpu.h
16
+++ b/target/arm/tcg/a64.decode
21
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMTBFlags {
17
@@ -XXX,XX +XXX,XX @@ MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
22
18
MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
23
typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
19
MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
24
20
MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
25
+typedef struct NVICState NVICState;
26
+
21
+
27
typedef struct CPUArchState {
22
+# MRS, MSR (register), SYS, SYSL. These are all essentially the
28
/* Regs for current mode. */
23
+# same instruction as far as QEMU is concerned.
29
uint32_t regs[16];
24
+# NB: op0 is bits [20:19], but op0=0b00 is other insns, so we have
30
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
25
+# to hand-decode it.
31
} sau;
26
+SYS 1101 0101 00 l:1 01 op1:3 crn:4 crm:4 op2:3 rt:5 op0=1
32
27
+SYS 1101 0101 00 l:1 10 op1:3 crn:4 crm:4 op2:3 rt:5 op0=2
33
#if !defined(CONFIG_USER_ONLY)
28
+SYS 1101 0101 00 l:1 11 op1:3 crn:4 crm:4 op2:3 rt:5 op0=3
34
- void *nvic;
29
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
35
+ NVICState *nvic;
30
index XXXXXXX..XXXXXXX 100644
36
const struct arm_boot_info *boot_info;
31
--- a/target/arm/tcg/translate-a64.c
37
/* Store GICv3CPUState to access from this struct */
32
+++ b/target/arm/tcg/translate-a64.c
38
void *gicv3state;
33
@@ -XXX,XX +XXX,XX @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
39
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
34
* These are all essentially the same insn in 'read' and 'write'
40
35
* versions, with varying op0 fields.
41
/* Interface between CPU and Interrupt controller. */
36
*/
42
#ifndef CONFIG_USER_ONLY
37
-static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
43
-bool armv7m_nvic_can_take_pending_exception(void *opaque);
38
+static void handle_sys(DisasContext *s, bool isread,
44
+bool armv7m_nvic_can_take_pending_exception(NVICState *s);
39
unsigned int op0, unsigned int op1, unsigned int op2,
45
#else
40
unsigned int crn, unsigned int crm, unsigned int rt)
46
-static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
47
+static inline bool armv7m_nvic_can_take_pending_exception(NVICState *s)
48
{
41
{
49
return true;
42
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
50
}
51
#endif
52
/**
53
* armv7m_nvic_set_pending: mark the specified exception as pending
54
- * @opaque: the NVIC
55
+ * @s: the NVIC
56
* @irq: the exception number to mark pending
57
* @secure: false for non-banked exceptions or for the nonsecure
58
* version of a banked exception, true for the secure version of a banked
59
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
60
* if @secure is true and @irq does not specify one of the fixed set
61
* of architecturally banked exceptions.
62
*/
63
-void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
64
+void armv7m_nvic_set_pending(NVICState *s, int irq, bool secure);
65
/**
66
* armv7m_nvic_set_pending_derived: mark this derived exception as pending
67
- * @opaque: the NVIC
68
+ * @s: the NVIC
69
* @irq: the exception number to mark pending
70
* @secure: false for non-banked exceptions or for the nonsecure
71
* version of a banked exception, true for the secure version of a banked
72
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
73
* exceptions (exceptions generated in the course of trying to take
74
* a different exception).
75
*/
76
-void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
77
+void armv7m_nvic_set_pending_derived(NVICState *s, int irq, bool secure);
78
/**
79
* armv7m_nvic_set_pending_lazyfp: mark this lazy FP exception as pending
80
- * @opaque: the NVIC
81
+ * @s: the NVIC
82
* @irq: the exception number to mark pending
83
* @secure: false for non-banked exceptions or for the nonsecure
84
* version of a banked exception, true for the secure version of a banked
85
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
86
* Similar to armv7m_nvic_set_pending(), but specifically for exceptions
87
* generated in the course of lazy stacking of FP registers.
88
*/
89
-void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure);
90
+void armv7m_nvic_set_pending_lazyfp(NVICState *s, int irq, bool secure);
91
/**
92
* armv7m_nvic_get_pending_irq_info: return highest priority pending
93
* exception, and whether it targets Secure state
94
- * @opaque: the NVIC
95
+ * @s: the NVIC
96
* @pirq: set to pending exception number
97
* @ptargets_secure: set to whether pending exception targets Secure
98
*
99
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure);
100
* to true if the current highest priority pending exception should
101
* be taken to Secure state, false for NS.
102
*/
103
-void armv7m_nvic_get_pending_irq_info(void *opaque, int *pirq,
104
+void armv7m_nvic_get_pending_irq_info(NVICState *s, int *pirq,
105
bool *ptargets_secure);
106
/**
107
* armv7m_nvic_acknowledge_irq: make highest priority pending exception active
108
- * @opaque: the NVIC
109
+ * @s: the NVIC
110
*
111
* Move the current highest priority pending exception from the pending
112
* state to the active state, and update v7m.exception to indicate that
113
* it is the exception currently being handled.
114
*/
115
-void armv7m_nvic_acknowledge_irq(void *opaque);
116
+void armv7m_nvic_acknowledge_irq(NVICState *s);
117
/**
118
* armv7m_nvic_complete_irq: complete specified interrupt or exception
119
- * @opaque: the NVIC
120
+ * @s: the NVIC
121
* @irq: the exception number to complete
122
* @secure: true if this exception was secure
123
*
124
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque);
125
* 0 if there is still an irq active after this one was completed
126
* (Ignoring -1, this is the same as the RETTOBASE value before completion.)
127
*/
128
-int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure);
129
+int armv7m_nvic_complete_irq(NVICState *s, int irq, bool secure);
130
/**
131
* armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
132
- * @opaque: the NVIC
133
+ * @s: the NVIC
134
* @irq: the exception number to mark pending
135
* @secure: false for non-banked exceptions or for the nonsecure
136
* version of a banked exception, true for the secure version of a banked
137
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure);
138
* interrupt the current execution priority. This controls whether the
139
* RDY bit for it in the FPCCR is set.
140
*/
141
-bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure);
142
+bool armv7m_nvic_get_ready_status(NVICState *s, int irq, bool secure);
143
/**
144
* armv7m_nvic_raw_execution_priority: return the raw execution priority
145
- * @opaque: the NVIC
146
+ * @s: the NVIC
147
*
148
* Returns: the raw execution priority as defined by the v8M architecture.
149
* This is the execution priority minus the effects of AIRCR.PRIS,
150
* and minus any PRIMASK/FAULTMASK/BASEPRI priority boosting.
151
* (v8M ARM ARM I_PKLD.)
152
*/
153
-int armv7m_nvic_raw_execution_priority(void *opaque);
154
+int armv7m_nvic_raw_execution_priority(NVICState *s);
155
/**
156
* armv7m_nvic_neg_prio_requested: return true if the requested execution
157
* priority is negative for the specified security state.
158
- * @opaque: the NVIC
159
+ * @s: the NVIC
160
* @secure: the security state to test
161
* This corresponds to the pseudocode IsReqExecPriNeg().
162
*/
163
#ifndef CONFIG_USER_ONLY
164
-bool armv7m_nvic_neg_prio_requested(void *opaque, bool secure);
165
+bool armv7m_nvic_neg_prio_requested(NVICState *s, bool secure);
166
#else
167
-static inline bool armv7m_nvic_neg_prio_requested(void *opaque, bool secure)
168
+static inline bool armv7m_nvic_neg_prio_requested(NVICState *s, bool secure)
169
{
170
return false;
171
}
172
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/hw/intc/armv7m_nvic.c
175
+++ b/hw/intc/armv7m_nvic.c
176
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
177
return MIN(running, s->exception_prio);
178
}
179
180
-bool armv7m_nvic_neg_prio_requested(void *opaque, bool secure)
181
+bool armv7m_nvic_neg_prio_requested(NVICState *s, bool secure)
182
{
183
/* Return true if the requested execution priority is negative
184
* for the specified security state, ie that security state
185
@@ -XXX,XX +XXX,XX @@ bool armv7m_nvic_neg_prio_requested(void *opaque, bool secure)
186
* mean we don't allow FAULTMASK_NS to actually make the execution
187
* priority negative). Compare pseudocode IsReqExcPriNeg().
188
*/
189
- NVICState *s = opaque;
190
-
191
if (s->cpu->env.v7m.faultmask[secure]) {
192
return true;
193
}
194
@@ -XXX,XX +XXX,XX @@ bool armv7m_nvic_neg_prio_requested(void *opaque, bool secure)
195
return false;
196
}
197
198
-bool armv7m_nvic_can_take_pending_exception(void *opaque)
199
+bool armv7m_nvic_can_take_pending_exception(NVICState *s)
200
{
201
- NVICState *s = opaque;
202
-
203
return nvic_exec_prio(s) > nvic_pending_prio(s);
204
}
205
206
-int armv7m_nvic_raw_execution_priority(void *opaque)
207
+int armv7m_nvic_raw_execution_priority(NVICState *s)
208
{
209
- NVICState *s = opaque;
210
-
211
return s->exception_prio;
212
}
213
214
@@ -XXX,XX +XXX,XX @@ static void nvic_irq_update(NVICState *s)
215
* if @secure is true and @irq does not specify one of the fixed set
216
* of architecturally banked exceptions.
217
*/
218
-static void armv7m_nvic_clear_pending(void *opaque, int irq, bool secure)
219
+static void armv7m_nvic_clear_pending(NVICState *s, int irq, bool secure)
220
{
221
- NVICState *s = (NVICState *)opaque;
222
VecInfo *vec;
223
224
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
225
@@ -XXX,XX +XXX,XX @@ static void do_armv7m_nvic_set_pending(void *opaque, int irq, bool secure,
226
}
43
}
227
}
44
}
228
45
229
-void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
46
-/* System
230
+void armv7m_nvic_set_pending(NVICState *s, int irq, bool secure)
47
- * 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
48
- * +---------------------+---+-----+-----+-------+-------+-----+------+
49
- * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 | CRn | CRm | op2 | Rt |
50
- * +---------------------+---+-----+-----+-------+-------+-----+------+
51
- */
52
-static void disas_system(DisasContext *s, uint32_t insn)
53
+static bool trans_SYS(DisasContext *s, arg_SYS *a)
231
{
54
{
232
- do_armv7m_nvic_set_pending(opaque, irq, secure, false);
55
- unsigned int l, op0, op1, crn, crm, op2, rt;
233
+ do_armv7m_nvic_set_pending(s, irq, secure, false);
56
- l = extract32(insn, 21, 1);
57
- op0 = extract32(insn, 19, 2);
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;
234
}
71
}
235
72
236
-void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
73
/* Exception generation
237
+void armv7m_nvic_set_pending_derived(NVICState *s, int irq, bool secure)
74
@@ -XXX,XX +XXX,XX @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
238
{
75
switch (extract32(insn, 25, 7)) {
239
- do_armv7m_nvic_set_pending(opaque, irq, secure, true);
76
case 0x6a: /* Exception generation / System */
240
+ do_armv7m_nvic_set_pending(s, irq, secure, true);
77
if (insn & (1 << 24)) {
241
}
78
- if (extract32(insn, 22, 2) == 0) {
242
79
- disas_system(s, insn);
243
-void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure)
80
- } else {
244
+void armv7m_nvic_set_pending_lazyfp(NVICState *s, int irq, bool secure)
81
- unallocated_encoding(s);
245
{
82
- }
246
/*
83
+ unallocated_encoding(s);
247
* Pend an exception during lazy FP stacking. This differs
84
} else {
248
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure)
85
disas_exc(s, insn);
249
* whether we should escalate depends on the saved context
86
}
250
* in the FPCCR register, not on the current state of the CPU/NVIC.
251
*/
252
- NVICState *s = (NVICState *)opaque;
253
bool banked = exc_is_banked(irq);
254
VecInfo *vec;
255
bool targets_secure;
256
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure)
257
}
258
259
/* Make pending IRQ active. */
260
-void armv7m_nvic_acknowledge_irq(void *opaque)
261
+void armv7m_nvic_acknowledge_irq(NVICState *s)
262
{
263
- NVICState *s = (NVICState *)opaque;
264
CPUARMState *env = &s->cpu->env;
265
const int pending = s->vectpending;
266
const int running = nvic_exec_prio(s);
267
@@ -XXX,XX +XXX,XX @@ static bool vectpending_targets_secure(NVICState *s)
268
exc_targets_secure(s, s->vectpending);
269
}
270
271
-void armv7m_nvic_get_pending_irq_info(void *opaque,
272
+void armv7m_nvic_get_pending_irq_info(NVICState *s,
273
int *pirq, bool *ptargets_secure)
274
{
275
- NVICState *s = (NVICState *)opaque;
276
const int pending = s->vectpending;
277
bool targets_secure;
278
279
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_get_pending_irq_info(void *opaque,
280
*pirq = pending;
281
}
282
283
-int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
284
+int armv7m_nvic_complete_irq(NVICState *s, int irq, bool secure)
285
{
286
- NVICState *s = (NVICState *)opaque;
287
VecInfo *vec = NULL;
288
int ret = 0;
289
290
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
291
return ret;
292
}
293
294
-bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
295
+bool armv7m_nvic_get_ready_status(NVICState *s, int irq, bool secure)
296
{
297
/*
298
* Return whether an exception is "ready", i.e. it is enabled and is
299
@@ -XXX,XX +XXX,XX @@ bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
300
* for non-banked exceptions secure is always false; for banked exceptions
301
* it indicates which of the exceptions is required.
302
*/
303
- NVICState *s = (NVICState *)opaque;
304
bool banked = exc_is_banked(irq);
305
VecInfo *vec;
306
int running = nvic_exec_prio(s);
307
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
308
index XXXXXXX..XXXXXXX 100644
309
--- a/target/arm/cpu.c
310
+++ b/target/arm/cpu.c
311
@@ -XXX,XX +XXX,XX @@
312
#if !defined(CONFIG_USER_ONLY)
313
#include "hw/loader.h"
314
#include "hw/boards.h"
315
+#include "hw/intc/armv7m_nvic.h"
316
#endif
317
#include "sysemu/tcg.h"
318
#include "sysemu/qtest.h"
319
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
320
index XXXXXXX..XXXXXXX 100644
321
--- a/target/arm/m_helper.c
322
+++ b/target/arm/m_helper.c
323
@@ -XXX,XX +XXX,XX @@ static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
324
* that we will need later in order to do lazy FP reg stacking.
325
*/
326
bool is_secure = env->v7m.secure;
327
- void *nvic = env->nvic;
328
+ NVICState *nvic = env->nvic;
329
/*
330
* Some bits are unbanked and live always in fpccr[M_REG_S]; some bits
331
* are banked and we want to update the bit in the bank for the
332
--
87
--
333
2.34.1
88
2.34.1
334
89
335
90
diff view generated by jsdifflib
New patch
1
Convert the exception generation instructions SVC, HVC, SMC, BRK and
2
HLT to decodetree.
1
3
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
1
From: Fabiano Rosas <farosas@suse.de>
1
Convert the instructions in the load/store exclusive (STXR,
2
2
STLXR, LDXR, LDAXR) and load/store ordered (STLR, STLLR,
3
Signed-off-by: Fabiano Rosas <farosas@suse.de>
3
LDAR, LDLAR) to decodetree.
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
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Acked-by: Thomas Huth <thuth@redhat.com>
18
Message-id: 20230602155223.2040685-9-peter.maydell@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
19
---
8
tests/qtest/arm-cpu-features.c | 28 ++++++++++++++++++----------
20
target/arm/tcg/a64.decode | 11 +++
9
1 file changed, 18 insertions(+), 10 deletions(-)
21
target/arm/tcg/translate-a64.c | 154 ++++++++++++++++++++-------------
10
22
2 files changed, 103 insertions(+), 62 deletions(-)
11
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
23
24
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
12
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qtest/arm-cpu-features.c
26
--- a/target/arm/tcg/a64.decode
14
+++ b/tests/qtest/arm-cpu-features.c
27
+++ b/target/arm/tcg/a64.decode
15
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ HLT 1101 0100 010 ................ 000 00 @i16
16
#define SVE_MAX_VQ 16
29
# DCPS1 1101 0100 101 ................ 000 01 @i16
17
30
# DCPS2 1101 0100 101 ................ 000 10 @i16
18
#define MACHINE "-machine virt,gic-version=max -accel tcg "
31
# DCPS3 1101 0100 101 ................ 000 11 @i16
19
-#define MACHINE_KVM "-machine virt,gic-version=max -accel kvm -accel tcg "
32
+
20
+#define MACHINE_KVM "-machine virt,gic-version=max -accel kvm "
33
+# Loads and stores
21
#define QUERY_HEAD "{ 'execute': 'query-cpu-model-expansion', " \
34
+
22
" 'arguments': { 'type': 'full', "
35
+&stxr rn rt rt2 rs sz lasr
23
#define QUERY_TAIL "}}"
36
+&stlr rn rt sz lasr
24
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
37
+@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
25
{
38
+@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
26
g_test_init(&argc, &argv, NULL);
39
+STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
27
40
+LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
28
- qtest_add_data_func("/arm/query-cpu-model-expansion",
41
+STLR .. 001000 100 11111 . 11111 ..... ..... @stlr # inc STLLR
29
- NULL, test_query_cpu_model_expansion);
42
+LDAR .. 001000 110 11111 . 11111 ..... ..... @stlr # inc LDLAR
30
+ if (qtest_has_accel("tcg")) {
43
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
31
+ qtest_add_data_func("/arm/query-cpu-model-expansion",
44
index XXXXXXX..XXXXXXX 100644
32
+ NULL, test_query_cpu_model_expansion);
45
--- a/target/arm/tcg/translate-a64.c
33
+ }
46
+++ b/target/arm/tcg/translate-a64.c
34
+
47
@@ -XXX,XX +XXX,XX @@ static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
35
+ if (!g_str_equal(qtest_get_arch(), "aarch64")) {
48
return regsize == 64;
36
+ goto out;
49
}
37
+ }
50
38
51
+static bool ldst_iss_sf(int size, bool sign, bool ext)
39
/*
52
+{
40
* For now we only run KVM specific tests with AArch64 QEMU in
53
+
41
* order avoid attempting to run an AArch32 QEMU with KVM on
54
+ if (sign) {
42
* AArch64 hosts. That won't work and isn't easy to detect.
55
+ /*
43
*/
56
+ * Signed loads are 64 bit results if we are not going to
44
- if (g_str_equal(qtest_get_arch(), "aarch64") && qtest_has_accel("kvm")) {
57
+ * do a zero-extend from 32 to 64 after the load.
45
+ if (qtest_has_accel("kvm")) {
58
+ * (For a store, sign and ext are always false.)
46
/*
59
+ */
47
* This tests target the 'host' CPU type, so register it only if
60
+ return !ext;
48
* KVM is available.
61
+ } else {
49
*/
62
+ /* Unsigned loads/stores work at the specified size */
50
qtest_add_data_func("/arm/kvm/query-cpu-model-expansion",
63
+ return size == MO_64;
51
NULL, test_query_cpu_model_expansion_kvm);
64
+ }
52
- }
65
+}
53
66
+
54
- if (g_str_equal(qtest_get_arch(), "aarch64")) {
67
+static bool trans_STXR(DisasContext *s, arg_stxr *a)
55
- qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-max-vq-8",
68
+{
56
- NULL, sve_tests_sve_max_vq_8);
69
+ if (a->rn == 31) {
57
- qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-off",
70
+ gen_check_sp_alignment(s);
58
- NULL, sve_tests_sve_off);
71
+ }
59
qtest_add_data_func("/arm/kvm/query-cpu-model-expansion/sve-off",
72
+ if (a->lasr) {
60
NULL, sve_tests_sve_off_kvm);
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;
61
}
221
}
62
222
unallocated_encoding(s);
63
+ if (qtest_has_accel("tcg")) {
64
+ qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-max-vq-8",
65
+ NULL, sve_tests_sve_max_vq_8);
66
+ qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-off",
67
+ NULL, sve_tests_sve_off);
68
+ }
69
+
70
+out:
71
return g_test_run();
72
}
223
}
73
--
224
--
74
2.34.1
225
2.34.1
diff view generated by jsdifflib
1
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
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.
2
4
3
Addresses targeting the second translation table (TTB1) in the SMMU have
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
all upper bits set (except for the top byte when TBI is enabled). Fix
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
the TTB1 check.
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(-)
6
12
7
Reported-by: Ola Hugosson <ola.hugosson@arm.com>
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
8
Reviewed-by: Eric Auger <eric.auger@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
11
Message-id: 20230214171921.1917916-3-jean-philippe@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/arm/smmu-common.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/smmu-common.c
15
--- a/target/arm/tcg/a64.decode
20
+++ b/hw/arm/smmu-common.c
16
+++ b/target/arm/tcg/a64.decode
21
@@ -XXX,XX +XXX,XX @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova)
17
@@ -XXX,XX +XXX,XX @@ HLT 1101 0100 010 ................ 000 00 @i16
22
/* there is a ttbr0 region and we are in it (high bits all zero) */
18
&stlr rn rt sz lasr
23
return &cfg->tt[0];
19
@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
24
} else if (cfg->tt[1].tsz &&
20
@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
25
- !extract64(iova, 64 - cfg->tt[1].tsz, cfg->tt[1].tsz - tbi_byte)) {
21
+%imm1_30_p2 30:1 !function=plus_2
26
+ sextract64(iova, 64 - cfg->tt[1].tsz, cfg->tt[1].tsz - tbi_byte) == -1) {
22
+@stxp .. ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=%imm1_30_p2
27
/* there is a ttbr1 region and we are in it (high bits all one) */
23
STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
28
return &cfg->tt[1];
24
LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
29
} else if (!cfg->tt[0].tsz) {
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;
30
--
177
--
31
2.34.1
178
2.34.1
diff view generated by jsdifflib
1
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
1
Convert the "Load register (literal)" instruction class to
2
decodetree.
2
3
3
Addresses targeting the second translation table (TTB1) in the SMMU have
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
all upper bits set. Ensure the IOMMU region covers all 64 bits.
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(-)
5
11
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
7
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
8
Reviewed-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20230214171921.1917916-2-jean-philippe@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/smmu-common.h | 2 --
13
hw/arm/smmu-common.c | 2 +-
14
2 files changed, 1 insertion(+), 3 deletions(-)
15
16
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/smmu-common.h
14
--- a/target/arm/tcg/a64.decode
19
+++ b/include/hw/arm/smmu-common.h
15
+++ b/target/arm/tcg/a64.decode
20
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ LDXP 1 . 001000 011 ..... . ..... ..... ..... @stxp # inc LDAXP
21
#define SMMU_PCI_DEVFN_MAX 256
17
CASP 0 . 001000 0 - 1 rs:5 - 11111 rn:5 rt:5 sz=%imm1_30_p2
22
#define SMMU_PCI_DEVFN(sid) (sid & 0xFF)
18
# CAS, CASA, CASAL, CASL
23
19
CAS sz:2 001000 1 - 1 rs:5 - 11111 rn:5 rt:5
24
-#define SMMU_MAX_VA_BITS 48
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
}
25
-
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
26
/*
121
/*
27
* Page table walk error types
122
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
28
*/
123
static void disas_ldst(DisasContext *s, uint32_t insn)
29
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
124
{
30
index XXXXXXX..XXXXXXX 100644
125
switch (extract32(insn, 24, 6)) {
31
--- a/hw/arm/smmu-common.c
126
- case 0x18: case 0x1c: /* Load register (literal) */
32
+++ b/hw/arm/smmu-common.c
127
- disas_ld_lit(s, insn);
33
@@ -XXX,XX +XXX,XX @@ static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
128
- break;
34
129
case 0x28: case 0x29:
35
memory_region_init_iommu(&sdev->iommu, sizeof(sdev->iommu),
130
case 0x2c: case 0x2d: /* Load/store pair (all forms) */
36
s->mrtypename,
131
disas_ldst_pair(s, insn);
37
- OBJECT(s), name, 1ULL << SMMU_MAX_VA_BITS);
38
+ OBJECT(s), name, UINT64_MAX);
39
address_space_init(&sdev->as,
40
MEMORY_REGION(&sdev->iommu), name);
41
trace_smmu_add_mr(name);
42
--
132
--
43
2.34.1
133
2.34.1
diff view generated by jsdifflib
1
From: Cornelia Huck <cohuck@redhat.com>
1
Convert the load/store register pair insns (LDP, STP,
2
LDNP, STNP, LDPSW, STGP) to decodetree.
2
3
3
Just use current_accel_name() directly.
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(-)
4
11
5
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
6
Reviewed-by: Eric Auger <eric.auger@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/arm/virt.c | 6 +++---
11
1 file changed, 3 insertions(+), 3 deletions(-)
12
13
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/virt.c
14
--- a/target/arm/tcg/a64.decode
16
+++ b/hw/arm/virt.c
15
+++ b/target/arm/tcg/a64.decode
17
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
16
@@ -XXX,XX +XXX,XX @@ LD_lit_v 10 011 1 00 ................... ..... @ldlit sz=4 sign=0
18
if (vms->secure && (kvm_enabled() || hvf_enabled())) {
17
19
error_report("mach-virt: %s does not support providing "
18
# PRFM
20
"Security extensions (TrustZone) to the guest CPU",
19
NOP 11 011 0 00 ------------------- -----
21
- kvm_enabled() ? "KVM" : "HVF");
20
+
22
+ current_accel_name());
21
+&ldstpair rt2 rt rn imm sz sign w p
23
exit(1);
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);
24
}
198
}
25
199
26
if (vms->virt && (kvm_enabled() || hvf_enabled())) {
200
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
27
error_report("mach-virt: %s does not support providing "
201
- if (!postindex) {
28
"Virtualization extensions to the guest CPU",
202
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
29
- kvm_enabled() ? "KVM" : "HVF");
203
+ if (!a->p) {
30
+ current_accel_name());
204
+ tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
31
exit(1);
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);
32
}
381
}
33
382
34
if (vms->mte && (kvm_enabled() || hvf_enabled())) {
383
- if (set_tag) {
35
error_report("mach-virt: %s does not support providing "
384
- if (!s->ata) {
36
"MTE to the guest CPU",
385
- /*
37
- kvm_enabled() ? "KVM" : "HVF");
386
- * TODO: We could rely on the stores below, at least for
38
+ current_accel_name());
387
- * system mode, if we arrange to add MO_ALIGN_16.
39
exit(1);
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);
40
}
494
}
41
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);
42
--
533
--
43
2.34.1
534
2.34.1
diff view generated by jsdifflib
1
From: Mostafa Saleh <smostafa@google.com>
1
Convert the load and store instructions which use a 9-bit
2
immediate offset to decodetree.
2
3
3
GBPA register can be used to globally abort all
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
transactions.
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(-)
5
11
6
It is described in the SMMU manual in "6.3.14 SMMU_GBPA".
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
7
ABORT reset value is IMPLEMENTATION DEFINED, it is chosen to
8
be zero(Do not abort incoming transactions).
9
10
Other fields have default values of Use Incoming.
11
12
If UPDATE is not set, the write is ignored. This is the only permitted
13
behavior in SMMUv3.2 and later.(6.3.14.1 Update procedure)
14
15
As this patch adds a new state to the SMMU (GBPA), it is added
16
in a new subsection for forward migration compatibility.
17
GBPA is only migrated if its value is different from the reset value.
18
It does this to be backward migration compatible if SW didn't write
19
the register.
20
21
Signed-off-by: Mostafa Saleh <smostafa@google.com>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Eric Auger <eric.auger@redhat.com>
24
Message-id: 20230214094009.2445653-1-smostafa@google.com
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
---
28
hw/arm/smmuv3-internal.h | 7 +++++++
29
include/hw/arm/smmuv3.h | 1 +
30
hw/arm/smmuv3.c | 43 +++++++++++++++++++++++++++++++++++++++-
31
3 files changed, 50 insertions(+), 1 deletion(-)
32
33
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
34
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/smmuv3-internal.h
14
--- a/target/arm/tcg/a64.decode
36
+++ b/hw/arm/smmuv3-internal.h
15
+++ b/target/arm/tcg/a64.decode
37
@@ -XXX,XX +XXX,XX @@ REG32(CR0ACK, 0x24)
16
@@ -XXX,XX +XXX,XX @@ LDP_v 10 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p
38
REG32(CR1, 0x28)
17
STGP 01 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
39
REG32(CR2, 0x2c)
18
STGP 01 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
40
REG32(STATUSR, 0x40)
19
STGP 01 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
41
+REG32(GBPA, 0x44)
20
+
42
+ FIELD(GBPA, ABORT, 20, 1)
21
+# Load/store register (unscaled immediate)
43
+ FIELD(GBPA, UPDATE, 31, 1)
22
+&ldst_imm rt rn imm sz sign w p unpriv ext
44
+
23
+@ldst_imm .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=0
45
+/* Use incoming. */
24
+@ldst_imm_pre .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=1
46
+#define SMMU_GBPA_RESET_VAL 0x1000
25
+@ldst_imm_post .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=1 w=1
47
+
26
+@ldst_imm_user .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=1 p=0 w=0
48
REG32(IRQ_CTRL, 0x50)
27
+
49
FIELD(IRQ_CTRL, GERROR_IRQEN, 0, 1)
28
+STR_i sz:2 111 0 00 00 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
50
FIELD(IRQ_CTRL, PRI_IRQEN, 1, 1)
29
+LDR_i 00 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=0
51
diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
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
52
index XXXXXXX..XXXXXXX 100644
90
index XXXXXXX..XXXXXXX 100644
53
--- a/include/hw/arm/smmuv3.h
91
--- a/target/arm/tcg/translate-a64.c
54
+++ b/include/hw/arm/smmuv3.h
92
+++ b/target/arm/tcg/translate-a64.c
55
@@ -XXX,XX +XXX,XX @@ struct SMMUv3State {
93
@@ -XXX,XX +XXX,XX @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
56
uint32_t cr[3];
94
return true;
57
uint32_t cr0ack;
58
uint32_t statusr;
59
+ uint32_t gbpa;
60
uint32_t irq_ctrl;
61
uint32_t gerror;
62
uint32_t gerrorn;
63
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/smmuv3.c
66
+++ b/hw/arm/smmuv3.c
67
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
68
s->gerror = 0;
69
s->gerrorn = 0;
70
s->statusr = 0;
71
+ s->gbpa = SMMU_GBPA_RESET_VAL;
72
}
95
}
73
96
74
static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
97
-/*
75
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
98
- * Load/store (immediate post-indexed)
76
qemu_mutex_lock(&s->mutex);
99
- * Load/store (immediate pre-indexed)
77
100
- * Load/store (unscaled immediate)
78
if (!smmu_enabled(s)) {
101
- *
79
- status = SMMU_TRANS_DISABLE;
102
- * 31 30 29 27 26 25 24 23 22 21 20 12 11 10 9 5 4 0
80
+ if (FIELD_EX32(s->gbpa, GBPA, ABORT)) {
103
- * +----+-------+---+-----+-----+---+--------+-----+------+------+
81
+ status = SMMU_TRANS_ABORT;
104
- * |size| 1 1 1 | V | 0 0 | opc | 0 | imm9 | idx | Rn | Rt |
82
+ } else {
105
- * +----+-------+---+-----+-----+---+--------+-----+------+------+
83
+ status = SMMU_TRANS_DISABLE;
106
- *
84
+ }
107
- * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
85
goto epilogue;
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);
86
}
189
}
87
190
88
@@ -XXX,XX +XXX,XX @@ static MemTxResult smmu_writel(SMMUv3State *s, hwaddr offset,
191
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
89
case A_GERROR_IRQ_CFG2:
192
- if (!post_index) {
90
s->gerror_irq_cfg2 = data;
193
- tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
91
return MEMTX_OK;
194
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
92
+ case A_GBPA:
195
+ if (!a->p) {
93
+ /*
196
+ tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
94
+ * If UPDATE is not set, the write is ignored. This is the only
197
}
95
+ * permitted behavior in SMMUv3.2 and later.
198
+ memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
96
+ */
199
+ *clean_addr = gen_mte_check1_mmuidx(s, *dirty_addr, is_store,
97
+ if (data & R_GBPA_UPDATE_MASK) {
200
+ a->w || a->rn != 31,
98
+ /* Ignore update bit as write is synchronous. */
201
+ mop, a->unpriv, memidx);
99
+ s->gbpa = data & ~R_GBPA_UPDATE_MASK;
202
+}
100
+ }
203
101
+ return MEMTX_OK;
204
- memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
102
case A_STRTAB_BASE: /* 64b */
205
-
103
s->strtab_base = deposit64(s->strtab_base, 0, 32, data);
206
- clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
104
return MEMTX_OK;
207
- writeback || rn != 31,
105
@@ -XXX,XX +XXX,XX @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset,
208
- memop, is_unpriv, memidx);
106
case A_STATUSR:
209
-
107
*data = s->statusr;
210
- if (is_vector) {
108
return MEMTX_OK;
211
- if (is_store) {
109
+ case A_GBPA:
212
- do_fp_st(s, rt, clean_addr, memop);
110
+ *data = s->gbpa;
213
- } else {
111
+ return MEMTX_OK;
214
- do_fp_ld(s, rt, clean_addr, memop);
112
case A_IRQ_CTRL:
215
- }
113
case A_IRQ_CTRL_ACK:
216
- } else {
114
*data = s->irq_ctrl;
217
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
115
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_smmuv3_queue = {
218
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
116
},
219
-
117
};
220
- if (is_store) {
118
221
- do_gpr_st_memidx(s, tcg_rt, clean_addr, memop, memidx,
119
+static bool smmuv3_gbpa_needed(void *opaque)
222
- iss_valid, rt, iss_sf, false);
120
+{
223
- } else {
121
+ SMMUv3State *s = opaque;
224
- do_gpr_ld_memidx(s, tcg_rt, clean_addr, memop,
122
+
225
- is_extended, memidx,
123
+ /* Only migrate GBPA if it has different reset value. */
226
- iss_valid, rt, iss_sf, false);
124
+ return s->gbpa != SMMU_GBPA_RESET_VAL;
227
+static void op_addr_ldst_imm_post(DisasContext *s, arg_ldst_imm *a,
125
+}
228
+ TCGv_i64 dirty_addr, uint64_t offset)
126
+
229
+{
127
+static const VMStateDescription vmstate_gbpa = {
230
+ if (a->w) {
128
+ .name = "smmuv3/gbpa",
231
+ if (a->p) {
129
+ .version_id = 1,
232
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
130
+ .minimum_version_id = 1,
233
}
131
+ .needed = smmuv3_gbpa_needed,
234
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
132
+ .fields = (VMStateField[]) {
235
}
133
+ VMSTATE_UINT32(gbpa, SMMUv3State),
236
+}
134
+ VMSTATE_END_OF_LIST()
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;
135
+ }
302
+ }
136
+};
303
+ mop = finalize_memop_asimd(s, a->sz);
137
+
304
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, false, mop);
138
static const VMStateDescription vmstate_smmuv3 = {
305
+ do_fp_ld(s, a->rt, clean_addr, mop);
139
.name = "smmuv3",
306
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
140
.version_id = 1,
307
+ return true;
141
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_smmuv3 = {
308
}
142
309
143
VMSTATE_END_OF_LIST(),
310
/*
144
},
311
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
145
+ .subsections = (const VMStateDescription * []) {
312
switch (extract32(insn, 24, 2)) {
146
+ &vmstate_gbpa,
313
case 0:
147
+ NULL
314
if (extract32(insn, 21, 1) == 0) {
148
+ }
315
- /* Load/store register (unscaled immediate)
149
};
316
- * Load/store immediate pre/post-indexed
150
317
- * Load/store register unprivileged
151
static void smmuv3_instance_init(Object *obj)
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:
152
--
325
--
153
2.34.1
326
2.34.1
diff view generated by jsdifflib
1
From: Fabiano Rosas <farosas@suse.de>
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.
2
4
3
Since commit cf7c6d1004 ("target/arm: Split out cpregs.h") we now have
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
a cpregs.h header which is more suitable for this code.
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(-)
5
12
6
Code moved verbatim.
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
7
8
Signed-off-by: Fabiano Rosas <farosas@suse.de>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/cpregs.h | 98 +++++++++++++++++++++++++++++++++++++++++++++
15
target/arm/cpu.h | 91 -----------------------------------------
16
2 files changed, 98 insertions(+), 91 deletions(-)
17
18
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpregs.h
15
--- a/target/arm/tcg/a64.decode
21
+++ b/target/arm/cpregs.h
16
+++ b/target/arm/tcg/a64.decode
22
@@ -XXX,XX +XXX,XX @@ enum {
17
@@ -XXX,XX +XXX,XX @@ STR_v_i sz:2 111 1 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0
23
ARM_CP_SME = 1 << 19,
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
24
};
52
};
25
53
26
+/*
54
+/*
27
+ * Interface for defining coprocessor registers.
55
+ * Helpers for extracting complex instruction fields
28
+ * Registers are defined in tables of arm_cp_reginfo structs
29
+ * which are passed to define_arm_cp_regs().
30
+ */
56
+ */
31
+
57
+
32
+/*
58
+/*
33
+ * When looking up a coprocessor register we look for it
59
+ * For load/store with an unsigned 12 bit immediate scaled by the element
34
+ * via an integer which encodes all of:
60
+ * size. The input has the immediate field in bits [14:3] and the element
35
+ * coprocessor number
61
+ * size in [2:0].
36
+ * Crn, Crm, opc1, opc2 fields
37
+ * 32 or 64 bit register (ie is it accessed via MRC/MCR
38
+ * or via MRRC/MCRR?)
39
+ * non-secure/secure bank (AArch32 only)
40
+ * We allow 4 bits for opc1 because MRRC/MCRR have a 4 bit field.
41
+ * (In this case crn and opc2 should be zero.)
42
+ * For AArch64, there is no 32/64 bit size distinction;
43
+ * instead all registers have a 2 bit op0, 3 bit op1 and op2,
44
+ * and 4 bit CRn and CRm. The encoding patterns are chosen
45
+ * to be easy to convert to and from the KVM encodings, and also
46
+ * so that the hashtable can contain both AArch32 and AArch64
47
+ * registers (to allow for interprocessing where we might run
48
+ * 32 bit code on a 64 bit core).
49
+ */
62
+ */
50
+/*
63
+static int uimm_scaled(DisasContext *s, int x)
51
+ * This bit is private to our hashtable cpreg; in KVM register
52
+ * IDs the AArch64/32 distinction is the KVM_REG_ARM/ARM64
53
+ * in the upper bits of the 64 bit ID.
54
+ */
55
+#define CP_REG_AA64_SHIFT 28
56
+#define CP_REG_AA64_MASK (1 << CP_REG_AA64_SHIFT)
57
+
58
+/*
59
+ * To enable banking of coprocessor registers depending on ns-bit we
60
+ * add a bit to distinguish between secure and non-secure cpregs in the
61
+ * hashtable.
62
+ */
63
+#define CP_REG_NS_SHIFT 29
64
+#define CP_REG_NS_MASK (1 << CP_REG_NS_SHIFT)
65
+
66
+#define ENCODE_CP_REG(cp, is64, ns, crn, crm, opc1, opc2) \
67
+ ((ns) << CP_REG_NS_SHIFT | ((cp) << 16) | ((is64) << 15) | \
68
+ ((crn) << 11) | ((crm) << 7) | ((opc1) << 3) | (opc2))
69
+
70
+#define ENCODE_AA64_CP_REG(cp, crn, crm, op0, op1, op2) \
71
+ (CP_REG_AA64_MASK | \
72
+ ((cp) << CP_REG_ARM_COPROC_SHIFT) | \
73
+ ((op0) << CP_REG_ARM64_SYSREG_OP0_SHIFT) | \
74
+ ((op1) << CP_REG_ARM64_SYSREG_OP1_SHIFT) | \
75
+ ((crn) << CP_REG_ARM64_SYSREG_CRN_SHIFT) | \
76
+ ((crm) << CP_REG_ARM64_SYSREG_CRM_SHIFT) | \
77
+ ((op2) << CP_REG_ARM64_SYSREG_OP2_SHIFT))
78
+
79
+/*
80
+ * Convert a full 64 bit KVM register ID to the truncated 32 bit
81
+ * version used as a key for the coprocessor register hashtable
82
+ */
83
+static inline uint32_t kvm_to_cpreg_id(uint64_t kvmid)
84
+{
64
+{
85
+ uint32_t cpregid = kvmid;
65
+ unsigned imm = x >> 3;
86
+ if ((kvmid & CP_REG_ARCH_MASK) == CP_REG_ARM64) {
66
+ unsigned scale = extract32(x, 0, 3);
87
+ cpregid |= CP_REG_AA64_MASK;
67
+ return imm << scale;
88
+ } else {
89
+ if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) {
90
+ cpregid |= (1 << 15);
91
+ }
92
+
93
+ /*
94
+ * KVM is always non-secure so add the NS flag on AArch32 register
95
+ * entries.
96
+ */
97
+ cpregid |= 1 << CP_REG_NS_SHIFT;
98
+ }
99
+ return cpregid;
100
+}
101
+
102
+/*
103
+ * Convert a truncated 32 bit hashtable key into the full
104
+ * 64 bit KVM register ID.
105
+ */
106
+static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
107
+{
108
+ uint64_t kvmid;
109
+
110
+ if (cpregid & CP_REG_AA64_MASK) {
111
+ kvmid = cpregid & ~CP_REG_AA64_MASK;
112
+ kvmid |= CP_REG_SIZE_U64 | CP_REG_ARM64;
113
+ } else {
114
+ kvmid = cpregid & ~(1 << 15);
115
+ if (cpregid & (1 << 15)) {
116
+ kvmid |= CP_REG_SIZE_U64 | CP_REG_ARM;
117
+ } else {
118
+ kvmid |= CP_REG_SIZE_U32 | CP_REG_ARM;
119
+ }
120
+ }
121
+ return kvmid;
122
+}
68
+}
123
+
69
+
124
/*
70
/*
125
* Valid values for ARMCPRegInfo state field, indicating which of
71
* Include the generated decoders.
126
* the AArch32 and AArch64 execution states this register is visible in.
72
*/
127
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
73
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
128
index XXXXXXX..XXXXXXX 100644
74
}
129
--- a/target/arm/cpu.h
75
}
130
+++ b/target/arm/cpu.h
76
131
@@ -XXX,XX +XXX,XX @@ void arm_cpu_list(void);
77
-/*
132
uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
78
- * Load/store (unsigned immediate)
133
uint32_t cur_el, bool secure);
79
- *
134
80
- * 31 30 29 27 26 25 24 23 22 21 10 9 5
135
-/* Interface for defining coprocessor registers.
81
- * +----+-------+---+-----+-----+------------+-------+------+
136
- * Registers are defined in tables of arm_cp_reginfo structs
82
- * |size| 1 1 1 | V | 0 1 | opc | imm12 | Rn | Rt |
137
- * which are passed to define_arm_cp_regs().
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
138
- */
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;
139
-
108
-
140
-/* When looking up a coprocessor register we look for it
109
- if (is_vector) {
141
- * via an integer which encodes all of:
110
- size |= (opc & 2) << 1;
142
- * coprocessor number
111
- if (size > 4) {
143
- * Crn, Crm, opc1, opc2 fields
112
- unallocated_encoding(s);
144
- * 32 or 64 bit register (ie is it accessed via MRC/MCR
113
- return;
145
- * or via MRRC/MCRR?)
114
- }
146
- * non-secure/secure bank (AArch32 only)
115
- is_store = !extract32(opc, 0, 1);
147
- * We allow 4 bits for opc1 because MRRC/MCRR have a 4 bit field.
116
- if (!fp_access_check(s)) {
148
- * (In this case crn and opc2 should be zero.)
117
- return;
149
- * For AArch64, there is no 32/64 bit size distinction;
118
- }
150
- * instead all registers have a 2 bit op0, 3 bit op1 and op2,
119
- memop = finalize_memop_asimd(s, size);
151
- * and 4 bit CRn and CRm. The encoding patterns are chosen
120
- } else {
152
- * to be easy to convert to and from the KVM encodings, and also
121
- if (size == 3 && opc == 2) {
153
- * so that the hashtable can contain both AArch32 and AArch64
122
- /* PRFM - prefetch */
154
- * registers (to allow for interprocessing where we might run
123
- return;
155
- * 32 bit code on a 64 bit core).
124
- }
156
- */
125
- if (opc == 3 && size > 1) {
157
-/* This bit is private to our hashtable cpreg; in KVM register
126
- unallocated_encoding(s);
158
- * IDs the AArch64/32 distinction is the KVM_REG_ARM/ARM64
127
- return;
159
- * in the upper bits of the 64 bit ID.
128
- }
160
- */
129
- is_store = (opc == 0);
161
-#define CP_REG_AA64_SHIFT 28
130
- is_signed = !is_store && extract32(opc, 1, 1);
162
-#define CP_REG_AA64_MASK (1 << CP_REG_AA64_SHIFT)
131
- is_extended = (size < 3) && extract32(opc, 0, 1);
132
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
133
- }
163
-
134
-
164
-/* To enable banking of coprocessor registers depending on ns-bit we
135
- if (rn == 31) {
165
- * add a bit to distinguish between secure and non-secure cpregs in the
136
- gen_check_sp_alignment(s);
166
- * hashtable.
137
- }
167
- */
138
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
168
-#define CP_REG_NS_SHIFT 29
139
- offset = imm12 << size;
169
-#define CP_REG_NS_MASK (1 << CP_REG_NS_SHIFT)
140
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
170
-
141
-
171
-#define ENCODE_CP_REG(cp, is64, ns, crn, crm, opc1, opc2) \
142
- clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, memop);
172
- ((ns) << CP_REG_NS_SHIFT | ((cp) << 16) | ((is64) << 15) | \
173
- ((crn) << 11) | ((crm) << 7) | ((opc1) << 3) | (opc2))
174
-
143
-
175
-#define ENCODE_AA64_CP_REG(cp, crn, crm, op0, op1, op2) \
144
- if (is_vector) {
176
- (CP_REG_AA64_MASK | \
145
- if (is_store) {
177
- ((cp) << CP_REG_ARM_COPROC_SHIFT) | \
146
- do_fp_st(s, rt, clean_addr, memop);
178
- ((op0) << CP_REG_ARM64_SYSREG_OP0_SHIFT) | \
147
- } else {
179
- ((op1) << CP_REG_ARM64_SYSREG_OP1_SHIFT) | \
148
- do_fp_ld(s, rt, clean_addr, memop);
180
- ((crn) << CP_REG_ARM64_SYSREG_CRN_SHIFT) | \
149
- }
181
- ((crm) << CP_REG_ARM64_SYSREG_CRM_SHIFT) | \
182
- ((op2) << CP_REG_ARM64_SYSREG_OP2_SHIFT))
183
-
184
-/* Convert a full 64 bit KVM register ID to the truncated 32 bit
185
- * version used as a key for the coprocessor register hashtable
186
- */
187
-static inline uint32_t kvm_to_cpreg_id(uint64_t kvmid)
188
-{
189
- uint32_t cpregid = kvmid;
190
- if ((kvmid & CP_REG_ARCH_MASK) == CP_REG_ARM64) {
191
- cpregid |= CP_REG_AA64_MASK;
192
- } else {
150
- } else {
193
- if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) {
151
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
194
- cpregid |= (1 << 15);
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);
195
- }
158
- }
196
-
197
- /* KVM is always non-secure so add the NS flag on AArch32 register
198
- * entries.
199
- */
200
- cpregid |= 1 << CP_REG_NS_SHIFT;
201
- }
159
- }
202
- return cpregid;
203
-}
160
-}
204
-
161
-
205
-/* Convert a truncated 32 bit hashtable key into the full
162
/* Atomic memory operations
206
- * 64 bit KVM register ID.
163
*
207
- */
164
* 31 30 27 26 24 22 21 16 15 12 10 5 0
208
-static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
165
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
209
-{
166
return;
210
- uint64_t kvmid;
167
}
211
-
168
break;
212
- if (cpregid & CP_REG_AA64_MASK) {
169
- case 1:
213
- kvmid = cpregid & ~CP_REG_AA64_MASK;
170
- disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector);
214
- kvmid |= CP_REG_SIZE_U64 | CP_REG_ARM64;
171
- return;
215
- } else {
172
}
216
- kvmid = cpregid & ~(1 << 15);
173
unallocated_encoding(s);
217
- if (cpregid & (1 << 15)) {
174
}
218
- kvmid |= CP_REG_SIZE_U64 | CP_REG_ARM;
219
- } else {
220
- kvmid |= CP_REG_SIZE_U32 | CP_REG_ARM;
221
- }
222
- }
223
- return kvmid;
224
-}
225
-
226
/* Return the highest implemented Exception Level */
227
static inline int arm_highest_el(CPUARMState *env)
228
{
229
--
175
--
230
2.34.1
176
2.34.1
231
232
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
Convert the LDR and STR instructions which take a register
2
plus register offset to decodetree.
2
3
3
Havard is no longer working on the Nuvoton systems for a while
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
and won't be able to do any work on it in the future. So I'll
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
take over maintaining the Nuvoton system from him.
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(-)
6
11
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
8
Acked-by: Havard Skinnemoen <hskinnemoen@google.com>
9
Reviewed-by: Philippe Mathieu-Daude <philmd@linaro.org>
10
Message-id: 20230208235433.3989937-2-wuhaotsh@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
MAINTAINERS | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/MAINTAINERS b/MAINTAINERS
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/MAINTAINERS
14
--- a/target/arm/tcg/a64.decode
19
+++ b/MAINTAINERS
15
+++ b/target/arm/tcg/a64.decode
20
@@ -XXX,XX +XXX,XX @@ F: include/hw/net/mv88w8618_eth.h
16
@@ -XXX,XX +XXX,XX @@ STR_v_i sz:2 111 1 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=
21
F: docs/system/arm/musicpal.rst
17
STR_v_i 00 111 1 01 10 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
22
18
LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0
23
Nuvoton NPCM7xx
19
LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
24
-M: Havard Skinnemoen <hskinnemoen@google.com>
20
+
25
M: Tyrone Ting <kfting@nuvoton.com>
21
+# Load/store with register offset
26
+M: Hao Wu <wuhaotsh@google.com>
22
+&ldst rm rn rt sign ext sz opt s
27
L: qemu-arm@nongnu.org
23
+@ldst .. ... . .. .. . rm:5 opt:3 s:1 .. rn:5 rt:5 &ldst
28
S: Supported
24
+STR sz:2 111 0 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
29
F: hw/*/npcm7xx*
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;
30
--
249
--
31
2.34.1
250
2.34.1
diff view generated by jsdifflib
New patch
1
Convert the insns in the atomic memory operations group to
2
decodetree.
1
3
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
1
From: Fabiano Rosas <farosas@suse.de>
1
Convert the instructions in the load/store register (pointer
2
authentication) group ot decodetree: LDRAA, LDRAB.
2
3
3
Move this earlier to make the next patch diff cleaner. While here
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
update the comment slightly to not give the impression that the
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
misalignment affects only TCG.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230602155223.2040685-17-peter.maydell@linaro.org
8
---
9
target/arm/tcg/a64.decode | 7 +++
10
target/arm/tcg/translate-a64.c | 83 +++++++---------------------------
11
2 files changed, 23 insertions(+), 67 deletions(-)
6
12
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Fabiano Rosas <farosas@suse.de>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/machine.c | 18 +++++++++---------
14
1 file changed, 9 insertions(+), 9 deletions(-)
15
16
diff --git a/target/arm/machine.c b/target/arm/machine.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/machine.c
15
--- a/target/arm/tcg/a64.decode
19
+++ b/target/arm/machine.c
16
+++ b/target/arm/tcg/a64.decode
20
@@ -XXX,XX +XXX,XX @@ static int cpu_post_load(void *opaque, int version_id)
17
@@ -XXX,XX +XXX,XX @@ LDUMIN .. 111 0 00 . . 1 ..... 0111 00 ..... ..... @atomic
18
SWP .. 111 0 00 . . 1 ..... 1000 00 ..... ..... @atomic
19
20
LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
21
+
22
+# Load/store register (pointer authentication)
23
+
24
+# LDRA immediate is 10 bits signed and scaled, but the bits aren't all contiguous
25
+%ldra_imm 22:s1 12:9 !function=times_2
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
30
--- a/target/arm/tcg/translate-a64.c
31
+++ b/target/arm/tcg/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_LDAPR(DisasContext *s, arg_LDAPR *a)
33
return true;
34
}
35
36
-/*
37
- * PAC memory operations
38
- *
39
- * 31 30 27 26 24 22 21 12 11 10 5 0
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,
21
}
84
}
22
}
85
}
23
86
24
+ /*
87
- /* Form the 10-bit signed, scaled offset. */
25
+ * Misaligned thumb pc is architecturally impossible. Fail the
88
- offset = (extract32(insn, 22, 1) << 9) | extract32(insn, 12, 9);
26
+ * incoming migration. For TCG it would trigger the assert in
89
- offset = sextract32(offset << size, 0, 10 + size);
27
+ * thumb_tr_translate_insn().
90
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
28
+ */
91
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, a->imm);
29
+ if (!is_a64(env) && env->thumb && (env->regs[15] & 1)) {
92
30
+ return -1;
93
- memop = finalize_memop(s, size);
31
+ }
94
+ memop = finalize_memop(s, MO_64);
32
+
95
33
hw_breakpoint_update_all(cpu);
96
/* Note that "clean" and "dirty" here refer to TBI not PAC. */
34
hw_watchpoint_update_all(cpu);
97
clean_addr = gen_mte_check1(s, dirty_addr, false,
35
98
- is_wback || rn != 31, memop);
36
@@ -XXX,XX +XXX,XX @@ static int cpu_post_load(void *opaque, int version_id)
99
+ a->w || a->rn != 31, memop);
37
}
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);
38
}
113
}
39
114
+ return true;
40
- /*
115
}
41
- * Misaligned thumb pc is architecturally impossible.
116
42
- * We have an assert in thumb_tr_translate_insn to verify this.
117
/*
43
- * Fail an incoming migrate to avoid this assert.
118
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
44
- */
119
}
45
- if (!is_a64(env) && env->thumb && (env->regs[15] & 1)) {
120
}
46
- return -1;
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;
47
- }
143
- }
144
- unallocated_encoding(s);
145
-}
48
-
146
-
49
if (!kvm_enabled()) {
147
/* AdvSIMD load/store multiple structures
50
pmu_op_finish(&cpu->env);
148
*
51
}
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;
52
--
161
--
53
2.34.1
162
2.34.1
54
163
55
164
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Convert the instructions in the LDAPR/STLR (unscaled immediate)
2
group to decodetree.
2
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Message-id: 20230602155223.2040685-18-peter.maydell@linaro.org
5
Message-id: 20230206223502.25122-5-philmd@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/helper.c | 12 ++++++++++--
8
target/arm/tcg/a64.decode | 10 +++
9
1 file changed, 10 insertions(+), 2 deletions(-)
9
target/arm/tcg/translate-a64.c | 132 ++++++++++++---------------------
10
2 files changed, 56 insertions(+), 86 deletions(-)
10
11
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
14
--- a/target/arm/tcg/a64.decode
14
+++ b/target/arm/helper.c
15
+++ b/target/arm/tcg/a64.decode
15
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
16
@@ -XXX,XX +XXX,XX @@ LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
17
%ldra_imm 22:s1 12:9 !function=times_2
18
19
LDRA 11 111 0 00 m:1 . 1 ......... w:1 1 rn:5 rt:5 imm=%ldra_imm
20
+
21
+&ldapr_stlr_i rn rt imm sz sign ext
22
+@ldapr_stlr_i .. ...... .. . imm:9 .. rn:5 rt:5 &ldapr_stlr_i
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,
16
}
35
}
17
}
36
}
18
37
19
+#ifndef CONFIG_USER_ONLY
38
-/* Update the Sixty-Four bit (SF) registersize. This logic is derived
20
/*
39
+/*
21
* We don't know until after realize whether there's a GICv3
40
+ * Compute the ISS.SF bit for syndrome information if an exception
22
* attached, and that is what registers the gicv3 sysregs.
41
+ * is taken on a load or store. This indicates whether the instruction
23
@@ -XXX,XX +XXX,XX @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri)
42
+ * is accessing a 32-bit or 64-bit register. This logic is derived
24
return pfr1;
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;
25
}
63
}
26
64
27
-#ifndef CONFIG_USER_ONLY
65
-/*
28
static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
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)
29
{
81
{
30
ARMCPU *cpu = env_archcpu(env);
82
- int rt = extract32(insn, 0, 5);
31
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
83
- int rn = extract32(insn, 5, 5);
32
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 1,
84
- int offset = sextract32(insn, 12, 9);
33
.access = PL1_R, .type = ARM_CP_NO_RAW,
85
- int opc = extract32(insn, 22, 2);
34
.accessfn = access_aa32_tid3,
86
- int size = extract32(insn, 30, 2);
35
+#ifdef CONFIG_USER_ONLY
87
TCGv_i64 clean_addr, dirty_addr;
36
+ .type = ARM_CP_CONST,
88
- bool is_store = false;
37
+ .resetvalue = cpu->isar.id_pfr1,
89
- bool extend = false;
38
+#else
90
- bool iss_sf;
39
+ .type = ARM_CP_NO_RAW,
91
- MemOp mop = size;
40
+ .accessfn = access_aa32_tid3,
92
+ MemOp mop = a->sz | (a->sign ? MO_SIGN : 0);
41
.readfn = id_pfr1_read,
93
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
42
- .writefn = arm_cp_write_ignore },
94
43
+ .writefn = arm_cp_write_ignore
95
if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
44
+#endif
96
- unallocated_encoding(s);
45
+ },
97
- return;
46
{ .name = "ID_DFR0", .state = ARM_CP_STATE_BOTH,
98
+ return false;
47
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2,
99
}
48
.access = PL1_R, .type = ARM_CP_CONST,
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
+ }
179
+
180
+ mop = check_ordered_align(s, a->rn, a->imm, true, mop);
181
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
182
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, a->imm);
183
+ clean_addr = clean_data_tbi(s, dirty_addr);
184
+
185
+ /* Store-Release semantics */
186
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
187
+ do_gpr_st(s, cpu_reg(s, a->rt), clean_addr, mop, true, a->rt, iss_sf, true);
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
}
49
--
201
--
50
2.34.1
202
2.34.1
51
52
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Convert the instructions in the ASIMD load/store multiple structures
2
instruction classes to decodetree.
2
3
3
While dozens of files include "cpu.h", only 3 files require
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
these NVIC helper declarations.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-19-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 20 +++
9
target/arm/tcg/translate-a64.c | 222 ++++++++++++++++-----------------
10
2 files changed, 131 insertions(+), 111 deletions(-)
5
11
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20230206223502.25122-12-philmd@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/intc/armv7m_nvic.h | 123 ++++++++++++++++++++++++++++++++++
12
target/arm/cpu.h | 123 ----------------------------------
13
target/arm/cpu.c | 4 +-
14
target/arm/cpu_tcg.c | 3 +
15
target/arm/m_helper.c | 3 +
16
5 files changed, 132 insertions(+), 124 deletions(-)
17
18
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/intc/armv7m_nvic.h
14
--- a/target/arm/tcg/a64.decode
21
+++ b/include/hw/intc/armv7m_nvic.h
15
+++ b/target/arm/tcg/a64.decode
22
@@ -XXX,XX +XXX,XX @@ struct NVICState {
16
@@ -XXX,XX +XXX,XX @@ LDAPR_i 01 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext
23
qemu_irq sysresetreq;
17
LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=2
24
};
18
LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
25
19
LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
26
+/* Interface between CPU and Interrupt controller. */
20
+
27
+/**
21
+# Load/store multiple structures
28
+ * armv7m_nvic_set_pending: mark the specified exception as pending
22
+# The 4-bit opcode in [15:12] encodes repeat count and structure elements
29
+ * @s: the NVIC
23
+&ldst_mult rm rn rt sz q p rpt selem
30
+ * @irq: the exception number to mark pending
24
+@ldst_mult . q:1 ...... p:1 . . rm:5 .... sz:2 rn:5 rt:5 &ldst_mult
31
+ * @secure: false for non-banked exceptions or for the nonsecure
25
+ST_mult 0 . 001100 . 0 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
32
+ * version of a banked exception, true for the secure version of a banked
26
+ST_mult 0 . 001100 . 0 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
33
+ * exception.
27
+ST_mult 0 . 001100 . 0 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
34
+ *
28
+ST_mult 0 . 001100 . 0 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
35
+ * Marks the specified exception as pending. Note that we will assert()
29
+ST_mult 0 . 001100 . 0 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
36
+ * if @secure is true and @irq does not specify one of the fixed set
30
+ST_mult 0 . 001100 . 0 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
37
+ * of architecturally banked exceptions.
31
+ST_mult 0 . 001100 . 0 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
38
+ */
32
+
39
+void armv7m_nvic_set_pending(NVICState *s, int irq, bool secure);
33
+LD_mult 0 . 001100 . 1 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
40
+/**
34
+LD_mult 0 . 001100 . 1 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
41
+ * armv7m_nvic_set_pending_derived: mark this derived exception as pending
35
+LD_mult 0 . 001100 . 1 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
42
+ * @s: the NVIC
36
+LD_mult 0 . 001100 . 1 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
43
+ * @irq: the exception number to mark pending
37
+LD_mult 0 . 001100 . 1 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
44
+ * @secure: false for non-banked exceptions or for the nonsecure
38
+LD_mult 0 . 001100 . 1 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
45
+ * version of a banked exception, true for the secure version of a banked
39
+LD_mult 0 . 001100 . 1 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
46
+ * exception.
40
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
47
+ *
41
index XXXXXXX..XXXXXXX 100644
48
+ * Similar to armv7m_nvic_set_pending(), but specifically for derived
42
--- a/target/arm/tcg/translate-a64.c
49
+ * exceptions (exceptions generated in the course of trying to take
43
+++ b/target/arm/tcg/translate-a64.c
50
+ * a different exception).
44
@@ -XXX,XX +XXX,XX @@ static bool trans_STLR_i(DisasContext *s, arg_ldapr_stlr_i *a)
51
+ */
45
return true;
52
+void armv7m_nvic_set_pending_derived(NVICState *s, int irq, bool secure);
46
}
53
+/**
47
54
+ * armv7m_nvic_set_pending_lazyfp: mark this lazy FP exception as pending
48
-/* AdvSIMD load/store multiple structures
55
+ * @s: the NVIC
49
- *
56
+ * @irq: the exception number to mark pending
50
- * 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
57
+ * @secure: false for non-banked exceptions or for the nonsecure
51
- * +---+---+---------------+---+-------------+--------+------+------+------+
58
+ * version of a banked exception, true for the secure version of a banked
52
- * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size | Rn | Rt |
59
+ * exception.
53
- * +---+---+---------------+---+-------------+--------+------+------+------+
60
+ *
54
- *
61
+ * Similar to armv7m_nvic_set_pending(), but specifically for exceptions
55
- * AdvSIMD load/store multiple structures (post-indexed)
62
+ * generated in the course of lazy stacking of FP registers.
56
- *
63
+ */
57
- * 31 30 29 23 22 21 20 16 15 12 11 10 9 5 4 0
64
+void armv7m_nvic_set_pending_lazyfp(NVICState *s, int irq, bool secure);
58
- * +---+---+---------------+---+---+---------+--------+------+------+------+
65
+/**
59
- * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 | Rm | opcode | size | Rn | Rt |
66
+ * armv7m_nvic_get_pending_irq_info: return highest priority pending
60
- * +---+---+---------------+---+---+---------+--------+------+------+------+
67
+ * exception, and whether it targets Secure state
61
- *
68
+ * @s: the NVIC
62
- * Rt: first (or only) SIMD&FP register to be transferred
69
+ * @pirq: set to pending exception number
63
- * Rn: base address or SP
70
+ * @ptargets_secure: set to whether pending exception targets Secure
64
- * Rm (post-index only): post-index register (when !31) or size dependent #imm
71
+ *
65
- */
72
+ * This function writes the number of the highest priority pending
66
-static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
73
+ * exception (the one which would be made active by
67
+static bool trans_LD_mult(DisasContext *s, arg_ldst_mult *a)
74
+ * armv7m_nvic_acknowledge_irq()) to @pirq, and sets @ptargets_secure
68
{
75
+ * to true if the current highest priority pending exception should
69
- int rt = extract32(insn, 0, 5);
76
+ * be taken to Secure state, false for NS.
70
- int rn = extract32(insn, 5, 5);
77
+ */
71
- int rm = extract32(insn, 16, 5);
78
+void armv7m_nvic_get_pending_irq_info(NVICState *s, int *pirq,
72
- int size = extract32(insn, 10, 2);
79
+ bool *ptargets_secure);
73
- int opcode = extract32(insn, 12, 4);
80
+/**
74
- bool is_store = !extract32(insn, 22, 1);
81
+ * armv7m_nvic_acknowledge_irq: make highest priority pending exception active
75
- bool is_postidx = extract32(insn, 23, 1);
82
+ * @s: the NVIC
76
- bool is_q = extract32(insn, 30, 1);
83
+ *
77
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
84
+ * Move the current highest priority pending exception from the pending
78
MemOp endian, align, mop;
85
+ * state to the active state, and update v7m.exception to indicate that
79
86
+ * it is the exception currently being handled.
80
int total; /* total bytes */
87
+ */
81
int elements; /* elements per vector */
88
+void armv7m_nvic_acknowledge_irq(NVICState *s);
82
- int rpt; /* num iterations */
89
+/**
83
- int selem; /* structure elements */
90
+ * armv7m_nvic_complete_irq: complete specified interrupt or exception
84
int r;
91
+ * @s: the NVIC
85
+ int size = a->sz;
92
+ * @irq: the exception number to complete
86
93
+ * @secure: true if this exception was secure
87
- if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
94
+ *
88
- unallocated_encoding(s);
95
+ * Returns: -1 if the irq was not active
89
- return;
96
+ * 1 if completing this irq brought us back to base (no active irqs)
90
+ if (!a->p && a->rm != 0) {
97
+ * 0 if there is still an irq active after this one was completed
91
+ /* For non-postindexed accesses the Rm field must be 0 */
98
+ * (Ignoring -1, this is the same as the RETTOBASE value before completion.)
92
+ return false;
99
+ */
93
}
100
+int armv7m_nvic_complete_irq(NVICState *s, int irq, bool secure);
94
-
101
+/**
95
- if (!is_postidx && rm != 0) {
102
+ * armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
96
- unallocated_encoding(s);
103
+ * @s: the NVIC
97
- return;
104
+ * @irq: the exception number to mark pending
98
+ if (size == 3 && !a->q && a->selem != 1) {
105
+ * @secure: false for non-banked exceptions or for the nonsecure
99
+ return false;
106
+ * version of a banked exception, true for the secure version of a banked
100
}
107
+ * exception.
101
-
108
+ *
102
- /* From the shared decode logic */
109
+ * Return whether an exception is "ready", i.e. whether the exception is
103
- switch (opcode) {
110
+ * enabled and is configured at a priority which would allow it to
104
- case 0x0:
111
+ * interrupt the current execution priority. This controls whether the
105
- rpt = 1;
112
+ * RDY bit for it in the FPCCR is set.
106
- selem = 4;
113
+ */
107
- break;
114
+bool armv7m_nvic_get_ready_status(NVICState *s, int irq, bool secure);
108
- case 0x2:
115
+/**
109
- rpt = 4;
116
+ * armv7m_nvic_raw_execution_priority: return the raw execution priority
110
- selem = 1;
117
+ * @s: the NVIC
111
- break;
118
+ *
112
- case 0x4:
119
+ * Returns: the raw execution priority as defined by the v8M architecture.
113
- rpt = 1;
120
+ * This is the execution priority minus the effects of AIRCR.PRIS,
114
- selem = 3;
121
+ * and minus any PRIMASK/FAULTMASK/BASEPRI priority boosting.
115
- break;
122
+ * (v8M ARM ARM I_PKLD.)
116
- case 0x6:
123
+ */
117
- rpt = 3;
124
+int armv7m_nvic_raw_execution_priority(NVICState *s);
118
- selem = 1;
125
+/**
119
- break;
126
+ * armv7m_nvic_neg_prio_requested: return true if the requested execution
120
- case 0x7:
127
+ * priority is negative for the specified security state.
121
- rpt = 1;
128
+ * @s: the NVIC
122
- selem = 1;
129
+ * @secure: the security state to test
123
- break;
130
+ * This corresponds to the pseudocode IsReqExecPriNeg().
124
- case 0x8:
131
+ */
125
- rpt = 1;
132
+#ifndef CONFIG_USER_ONLY
126
- selem = 2;
133
+bool armv7m_nvic_neg_prio_requested(NVICState *s, bool secure);
127
- break;
134
+#else
128
- case 0xa:
135
+static inline bool armv7m_nvic_neg_prio_requested(NVICState *s, bool secure)
129
- rpt = 2;
136
+{
130
- selem = 1;
137
+ return false;
131
- break;
138
+}
132
- default:
139
+#endif
133
- unallocated_encoding(s);
140
+#ifndef CONFIG_USER_ONLY
134
- return;
141
+bool armv7m_nvic_can_take_pending_exception(NVICState *s);
135
- }
142
+#else
136
-
143
+static inline bool armv7m_nvic_can_take_pending_exception(NVICState *s)
137
- if (size == 3 && !is_q && selem != 1) {
144
+{
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
+ }
230
+
231
+ if (a->p) {
232
+ if (a->rm == 31) {
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
+ }
145
+ return true;
238
+ return true;
146
+}
239
+}
147
+#endif
240
+
148
+
241
+static bool trans_ST_mult(DisasContext *s, arg_ldst_mult *a)
149
#endif
242
+{
150
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
243
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
151
index XXXXXXX..XXXXXXX 100644
244
+ MemOp endian, align, mop;
152
--- a/target/arm/cpu.h
245
+
153
+++ b/target/arm/cpu.h
246
+ int total; /* total bytes */
154
@@ -XXX,XX +XXX,XX @@ void arm_cpu_list(void);
247
+ int elements; /* elements per vector */
155
uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
248
+ int r;
156
uint32_t cur_el, bool secure);
249
+ int size = a->sz;
157
250
+
158
-/* Interface between CPU and Interrupt controller. */
251
+ if (!a->p && a->rm != 0) {
159
-#ifndef CONFIG_USER_ONLY
252
+ /* For non-postindexed accesses the Rm field must be 0 */
160
-bool armv7m_nvic_can_take_pending_exception(NVICState *s);
253
+ return false;
161
-#else
254
+ }
162
-static inline bool armv7m_nvic_can_take_pending_exception(NVICState *s)
255
+ if (size == 3 && !a->q && a->selem != 1) {
163
-{
256
+ return false;
164
- return true;
257
+ }
165
-}
258
+ if (!fp_access_check(s)) {
166
-#endif
259
+ return true;
167
-/**
260
+ }
168
- * armv7m_nvic_set_pending: mark the specified exception as pending
261
+
169
- * @s: the NVIC
262
+ if (a->rn == 31) {
170
- * @irq: the exception number to mark pending
263
+ gen_check_sp_alignment(s);
171
- * @secure: false for non-banked exceptions or for the nonsecure
264
+ }
172
- * version of a banked exception, true for the secure version of a banked
265
+
173
- * exception.
266
+ /* For our purposes, bytes are always little-endian. */
174
- *
267
+ endian = s->be_data;
175
- * Marks the specified exception as pending. Note that we will assert()
268
+ if (size == 0) {
176
- * if @secure is true and @irq does not specify one of the fixed set
269
+ endian = MO_LE;
177
- * of architecturally banked exceptions.
270
+ }
178
- */
271
+
179
-void armv7m_nvic_set_pending(NVICState *s, int irq, bool secure);
272
+ total = a->rpt * a->selem * (a->q ? 16 : 8);
180
-/**
273
+ tcg_rn = cpu_reg_sp(s, a->rn);
181
- * armv7m_nvic_set_pending_derived: mark this derived exception as pending
274
+
182
- * @s: the NVIC
275
+ /*
183
- * @irq: the exception number to mark pending
276
+ * Issue the MTE check vs the logical repeat count, before we
184
- * @secure: false for non-banked exceptions or for the nonsecure
277
+ * promote consecutive little-endian elements below.
185
- * version of a banked exception, true for the secure version of a banked
278
+ */
186
- * exception.
279
+ clean_addr = gen_mte_checkN(s, tcg_rn, true, a->p || a->rn != 31, total,
187
- *
280
+ finalize_memop_asimd(s, size));
188
- * Similar to armv7m_nvic_set_pending(), but specifically for derived
281
+
189
- * exceptions (exceptions generated in the course of trying to take
282
+ /*
190
- * a different exception).
283
+ * Consecutive little-endian elements from a single register
191
- */
284
+ * can be promoted to a larger little-endian operation.
192
-void armv7m_nvic_set_pending_derived(NVICState *s, int irq, bool secure);
285
+ */
193
-/**
286
+ align = MO_ALIGN;
194
- * armv7m_nvic_set_pending_lazyfp: mark this lazy FP exception as pending
287
+ if (a->selem == 1 && endian == MO_LE) {
195
- * @s: the NVIC
288
+ align = pow2_align(size);
196
- * @irq: the exception number to mark pending
289
+ size = 3;
197
- * @secure: false for non-banked exceptions or for the nonsecure
290
+ }
198
- * version of a banked exception, true for the secure version of a banked
291
+ if (!s->align_mem) {
199
- * exception.
292
+ align = 0;
200
- *
293
+ }
201
- * Similar to armv7m_nvic_set_pending(), but specifically for exceptions
294
+ mop = endian | size | align;
202
- * generated in the course of lazy stacking of FP registers.
295
+
203
- */
296
+ elements = (a->q ? 16 : 8) >> size;
204
-void armv7m_nvic_set_pending_lazyfp(NVICState *s, int irq, bool secure);
297
+ tcg_ebytes = tcg_constant_i64(1 << size);
205
-/**
298
+ for (r = 0; r < a->rpt; r++) {
206
- * armv7m_nvic_get_pending_irq_info: return highest priority pending
299
+ int e;
207
- * exception, and whether it targets Secure state
300
+ for (e = 0; e < elements; e++) {
208
- * @s: the NVIC
301
+ int xs;
209
- * @pirq: set to pending exception number
302
+ for (xs = 0; xs < a->selem; xs++) {
210
- * @ptargets_secure: set to whether pending exception targets Secure
303
+ int tt = (a->rt + r + xs) % 32;
211
- *
304
+ do_vec_st(s, tt, e, clean_addr, mop);
212
- * This function writes the number of the highest priority pending
305
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
213
- * exception (the one which would be made active by
306
+ }
214
- * armv7m_nvic_acknowledge_irq()) to @pirq, and sets @ptargets_secure
307
}
215
- * to true if the current highest priority pending exception should
308
}
216
- * be taken to Secure state, false for NS.
309
217
- */
310
- if (is_postidx) {
218
-void armv7m_nvic_get_pending_irq_info(NVICState *s, int *pirq,
311
- if (rm == 31) {
219
- bool *ptargets_secure);
312
+ if (a->p) {
220
-/**
313
+ if (a->rm == 31) {
221
- * armv7m_nvic_acknowledge_irq: make highest priority pending exception active
314
tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
222
- * @s: the NVIC
315
} else {
223
- *
316
- tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
224
- * Move the current highest priority pending exception from the pending
317
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
225
- * state to the active state, and update v7m.exception to indicate that
318
}
226
- * it is the exception currently being handled.
319
}
227
- */
320
+ return true;
228
-void armv7m_nvic_acknowledge_irq(NVICState *s);
321
}
229
-/**
322
230
- * armv7m_nvic_complete_irq: complete specified interrupt or exception
323
/* AdvSIMD load/store single structure
231
- * @s: the NVIC
324
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
232
- * @irq: the exception number to complete
325
static void disas_ldst(DisasContext *s, uint32_t insn)
233
- * @secure: true if this exception was secure
326
{
234
- *
327
switch (extract32(insn, 24, 6)) {
235
- * Returns: -1 if the irq was not active
328
- case 0x0c: /* AdvSIMD load/store multiple structures */
236
- * 1 if completing this irq brought us back to base (no active irqs)
329
- disas_ldst_multiple_struct(s, insn);
237
- * 0 if there is still an irq active after this one was completed
330
- break;
238
- * (Ignoring -1, this is the same as the RETTOBASE value before completion.)
331
case 0x0d: /* AdvSIMD load/store single structure */
239
- */
332
disas_ldst_single_struct(s, insn);
240
-int armv7m_nvic_complete_irq(NVICState *s, int irq, bool secure);
333
break;
241
-/**
242
- * armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
243
- * @s: the NVIC
244
- * @irq: the exception number to mark pending
245
- * @secure: false for non-banked exceptions or for the nonsecure
246
- * version of a banked exception, true for the secure version of a banked
247
- * exception.
248
- *
249
- * Return whether an exception is "ready", i.e. whether the exception is
250
- * enabled and is configured at a priority which would allow it to
251
- * interrupt the current execution priority. This controls whether the
252
- * RDY bit for it in the FPCCR is set.
253
- */
254
-bool armv7m_nvic_get_ready_status(NVICState *s, int irq, bool secure);
255
-/**
256
- * armv7m_nvic_raw_execution_priority: return the raw execution priority
257
- * @s: the NVIC
258
- *
259
- * Returns: the raw execution priority as defined by the v8M architecture.
260
- * This is the execution priority minus the effects of AIRCR.PRIS,
261
- * and minus any PRIMASK/FAULTMASK/BASEPRI priority boosting.
262
- * (v8M ARM ARM I_PKLD.)
263
- */
264
-int armv7m_nvic_raw_execution_priority(NVICState *s);
265
-/**
266
- * armv7m_nvic_neg_prio_requested: return true if the requested execution
267
- * priority is negative for the specified security state.
268
- * @s: the NVIC
269
- * @secure: the security state to test
270
- * This corresponds to the pseudocode IsReqExecPriNeg().
271
- */
272
-#ifndef CONFIG_USER_ONLY
273
-bool armv7m_nvic_neg_prio_requested(NVICState *s, bool secure);
274
-#else
275
-static inline bool armv7m_nvic_neg_prio_requested(NVICState *s, bool secure)
276
-{
277
- return false;
278
-}
279
-#endif
280
-
281
/* Interface for defining coprocessor registers.
282
* Registers are defined in tables of arm_cp_reginfo structs
283
* which are passed to define_arm_cp_regs().
284
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
285
index XXXXXXX..XXXXXXX 100644
286
--- a/target/arm/cpu.c
287
+++ b/target/arm/cpu.c
288
@@ -XXX,XX +XXX,XX @@
289
#if !defined(CONFIG_USER_ONLY)
290
#include "hw/loader.h"
291
#include "hw/boards.h"
292
+#ifdef CONFIG_TCG
293
#include "hw/intc/armv7m_nvic.h"
294
-#endif
295
+#endif /* CONFIG_TCG */
296
+#endif /* !CONFIG_USER_ONLY */
297
#include "sysemu/tcg.h"
298
#include "sysemu/qtest.h"
299
#include "sysemu/hw_accel.h"
300
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
301
index XXXXXXX..XXXXXXX 100644
302
--- a/target/arm/cpu_tcg.c
303
+++ b/target/arm/cpu_tcg.c
304
@@ -XXX,XX +XXX,XX @@
305
#include "hw/boards.h"
306
#endif
307
#include "cpregs.h"
308
+#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
309
+#include "hw/intc/armv7m_nvic.h"
310
+#endif
311
312
313
/* Share AArch32 -cpu max features with AArch64. */
314
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
315
index XXXXXXX..XXXXXXX 100644
316
--- a/target/arm/m_helper.c
317
+++ b/target/arm/m_helper.c
318
@@ -XXX,XX +XXX,XX @@
319
#include "exec/cpu_ldst.h"
320
#include "semihosting/common-semi.h"
321
#endif
322
+#if !defined(CONFIG_USER_ONLY)
323
+#include "hw/intc/armv7m_nvic.h"
324
+#endif
325
326
static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask,
327
uint32_t reg, uint32_t val)
328
--
334
--
329
2.34.1
335
2.34.1
330
331
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Convert the ASIMD load/store single structure insns to decodetree.
2
2
3
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Message-id: 20230602155223.2040685-20-peter.maydell@linaro.org
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230206223502.25122-3-philmd@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
6
---
9
target/arm/m_helper.c | 11 ++++++++---
7
target/arm/tcg/a64.decode | 34 +++++
10
1 file changed, 8 insertions(+), 3 deletions(-)
8
target/arm/tcg/translate-a64.c | 219 +++++++++++++++------------------
9
2 files changed, 136 insertions(+), 117 deletions(-)
11
10
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
11
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
13
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/m_helper.c
14
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
15
@@ -XXX,XX +XXX,XX @@ LD_mult 0 . 001100 . 1 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 sele
17
return 0;
16
LD_mult 0 . 001100 . 1 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
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;
18
}
59
}
19
60
20
-#else
61
-/* AdvSIMD load/store single structure
21
+ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
62
- *
63
- * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 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
+}
214
+
215
+static bool trans_LD_single(DisasContext *s, arg_ldst_single *a)
22
+{
216
+{
23
+ return ARMMMUIdx_MUser;
217
+ int xs, total, rt;
218
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
219
+ MemOp mop;
220
+
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
+ }
251
+ }
252
+ return true;
24
+}
253
+}
25
+
254
+
26
+#else /* !CONFIG_USER_ONLY */
255
+static bool trans_LD_single_repl(DisasContext *s, arg_LD_single_repl *a)
256
+{
257
+ int xs, total, rt;
258
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
259
+ MemOp mop;
260
+
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
+ }
296
+ }
297
+ return true;
298
}
27
299
28
/*
300
/*
29
* What kind of stack write are we doing? This affects how exceptions
301
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
30
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
302
static void disas_ldst(DisasContext *s, uint32_t insn)
31
return tt_resp;
32
}
33
34
-#endif /* !CONFIG_USER_ONLY */
35
-
36
ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
37
bool secstate, bool priv, bool negpri)
38
{
303
{
39
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
304
switch (extract32(insn, 24, 6)) {
40
305
- case 0x0d: /* AdvSIMD load/store single structure */
41
return arm_v7m_mmu_idx_for_secstate_and_priv(env, secstate, priv);
306
- disas_ldst_single_struct(s, insn);
42
}
307
- break;
43
+
308
case 0x19:
44
+#endif /* !CONFIG_USER_ONLY */
309
if (extract32(insn, 21, 1) != 0) {
310
disas_ldst_tag(s, insn);
45
--
311
--
46
2.34.1
312
2.34.1
47
48
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Convert the instructions in the load/store memory tags instruction
2
group to decodetree.
2
3
3
arm_v7m_mmu_idx_all() and arm_v7m_mmu_idx_for_secstate_and_priv()
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
are only used for system emulation in m_helper.c.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Move the definitions to avoid prototype forward declarations.
6
Message-id: 20230602155223.2040685-21-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 25 +++
9
target/arm/tcg/translate-a64.c | 360 ++++++++++++++++-----------------
10
2 files changed, 199 insertions(+), 186 deletions(-)
6
11
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230206223502.25122-4-philmd@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/internals.h | 14 --------
13
target/arm/m_helper.c | 74 +++++++++++++++++++++---------------------
14
2 files changed, 37 insertions(+), 51 deletions(-)
15
16
diff --git a/target/arm/internals.h b/target/arm/internals.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/internals.h
14
--- a/target/arm/tcg/a64.decode
19
+++ b/target/arm/internals.h
15
+++ b/target/arm/tcg/a64.decode
20
@@ -XXX,XX +XXX,XX @@ static inline ARMMMUIdx core_to_aa64_mmu_idx(int mmu_idx)
16
@@ -XXX,XX +XXX,XX @@ LD_single 0 . 001101 . 1 . ..... 10 . 001 ..... ..... @ldst_single_d
21
17
22
int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx);
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
}
52
53
+/* For load/store memory tags: scale offset by LOG2_TAG_GRANULE */
54
+static int scale_by_log2_tag_granule(DisasContext *s, int x)
55
+{
56
+ return x << LOG2_TAG_GRANULE;
57
+}
58
+
59
/*
60
* Include the generated decoders.
61
*/
62
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_single_repl(DisasContext *s, arg_LD_single_repl *a)
63
return true;
64
}
23
65
24
-/*
66
-/*
25
- * Return the MMU index for a v7M CPU with all relevant information
67
- * Load/Store memory tags
26
- * manually specified.
68
- *
69
- * 31 30 29 24 22 21 12 10 5 0
70
- * +-----+-------------+-----+---+------+-----+------+------+
71
- * | 1 1 | 0 1 1 0 0 1 | op1 | 1 | imm9 | op2 | Rn | Rt |
72
- * +-----+-------------+-----+---+------+-----+------+------+
27
- */
73
- */
28
-ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
74
-static void disas_ldst_tag(DisasContext *s, uint32_t insn)
29
- bool secstate, bool priv, bool negpri);
75
+static bool trans_STZGM(DisasContext *s, arg_ldst_tag *a)
30
-
76
{
31
-/*
77
- int rt = extract32(insn, 0, 5);
32
- * Return the MMU index for a v7M CPU in the specified security and
78
- int rn = extract32(insn, 5, 5);
33
- * privilege state.
79
- uint64_t offset = sextract64(insn, 12, 9) << LOG2_TAG_GRANULE;
34
- */
80
- int op2 = extract32(insn, 10, 2);
35
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
81
- int op1 = extract32(insn, 22, 2);
36
- bool secstate, bool priv);
82
- bool is_load = false, is_pair = false, is_zero = false, is_mult = false;
37
-
83
- int index = 0;
38
/* Return the MMU index for a v7M CPU in the specified security state */
84
TCGv_i64 addr, clean_addr, tcg_rt;
39
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
85
+ int size = 4 << s->dcz_blocksize;
40
86
41
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
87
- /* We checked insn bits [29:24,21] in the caller. */
42
index XXXXXXX..XXXXXXX 100644
88
- if (extract32(insn, 30, 2) != 3) {
43
--- a/target/arm/m_helper.c
89
- goto do_unallocated;
44
+++ b/target/arm/m_helper.c
90
+ if (!dc_isar_feature(aa64_mte, s)) {
45
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
91
+ return false;
46
92
+ }
47
#else /* !CONFIG_USER_ONLY */
93
+ if (s->current_el == 0) {
48
94
+ return false;
49
+static ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
95
}
50
+ bool secstate, bool priv, bool negpri)
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
+}
188
+
189
+static bool trans_STGM(DisasContext *s, arg_ldst_tag *a)
51
+{
190
+{
52
+ ARMMMUIdx mmu_idx = ARM_MMU_IDX_M;
191
+ TCGv_i64 addr, clean_addr, tcg_rt;
53
+
192
+
54
+ if (priv) {
193
+ if (!dc_isar_feature(aa64_mte, s)) {
55
+ mmu_idx |= ARM_MMU_IDX_M_PRIV;
194
+ return false;
56
+ }
195
+ }
57
+
196
+ if (s->current_el == 0) {
58
+ if (negpri) {
197
+ return false;
59
+ mmu_idx |= ARM_MMU_IDX_M_NEGPRI;
198
+ }
60
+ }
199
+
61
+
200
+ if (a->rn == 31) {
62
+ if (secstate) {
201
+ gen_check_sp_alignment(s);
63
+ mmu_idx |= ARM_MMU_IDX_M_S;
202
+ }
64
+ }
203
+
65
+
204
+ addr = read_cpu_reg_sp(s, a->rn, true);
66
+ return mmu_idx;
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;
67
+}
219
+}
68
+
220
+
69
+static ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
221
+static bool trans_LDGM(DisasContext *s, arg_ldst_tag *a)
70
+ bool secstate, bool priv)
71
+{
222
+{
72
+ bool negpri = armv7m_nvic_neg_prio_requested(env->nvic, secstate);
223
+ TCGv_i64 addr, clean_addr, tcg_rt;
73
+
224
+
74
+ return arm_v7m_mmu_idx_all(env, secstate, priv, negpri);
225
+ if (!dc_isar_feature(aa64_mte, s)) {
226
+ return false;
227
+ }
228
+ if (s->current_el == 0) {
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;
75
+}
253
+}
76
+
254
+
77
+/* Return the MMU index for a v7M CPU in the specified security state */
255
+static bool trans_LDG(DisasContext *s, arg_ldst_tag *a)
78
+ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
79
+{
256
+{
80
+ bool priv = arm_v7m_is_handler_mode(env) ||
257
+ TCGv_i64 addr, clean_addr, tcg_rt;
81
+ !(env->v7m.control[secstate] & 1);
258
+
82
+
259
+ if (!dc_isar_feature(aa64_mte_insn_reg, s)) {
83
+ return arm_v7m_mmu_idx_for_secstate_and_priv(env, secstate, priv);
260
+ return false;
261
+ }
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;
84
+}
331
+}
85
+
332
+
86
/*
333
+static bool do_STG(DisasContext *s, arg_ldst_tag *a, bool is_zero, bool is_pair)
87
* What kind of stack write are we doing? This affects how exceptions
334
+{
88
* generated during the stacking are treated.
335
+ TCGv_i64 addr, tcg_rt;
89
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
336
+
90
return tt_resp;
337
+ if (a->rn == 31) {
338
+ gen_check_sp_alignment(s);
339
}
340
341
- if (is_load) {
342
- tcg_gen_andi_i64(addr, addr, -TAG_GRANULE);
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
+ }
351
+ tcg_rt = cpu_reg_sp(s, a->rt);
352
+ if (!s->ata) {
353
+ /*
354
+ * For STG and ST2G, we need to check alignment and probe memory.
355
+ * TODO: For STZG and STZ2G, we could rely on the stores below,
356
+ * at least for system mode; user-only won't enforce alignment.
357
+ */
358
+ if (is_pair) {
359
+ gen_helper_st2g_stub(cpu_env, addr);
360
} else {
361
- /*
362
- * Tag access disabled: we must check for aborts on the load
363
- * load from [rn+offset], and then insert a 0 tag into rt.
364
- */
365
- clean_addr = clean_data_tbi(s, addr);
366
- gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
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;
91
}
424
}
92
425
93
-ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
426
-/* Loads and stores */
94
- bool secstate, bool priv, bool negpri)
427
-static void disas_ldst(DisasContext *s, uint32_t insn)
95
-{
428
-{
96
- ARMMMUIdx mmu_idx = ARM_MMU_IDX_M;
429
- switch (extract32(insn, 24, 6)) {
97
-
430
- case 0x19:
98
- if (priv) {
431
- if (extract32(insn, 21, 1) != 0) {
99
- mmu_idx |= ARM_MMU_IDX_M_PRIV;
432
- disas_ldst_tag(s, insn);
433
- } else {
434
- unallocated_encoding(s);
435
- }
436
- break;
437
- default:
438
- unallocated_encoding(s);
439
- break;
100
- }
440
- }
101
-
102
- if (negpri) {
103
- mmu_idx |= ARM_MMU_IDX_M_NEGPRI;
104
- }
105
-
106
- if (secstate) {
107
- mmu_idx |= ARM_MMU_IDX_M_S;
108
- }
109
-
110
- return mmu_idx;
111
-}
441
-}
112
-
442
+TRANS_FEAT(STG, aa64_mte_insn_reg, do_STG, a, false, false)
113
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
443
+TRANS_FEAT(STZG, aa64_mte_insn_reg, do_STG, a, true, false)
114
- bool secstate, bool priv)
444
+TRANS_FEAT(ST2G, aa64_mte_insn_reg, do_STG, a, false, true)
115
-{
445
+TRANS_FEAT(STZ2G, aa64_mte_insn_reg, do_STG, a, true, true)
116
- bool negpri = armv7m_nvic_neg_prio_requested(env->nvic, secstate);
446
117
-
447
typedef void ArithTwoOp(TCGv_i64, TCGv_i64, TCGv_i64);
118
- return arm_v7m_mmu_idx_all(env, secstate, priv, negpri);
448
119
-}
449
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
120
-
450
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
121
-/* Return the MMU index for a v7M CPU in the specified security state */
451
{
122
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
452
switch (extract32(insn, 25, 4)) {
123
-{
453
- case 0x4:
124
- bool priv = arm_v7m_is_handler_mode(env) ||
454
- case 0x6:
125
- !(env->v7m.control[secstate] & 1);
455
- case 0xc:
126
-
456
- case 0xe: /* Loads and stores */
127
- return arm_v7m_mmu_idx_for_secstate_and_priv(env, secstate, priv);
457
- disas_ldst(s, insn);
128
-}
458
- break;
129
-
459
case 0x5:
130
#endif /* !CONFIG_USER_ONLY */
460
case 0xd: /* Data processing - register */
461
disas_data_proc_reg(s, insn);
131
--
462
--
132
2.34.1
463
2.34.1
133
134
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
In commit 2c5fa0778c3b430 we fixed an endianness bug in the Allwinner
2
A10 PIC model; however in the process we introduced a regression.
3
This is because the old code was robust against the incoming 'level'
4
argument being something other than 0 or 1, whereas the new code was
5
not.
2
6
3
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
In particular, the allwinner-sdhost code treats its IRQ line
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
as 0-vs-non-0 rather than 0-vs-1, so when the SD controller
5
Message-id: 20230206223502.25122-9-philmd@linaro.org
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
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Tested-by: Guenter Roeck <linux@roeck-us.net>
21
Message-id: 20230606104609.3692557-2-peter.maydell@linaro.org
7
---
22
---
8
target/arm/cpu.h | 2 +-
23
hw/intc/allwinner-a10-pic.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
24
1 file changed, 1 insertion(+), 1 deletion(-)
10
25
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
12
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.h
28
--- a/hw/intc/allwinner-a10-pic.c
14
+++ b/target/arm/cpu.h
29
+++ b/hw/intc/allwinner-a10-pic.c
15
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
30
@@ -XXX,XX +XXX,XX @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
16
} sau;
31
AwA10PICState *s = opaque;
17
32
uint32_t *pending_reg = &s->irq_pending[irq / 32];
18
void *nvic;
33
19
- const struct arm_boot_info *boot_info;
34
- *pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
20
#if !defined(CONFIG_USER_ONLY)
35
+ *pending_reg = deposit32(*pending_reg, irq % 32, 1, !!level);
21
+ const struct arm_boot_info *boot_info;
36
aw_a10_pic_update(s);
22
/* Store GICv3CPUState to access from this struct */
37
}
23
void *gicv3state;
38
24
#else /* CONFIG_USER_ONLY */
25
--
39
--
26
2.34.1
40
2.34.1
27
41
28
42
diff view generated by jsdifflib
1
From: Claudio Fontana <cfontana@suse.de>
1
QEMU allows qemu_irq lines to transfer arbitrary integers. However
2
the convention is that for a simple IRQ line the values transferred
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.
2
6
3
for "all" builds (tcg + kvm), we want to avoid doing
7
Coerce the value to boolean to follow our usual convention.
4
the psci check if tcg is built-in, but not enabled.
5
8
6
Signed-off-by: Claudio Fontana <cfontana@suse.de>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Fabiano Rosas <farosas@suse.de>
9
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Tested-by: Guenter Roeck <linux@roeck-us.net>
12
Message-id: 20230606104609.3692557-3-peter.maydell@linaro.org
11
---
13
---
12
target/arm/helper.c | 3 ++-
14
hw/sd/allwinner-sdhost.c | 2 +-
13
1 file changed, 2 insertions(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
14
16
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
19
--- a/hw/sd/allwinner-sdhost.c
18
+++ b/target/arm/helper.c
20
+++ b/hw/sd/allwinner-sdhost.c
19
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_update_irq(AwSdHostState *s)
20
#include "hw/irq.h"
21
#include "sysemu/cpu-timers.h"
22
#include "sysemu/kvm.h"
23
+#include "sysemu/tcg.h"
24
#include "qapi/qapi-commands-machine-target.h"
25
#include "qapi/error.h"
26
#include "qemu/guest-random.h"
27
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_interrupt(CPUState *cs)
28
env->exception.syndrome);
29
}
22
}
30
23
31
- if (arm_is_psci_call(cpu, cs->exception_index)) {
24
trace_allwinner_sdhost_update_irq(irq);
32
+ if (tcg_enabled() && arm_is_psci_call(cpu, cs->exception_index)) {
25
- qemu_set_irq(s->irq, irq);
33
arm_handle_psci_call(cpu);
26
+ qemu_set_irq(s->irq, !!irq);
34
qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n");
27
}
35
return;
28
29
static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,
36
--
30
--
37
2.34.1
31
2.34.1
38
32
39
33
diff view generated by jsdifflib
1
From: Fabiano Rosas <farosas@suse.de>
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.
2
7
3
If a test was tagged with the "accel" tag and the specified
8
Unfortunately the nrf51_timer's implementation of this has a bug
4
accelerator it not present in the qemu binary, cancel the test.
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.
5
17
6
We can now write tests without explicit calls to require_accelerator,
18
The fix for this is to only advance update_counter_ns to the
7
just the tag is enough.
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.)
8
21
9
Signed-off-by: Fabiano Rosas <farosas@suse.de>
22
Cc: qemu-stable@nongnu.org
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.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
13
---
26
---
14
tests/avocado/avocado_qemu/__init__.py | 4 ++++
27
hw/timer/nrf51_timer.c | 7 ++++++-
15
1 file changed, 4 insertions(+)
28
1 file changed, 6 insertions(+), 1 deletion(-)
16
29
17
diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py
30
diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c
18
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/avocado/avocado_qemu/__init__.py
32
--- a/hw/timer/nrf51_timer.c
20
+++ b/tests/avocado/avocado_qemu/__init__.py
33
+++ b/hw/timer/nrf51_timer.c
21
@@ -XXX,XX +XXX,XX @@ def setUp(self):
34
@@ -XXX,XX +XXX,XX @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now)
22
35
uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
23
super().setUp('qemu-system-')
36
24
37
s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
25
+ accel_required = self._get_unique_tag_val('accel')
38
- s->update_counter_ns = now;
26
+ if accel_required:
39
+ /*
27
+ self.require_accelerator(accel_required)
40
+ * Only advance the sync time to the timestamp of the last tick,
28
+
41
+ * not all the way to 'now', so we don't lose time if we do
29
self.machine = self.params.get('machine',
42
+ * multiple resyncs in a single tick.
30
default=self._get_unique_tag_val('machine'))
43
+ */
44
+ s->update_counter_ns += ticks_to_ns(s, ticks);
45
return ticks;
46
}
31
47
32
--
48
--
33
2.34.1
49
2.34.1
34
35
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
Since commit acc0b8b05a when running the ZynqMP ZCU102 board with
3
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
4
a QEMU configured using --without-default-devices, we get:
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
5
Message-id: 20230607092112.655098-1-marcin.juszkiewicz@linaro.org
6
$ qemu-system-aarch64 -M xlnx-zcu102
7
qemu-system-aarch64: missing object type 'usb_dwc3'
8
Abort trap: 6
9
10
Fix by adding the missing Kconfig dependency.
11
12
Fixes: acc0b8b05a ("hw/arm/xlnx-zynqmp: Connect ZynqMP's USB controllers")
13
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Message-id: 20230216092327.2203-1-philmd@linaro.org
15
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
7
---
18
hw/arm/Kconfig | 1 +
8
hw/arm/Kconfig | 1 +
19
1 file changed, 1 insertion(+)
9
1 file changed, 1 insertion(+)
20
10
21
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
11
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
22
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/Kconfig
13
--- a/hw/arm/Kconfig
24
+++ b/hw/arm/Kconfig
14
+++ b/hw/arm/Kconfig
25
@@ -XXX,XX +XXX,XX @@ config XLNX_ZYNQMP_ARM
15
@@ -XXX,XX +XXX,XX @@ config SBSA_REF
26
select XLNX_CSU_DMA
16
select PL061 # GPIO
27
select XLNX_ZYNQMP
17
select USB_EHCI_SYSBUS
28
select XLNX_ZDMA
18
select WDT_SBSA
29
+ select USB_DWC3
19
+ select BOCHS_DISPLAY
30
20
31
config XLNX_VERSAL
21
config SABRELITE
32
bool
22
bool
33
--
23
--
34
2.34.1
24
2.34.1
35
36
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
From: Martin Kaiser <martin@kaiser.cx>
2
2
3
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
3
The Linux kernel added a flood check for RX data recently in commit
4
496a4471b7c3 ("serial: imx: work-around for hardware RX flood"). This
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
11
This patch adds support for the wake bit. wake is set when we receive a
12
new character (it's not set for break events). It seems that wake is
13
cleared by the kernel driver, the hardware does not have to clear it
14
automatically after data was read.
15
16
The wake bit can be configured as an interrupt source. Support this
17
mechanism as well.
18
19
Co-developed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
21
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
6
Message-id: 20230206223502.25122-6-philmd@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
24
---
9
linux-user/user-internals.h | 2 +-
25
include/hw/char/imx_serial.h | 1 +
10
target/arm/cpu.h | 2 +-
26
hw/char/imx_serial.c | 5 ++++-
11
linux-user/arm/cpu_loop.c | 4 ++--
27
2 files changed, 5 insertions(+), 1 deletion(-)
12
3 files changed, 4 insertions(+), 4 deletions(-)
13
28
14
diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
29
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
15
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/user-internals.h
31
--- a/include/hw/char/imx_serial.h
17
+++ b/linux-user/user-internals.h
32
+++ b/include/hw/char/imx_serial.h
18
@@ -XXX,XX +XXX,XX @@ void print_termios(void *arg);
33
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXSerialState, IMX_SERIAL)
19
#ifdef TARGET_ARM
34
20
static inline int regpairs_aligned(CPUArchState *cpu_env, int num)
35
#define UCR4_DREN BIT(0) /* Receive Data Ready interrupt enable */
36
#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
37
+#define UCR4_WKEN BIT(7) /* WAKE interrupt enable */
38
39
#define UTS1_TXEMPTY (1<<6)
40
#define UTS1_RXEMPTY (1<<5)
41
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/char/imx_serial.c
44
+++ b/hw/char/imx_serial.c
45
@@ -XXX,XX +XXX,XX @@ static void imx_update(IMXSerialState *s)
46
* TCEN and TXDC are both bit 3
47
* RDR and DREN are both bit 0
48
*/
49
- mask |= s->ucr4 & (UCR4_TCEN | UCR4_DREN);
50
+ mask |= s->ucr4 & (UCR4_WKEN | UCR4_TCEN | UCR4_DREN);
51
52
usr2 = s->usr2 & mask;
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)
21
{
57
{
22
- return cpu_env->eabi == 1;
58
+ IMXSerialState *s = (IMXSerialState *)opaque;
23
+ return cpu_env->eabi;
59
+
60
+ s->usr2 |= USR2_WAKE;
61
imx_put_data(opaque, *buf);
24
}
62
}
25
#elif defined(TARGET_MIPS) && defined(TARGET_ABI_MIPSO32)
26
static inline int regpairs_aligned(CPUArchState *cpu_env, int num) { return 1; }
27
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu.h
30
+++ b/target/arm/cpu.h
31
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
32
33
#if defined(CONFIG_USER_ONLY)
34
/* For usermode syscall translation. */
35
- int eabi;
36
+ bool eabi;
37
#endif
38
39
struct CPUBreakpoint *cpu_breakpoint[16];
40
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/linux-user/arm/cpu_loop.c
43
+++ b/linux-user/arm/cpu_loop.c
44
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
45
break;
46
case EXCP_SWI:
47
{
48
- env->eabi = 1;
49
+ env->eabi = true;
50
/* system call */
51
if (env->thumb) {
52
/* Thumb is always EABI style with syscall number in r7 */
53
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
54
* > 0xfffff and are handled below as out-of-range.
55
*/
56
n ^= ARM_SYSCALL_BASE;
57
- env->eabi = 0;
58
+ env->eabi = false;
59
}
60
}
61
63
62
--
64
--
63
2.34.1
65
2.34.1
64
66
65
67
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
3
We plan to add more hardware information into DeviceTree to limit amount
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
of hardcoded values in firmware.
5
Message-id: 20230206223502.25122-8-philmd@linaro.org
5
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
Message-id: 20230531171834.236569-1-marcin.juszkiewicz@linaro.org
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>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/cpu.h | 3 ++-
13
docs/system/arm/sbsa.rst | 38 +++++++++++++++++++++++++++++++-------
9
1 file changed, 2 insertions(+), 1 deletion(-)
14
1 file changed, 31 insertions(+), 7 deletions(-)
10
15
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/docs/system/arm/sbsa.rst b/docs/system/arm/sbsa.rst
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.h
18
--- a/docs/system/arm/sbsa.rst
14
+++ b/target/arm/cpu.h
19
+++ b/docs/system/arm/sbsa.rst
15
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
20
@@ -XXX,XX +XXX,XX @@ any real hardware the ``sbsa-ref`` board intends to look like real
16
21
hardware. The `Server Base System Architecture
17
void *nvic;
22
<https://developer.arm.com/documentation/den0029/latest>`_ defines a
18
const struct arm_boot_info *boot_info;
23
minimum base line of hardware support and importantly how the firmware
19
+#if !defined(CONFIG_USER_ONLY)
24
-reports that to any operating system. It is a static system that
20
/* Store GICv3CPUState to access from this struct */
25
-reports a very minimal DT to the firmware for non-discoverable
21
void *gicv3state;
26
-information about components affected by the qemu command line (i.e.
22
-#if defined(CONFIG_USER_ONLY)
27
-cpus and memory). As a result it must have a firmware specifically
23
+#else /* CONFIG_USER_ONLY */
28
-built to expect a certain hardware layout (as you would in a real
24
/* For usermode syscall translation. */
29
-machine).
25
bool eabi;
30
+reports that to any operating system.
26
#endif /* CONFIG_USER_ONLY */
31
32
It is intended to be a machine for developing firmware and testing
33
standards compliance with operating systems.
34
@@ -XXX,XX +XXX,XX @@ standards compliance with operating systems.
35
Supported devices
36
"""""""""""""""""
37
38
-The sbsa-ref board supports:
39
+The ``sbsa-ref`` board supports:
40
41
- A configurable number of AArch64 CPUs
42
- GIC version 3
43
@@ -XXX,XX +XXX,XX @@ The sbsa-ref board supports:
44
- Bochs display adapter on PCIe bus
45
- A generic SBSA watchdog device
46
47
+
48
+Board to firmware interface
49
+"""""""""""""""""""""""""""
50
+
51
+``sbsa-ref`` is a static system that reports a very minimal devicetree to the
52
+firmware for non-discoverable information about system components. This
53
+includes both internal hardware and parts affected by the qemu command line
54
+(i.e. CPUs and memory). As a result it must have a firmware specifically built
55
+to expect a certain hardware layout (as you would in a real machine).
56
+
57
+DeviceTree information
58
+''''''''''''''''''''''
59
+
60
+The devicetree provided by the board model to the firmware is not intended
61
+to be a complete compliant DT. It currently reports:
62
+
63
+ - CPUs
64
+ - memory
65
+ - platform version
66
+ - GIC addresses
67
+
68
+The platform version is only for informing platform firmware about
69
+what kind of ``sbsa-ref`` board it is running on. It is neither
70
+a QEMU versioned machine type nor a reflection of the level of the
71
+SBSA/SystemReady SR support provided.
72
+
73
+The ``machine-version-major`` value is updated when changes breaking
74
+fw compatibility are introduced. The ``machine-version-minor`` value
75
+is updated when features are added that don't break fw compatibility.
27
--
76
--
28
2.34.1
77
2.34.1
29
30
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
2
3
Nuvoton's PSPI is a general purpose SPI module which enables
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
4
connections to SPI-based peripheral devices.
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
5
Acked-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
6
Message-id: 20230612223456.33824-2-philmd@linaro.org
7
Reviewed-by: Chris Rauer <crauer@google.com>
7
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
8
Reviewed-by: Philippe Mathieu-Daude <philmd@linaro.org>
8
[PMD: Split from bigger patch: 1/4]
9
Message-id: 20230208235433.3989937-3-wuhaotsh@google.com
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
MAINTAINERS | 6 +-
12
include/hw/misc/raspberrypi-fw-defs.h | 163 ++++++++++++++++++++++++++
13
include/hw/ssi/npcm_pspi.h | 53 +++++++++
13
1 file changed, 163 insertions(+)
14
hw/ssi/npcm_pspi.c | 221 +++++++++++++++++++++++++++++++++++++
14
create mode 100644 include/hw/misc/raspberrypi-fw-defs.h
15
hw/ssi/meson.build | 2 +-
16
hw/ssi/trace-events | 5 +
17
5 files changed, 283 insertions(+), 4 deletions(-)
18
create mode 100644 include/hw/ssi/npcm_pspi.h
19
create mode 100644 hw/ssi/npcm_pspi.c
20
15
21
diff --git a/MAINTAINERS b/MAINTAINERS
16
diff --git a/include/hw/misc/raspberrypi-fw-defs.h b/include/hw/misc/raspberrypi-fw-defs.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/MAINTAINERS
24
+++ b/MAINTAINERS
25
@@ -XXX,XX +XXX,XX @@ M: Tyrone Ting <kfting@nuvoton.com>
26
M: Hao Wu <wuhaotsh@google.com>
27
L: qemu-arm@nongnu.org
28
S: Supported
29
-F: hw/*/npcm7xx*
30
-F: include/hw/*/npcm7xx*
31
-F: tests/qtest/npcm7xx*
32
+F: hw/*/npcm*
33
+F: include/hw/*/npcm*
34
+F: tests/qtest/npcm*
35
F: pc-bios/npcm7xx_bootrom.bin
36
F: roms/vbootrom
37
F: docs/system/arm/nuvoton.rst
38
diff --git a/include/hw/ssi/npcm_pspi.h b/include/hw/ssi/npcm_pspi.h
39
new file mode 100644
17
new file mode 100644
40
index XXXXXXX..XXXXXXX
18
index XXXXXXX..XXXXXXX
41
--- /dev/null
19
--- /dev/null
42
+++ b/include/hw/ssi/npcm_pspi.h
20
+++ b/include/hw/misc/raspberrypi-fw-defs.h
43
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
44
+/*
22
+/*
45
+ * Nuvoton Peripheral SPI Module
23
+ * Raspberry Pi firmware definitions
46
+ *
24
+ *
47
+ * Copyright 2023 Google LLC
25
+ * Copyright (C) 2022 Auriga LLC, based on Linux kernel
26
+ * `include/soc/bcm2835/raspberrypi-firmware.h` (Copyright © 2015 Broadcom)
48
+ *
27
+ *
49
+ * This program is free software; you can redistribute it and/or modify it
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
50
+ * under the terms of the GNU General Public License as published by the
51
+ * Free Software Foundation; either version 2 of the License, or
52
+ * (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful, but WITHOUT
55
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
56
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
57
+ * for more details.
58
+ */
29
+ */
59
+#ifndef NPCM_PSPI_H
60
+#define NPCM_PSPI_H
61
+
30
+
62
+#include "hw/ssi/ssi.h"
31
+#ifndef INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
63
+#include "hw/sysbus.h"
32
+#define INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
64
+
65
+/*
66
+ * Number of registers in our device state structure. Don't change this without
67
+ * incrementing the version_id in the vmstate.
68
+ */
69
+#define NPCM_PSPI_NR_REGS 3
70
+
71
+/**
72
+ * NPCMPSPIState - Device state for one Flash Interface Unit.
73
+ * @parent: System bus device.
74
+ * @mmio: Memory region for register access.
75
+ * @spi: The SPI bus mastered by this controller.
76
+ * @regs: Register contents.
77
+ * @irq: The interrupt request queue for this module.
78
+ *
79
+ * Each PSPI has a shared bank of registers, and controls up to four chip
80
+ * selects. Each chip select has a dedicated memory region which may be used to
81
+ * read and write the flash connected to that chip select as if it were memory.
82
+ */
83
+typedef struct NPCMPSPIState {
84
+ SysBusDevice parent;
85
+
86
+ MemoryRegion mmio;
87
+
88
+ SSIBus *spi;
89
+ uint16_t regs[NPCM_PSPI_NR_REGS];
90
+ qemu_irq irq;
91
+} NPCMPSPIState;
92
+
93
+#define TYPE_NPCM_PSPI "npcm-pspi"
94
+OBJECT_DECLARE_SIMPLE_TYPE(NPCMPSPIState, NPCM_PSPI)
95
+
96
+#endif /* NPCM_PSPI_H */
97
diff --git a/hw/ssi/npcm_pspi.c b/hw/ssi/npcm_pspi.c
98
new file mode 100644
99
index XXXXXXX..XXXXXXX
100
--- /dev/null
101
+++ b/hw/ssi/npcm_pspi.c
102
@@ -XXX,XX +XXX,XX @@
103
+/*
104
+ * Nuvoton NPCM Peripheral SPI Module (PSPI)
105
+ *
106
+ * Copyright 2023 Google LLC
107
+ *
108
+ * This program is free software; you can redistribute it and/or modify it
109
+ * under the terms of the GNU General Public License as published by the
110
+ * Free Software Foundation; either version 2 of the License, or
111
+ * (at your option) any later version.
112
+ *
113
+ * This program is distributed in the hope that it will be useful, but WITHOUT
114
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
115
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
116
+ * for more details.
117
+ */
118
+
33
+
119
+#include "qemu/osdep.h"
34
+#include "qemu/osdep.h"
120
+
35
+
121
+#include "hw/irq.h"
36
+enum rpi_firmware_property_tag {
122
+#include "hw/registerfields.h"
37
+ RPI_FWREQ_PROPERTY_END = 0,
123
+#include "hw/ssi/npcm_pspi.h"
38
+ RPI_FWREQ_GET_FIRMWARE_REVISION = 0x00000001,
124
+#include "migration/vmstate.h"
39
+ RPI_FWREQ_GET_FIRMWARE_VARIANT = 0x00000002,
125
+#include "qapi/error.h"
40
+ RPI_FWREQ_GET_FIRMWARE_HASH = 0x00000003,
126
+#include "qemu/error-report.h"
127
+#include "qemu/log.h"
128
+#include "qemu/module.h"
129
+#include "qemu/units.h"
130
+
41
+
131
+#include "trace.h"
42
+ RPI_FWREQ_SET_CURSOR_INFO = 0x00008010,
43
+ RPI_FWREQ_SET_CURSOR_STATE = 0x00008011,
132
+
44
+
133
+REG16(PSPI_DATA, 0x0)
45
+ RPI_FWREQ_GET_BOARD_MODEL = 0x00010001,
134
+REG16(PSPI_CTL1, 0x2)
46
+ RPI_FWREQ_GET_BOARD_REVISION = 0x00010002,
135
+ FIELD(PSPI_CTL1, SPIEN, 0, 1)
47
+ RPI_FWREQ_GET_BOARD_MAC_ADDRESS = 0x00010003,
136
+ FIELD(PSPI_CTL1, MOD, 2, 1)
48
+ RPI_FWREQ_GET_BOARD_SERIAL = 0x00010004,
137
+ FIELD(PSPI_CTL1, EIR, 5, 1)
49
+ RPI_FWREQ_GET_ARM_MEMORY = 0x00010005,
138
+ FIELD(PSPI_CTL1, EIW, 6, 1)
50
+ RPI_FWREQ_GET_VC_MEMORY = 0x00010006,
139
+ FIELD(PSPI_CTL1, SCM, 7, 1)
51
+ RPI_FWREQ_GET_CLOCKS = 0x00010007,
140
+ FIELD(PSPI_CTL1, SCIDL, 8, 1)
52
+ RPI_FWREQ_GET_POWER_STATE = 0x00020001,
141
+ FIELD(PSPI_CTL1, SCDV, 9, 7)
53
+ RPI_FWREQ_GET_TIMING = 0x00020002,
142
+REG16(PSPI_STAT, 0x4)
54
+ RPI_FWREQ_SET_POWER_STATE = 0x00028001,
143
+ FIELD(PSPI_STAT, BSY, 0, 1)
55
+ RPI_FWREQ_GET_CLOCK_STATE = 0x00030001,
144
+ FIELD(PSPI_STAT, RBF, 1, 1)
56
+ RPI_FWREQ_GET_CLOCK_RATE = 0x00030002,
57
+ RPI_FWREQ_GET_VOLTAGE = 0x00030003,
58
+ RPI_FWREQ_GET_MAX_CLOCK_RATE = 0x00030004,
59
+ RPI_FWREQ_GET_MAX_VOLTAGE = 0x00030005,
60
+ RPI_FWREQ_GET_TEMPERATURE = 0x00030006,
61
+ RPI_FWREQ_GET_MIN_CLOCK_RATE = 0x00030007,
62
+ RPI_FWREQ_GET_MIN_VOLTAGE = 0x00030008,
63
+ RPI_FWREQ_GET_TURBO = 0x00030009,
64
+ RPI_FWREQ_GET_MAX_TEMPERATURE = 0x0003000a,
65
+ RPI_FWREQ_GET_STC = 0x0003000b,
66
+ RPI_FWREQ_ALLOCATE_MEMORY = 0x0003000c,
67
+ RPI_FWREQ_LOCK_MEMORY = 0x0003000d,
68
+ RPI_FWREQ_UNLOCK_MEMORY = 0x0003000e,
69
+ RPI_FWREQ_RELEASE_MEMORY = 0x0003000f,
70
+ RPI_FWREQ_EXECUTE_CODE = 0x00030010,
71
+ RPI_FWREQ_EXECUTE_QPU = 0x00030011,
72
+ RPI_FWREQ_SET_ENABLE_QPU = 0x00030012,
73
+ RPI_FWREQ_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
74
+ RPI_FWREQ_GET_EDID_BLOCK = 0x00030020,
75
+ RPI_FWREQ_GET_CUSTOMER_OTP = 0x00030021,
76
+ RPI_FWREQ_GET_EDID_BLOCK_DISPLAY = 0x00030023,
77
+ RPI_FWREQ_GET_DOMAIN_STATE = 0x00030030,
78
+ RPI_FWREQ_GET_THROTTLED = 0x00030046,
79
+ RPI_FWREQ_GET_CLOCK_MEASURED = 0x00030047,
80
+ RPI_FWREQ_NOTIFY_REBOOT = 0x00030048,
81
+ RPI_FWREQ_SET_CLOCK_STATE = 0x00038001,
82
+ RPI_FWREQ_SET_CLOCK_RATE = 0x00038002,
83
+ RPI_FWREQ_SET_VOLTAGE = 0x00038003,
84
+ RPI_FWREQ_SET_MAX_CLOCK_RATE = 0x00038004,
85
+ RPI_FWREQ_SET_MIN_CLOCK_RATE = 0x00038007,
86
+ RPI_FWREQ_SET_TURBO = 0x00038009,
87
+ RPI_FWREQ_SET_CUSTOMER_OTP = 0x00038021,
88
+ RPI_FWREQ_SET_DOMAIN_STATE = 0x00038030,
89
+ RPI_FWREQ_GET_GPIO_STATE = 0x00030041,
90
+ RPI_FWREQ_SET_GPIO_STATE = 0x00038041,
91
+ RPI_FWREQ_SET_SDHOST_CLOCK = 0x00038042,
92
+ RPI_FWREQ_GET_GPIO_CONFIG = 0x00030043,
93
+ RPI_FWREQ_SET_GPIO_CONFIG = 0x00038043,
94
+ RPI_FWREQ_GET_PERIPH_REG = 0x00030045,
95
+ RPI_FWREQ_SET_PERIPH_REG = 0x00038045,
96
+ RPI_FWREQ_GET_POE_HAT_VAL = 0x00030049,
97
+ RPI_FWREQ_SET_POE_HAT_VAL = 0x00038049,
98
+ RPI_FWREQ_SET_POE_HAT_VAL_OLD = 0x00030050,
99
+ RPI_FWREQ_NOTIFY_XHCI_RESET = 0x00030058,
100
+ RPI_FWREQ_GET_REBOOT_FLAGS = 0x00030064,
101
+ RPI_FWREQ_SET_REBOOT_FLAGS = 0x00038064,
102
+ RPI_FWREQ_NOTIFY_DISPLAY_DONE = 0x00030066,
145
+
103
+
146
+static void npcm_pspi_update_irq(NPCMPSPIState *s)
104
+ /* Dispmanx TAGS */
147
+{
105
+ RPI_FWREQ_FRAMEBUFFER_ALLOCATE = 0x00040001,
148
+ int level = 0;
106
+ RPI_FWREQ_FRAMEBUFFER_BLANK = 0x00040002,
107
+ RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003,
108
+ RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004,
109
+ RPI_FWREQ_FRAMEBUFFER_GET_DEPTH = 0x00040005,
110
+ RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006,
111
+ RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007,
112
+ RPI_FWREQ_FRAMEBUFFER_GET_PITCH = 0x00040008,
113
+ RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
114
+ RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
115
+ RPI_FWREQ_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
116
+ RPI_FWREQ_FRAMEBUFFER_GET_LAYER = 0x0004000c,
117
+ RPI_FWREQ_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
118
+ RPI_FWREQ_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
119
+ RPI_FWREQ_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
120
+ RPI_FWREQ_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
121
+ RPI_FWREQ_FRAMEBUFFER_RELEASE = 0x00048001,
122
+ RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
123
+ RPI_FWREQ_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
124
+ RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
125
+ RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
126
+ RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
127
+ RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
128
+ RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
129
+ RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006,
130
+ RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007,
131
+ RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
132
+ RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
133
+ RPI_FWREQ_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
134
+ RPI_FWREQ_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
135
+ RPI_FWREQ_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
136
+ RPI_FWREQ_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
137
+ RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
138
+ RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
139
+ RPI_FWREQ_FRAMEBUFFER_SET_DEPTH = 0x00048005,
140
+ RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
141
+ RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
142
+ RPI_FWREQ_FRAMEBUFFER_SET_PITCH = 0x00048008,
143
+ RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
144
+ RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
145
+ RPI_FWREQ_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
149
+
146
+
150
+ /* Only fire IRQ when the module is enabled. */
147
+ RPI_FWREQ_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
151
+ if (FIELD_EX16(s->regs[R_PSPI_CTL1], PSPI_CTL1, SPIEN)) {
148
+ RPI_FWREQ_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
152
+ /* Update interrupt as BSY is cleared. */
149
+ RPI_FWREQ_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
153
+ if ((!FIELD_EX16(s->regs[R_PSPI_STAT], PSPI_STAT, BSY)) &&
150
+ RPI_FWREQ_FRAMEBUFFER_SET_LAYER = 0x0004800c,
154
+ FIELD_EX16(s->regs[R_PSPI_CTL1], PSPI_CTL1, EIW)) {
151
+ RPI_FWREQ_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
155
+ level = 1;
152
+ RPI_FWREQ_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
156
+ }
157
+
153
+
158
+ /* Update interrupt as RBF is set. */
154
+ RPI_FWREQ_VCHIQ_INIT = 0x00048010,
159
+ if (FIELD_EX16(s->regs[R_PSPI_STAT], PSPI_STAT, RBF) &&
160
+ FIELD_EX16(s->regs[R_PSPI_CTL1], PSPI_CTL1, EIR)) {
161
+ level = 1;
162
+ }
163
+ }
164
+ qemu_set_irq(s->irq, level);
165
+}
166
+
155
+
167
+static uint16_t npcm_pspi_read_data(NPCMPSPIState *s)
156
+ RPI_FWREQ_SET_PLANE = 0x00048015,
168
+{
157
+ RPI_FWREQ_GET_DISPLAY_TIMING = 0x00040017,
169
+ uint16_t value = s->regs[R_PSPI_DATA];
158
+ RPI_FWREQ_SET_TIMING = 0x00048017,
170
+
159
+ RPI_FWREQ_GET_DISPLAY_CFG = 0x00040018,
171
+ /* Clear stat bits as the value are read out. */
160
+ RPI_FWREQ_SET_DISPLAY_POWER = 0x00048019,
172
+ s->regs[R_PSPI_STAT] = 0;
161
+ RPI_FWREQ_GET_COMMAND_LINE = 0x00050001,
173
+
162
+ RPI_FWREQ_GET_DMA_CHANNELS = 0x00060001,
174
+ return value;
175
+}
176
+
177
+static void npcm_pspi_write_data(NPCMPSPIState *s, uint16_t data)
178
+{
179
+ uint16_t value = 0;
180
+
181
+ if (FIELD_EX16(s->regs[R_PSPI_CTL1], PSPI_CTL1, MOD)) {
182
+ value = ssi_transfer(s->spi, extract16(data, 8, 8)) << 8;
183
+ }
184
+ value |= ssi_transfer(s->spi, extract16(data, 0, 8));
185
+ s->regs[R_PSPI_DATA] = value;
186
+
187
+ /* Mark data as available */
188
+ s->regs[R_PSPI_STAT] = R_PSPI_STAT_BSY_MASK | R_PSPI_STAT_RBF_MASK;
189
+}
190
+
191
+/* Control register read handler. */
192
+static uint64_t npcm_pspi_ctrl_read(void *opaque, hwaddr addr,
193
+ unsigned int size)
194
+{
195
+ NPCMPSPIState *s = opaque;
196
+ uint16_t value;
197
+
198
+ switch (addr) {
199
+ case A_PSPI_DATA:
200
+ value = npcm_pspi_read_data(s);
201
+ break;
202
+
203
+ case A_PSPI_CTL1:
204
+ value = s->regs[R_PSPI_CTL1];
205
+ break;
206
+
207
+ case A_PSPI_STAT:
208
+ value = s->regs[R_PSPI_STAT];
209
+ break;
210
+
211
+ default:
212
+ qemu_log_mask(LOG_GUEST_ERROR,
213
+ "%s: write to invalid offset 0x%" PRIx64 "\n",
214
+ DEVICE(s)->canonical_path, addr);
215
+ return 0;
216
+ }
217
+ trace_npcm_pspi_ctrl_read(DEVICE(s)->canonical_path, addr, value);
218
+ npcm_pspi_update_irq(s);
219
+
220
+ return value;
221
+}
222
+
223
+/* Control register write handler. */
224
+static void npcm_pspi_ctrl_write(void *opaque, hwaddr addr, uint64_t v,
225
+ unsigned int size)
226
+{
227
+ NPCMPSPIState *s = opaque;
228
+ uint16_t value = v;
229
+
230
+ trace_npcm_pspi_ctrl_write(DEVICE(s)->canonical_path, addr, value);
231
+
232
+ switch (addr) {
233
+ case A_PSPI_DATA:
234
+ npcm_pspi_write_data(s, value);
235
+ break;
236
+
237
+ case A_PSPI_CTL1:
238
+ s->regs[R_PSPI_CTL1] = value;
239
+ break;
240
+
241
+ case A_PSPI_STAT:
242
+ qemu_log_mask(LOG_GUEST_ERROR,
243
+ "%s: write to read-only register PSPI_STAT: 0x%08"
244
+ PRIx64 "\n", DEVICE(s)->canonical_path, v);
245
+ break;
246
+
247
+ default:
248
+ qemu_log_mask(LOG_GUEST_ERROR,
249
+ "%s: write to invalid offset 0x%" PRIx64 "\n",
250
+ DEVICE(s)->canonical_path, addr);
251
+ return;
252
+ }
253
+ npcm_pspi_update_irq(s);
254
+}
255
+
256
+static const MemoryRegionOps npcm_pspi_ctrl_ops = {
257
+ .read = npcm_pspi_ctrl_read,
258
+ .write = npcm_pspi_ctrl_write,
259
+ .endianness = DEVICE_LITTLE_ENDIAN,
260
+ .valid = {
261
+ .min_access_size = 1,
262
+ .max_access_size = 2,
263
+ .unaligned = false,
264
+ },
265
+ .impl = {
266
+ .min_access_size = 2,
267
+ .max_access_size = 2,
268
+ .unaligned = false,
269
+ },
270
+};
163
+};
271
+
164
+
272
+static void npcm_pspi_enter_reset(Object *obj, ResetType type)
165
+enum rpi_firmware_clk_id {
273
+{
166
+ RPI_FIRMWARE_EMMC_CLK_ID = 1,
274
+ NPCMPSPIState *s = NPCM_PSPI(obj);
167
+ RPI_FIRMWARE_UART_CLK_ID,
275
+
168
+ RPI_FIRMWARE_ARM_CLK_ID,
276
+ trace_npcm_pspi_enter_reset(DEVICE(obj)->canonical_path, type);
169
+ RPI_FIRMWARE_CORE_CLK_ID,
277
+ memset(s->regs, 0, sizeof(s->regs));
170
+ RPI_FIRMWARE_V3D_CLK_ID,
278
+}
171
+ RPI_FIRMWARE_H264_CLK_ID,
279
+
172
+ RPI_FIRMWARE_ISP_CLK_ID,
280
+static void npcm_pspi_realize(DeviceState *dev, Error **errp)
173
+ RPI_FIRMWARE_SDRAM_CLK_ID,
281
+{
174
+ RPI_FIRMWARE_PIXEL_CLK_ID,
282
+ NPCMPSPIState *s = NPCM_PSPI(dev);
175
+ RPI_FIRMWARE_PWM_CLK_ID,
283
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
176
+ RPI_FIRMWARE_HEVC_CLK_ID,
284
+ Object *obj = OBJECT(dev);
177
+ RPI_FIRMWARE_EMMC2_CLK_ID,
285
+
178
+ RPI_FIRMWARE_M2MC_CLK_ID,
286
+ s->spi = ssi_create_bus(dev, "pspi");
179
+ RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
287
+ memory_region_init_io(&s->mmio, obj, &npcm_pspi_ctrl_ops, s,
180
+ RPI_FIRMWARE_VEC_CLK_ID,
288
+ "mmio", 4 * KiB);
181
+ RPI_FIRMWARE_NUM_CLK_ID,
289
+ sysbus_init_mmio(sbd, &s->mmio);
290
+ sysbus_init_irq(sbd, &s->irq);
291
+}
292
+
293
+static const VMStateDescription vmstate_npcm_pspi = {
294
+ .name = "npcm-pspi",
295
+ .version_id = 0,
296
+ .minimum_version_id = 0,
297
+ .fields = (VMStateField[]) {
298
+ VMSTATE_UINT16_ARRAY(regs, NPCMPSPIState, NPCM_PSPI_NR_REGS),
299
+ VMSTATE_END_OF_LIST(),
300
+ },
301
+};
182
+};
302
+
183
+
303
+
184
+#endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */
304
+static void npcm_pspi_class_init(ObjectClass *klass, void *data)
305
+{
306
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
307
+ DeviceClass *dc = DEVICE_CLASS(klass);
308
+
309
+ dc->desc = "NPCM Peripheral SPI Module";
310
+ dc->realize = npcm_pspi_realize;
311
+ dc->vmsd = &vmstate_npcm_pspi;
312
+ rc->phases.enter = npcm_pspi_enter_reset;
313
+}
314
+
315
+static const TypeInfo npcm_pspi_types[] = {
316
+ {
317
+ .name = TYPE_NPCM_PSPI,
318
+ .parent = TYPE_SYS_BUS_DEVICE,
319
+ .instance_size = sizeof(NPCMPSPIState),
320
+ .class_init = npcm_pspi_class_init,
321
+ },
322
+};
323
+DEFINE_TYPES(npcm_pspi_types);
324
diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build
325
index XXXXXXX..XXXXXXX 100644
326
--- a/hw/ssi/meson.build
327
+++ b/hw/ssi/meson.build
328
@@ -XXX,XX +XXX,XX @@
329
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_smc.c'))
330
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-spi.c'))
331
-softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_fiu.c'))
332
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_fiu.c', 'npcm_pspi.c'))
333
softmmu_ss.add(when: 'CONFIG_PL022', if_true: files('pl022.c'))
334
softmmu_ss.add(when: 'CONFIG_SIFIVE_SPI', if_true: files('sifive_spi.c'))
335
softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c'))
336
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
337
index XXXXXXX..XXXXXXX 100644
338
--- a/hw/ssi/trace-events
339
+++ b/hw/ssi/trace-events
340
@@ -XXX,XX +XXX,XX @@ npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s offset:
341
npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
342
npcm7xx_fiu_flash_write(const char *id, unsigned cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
343
344
+# npcm_pspi.c
345
+npcm_pspi_enter_reset(const char *id, int reset_type) "%s reset type: %d"
346
+npcm_pspi_ctrl_read(const char *id, uint64_t addr, uint16_t data) "%s offset: 0x%03" PRIx64 " value: 0x%04" PRIx16
347
+npcm_pspi_ctrl_write(const char *id, uint64_t addr, uint16_t data) "%s offset: 0x%03" PRIx64 " value: 0x%04" PRIx16
348
+
349
# ibex_spi_host.c
350
351
ibex_spi_host_reset(const char *msg) "%s"
352
--
185
--
353
2.34.1
186
2.34.1
187
188
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
2
3
Replace magic property values by a proper definition,
4
removing redundant comments.
5
6
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20230206223502.25122-10-philmd@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>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
14
---
8
target/arm/cpu.h | 2 +-
15
hw/misc/bcm2835_property.c | 101 +++++++++++++++++++------------------
9
1 file changed, 1 insertion(+), 1 deletion(-)
16
1 file changed, 51 insertions(+), 50 deletions(-)
10
17
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.h
20
--- a/hw/misc/bcm2835_property.c
14
+++ b/target/arm/cpu.h
21
+++ b/hw/misc/bcm2835_property.c
15
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
22
@@ -XXX,XX +XXX,XX @@
16
uint32_t ctrl;
23
#include "migration/vmstate.h"
17
} sau;
24
#include "hw/irq.h"
18
25
#include "hw/misc/bcm2835_mbox_defs.h"
19
- void *nvic;
26
+#include "hw/misc/raspberrypi-fw-defs.h"
20
#if !defined(CONFIG_USER_ONLY)
27
#include "sysemu/dma.h"
21
+ void *nvic;
28
#include "qemu/log.h"
22
const struct arm_boot_info *boot_info;
29
#include "qemu/module.h"
23
/* Store GICv3CPUState to access from this struct */
30
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
24
void *gicv3state;
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
25
--
307
--
26
2.34.1
308
2.34.1
27
309
28
310
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
2
3
Manually convert to OBJECT_DECLARE_SIMPLE_TYPE() macro,
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
4
similarly to automatic conversion from commit 8063396bf3
5
("Use OBJECT_DECLARE_SIMPLE_TYPE when possible").
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230206223502.25122-2-philmd@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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
include/hw/intc/armv7m_nvic.h | 5 +----
12
include/hw/arm/raspi_platform.h | 5 +++++
13
1 file changed, 1 insertion(+), 4 deletions(-)
13
hw/misc/bcm2835_property.c | 8 +++++---
14
2 files changed, 10 insertions(+), 3 deletions(-)
14
15
15
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
16
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/intc/armv7m_nvic.h
18
--- a/include/hw/arm/raspi_platform.h
18
+++ b/include/hw/intc/armv7m_nvic.h
19
+++ b/include/hw/arm/raspi_platform.h
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
20
#include "qom/object.h"
21
#define INTERRUPT_ILLEGAL_TYPE0 6
21
22
#define INTERRUPT_ILLEGAL_TYPE1 7
22
#define TYPE_NVIC "armv7m_nvic"
23
23
-
24
+/* Clock rates */
24
-typedef struct NVICState NVICState;
25
+#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
25
-DECLARE_INSTANCE_CHECKER(NVICState, NVIC,
26
+#define RPI_FIRMWARE_UART_CLK_RATE 3000000
26
- TYPE_NVIC)
27
+#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
27
+OBJECT_DECLARE_SIMPLE_TYPE(NVICState, NVIC)
28
+
28
29
#endif
29
/* Highest permitted number of exceptions (architectural limit) */
30
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
30
#define NVIC_MAX_VECTORS 512
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;
31
--
60
--
32
2.34.1
61
2.34.1
33
62
34
63
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
2
3
Although the 'eabi' field is only used in user emulation where
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
4
CPU reset doesn't occur, it doesn't belong to the area to reset.
5
Move it after the 'end_reset_fields' for consistency.
6
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20230206223502.25122-7-philmd@linaro.org
5
Message-id: 20230612223456.33824-5-philmd@linaro.org
6
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
7
[PMD: Split from bigger patch: 3/4]
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
[PMM: added a comment about RPI_FIRMWARE_CORE_CLK_RATE
10
really being SoC-specific]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
target/arm/cpu.h | 9 ++++-----
14
include/hw/arm/raspi_platform.h | 5 +++++
13
1 file changed, 4 insertions(+), 5 deletions(-)
15
hw/misc/bcm2835_property.c | 3 +++
16
2 files changed, 8 insertions(+)
14
17
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
20
--- a/include/hw/arm/raspi_platform.h
18
+++ b/target/arm/cpu.h
21
+++ b/include/hw/arm/raspi_platform.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
22
@@ -XXX,XX +XXX,XX @@
20
ARMVectorReg zarray[ARM_MAX_VQ * 16];
23
/* Clock rates */
24
#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
25
#define RPI_FIRMWARE_UART_CLK_RATE 3000000
26
+/*
27
+ * TODO: this is really SoC-specific; we might want to
28
+ * set it per-SoC if it turns out any guests care.
29
+ */
30
+#define RPI_FIRMWARE_CORE_CLK_RATE 350000000
31
#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
32
21
#endif
33
#endif
22
34
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
23
-#if defined(CONFIG_USER_ONLY)
35
index XXXXXXX..XXXXXXX 100644
24
- /* For usermode syscall translation. */
36
--- a/hw/misc/bcm2835_property.c
25
- bool eabi;
37
+++ b/hw/misc/bcm2835_property.c
26
-#endif
38
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
27
-
39
case RPI_FIRMWARE_UART_CLK_ID:
28
struct CPUBreakpoint *cpu_breakpoint[16];
40
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE);
29
struct CPUWatchpoint *cpu_watchpoint[16];
41
break;
30
42
+ case RPI_FIRMWARE_CORE_CLK_ID:
31
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
43
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_CORE_CLK_RATE);
32
const struct arm_boot_info *boot_info;
44
+ break;
33
/* Store GICv3CPUState to access from this struct */
45
default:
34
void *gicv3state;
46
stl_le_phys(&s->dma_as, value + 16,
35
+#if defined(CONFIG_USER_ONLY)
47
RPI_FIRMWARE_DEFAULT_CLK_RATE);
36
+ /* For usermode syscall translation. */
37
+ bool eabi;
38
+#endif /* CONFIG_USER_ONLY */
39
40
#ifdef TARGET_TAGGED_ADDRESSES
41
/* Linux syscall tagged address support */
42
--
48
--
43
2.34.1
49
2.34.1
44
50
45
51
diff view generated by jsdifflib