1
Hi; here's a target-arm pullreq. Mostly this is some decodetree
1
The following changes since commit 5767815218efd3cbfd409505ed824d5f356044ae:
2
conversion patches from me, plus a scattering of other bug fixes.
3
2
4
thanks
3
Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging (2024-02-14 15:45:52 +0000)
5
-- PMM
6
7
The following changes since commit e3660cc1e3cb136af50c0eaaeac27943c2438d1d:
8
9
Merge tag 'pull-loongarch-20230616' of https://gitlab.com/gaosong/qemu into staging (2023-06-16 12:30:16 +0200)
10
4
11
are available in the Git repository at:
5
are available in the Git repository at:
12
6
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230619
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240215
14
8
15
for you to fetch changes up to 074259c0f2ac40042dce766d870318cc22f388eb:
9
for you to fetch changes up to f780e63fe731b058fe52d43653600d8729a1b5f2:
16
10
17
hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property (2023-06-19 15:27:21 +0100)
11
docs: Add documentation for the mps3-an536 board (2024-02-15 14:32:39 +0000)
18
12
19
----------------------------------------------------------------
13
----------------------------------------------------------------
20
target-arm queue:
14
target-arm queue:
21
* Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
15
* hw/arm/xilinx_zynq: Wire FIQ between CPU <> GIC
22
* Return correct result for LDG when ATA=0
16
* linux-user/aarch64: Choose SYNC as the preferred MTE mode
23
* Conversion of system insns, loads and stores to decodetree
17
* Fix some errors in SVE/SME handling of MTE tags
24
* hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
18
* hw/pci-host/raven.c: Mark raven_io_ops as implementing unaligned accesses
25
* hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
19
* hw/block/tc58128: Don't emit deprecation warning under qtest
26
* hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
20
* tests/qtest: Fix handling of npcm7xx and GMAC tests
27
* hw/arm/Kconfig: sbsa-ref uses Bochs display
21
* hw/arm/virt: Wire up non-secure EL2 virtual timer IRQ
28
* imx_serial: set wake bit when we receive a data byte
22
* tests/qtest/npcm7xx_emc-test: Connect all NICs to a backend
29
* docs: sbsa: document board to firmware interface
23
* Don't assert on vmload/vmsave of M-profile CPUs
30
* hw/misc/bcm2835_property: avoid hard-coded constants
24
* hw/arm/smmuv3: add support for stage 1 access fault
25
* hw/arm/stellaris: QOM cleanups
26
* Use new CBAR encoding for all v8 CPUs, not all aarch64 CPUs
27
* Improve Cortex_R52 IMPDEF sysreg modelling
28
* Allow access to SPSR_hyp from hyp mode
29
* New board model mps3-an536 (Cortex-R52)
31
30
32
----------------------------------------------------------------
31
----------------------------------------------------------------
33
Marcin Juszkiewicz (2):
32
Luc Michel (1):
34
hw/arm/Kconfig: sbsa-ref uses Bochs display
33
hw/arm/smmuv3: add support for stage 1 access fault
35
docs: sbsa: document board to firmware interface
36
34
37
Martin Kaiser (1):
35
Nabih Estefan (1):
38
imx_serial: set wake bit when we receive a data byte
36
tests/qtest: Fix GMAC test to run on a machine in upstream QEMU
39
37
40
Peter Maydell (26):
38
Peter Maydell (22):
41
target/arm: Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
39
hw/pci-host/raven.c: Mark raven_io_ops as implementing unaligned accesses
42
target/arm: Return correct result for LDG when ATA=0
40
hw/block/tc58128: Don't emit deprecation warning under qtest
43
target/arm: Pass memop to gen_mte_check1_mmuidx() in reg_imm9 decode
41
tests/qtest/meson.build: Don't include qtests_npcm7xx in qtests_aarch64
44
target/arm: Consistently use finalize_memop_asimd() for ASIMD loads/stores
42
tests/qtest/bios-tables-test: Allow changes to virt GTDT
45
target/arm: Convert hint instruction space to decodetree
43
hw/arm/virt: Wire up non-secure EL2 virtual timer IRQ
46
target/arm: Convert barrier insns to decodetree
44
tests/qtest/bios-tables-tests: Update virt golden reference
47
target/arm: Convert CFINV, XAFLAG and AXFLAG to decodetree
45
hw/arm/npcm7xx: Call qemu_configure_nic_device() for GMAC modules
48
target/arm: Convert MSR (immediate) to decodetree
46
tests/qtest/npcm7xx_emc-test: Connect all NICs to a backend
49
target/arm: Convert MSR (reg), MRS, SYS, SYSL to decodetree
47
target/arm: Don't get MDCR_EL2 in pmu_counter_enabled() before checking ARM_FEATURE_PMU
50
target/arm: Convert exception generation instructions to decodetree
48
target/arm: Use new CBAR encoding for all v8 CPUs, not all aarch64 CPUs
51
target/arm: Convert load/store exclusive and ordered to decodetree
49
target/arm: The Cortex-R52 has a read-only CBAR
52
target/arm: Convert LDXP, STXP, CASP, CAS to decodetree
50
target/arm: Add Cortex-R52 IMPDEF sysregs
53
target/arm: Convert load reg (literal) group to decodetree
51
target/arm: Allow access to SPSR_hyp from hyp mode
54
target/arm: Convert load/store-pair to decodetree
52
hw/misc/mps2-scc: Fix condition for CFG3 register
55
target/arm: Convert ld/st reg+imm9 insns to decodetree
53
hw/misc/mps2-scc: Factor out which-board conditionals
56
target/arm: Convert LDR/STR with 12-bit immediate to decodetree
54
hw/misc/mps2-scc: Make changes needed for AN536 FPGA image
57
target/arm: Convert LDR/STR reg+reg to decodetree
55
hw/arm/mps3r: Initial skeleton for mps3-an536 board
58
target/arm: Convert atomic memory ops to decodetree
56
hw/arm/mps3r: Add CPUs, GIC, and per-CPU RAM
59
target/arm: Convert load (pointer auth) insns to decodetree
57
hw/arm/mps3r: Add UARTs
60
target/arm: Convert LDAPR/STLR (imm) to decodetree
58
hw/arm/mps3r: Add GPIO, watchdog, dual-timer, I2C devices
61
target/arm: Convert load/store (multiple structures) to decodetree
59
hw/arm/mps3r: Add remaining devices
62
target/arm: Convert load/store single structure to decodetree
60
docs: Add documentation for the mps3-an536 board
63
target/arm: Convert load/store tags insns to decodetree
64
hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
65
hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
66
hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
67
61
68
Sergey Kambalin (4):
62
Philippe Mathieu-Daudé (5):
69
hw/arm/raspi: Import Linux raspi definitions as 'raspberrypi-fw-defs.h'
63
hw/arm/xilinx_zynq: Wire FIQ between CPU <> GIC
70
hw/misc/bcm2835_property: Use 'raspberrypi-fw-defs.h' definitions
64
hw/arm/stellaris: Convert ADC controller to Resettable interface
71
hw/misc/bcm2835_property: Replace magic frequency values by definitions
65
hw/arm/stellaris: Convert I2C controller to Resettable interface
72
hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property
66
hw/arm/stellaris: Add missing QOM 'machine' parent
67
hw/arm/stellaris: Add missing QOM 'SoC' parent
73
68
74
docs/system/arm/sbsa.rst | 38 +-
69
Richard Henderson (6):
75
include/hw/arm/raspi_platform.h | 10 +
70
linux-user/aarch64: Choose SYNC as the preferred MTE mode
76
include/hw/char/imx_serial.h | 1 +
71
target/arm: Fix nregs computation in do_{ld,st}_zpa
77
include/hw/misc/raspberrypi-fw-defs.h | 163 ++
72
target/arm: Adjust and validate mtedesc sizem1
78
target/arm/tcg/a64.decode | 403 ++++
73
target/arm: Split out make_svemte_desc
79
hw/char/imx_serial.c | 5 +-
74
target/arm: Handle mte in do_ldrq, do_ldro
80
hw/intc/allwinner-a10-pic.c | 2 +-
75
target/arm: Fix SVE/SME gross MTE suppression checks
81
hw/misc/bcm2835_property.c | 112 +-
76
82
hw/sd/allwinner-sdhost.c | 2 +-
77
MAINTAINERS | 3 +-
83
hw/timer/nrf51_timer.c | 7 +-
78
docs/system/arm/mps2.rst | 37 +-
84
target/arm/tcg/translate-a64.c | 3319 +++++++++++++++------------------
79
configs/devices/arm-softmmu/default.mak | 1 +
85
hw/arm/Kconfig | 1 +
80
hw/arm/smmuv3-internal.h | 1 +
86
12 files changed, 2157 insertions(+), 1906 deletions(-)
81
include/hw/arm/smmu-common.h | 1 +
87
create mode 100644 include/hw/misc/raspberrypi-fw-defs.h
82
include/hw/arm/virt.h | 2 +
83
include/hw/misc/mps2-scc.h | 1 +
84
linux-user/aarch64/target_prctl.h | 29 +-
85
target/arm/internals.h | 2 +-
86
target/arm/tcg/translate-a64.h | 2 +
87
hw/arm/mps3r.c | 640 ++++++++++++++++++++++++++++++++
88
hw/arm/npcm7xx.c | 1 +
89
hw/arm/smmu-common.c | 11 +
90
hw/arm/smmuv3.c | 1 +
91
hw/arm/stellaris.c | 47 ++-
92
hw/arm/virt-acpi-build.c | 20 +-
93
hw/arm/virt.c | 60 ++-
94
hw/arm/xilinx_zynq.c | 2 +
95
hw/block/tc58128.c | 4 +-
96
hw/misc/mps2-scc.c | 138 ++++++-
97
hw/pci-host/raven.c | 1 +
98
target/arm/helper.c | 14 +-
99
target/arm/tcg/cpu32.c | 109 ++++++
100
target/arm/tcg/op_helper.c | 43 ++-
101
target/arm/tcg/sme_helper.c | 8 +-
102
target/arm/tcg/sve_helper.c | 12 +-
103
target/arm/tcg/translate-sme.c | 15 +-
104
target/arm/tcg/translate-sve.c | 83 +++--
105
target/arm/tcg/translate.c | 19 +-
106
tests/qtest/npcm7xx_emc-test.c | 5 +-
107
tests/qtest/npcm_gmac-test.c | 84 +----
108
hw/arm/Kconfig | 5 +
109
hw/arm/meson.build | 1 +
110
tests/data/acpi/virt/FACP | Bin 276 -> 276 bytes
111
tests/data/acpi/virt/GTDT | Bin 96 -> 104 bytes
112
tests/qtest/meson.build | 4 +-
113
36 files changed, 1184 insertions(+), 222 deletions(-)
114
create mode 100644 hw/arm/mps3r.c
115
diff view generated by jsdifflib
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
3
Similarly to commits dadbb58f59..5ae79fe825 for other ARM boards,
4
connect FIQ output of the GIC CPU interfaces to the CPU.
5
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Message-id: 20230612223456.33824-5-philmd@linaro.org
7
Message-id: 20240130152548.17855-1-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>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
include/hw/arm/raspi_platform.h | 5 +++++
11
hw/arm/xilinx_zynq.c | 2 ++
15
hw/misc/bcm2835_property.c | 3 +++
12
1 file changed, 2 insertions(+)
16
2 files changed, 8 insertions(+)
17
13
18
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
14
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/raspi_platform.h
16
--- a/hw/arm/xilinx_zynq.c
21
+++ b/include/hw/arm/raspi_platform.h
17
+++ b/hw/arm/xilinx_zynq.c
22
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
23
/* Clock rates */
19
sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE);
24
#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
20
sysbus_connect_irq(busdev, 0,
25
#define RPI_FIRMWARE_UART_CLK_RATE 3000000
21
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
26
+/*
22
+ sysbus_connect_irq(busdev, 1,
27
+ * TODO: this is really SoC-specific; we might want to
23
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ));
28
+ * set it per-SoC if it turns out any guests care.
24
29
+ */
25
for (n = 0; n < 64; n++) {
30
+#define RPI_FIRMWARE_CORE_CLK_RATE 350000000
26
pic[n] = qdev_get_gpio_in(dev, n);
31
#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
32
33
#endif
34
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/misc/bcm2835_property.c
37
+++ b/hw/misc/bcm2835_property.c
38
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
39
case RPI_FIRMWARE_UART_CLK_ID:
40
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE);
41
break;
42
+ case RPI_FIRMWARE_CORE_CLK_ID:
43
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_CORE_CLK_RATE);
44
+ break;
45
default:
46
stl_le_phys(&s->dma_as, value + 16,
47
RPI_FIRMWARE_DEFAULT_CLK_RATE);
48
--
27
--
49
2.34.1
28
2.34.1
50
29
51
30
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We plan to add more hardware information into DeviceTree to limit amount
3
The API does not generate an error for setting ASYNC | SYNC; that merely
4
of hardcoded values in firmware.
4
constrains the selection vs the per-cpu default. For qemu linux-user,
5
choose SYNC as the default.
5
6
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
Cc: qemu-stable@nongnu.org
7
Message-id: 20230531171834.236569-1-marcin.juszkiewicz@linaro.org
8
Reported-by: Gustavo Romero <gustavo.romero@linaro.org>
8
[PMM: fix format nits, add text about platform version fields from
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
a comment in the C source file]
10
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20240207025210.8837-2-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
docs/system/arm/sbsa.rst | 38 +++++++++++++++++++++++++++++++-------
14
linux-user/aarch64/target_prctl.h | 29 +++++++++++++++++------------
14
1 file changed, 31 insertions(+), 7 deletions(-)
15
1 file changed, 17 insertions(+), 12 deletions(-)
15
16
16
diff --git a/docs/system/arm/sbsa.rst b/docs/system/arm/sbsa.rst
17
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/system/arm/sbsa.rst
19
--- a/linux-user/aarch64/target_prctl.h
19
+++ b/docs/system/arm/sbsa.rst
20
+++ b/linux-user/aarch64/target_prctl.h
20
@@ -XXX,XX +XXX,XX @@ any real hardware the ``sbsa-ref`` board intends to look like real
21
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_set_tagged_addr_ctrl(CPUArchState *env, abi_long arg2)
21
hardware. The `Server Base System Architecture
22
env->tagged_addr_enable = arg2 & PR_TAGGED_ADDR_ENABLE;
22
<https://developer.arm.com/documentation/den0029/latest>`_ defines a
23
23
minimum base line of hardware support and importantly how the firmware
24
if (cpu_isar_feature(aa64_mte, cpu)) {
24
-reports that to any operating system. It is a static system that
25
- switch (arg2 & PR_MTE_TCF_MASK) {
25
-reports a very minimal DT to the firmware for non-discoverable
26
- case PR_MTE_TCF_NONE:
26
-information about components affected by the qemu command line (i.e.
27
- case PR_MTE_TCF_SYNC:
27
-cpus and memory). As a result it must have a firmware specifically
28
- case PR_MTE_TCF_ASYNC:
28
-built to expect a certain hardware layout (as you would in a real
29
- break;
29
-machine).
30
- default:
30
+reports that to any operating system.
31
- return -EINVAL;
31
32
- }
32
It is intended to be a machine for developing firmware and testing
33
-
33
standards compliance with operating systems.
34
/*
34
@@ -XXX,XX +XXX,XX @@ standards compliance with operating systems.
35
* Write PR_MTE_TCF to SCTLR_EL1[TCF0].
35
Supported devices
36
- * Note that the syscall values are consistent with hw.
36
"""""""""""""""""
37
+ *
37
38
+ * The kernel has a per-cpu configuration for the sysadmin,
38
-The sbsa-ref board supports:
39
+ * /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred,
39
+The ``sbsa-ref`` board supports:
40
+ * which qemu does not implement.
40
41
+ *
41
- A configurable number of AArch64 CPUs
42
+ * Because there is no performance difference between the modes, and
42
- GIC version 3
43
+ * because SYNC is most useful for debugging MTE errors, choose SYNC
43
@@ -XXX,XX +XXX,XX @@ The sbsa-ref board supports:
44
+ * as the preferred mode. With this preference, and the way the API
44
- Bochs display adapter on PCIe bus
45
+ * uses only two bits, there is no way for the program to select
45
- A generic SBSA watchdog device
46
+ * ASYMM mode.
46
47
*/
47
+
48
- env->cp15.sctlr_el[1] =
48
+Board to firmware interface
49
- deposit64(env->cp15.sctlr_el[1], 38, 2, arg2 >> PR_MTE_TCF_SHIFT);
49
+"""""""""""""""""""""""""""
50
+ unsigned tcf = 0;
50
+
51
+ if (arg2 & PR_MTE_TCF_SYNC) {
51
+``sbsa-ref`` is a static system that reports a very minimal devicetree to the
52
+ tcf = 1;
52
+firmware for non-discoverable information about system components. This
53
+ } else if (arg2 & PR_MTE_TCF_ASYNC) {
53
+includes both internal hardware and parts affected by the qemu command line
54
+ tcf = 2;
54
+(i.e. CPUs and memory). As a result it must have a firmware specifically built
55
+ }
55
+to expect a certain hardware layout (as you would in a real machine).
56
+ env->cp15.sctlr_el[1] = deposit64(env->cp15.sctlr_el[1], 38, 2, tcf);
56
+
57
57
+DeviceTree information
58
/*
58
+''''''''''''''''''''''
59
* Write PR_MTE_TAG to GCR_EL1[Exclude].
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.
76
--
60
--
77
2.34.1
61
2.34.1
diff view generated by jsdifflib
1
Convert the ASIMD load/store single structure insns to decodetree.
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The field is encoded as [0-3], which is convenient for
4
indexing our array of function pointers, but the true
5
value is [1-4]. Adjust before calling do_mem_zpa.
6
7
Add an assert, and move the comment re passing ZT to
8
the helper back next to the relevant code.
9
10
Cc: qemu-stable@nongnu.org
11
Fixes: 206adacfb8d ("target/arm: Add mte helpers for sve scalar + int loads")
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
14
Message-id: 20240207025210.8837-3-richard.henderson@linaro.org
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Message-id: 20230602155223.2040685-20-peter.maydell@linaro.org
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
17
---
7
target/arm/tcg/a64.decode | 34 +++++
18
target/arm/tcg/translate-sve.c | 16 ++++++++--------
8
target/arm/tcg/translate-a64.c | 219 +++++++++++++++------------------
19
1 file changed, 8 insertions(+), 8 deletions(-)
9
2 files changed, 136 insertions(+), 117 deletions(-)
10
20
11
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
21
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
12
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/tcg/a64.decode
23
--- a/target/arm/tcg/translate-sve.c
14
+++ b/target/arm/tcg/a64.decode
24
+++ b/target/arm/tcg/translate-sve.c
15
@@ -XXX,XX +XXX,XX @@ LD_mult 0 . 001100 . 1 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 sele
25
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
16
LD_mult 0 . 001100 . 1 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
26
TCGv_ptr t_pg;
17
LD_mult 0 . 001100 . 1 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
27
int desc = 0;
18
LD_mult 0 . 001100 . 1 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
28
19
+
29
- /*
20
+# Load/store single structure
30
- * For e.g. LD4, there are not enough arguments to pass all 4
21
+&ldst_single rm rn rt p selem index scale
31
- * registers as pointers, so encode the regno into the data field.
22
+
32
- * For consistency, do this even for LD1.
23
+%ldst_single_selem 13:1 21:1 !function=plus_1
33
- */
24
+
34
+ assert(mte_n >= 1 && mte_n <= 4);
25
+%ldst_single_index_b 30:1 10:3
35
if (s->mte_active[0]) {
26
+%ldst_single_index_h 30:1 11:2
36
int msz = dtype_msz(dtype);
27
+%ldst_single_index_s 30:1 12:1
37
28
+
38
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
29
+@ldst_single_b .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
39
addr = clean_data_tbi(s, addr);
30
+ &ldst_single scale=0 selem=%ldst_single_selem \
40
}
31
+ index=%ldst_single_index_b
41
32
+@ldst_single_h .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
42
+ /*
33
+ &ldst_single scale=1 selem=%ldst_single_selem \
43
+ * For e.g. LD4, there are not enough arguments to pass all 4
34
+ index=%ldst_single_index_h
44
+ * registers as pointers, so encode the regno into the data field.
35
+@ldst_single_s .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
45
+ * For consistency, do this even for LD1.
36
+ &ldst_single scale=2 selem=%ldst_single_selem \
46
+ */
37
+ index=%ldst_single_index_s
47
desc = simd_desc(vsz, vsz, zt | desc);
38
+@ldst_single_d . index:1 ...... p:1 .. rm:5 ...... rn:5 rt:5 \
48
t_pg = tcg_temp_new_ptr();
39
+ &ldst_single scale=3 selem=%ldst_single_selem
49
40
+
50
@@ -XXX,XX +XXX,XX @@ static void do_ld_zpa(DisasContext *s, int zt, int pg,
41
+ST_single 0 . 001101 . 0 . ..... 00 . ... ..... ..... @ldst_single_b
51
* accessible via the instruction encoding.
42
+ST_single 0 . 001101 . 0 . ..... 01 . ..0 ..... ..... @ldst_single_h
52
*/
43
+ST_single 0 . 001101 . 0 . ..... 10 . .00 ..... ..... @ldst_single_s
53
assert(fn != NULL);
44
+ST_single 0 . 001101 . 0 . ..... 10 . 001 ..... ..... @ldst_single_d
54
- do_mem_zpa(s, zt, pg, addr, dtype, nreg, false, fn);
45
+
55
+ do_mem_zpa(s, zt, pg, addr, dtype, nreg + 1, false, fn);
46
+LD_single 0 . 001101 . 1 . ..... 00 . ... ..... ..... @ldst_single_b
47
+LD_single 0 . 001101 . 1 . ..... 01 . ..0 ..... ..... @ldst_single_h
48
+LD_single 0 . 001101 . 1 . ..... 10 . .00 ..... ..... @ldst_single_s
49
+LD_single 0 . 001101 . 1 . ..... 10 . 001 ..... ..... @ldst_single_d
50
+
51
+# Replicating load case
52
+LD_single_repl 0 q:1 001101 p:1 1 . rm:5 11 . 0 scale:2 rn:5 rt:5 selem=%ldst_single_selem
53
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/tcg/translate-a64.c
56
+++ b/target/arm/tcg/translate-a64.c
57
@@ -XXX,XX +XXX,XX @@ static bool trans_ST_mult(DisasContext *s, arg_ldst_mult *a)
58
return true;
59
}
56
}
60
57
61
-/* AdvSIMD load/store single structure
58
static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a)
62
- *
59
@@ -XXX,XX +XXX,XX @@ static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
63
- * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
60
if (nreg == 0) {
64
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
61
/* ST1 */
65
- * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size | Rn | Rt |
62
fn = fn_single[s->mte_active[0]][be][msz][esz];
66
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
63
- nreg = 1;
67
- *
64
} else {
68
- * AdvSIMD load/store single structure (post-indexed)
65
/* ST2, ST3, ST4 -- msz == esz, enforced by encoding */
69
- *
66
assert(msz == esz);
70
- * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
67
fn = fn_multiple[s->mte_active[0]][be][nreg - 1][msz];
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
}
68
}
112
- if (!is_postidx && rm != 0) {
69
assert(fn != NULL);
113
- unallocated_encoding(s);
70
- do_mem_zpa(s, zt, pg, addr, msz_dtype(s, msz), nreg, true, fn);
114
- return;
71
+ do_mem_zpa(s, zt, pg, addr, msz_dtype(s, msz), nreg + 1, true, fn);
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)
216
+{
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;
253
+}
254
+
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
}
72
}
299
73
300
/*
74
static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a)
301
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
302
static void disas_ldst(DisasContext *s, uint32_t insn)
303
{
304
switch (extract32(insn, 24, 6)) {
305
- case 0x0d: /* AdvSIMD load/store single structure */
306
- disas_ldst_single_struct(s, insn);
307
- break;
308
case 0x19:
309
if (extract32(insn, 21, 1) != 0) {
310
disas_ldst_tag(s, insn);
311
--
75
--
312
2.34.1
76
2.34.1
diff view generated by jsdifflib
1
The LDG instruction loads the tag from a memory address (identified
1
From: Richard Henderson <richard.henderson@linaro.org>
2
by [Xn + offset]), and then merges that tag into the destination
3
register Xt. We implemented this correctly for the case when
4
allocation tags are enabled, but didn't get it right when ATA=0:
5
instead of merging the tag bits into Xt, we merged them into the
6
memory address [Xn + offset] and then set Xt to that.
7
2
8
Merge the tag bits into the old Xt value, as they should be.
3
When we added SVE_MTEDESC_SHIFT, we effectively limited the
4
maximum size of MTEDESC. Adjust SIZEM1 to consume the remaining
5
bits (32 - 10 - 5 - 12 == 5). Assert that the data to be stored
6
fits within the field (expecting 8 * 4 - 1 == 31, exact fit).
9
7
10
Cc: qemu-stable@nongnu.org
8
Cc: qemu-stable@nongnu.org
11
Fixes: c15294c1e36a7dd9b25 ("target/arm: Implement LDG, STG, ST2G instructions")
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
12
Message-id: 20240207025210.8837-4-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
14
---
15
target/arm/tcg/translate-a64.c | 6 +++++-
15
target/arm/internals.h | 2 +-
16
1 file changed, 5 insertions(+), 1 deletion(-)
16
target/arm/tcg/translate-sve.c | 7 ++++---
17
2 files changed, 5 insertions(+), 4 deletions(-)
17
18
18
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
19
diff --git a/target/arm/internals.h b/target/arm/internals.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/tcg/translate-a64.c
21
--- a/target/arm/internals.h
21
+++ b/target/arm/tcg/translate-a64.c
22
+++ b/target/arm/internals.h
22
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
23
@@ -XXX,XX +XXX,XX @@ FIELD(MTEDESC, TBI, 4, 2)
23
if (s->ata) {
24
FIELD(MTEDESC, TCMA, 6, 2)
24
gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
25
FIELD(MTEDESC, WRITE, 8, 1)
25
} else {
26
FIELD(MTEDESC, ALIGN, 9, 3)
26
+ /*
27
-FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12) /* size - 1 */
27
+ * Tag access disabled: we must check for aborts on the load
28
+FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - SVE_MTEDESC_SHIFT - 12) /* size - 1 */
28
+ * load from [rn+offset], and then insert a 0 tag into rt.
29
29
+ */
30
bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr);
30
clean_addr = clean_data_tbi(s, addr);
31
uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra);
31
gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
32
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
32
- gen_address_with_allocation_tag0(tcg_rt, addr);
33
index XXXXXXX..XXXXXXX 100644
33
+ gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
34
--- a/target/arm/tcg/translate-sve.c
34
}
35
+++ b/target/arm/tcg/translate-sve.c
36
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
37
{
38
unsigned vsz = vec_full_reg_size(s);
39
TCGv_ptr t_pg;
40
+ uint32_t sizem1;
41
int desc = 0;
42
43
assert(mte_n >= 1 && mte_n <= 4);
44
+ sizem1 = (mte_n << dtype_msz(dtype)) - 1;
45
+ assert(sizem1 <= R_MTEDESC_SIZEM1_MASK >> R_MTEDESC_SIZEM1_SHIFT);
46
if (s->mte_active[0]) {
47
- int msz = dtype_msz(dtype);
48
-
49
desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s));
50
desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
51
desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
52
desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
53
- desc = FIELD_DP32(desc, MTEDESC, SIZEM1, (mte_n << msz) - 1);
54
+ desc = FIELD_DP32(desc, MTEDESC, SIZEM1, sizem1);
55
desc <<= SVE_MTEDESC_SHIFT;
35
} else {
56
} else {
36
tcg_rt = cpu_reg_sp(s, rt);
57
addr = clean_data_tbi(s, addr);
37
--
58
--
38
2.34.1
59
2.34.1
diff view generated by jsdifflib
1
The nrf51_timer has a free-running counter which we implement using
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the pattern of using two fields (update_counter_ns, counter) to track
3
the last point at which we calculated the counter value, and the
4
counter value at that time. Then we can find the current counter
5
value by converting the difference in wall-clock time between then
6
and now to a tick count that we need to add to the counter value.
7
2
8
Unfortunately the nrf51_timer's implementation of this has a bug
3
Share code that creates mtedesc and embeds within simd_desc.
9
which means it loses time every time update_counter() is called.
10
After updating s->counter it always sets s->update_counter_ns to
11
'now', even though the actual point when s->counter hit the new value
12
will be some point in the past (half a tick, say). In the worst case
13
(guest code in a tight loop reading the counter, icount mode) the
14
counter is continually queried less than a tick after it was last
15
read, so s->counter never advances but s->update_counter_ns does, and
16
the guest never makes forward progress.
17
18
The fix for this is to only advance update_counter_ns to the
19
timestamp of the last tick, not all the way to 'now'. (This is the
20
pattern used in hw/misc/mps2-fpgaio.c's counter.)
21
4
22
Cc: qemu-stable@nongnu.org
5
Cc: qemu-stable@nongnu.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
9
Message-id: 20240207025210.8837-5-richard.henderson@linaro.org
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Joel Stanley <joel@jms.id.au>
25
Message-id: 20230606134917.3782215-1-peter.maydell@linaro.org
26
---
11
---
27
hw/timer/nrf51_timer.c | 7 ++++++-
12
target/arm/tcg/translate-a64.h | 2 ++
28
1 file changed, 6 insertions(+), 1 deletion(-)
13
target/arm/tcg/translate-sme.c | 15 +++--------
14
target/arm/tcg/translate-sve.c | 47 ++++++++++++++++++----------------
15
3 files changed, 31 insertions(+), 33 deletions(-)
29
16
30
diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c
17
diff --git a/target/arm/tcg/translate-a64.h b/target/arm/tcg/translate-a64.h
31
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/nrf51_timer.c
19
--- a/target/arm/tcg/translate-a64.h
33
+++ b/hw/timer/nrf51_timer.c
20
+++ b/target/arm/tcg/translate-a64.h
34
@@ -XXX,XX +XXX,XX @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now)
21
@@ -XXX,XX +XXX,XX @@ bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
35
uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
22
bool sve_access_check(DisasContext *s);
36
23
bool sme_enabled_check(DisasContext *s);
37
s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
24
bool sme_enabled_check_with_svcr(DisasContext *s, unsigned);
38
- s->update_counter_ns = now;
25
+uint32_t make_svemte_desc(DisasContext *s, unsigned vsz, uint32_t nregs,
39
+ /*
26
+ uint32_t msz, bool is_write, uint32_t data);
40
+ * Only advance the sync time to the timestamp of the last tick,
27
41
+ * not all the way to 'now', so we don't lose time if we do
28
/* This function corresponds to CheckStreamingSVEEnabled. */
42
+ * multiple resyncs in a single tick.
29
static inline bool sme_sm_enabled_check(DisasContext *s)
43
+ */
30
diff --git a/target/arm/tcg/translate-sme.c b/target/arm/tcg/translate-sme.c
44
+ s->update_counter_ns += ticks_to_ns(s, ticks);
31
index XXXXXXX..XXXXXXX 100644
45
return ticks;
32
--- a/target/arm/tcg/translate-sme.c
33
+++ b/target/arm/tcg/translate-sme.c
34
@@ -XXX,XX +XXX,XX @@ static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
35
36
TCGv_ptr t_za, t_pg;
37
TCGv_i64 addr;
38
- int svl, desc = 0;
39
+ uint32_t desc;
40
bool be = s->be_data == MO_BE;
41
bool mte = s->mte_active[0];
42
43
@@ -XXX,XX +XXX,XX @@ static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
44
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), a->esz);
45
tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
46
47
- if (mte) {
48
- desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s));
49
- desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
50
- desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
51
- desc = FIELD_DP32(desc, MTEDESC, WRITE, a->st);
52
- desc = FIELD_DP32(desc, MTEDESC, SIZEM1, (1 << a->esz) - 1);
53
- desc <<= SVE_MTEDESC_SHIFT;
54
- } else {
55
+ if (!mte) {
56
addr = clean_data_tbi(s, addr);
57
}
58
- svl = streaming_vec_reg_size(s);
59
- desc = simd_desc(svl, svl, desc);
60
+
61
+ desc = make_svemte_desc(s, streaming_vec_reg_size(s), 1, a->esz, a->st, 0);
62
63
fns[a->esz][be][a->v][mte][a->st](tcg_env, t_za, t_pg, addr,
64
tcg_constant_i32(desc));
65
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/tcg/translate-sve.c
68
+++ b/target/arm/tcg/translate-sve.c
69
@@ -XXX,XX +XXX,XX @@ static const uint8_t dtype_esz[16] = {
70
3, 2, 1, 3
71
};
72
73
-static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
74
- int dtype, uint32_t mte_n, bool is_write,
75
- gen_helper_gvec_mem *fn)
76
+uint32_t make_svemte_desc(DisasContext *s, unsigned vsz, uint32_t nregs,
77
+ uint32_t msz, bool is_write, uint32_t data)
78
{
79
- unsigned vsz = vec_full_reg_size(s);
80
- TCGv_ptr t_pg;
81
uint32_t sizem1;
82
- int desc = 0;
83
+ uint32_t desc = 0;
84
85
- assert(mte_n >= 1 && mte_n <= 4);
86
- sizem1 = (mte_n << dtype_msz(dtype)) - 1;
87
+ /* Assert all of the data fits, with or without MTE enabled. */
88
+ assert(nregs >= 1 && nregs <= 4);
89
+ sizem1 = (nregs << msz) - 1;
90
assert(sizem1 <= R_MTEDESC_SIZEM1_MASK >> R_MTEDESC_SIZEM1_SHIFT);
91
+ assert(data < 1u << SVE_MTEDESC_SHIFT);
92
+
93
if (s->mte_active[0]) {
94
desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s));
95
desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
96
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
97
desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
98
desc = FIELD_DP32(desc, MTEDESC, SIZEM1, sizem1);
99
desc <<= SVE_MTEDESC_SHIFT;
100
- } else {
101
+ }
102
+ return simd_desc(vsz, vsz, desc | data);
103
+}
104
+
105
+static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
106
+ int dtype, uint32_t nregs, bool is_write,
107
+ gen_helper_gvec_mem *fn)
108
+{
109
+ TCGv_ptr t_pg;
110
+ uint32_t desc;
111
+
112
+ if (!s->mte_active[0]) {
113
addr = clean_data_tbi(s, addr);
114
}
115
116
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
117
* registers as pointers, so encode the regno into the data field.
118
* For consistency, do this even for LD1.
119
*/
120
- desc = simd_desc(vsz, vsz, zt | desc);
121
+ desc = make_svemte_desc(s, vec_full_reg_size(s), nregs,
122
+ dtype_msz(dtype), is_write, zt);
123
t_pg = tcg_temp_new_ptr();
124
125
tcg_gen_addi_ptr(t_pg, tcg_env, pred_full_reg_offset(s, pg));
126
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm,
127
int scale, TCGv_i64 scalar, int msz, bool is_write,
128
gen_helper_gvec_mem_scatter *fn)
129
{
130
- unsigned vsz = vec_full_reg_size(s);
131
TCGv_ptr t_zm = tcg_temp_new_ptr();
132
TCGv_ptr t_pg = tcg_temp_new_ptr();
133
TCGv_ptr t_zt = tcg_temp_new_ptr();
134
- int desc = 0;
135
-
136
- if (s->mte_active[0]) {
137
- desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s));
138
- desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
139
- desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
140
- desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
141
- desc = FIELD_DP32(desc, MTEDESC, SIZEM1, (1 << msz) - 1);
142
- desc <<= SVE_MTEDESC_SHIFT;
143
- }
144
- desc = simd_desc(vsz, vsz, desc | scale);
145
+ uint32_t desc;
146
147
tcg_gen_addi_ptr(t_pg, tcg_env, pred_full_reg_offset(s, pg));
148
tcg_gen_addi_ptr(t_zm, tcg_env, vec_full_reg_offset(s, zm));
149
tcg_gen_addi_ptr(t_zt, tcg_env, vec_full_reg_offset(s, zt));
150
+
151
+ desc = make_svemte_desc(s, vec_full_reg_size(s), 1, msz, is_write, scale);
152
fn(tcg_env, t_zt, t_pg, t_zm, scalar, tcg_constant_i32(desc));
46
}
153
}
47
154
48
--
155
--
49
2.34.1
156
2.34.1
diff view generated by jsdifflib
1
In the recent refactoring we missed a few places which should be
1
From: Richard Henderson <richard.henderson@linaro.org>
2
calling finalize_memop_asimd() for ASIMD loads and stores but
3
instead are just calling finalize_memop(); fix these.
4
2
5
For the disas_ldst_single_struct() and disas_ldst_multiple_struct()
3
These functions "use the standard load helpers", but
6
cases, this is not a behaviour change because there the size
4
fail to clean_data_tbi or populate mtedesc.
7
is never MO_128 and the two finalize functions do the same thing.
8
5
6
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
10
Message-id: 20240207025210.8837-6-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
12
---
12
target/arm/tcg/translate-a64.c | 10 ++++++----
13
target/arm/tcg/translate-sve.c | 15 +++++++++++++--
13
1 file changed, 6 insertions(+), 4 deletions(-)
14
1 file changed, 13 insertions(+), 2 deletions(-)
14
15
15
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
16
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/tcg/translate-a64.c
18
--- a/target/arm/tcg/translate-sve.c
18
+++ b/target/arm/tcg/translate-a64.c
19
+++ b/target/arm/tcg/translate-sve.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
20
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
20
if (!fp_access_check(s)) {
21
unsigned vsz = vec_full_reg_size(s);
21
return;
22
TCGv_ptr t_pg;
22
}
23
int poff;
23
+ memop = finalize_memop_asimd(s, size);
24
+ uint32_t desc;
24
} else {
25
25
if (size == 3 && opc == 2) {
26
/* Load the first quadword using the normal predicated load helpers. */
26
/* PRFM - prefetch */
27
+ if (!s->mte_active[0]) {
27
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
28
+ addr = clean_data_tbi(s, addr);
28
is_store = (opc == 0);
29
+ }
29
is_signed = !is_store && extract32(opc, 1, 1);
30
+
30
is_extended = (size < 3) && extract32(opc, 0, 1);
31
poff = pred_full_reg_offset(s, pg);
31
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
32
if (vsz > 16) {
33
/*
34
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
35
36
gen_helper_gvec_mem *fn
37
= ldr_fns[s->mte_active[0]][s->be_data == MO_BE][dtype][0];
38
- fn(tcg_env, t_pg, addr, tcg_constant_i32(simd_desc(16, 16, zt)));
39
+ desc = make_svemte_desc(s, 16, 1, dtype_msz(dtype), false, zt);
40
+ fn(tcg_env, t_pg, addr, tcg_constant_i32(desc));
41
42
/* Replicate that first quadword. */
43
if (vsz > 16) {
44
@@ -XXX,XX +XXX,XX @@ static void do_ldro(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
45
unsigned vsz_r32;
46
TCGv_ptr t_pg;
47
int poff, doff;
48
+ uint32_t desc;
49
50
if (vsz < 32) {
51
/*
52
@@ -XXX,XX +XXX,XX @@ static void do_ldro(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
32
}
53
}
33
54
34
if (rn == 31) {
55
/* Load the first octaword using the normal predicated load helpers. */
35
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
56
+ if (!s->mte_active[0]) {
36
57
+ addr = clean_data_tbi(s, addr);
37
tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
58
+ }
38
59
39
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
60
poff = pred_full_reg_offset(s, pg);
40
clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, memop);
61
if (vsz > 32) {
41
62
@@ -XXX,XX +XXX,XX @@ static void do_ldro(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
42
if (is_vector) {
63
43
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
64
gen_helper_gvec_mem *fn
44
if (!fp_access_check(s)) {
65
= ldr_fns[s->mte_active[0]][s->be_data == MO_BE][dtype][0];
45
return;
66
- fn(tcg_env, t_pg, addr, tcg_constant_i32(simd_desc(32, 32, zt)));
46
}
67
+ desc = make_svemte_desc(s, 32, 1, dtype_msz(dtype), false, zt);
47
+ memop = finalize_memop_asimd(s, size);
68
+ fn(tcg_env, t_pg, addr, tcg_constant_i32(desc));
48
} else {
49
if (size == 3 && opc == 2) {
50
/* PRFM - prefetch */
51
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
52
is_store = (opc == 0);
53
is_signed = !is_store && extract32(opc, 1, 1);
54
is_extended = (size < 3) && extract32(opc, 0, 1);
55
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
56
}
57
58
if (rn == 31) {
59
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
60
offset = imm12 << size;
61
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
62
63
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
64
clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, memop);
65
66
if (is_vector) {
67
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
68
* promote consecutive little-endian elements below.
69
*/
70
clean_addr = gen_mte_checkN(s, tcg_rn, is_store, is_postidx || rn != 31,
71
- total, finalize_memop(s, size));
72
+ total, finalize_memop_asimd(s, size));
73
69
74
/*
70
/*
75
* Consecutive little-endian elements from a single register
71
* Replicate that first octaword.
76
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
77
total = selem << scale;
78
tcg_rn = cpu_reg_sp(s, rn);
79
80
- mop = finalize_memop(s, scale);
81
+ mop = finalize_memop_asimd(s, scale);
82
83
clean_addr = gen_mte_checkN(s, tcg_rn, !is_load, is_postidx || rn != 31,
84
total, mop);
85
--
72
--
86
2.34.1
73
2.34.1
diff view generated by jsdifflib
1
Convert the instructions in the load/store memory tags instruction
1
From: Richard Henderson <richard.henderson@linaro.org>
2
group to decodetree.
3
2
3
The TBI and TCMA bits are located within mtedesc, not desc.
4
5
Cc: qemu-stable@nongnu.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
9
Message-id: 20240207025210.8837-7-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-21-peter.maydell@linaro.org
7
---
11
---
8
target/arm/tcg/a64.decode | 25 +++
12
target/arm/tcg/sme_helper.c | 8 ++++----
9
target/arm/tcg/translate-a64.c | 360 ++++++++++++++++-----------------
13
target/arm/tcg/sve_helper.c | 12 ++++++------
10
2 files changed, 199 insertions(+), 186 deletions(-)
14
2 files changed, 10 insertions(+), 10 deletions(-)
11
15
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
16
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
18
--- a/target/arm/tcg/sme_helper.c
15
+++ b/target/arm/tcg/a64.decode
19
+++ b/target/arm/tcg/sme_helper.c
16
@@ -XXX,XX +XXX,XX @@ LD_single 0 . 001101 . 1 . ..... 10 . 001 ..... ..... @ldst_single_d
20
@@ -XXX,XX +XXX,XX @@ void sme_ld1_mte(CPUARMState *env, void *za, uint64_t *vg,
17
21
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
18
# Replicating load case
22
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
23
/* Perform gross MTE suppression early. */
20
+
24
- if (!tbi_check(desc, bit55) ||
21
+%tag_offset 12:s9 !function=scale_by_log2_tag_granule
25
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
22
+&ldst_tag rn rt imm p w
26
+ if (!tbi_check(mtedesc, bit55) ||
23
+@ldst_tag ........ .. . ......... .. rn:5 rt:5 &ldst_tag imm=%tag_offset
27
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
24
+@ldst_tag_mult ........ .. . 000000000 .. rn:5 rt:5 &ldst_tag imm=0
28
mtedesc = 0;
25
+
29
}
26
+STZGM 11011001 00 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
30
27
+STG 11011001 00 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
31
@@ -XXX,XX +XXX,XX @@ void sme_st1_mte(CPUARMState *env, void *za, uint64_t *vg, target_ulong addr,
28
+STG 11011001 00 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
32
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
29
+STG 11011001 00 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
33
30
+
34
/* Perform gross MTE suppression early. */
31
+LDG 11011001 01 1 ......... 00 ..... ..... @ldst_tag p=0 w=0
35
- if (!tbi_check(desc, bit55) ||
32
+STZG 11011001 01 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
36
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
33
+STZG 11011001 01 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
37
+ if (!tbi_check(mtedesc, bit55) ||
34
+STZG 11011001 01 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
38
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
35
+
39
mtedesc = 0;
36
+STGM 11011001 10 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
40
}
37
+ST2G 11011001 10 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
41
38
+ST2G 11011001 10 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
42
diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c
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
43
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/tcg/translate-a64.c
44
--- a/target/arm/tcg/sve_helper.c
48
+++ b/target/arm/tcg/translate-a64.c
45
+++ b/target/arm/tcg/sve_helper.c
49
@@ -XXX,XX +XXX,XX @@ static int uimm_scaled(DisasContext *s, int x)
46
@@ -XXX,XX +XXX,XX @@ void sve_ldN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr,
50
return imm << scale;
47
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
51
}
48
52
49
/* Perform gross MTE suppression early. */
53
+/* For load/store memory tags: scale offset by LOG2_TAG_GRANULE */
50
- if (!tbi_check(desc, bit55) ||
54
+static int scale_by_log2_tag_granule(DisasContext *s, int x)
51
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
55
+{
52
+ if (!tbi_check(mtedesc, bit55) ||
56
+ return x << LOG2_TAG_GRANULE;
53
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
57
+}
54
mtedesc = 0;
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
}
65
66
-/*
67
- * Load/Store memory tags
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
- * +-----+-------------+-----+---+------+-----+------+------+
73
- */
74
-static void disas_ldst_tag(DisasContext *s, uint32_t insn)
75
+static bool trans_STZGM(DisasContext *s, arg_ldst_tag *a)
76
{
77
- int rt = extract32(insn, 0, 5);
78
- int rn = extract32(insn, 5, 5);
79
- uint64_t offset = sextract64(insn, 12, 9) << LOG2_TAG_GRANULE;
80
- int op2 = extract32(insn, 10, 2);
81
- int op1 = extract32(insn, 22, 2);
82
- bool is_load = false, is_pair = false, is_zero = false, is_mult = false;
83
- int index = 0;
84
TCGv_i64 addr, clean_addr, tcg_rt;
85
+ int size = 4 << s->dcz_blocksize;
86
87
- /* We checked insn bits [29:24,21] in the caller. */
88
- if (extract32(insn, 30, 2) != 3) {
89
- goto do_unallocated;
90
+ if (!dc_isar_feature(aa64_mte, s)) {
91
+ return false;
92
+ }
93
+ if (s->current_el == 0) {
94
+ return false;
95
}
55
}
96
56
97
- /*
57
@@ -XXX,XX +XXX,XX @@ void sve_ldnfff1_r_mte(CPUARMState *env, void *vg, target_ulong addr,
98
- * @index is a tri-state variable which has 3 states:
58
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
99
- * < 0 : post-index, writeback
59
100
- * = 0 : signed offset
60
/* Perform gross MTE suppression early. */
101
- * > 0 : pre-index, writeback
61
- if (!tbi_check(desc, bit55) ||
102
- */
62
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
103
- switch (op1) {
63
+ if (!tbi_check(mtedesc, bit55) ||
104
- case 0:
64
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
105
- if (op2 != 0) {
65
mtedesc = 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
}
66
}
169
67
170
- addr = read_cpu_reg_sp(s, rn, true);
68
@@ -XXX,XX +XXX,XX @@ void sve_stN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr,
171
- if (index >= 0) {
69
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
172
+ addr = read_cpu_reg_sp(s, a->rn, true);
70
173
+ tcg_gen_addi_i64(addr, addr, a->imm);
71
/* Perform gross MTE suppression early. */
174
+ tcg_rt = cpu_reg(s, a->rt);
72
- if (!tbi_check(desc, bit55) ||
175
+
73
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
176
+ if (s->ata) {
74
+ if (!tbi_check(mtedesc, bit55) ||
177
+ gen_helper_stzgm_tags(cpu_env, addr, tcg_rt);
75
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
178
+ }
76
mtedesc = 0;
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)
190
+{
191
+ TCGv_i64 addr, clean_addr, tcg_rt;
192
+
193
+ if (!dc_isar_feature(aa64_mte, s)) {
194
+ return false;
195
+ }
196
+ if (s->current_el == 0) {
197
+ return false;
198
+ }
199
+
200
+ if (a->rn == 31) {
201
+ gen_check_sp_alignment(s);
202
+ }
203
+
204
+ addr = read_cpu_reg_sp(s, a->rn, true);
205
+ tcg_gen_addi_i64(addr, addr, a->imm);
206
+ tcg_rt = cpu_reg(s, a->rt);
207
+
208
+ if (s->ata) {
209
+ gen_helper_stgm(cpu_env, addr, tcg_rt);
210
+ } else {
211
+ MMUAccessType acc = MMU_DATA_STORE;
212
+ int size = 4 << GMID_EL1_BS;
213
+
214
+ clean_addr = clean_data_tbi(s, addr);
215
+ tcg_gen_andi_i64(clean_addr, clean_addr, -size);
216
+ gen_probe_access(s, clean_addr, acc, size);
217
+ }
218
+ return true;
219
+}
220
+
221
+static bool trans_LDGM(DisasContext *s, arg_ldst_tag *a)
222
+{
223
+ TCGv_i64 addr, clean_addr, tcg_rt;
224
+
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;
253
+}
254
+
255
+static bool trans_LDG(DisasContext *s, arg_ldst_tag *a)
256
+{
257
+ TCGv_i64 addr, clean_addr, tcg_rt;
258
+
259
+ if (!dc_isar_feature(aa64_mte_insn_reg, s)) {
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
}
77
}
273
78
274
- if (is_mult) {
275
- tcg_rt = cpu_reg(s, rt);
276
+ tcg_gen_andi_i64(addr, addr, -TAG_GRANULE);
277
+ tcg_rt = cpu_reg(s, a->rt);
278
+ if (s->ata) {
279
+ gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
280
+ } else {
281
+ /*
282
+ * Tag access disabled: we must check for aborts on the load
283
+ * load from [rn+offset], and then insert a 0 tag into rt.
284
+ */
285
+ clean_addr = clean_data_tbi(s, addr);
286
+ gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
287
+ gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
288
+ }
289
290
- if (is_zero) {
291
- int size = 4 << s->dcz_blocksize;
292
-
293
- if (s->ata) {
294
- gen_helper_stzgm_tags(cpu_env, addr, tcg_rt);
295
- }
296
- /*
297
- * The non-tags portion of STZGM is mostly like DC_ZVA,
298
- * except the alignment happens before the access.
299
- */
300
- clean_addr = clean_data_tbi(s, addr);
301
- tcg_gen_andi_i64(clean_addr, clean_addr, -size);
302
- gen_helper_dc_zva(cpu_env, clean_addr);
303
- } else if (s->ata) {
304
- if (is_load) {
305
- gen_helper_ldgm(tcg_rt, cpu_env, addr);
306
- } else {
307
- gen_helper_stgm(cpu_env, addr, tcg_rt);
308
- }
309
- } else {
310
- MMUAccessType acc = is_load ? MMU_DATA_LOAD : MMU_DATA_STORE;
311
- int size = 4 << GMID_EL1_BS;
312
-
313
- clean_addr = clean_data_tbi(s, addr);
314
- tcg_gen_andi_i64(clean_addr, clean_addr, -size);
315
- gen_probe_access(s, clean_addr, acc, size);
316
-
317
- if (is_load) {
318
- /* The result tags are zeros. */
319
- tcg_gen_movi_i64(tcg_rt, 0);
320
- }
321
+ if (a->w) {
322
+ /* pre-index or post-index */
323
+ if (a->p) {
324
+ /* post-index */
325
+ tcg_gen_addi_i64(addr, addr, a->imm);
326
}
327
- return;
328
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), addr);
329
+ }
330
+ return true;
331
+}
332
+
333
+static bool do_STG(DisasContext *s, arg_ldst_tag *a, bool is_zero, bool is_pair)
334
+{
335
+ TCGv_i64 addr, tcg_rt;
336
+
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;
424
}
425
426
-/* Loads and stores */
427
-static void disas_ldst(DisasContext *s, uint32_t insn)
428
-{
429
- switch (extract32(insn, 24, 6)) {
430
- case 0x19:
431
- if (extract32(insn, 21, 1) != 0) {
432
- disas_ldst_tag(s, insn);
433
- } else {
434
- unallocated_encoding(s);
435
- }
436
- break;
437
- default:
438
- unallocated_encoding(s);
439
- break;
440
- }
441
-}
442
+TRANS_FEAT(STG, aa64_mte_insn_reg, do_STG, a, false, false)
443
+TRANS_FEAT(STZG, aa64_mte_insn_reg, do_STG, a, true, false)
444
+TRANS_FEAT(ST2G, aa64_mte_insn_reg, do_STG, a, false, true)
445
+TRANS_FEAT(STZ2G, aa64_mte_insn_reg, do_STG, a, true, true)
446
447
typedef void ArithTwoOp(TCGv_i64, TCGv_i64, TCGv_i64);
448
449
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
450
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
451
{
452
switch (extract32(insn, 25, 4)) {
453
- case 0x4:
454
- case 0x6:
455
- case 0xc:
456
- case 0xe: /* Loads and stores */
457
- disas_ldst(s, insn);
458
- break;
459
case 0x5:
460
case 0xd: /* Data processing - register */
461
disas_data_proc_reg(s, insn);
462
--
79
--
463
2.34.1
80
2.34.1
diff view generated by jsdifflib
1
From: Martin Kaiser <martin@kaiser.cx>
1
The raven_io_ops MemoryRegionOps is the only one in the source tree
2
which sets .valid.unaligned to indicate that it should support
3
unaligned accesses and which does not also set .impl.unaligned to
4
indicate that its read and write functions can do the unaligned
5
handling themselves. This is a problem, because at the moment the
6
core memory system does not implement the support for handling
7
unaligned accesses by doing a series of aligned accesses and
8
combining them (system/memory.c:access_with_adjusted_size() has a
9
TODO comment noting this).
2
10
3
The Linux kernel added a flood check for RX data recently in commit
11
Fortunately raven_io_read() and raven_io_write() will correctly deal
4
496a4471b7c3 ("serial: imx: work-around for hardware RX flood"). This
12
with the case of being passed an unaligned address, so we can fix the
5
check uses the wake bit in the UART status register 2. The wake bit
13
missing unaligned access support by setting .impl.unaligned in the
6
indicates that the receiver detected a start bit on the RX line. If the
14
MemoryRegionOps struct.
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
15
11
This patch adds support for the wake bit. wake is set when we receive a
16
Fixes: 9a1839164c9c8f06 ("raven: Implement non-contiguous I/O region")
12
new character (it's not set for break events). It seems that wake is
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
cleared by the kernel driver, the hardware does not have to clear it
18
Tested-by: Cédric Le Goater <clg@redhat.com>
14
automatically after data was read.
19
Reviewed-by: Cédric Le Goater <clg@redhat.com>
20
Message-id: 20240112134640.1775041-1-peter.maydell@linaro.org
21
---
22
hw/pci-host/raven.c | 1 +
23
1 file changed, 1 insertion(+)
15
24
16
The wake bit can be configured as an interrupt source. Support this
25
diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c
17
mechanism as well.
18
19
Co-developed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
21
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
22
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
25
include/hw/char/imx_serial.h | 1 +
26
hw/char/imx_serial.c | 5 ++++-
27
2 files changed, 5 insertions(+), 1 deletion(-)
28
29
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
30
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/char/imx_serial.h
27
--- a/hw/pci-host/raven.c
32
+++ b/include/hw/char/imx_serial.h
28
+++ b/hw/pci-host/raven.c
33
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXSerialState, IMX_SERIAL)
29
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps raven_io_ops = {
34
30
.write = raven_io_write,
35
#define UCR4_DREN BIT(0) /* Receive Data Ready interrupt enable */
31
.endianness = DEVICE_LITTLE_ENDIAN,
36
#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
32
.impl.max_access_size = 4,
37
+#define UCR4_WKEN BIT(7) /* WAKE interrupt enable */
33
+ .impl.unaligned = true,
38
34
.valid.unaligned = true,
39
#define UTS1_TXEMPTY (1<<6)
35
};
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)
57
{
58
+ IMXSerialState *s = (IMXSerialState *)opaque;
59
+
60
+ s->usr2 |= USR2_WAKE;
61
imx_put_data(opaque, *buf);
62
}
63
36
64
--
37
--
65
2.34.1
38
2.34.1
66
39
67
40
diff view generated by jsdifflib
New patch
1
Suppress the deprecation warning when we're running under qtest,
2
to avoid "make check" including warning messages in its output.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Message-id: 20240206154151.155620-1-peter.maydell@linaro.org
7
---
8
hw/block/tc58128.c | 4 +++-
9
1 file changed, 3 insertions(+), 1 deletion(-)
10
11
diff --git a/hw/block/tc58128.c b/hw/block/tc58128.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/block/tc58128.c
14
+++ b/hw/block/tc58128.c
15
@@ -XXX,XX +XXX,XX @@ static sh7750_io_device tc58128 = {
16
17
int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2)
18
{
19
- warn_report_once("The TC58128 flash device is deprecated");
20
+ if (!qtest_enabled()) {
21
+ warn_report_once("The TC58128 flash device is deprecated");
22
+ }
23
init_dev(&tc58128_devs[0], zone1);
24
init_dev(&tc58128_devs[1], zone2);
25
return sh7750_register_io_device(s, &tc58128);
26
--
27
2.34.1
28
29
diff view generated by jsdifflib
New patch
1
We deliberately don't include qtests_npcm7xx in qtests_aarch64,
2
because we already get the coverage of those tests via qtests_arm,
3
and we don't want to use extra CI minutes testing them twice.
1
4
5
In commit 327b680877b79c4b we added it to qtests_aarch64; revert
6
that change.
7
8
Fixes: 327b680877b79c4b ("tests/qtest: Creating qtest for GMAC Module")
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20240206163043.315535-1-peter.maydell@linaro.org
12
---
13
tests/qtest/meson.build | 1 -
14
1 file changed, 1 deletion(-)
15
16
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qtest/meson.build
19
+++ b/tests/qtest/meson.build
20
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
21
(config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \
22
(config_all_accel.has_key('CONFIG_TCG') and \
23
config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
24
- (config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
25
['arm-cpu-features',
26
'numa-test',
27
'boot-serial-test',
28
--
29
2.34.1
30
31
diff view generated by jsdifflib
1
Convert the insns in the atomic memory operations group to
1
Allow changes to the virt GTDT -- we are going to add the IRQ
2
decodetree.
2
entry for a new timer to it.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
6
Message-id: 20230602155223.2040685-16-peter.maydell@linaro.org
6
Message-id: 20240122143537.233498-2-peter.maydell@linaro.org
7
---
7
---
8
target/arm/tcg/a64.decode | 15 ++++
8
tests/qtest/bios-tables-test-allowed-diff.h | 2 ++
9
target/arm/tcg/translate-a64.c | 153 ++++++++++++---------------------
9
1 file changed, 2 insertions(+)
10
2 files changed, 70 insertions(+), 98 deletions(-)
11
10
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
11
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
13
--- a/tests/qtest/bios-tables-test-allowed-diff.h
15
+++ b/target/arm/tcg/a64.decode
14
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
16
@@ -XXX,XX +XXX,XX @@ STR_v sz:2 111 1 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
15
@@ -1 +1,3 @@
17
STR_v 00 111 1 00 10 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
16
/* List of comma-separated changed AML files to ignore */
18
LDR_v sz:2 111 1 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
17
+"tests/data/acpi/virt/FACP",
19
LDR_v 00 111 1 00 11 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
18
+"tests/data/acpi/virt/GTDT",
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
--
19
--
225
2.34.1
20
2.34.1
diff view generated by jsdifflib
1
Convert the LDR and STR instructions which take a register
1
Armv8.1+ CPUs have the Virtual Host Extension (VHE) which adds a
2
plus register offset to decodetree.
2
non-secure EL2 virtual timer. We implemented the timer itself in the
3
CPU model, but never wired up its IRQ line to the GIC.
4
5
Wire up the IRQ line (this is always safe whether the CPU has the
6
interrupt or not, since it always creates the outbound IRQ line).
7
Report it to the guest via dtb and ACPI if the CPU has the feature.
8
9
The DTB binding is documented in the kernel's
10
Documentation/devicetree/bindings/timer/arm\,arch_timer.yaml
11
and the ACPI table entries are documented in the ACPI specification
12
version 6.3 or later.
13
14
Because the IRQ line ACPI binding is new in 6.3, we need to bump the
15
FADT table rev to show that we might be using 6.3 features.
16
17
Note that exposing this IRQ in the DTB will trigger a bug in EDK2
18
versions prior to edk2-stable202311, for users who use the virt board
19
with 'virtualization=on' to enable EL2 emulation and are booting an
20
EDK2 guest BIOS, if that EDK2 has assertions enabled. The effect is
21
that EDK2 will assert on bootup:
22
23
ASSERT [ArmTimerDxe] /home/kraxel/projects/qemu/roms/edk2/ArmVirtPkg/Library/ArmVirtTimerFdtClientLib/ArmVirtTimerFdtClientLib.c(72): PropSize == 36 || PropSize == 48
24
25
If you see that assertion you should do one of:
26
* update your EDK2 binaries to edk2-stable202311 or newer
27
* use the 'virt-8.2' versioned machine type
28
* not use 'virtualization=on'
29
30
(The versions shipped with QEMU itself have the fix.)
3
31
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
33
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
6
Message-id: 20230602155223.2040685-15-peter.maydell@linaro.org
34
Message-id: 20240122143537.233498-3-peter.maydell@linaro.org
7
---
35
---
8
target/arm/tcg/a64.decode | 22 +++++
36
include/hw/arm/virt.h | 2 ++
9
target/arm/tcg/translate-a64.c | 173 +++++++++++++++------------------
37
hw/arm/virt-acpi-build.c | 20 ++++++++++----
10
2 files changed, 103 insertions(+), 92 deletions(-)
38
hw/arm/virt.c | 60 ++++++++++++++++++++++++++++++++++------
11
39
3 files changed, 67 insertions(+), 15 deletions(-)
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
40
41
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
13
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
43
--- a/include/hw/arm/virt.h
15
+++ b/target/arm/tcg/a64.decode
44
+++ b/include/hw/arm/virt.h
16
@@ -XXX,XX +XXX,XX @@ STR_v_i sz:2 111 1 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=
45
@@ -XXX,XX +XXX,XX @@ struct VirtMachineClass {
17
STR_v_i 00 111 1 01 10 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
46
/* Machines < 6.2 have no support for describing cpu topology to guest */
18
LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0
47
bool no_cpu_topology;
19
LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
48
bool no_tcg_lpa2;
20
+
49
+ bool no_ns_el2_virt_timer_irq;
21
+# Load/store with register offset
50
};
22
+&ldst rm rn rt sign ext sz opt s
51
23
+@ldst .. ... . .. .. . rm:5 opt:3 s:1 .. rn:5 rt:5 &ldst
52
struct VirtMachineState {
24
+STR sz:2 111 0 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
53
@@ -XXX,XX +XXX,XX @@ struct VirtMachineState {
25
+LDR 00 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=0
54
PCIBus *bus;
26
+LDR 01 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=1
55
char *oem_id;
27
+LDR 10 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=2
56
char *oem_table_id;
28
+LDR 11 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=3
57
+ bool ns_el2_virt_timer_irq;
29
+LDR 00 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=0
58
};
30
+LDR 01 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=1
59
31
+LDR 10 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=2
60
#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
32
+LDR 00 111 0 00 11 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=1 sz=0
61
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
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
62
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/tcg/translate-a64.c
63
--- a/hw/arm/virt-acpi-build.c
45
+++ b/target/arm/tcg/translate-a64.c
64
+++ b/hw/arm/virt-acpi-build.c
46
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_v_i(DisasContext *s, arg_ldst_imm *a)
65
@@ -XXX,XX +XXX,XX @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
47
return true;
66
}
48
}
67
49
68
/*
50
-/*
69
- * ACPI spec, Revision 5.1
51
- * Load/store (register offset)
70
- * 5.2.24 Generic Timer Description Table (GTDT)
52
- *
71
+ * ACPI spec, Revision 6.5
53
- * 31 30 29 27 26 25 24 23 22 21 20 16 15 13 12 11 10 9 5 4 0
72
+ * 5.2.25 Generic Timer Description Table (GTDT)
54
- * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
73
*/
55
- * |size| 1 1 1 | V | 0 0 | opc | 1 | Rm | opt | S| 1 0 | Rn | Rt |
74
static void
56
- * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
75
build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
57
- *
76
@@ -XXX,XX +XXX,XX @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
58
- * For non-vector:
77
uint32_t irqflags = vmc->claim_edge_triggered_timers ?
59
- * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
78
1 : /* Interrupt is Edge triggered */
60
- * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
79
0; /* Interrupt is Level triggered */
61
- * For vector:
80
- AcpiTable table = { .sig = "GTDT", .rev = 2, .oem_id = vms->oem_id,
62
- * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
81
+ AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
63
- * opc<0>: 0 -> store, 1 -> load
82
.oem_table_id = vms->oem_table_id };
64
- * V: 1 -> vector/simd
83
65
- * opt: extend encoding (see DecodeRegExtend)
84
acpi_table_begin(&table, table_data);
66
- * S: if S=1 then scale (essentially index by sizeof(size))
85
@@ -XXX,XX +XXX,XX @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
67
- * Rt: register to transfer into/out of
86
build_append_int_noprefix(table_data, 0, 4);
68
- * Rn: address register or SP for base
87
/* Platform Timer Offset */
69
- * Rm: offset register or ZR for offset
88
build_append_int_noprefix(table_data, 0, 4);
70
- */
89
-
71
-static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
90
+ if (vms->ns_el2_virt_timer_irq) {
72
- int opc,
91
+ /* Virtual EL2 Timer GSIV */
73
- int size,
92
+ build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
74
- int rt,
93
+ /* Virtual EL2 Timer Flags */
75
- bool is_vector)
94
+ build_append_int_noprefix(table_data, irqflags, 4);
76
+static void op_addr_ldst_pre(DisasContext *s, arg_ldst *a,
95
+ } else {
77
+ TCGv_i64 *clean_addr, TCGv_i64 *dirty_addr,
96
+ build_append_int_noprefix(table_data, 0, 4);
78
+ bool is_store, MemOp memop)
97
+ build_append_int_noprefix(table_data, 0, 4);
98
+ }
99
acpi_table_end(linker, &table);
100
}
101
102
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
103
static void build_fadt_rev6(GArray *table_data, BIOSLinker *linker,
104
VirtMachineState *vms, unsigned dsdt_tbl_offset)
79
{
105
{
80
- int rn = extract32(insn, 5, 5);
106
- /* ACPI v6.0 */
81
- int shift = extract32(insn, 12, 1);
107
+ /* ACPI v6.3 */
82
- int rm = extract32(insn, 16, 5);
108
AcpiFadtData fadt = {
83
- int opt = extract32(insn, 13, 3);
109
.rev = 6,
84
- bool is_signed = false;
110
- .minor_ver = 0,
85
- bool is_store = false;
111
+ .minor_ver = 3,
86
- bool is_extended = false;
112
.flags = 1 << ACPI_FADT_F_HW_REDUCED_ACPI,
87
- TCGv_i64 tcg_rm, clean_addr, dirty_addr;
113
.xdsdt_tbl_offset = &dsdt_tbl_offset,
88
- MemOp memop;
114
};
89
+ TCGv_i64 tcg_rm;
115
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
90
116
index XXXXXXX..XXXXXXX 100644
91
- if (extract32(opt, 1, 1) == 0) {
117
--- a/hw/arm/virt.c
92
- unallocated_encoding(s);
118
+++ b/hw/arm/virt.c
93
- return;
119
@@ -XXX,XX +XXX,XX @@ static void create_randomness(MachineState *ms, const char *node)
94
- }
120
qemu_fdt_setprop(ms->fdt, node, "rng-seed", seed.rng, sizeof(seed.rng));
95
-
121
}
96
- if (is_vector) {
122
97
- size |= (opc & 2) << 1;
123
+/*
98
- if (size > 4) {
124
+ * The CPU object always exposes the NS EL2 virt timer IRQ line,
99
- unallocated_encoding(s);
125
+ * but we don't want to advertise it to the guest in the dtb or ACPI
100
- return;
126
+ * table unless it's really going to do something.
101
- }
127
+ */
102
- is_store = !extract32(opc, 0, 1);
128
+static bool ns_el2_virt_timer_present(void)
103
- if (!fp_access_check(s)) {
129
+{
104
- return;
130
+ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(0));
105
- }
131
+ CPUARMState *env = &cpu->env;
106
- memop = finalize_memop_asimd(s, size);
132
+
107
- } else {
133
+ return arm_feature(env, ARM_FEATURE_AARCH64) &&
108
- if (size == 3 && opc == 2) {
134
+ arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu);
109
- /* PRFM - prefetch */
135
+}
110
- return;
136
+
111
- }
137
static void create_fdt(VirtMachineState *vms)
112
- if (opc == 3 && size > 1) {
138
{
113
- unallocated_encoding(s);
139
MachineState *ms = MACHINE(vms);
114
- return;
140
@@ -XXX,XX +XXX,XX @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
115
- }
141
"arm,armv7-timer");
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
}
142
}
126
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
143
qemu_fdt_setprop(ms->fdt, "/timer", "always-on", NULL, 0);
127
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
144
- qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
128
145
- GIC_FDT_IRQ_TYPE_PPI,
129
- tcg_rm = read_cpu_reg(s, rm, 1);
146
- INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ), irqflags,
130
- ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
147
- GIC_FDT_IRQ_TYPE_PPI,
131
+ tcg_rm = read_cpu_reg(s, a->rm, 1);
148
- INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ), irqflags,
132
+ ext_and_shift_reg(tcg_rm, tcg_rm, a->opt, a->s ? a->sz : 0);
149
- GIC_FDT_IRQ_TYPE_PPI,
133
150
- INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ), irqflags,
134
- tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
151
- GIC_FDT_IRQ_TYPE_PPI,
135
+ tcg_gen_add_i64(*dirty_addr, *dirty_addr, tcg_rm);
152
- INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ), irqflags);
136
+ *clean_addr = gen_mte_check1(s, *dirty_addr, is_store, true, memop);
153
+ if (vms->ns_el2_virt_timer_irq) {
137
+}
154
+ qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
138
155
+ GIC_FDT_IRQ_TYPE_PPI,
139
- clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, memop);
156
+ INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ), irqflags,
140
+static bool trans_LDR(DisasContext *s, arg_ldst *a)
157
+ GIC_FDT_IRQ_TYPE_PPI,
141
+{
158
+ INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ), irqflags,
142
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
159
+ GIC_FDT_IRQ_TYPE_PPI,
143
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
160
+ INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ), irqflags,
144
+ MemOp memop;
161
+ GIC_FDT_IRQ_TYPE_PPI,
145
162
+ INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ), irqflags,
146
- if (is_vector) {
163
+ GIC_FDT_IRQ_TYPE_PPI,
147
- if (is_store) {
164
+ INTID_TO_PPI(ARCH_TIMER_NS_EL2_VIRT_IRQ), irqflags);
148
- do_fp_st(s, rt, clean_addr, memop);
165
+ } else {
149
- } else {
166
+ qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
150
- do_fp_ld(s, rt, clean_addr, memop);
167
+ GIC_FDT_IRQ_TYPE_PPI,
151
- }
168
+ INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ), irqflags,
152
- } else {
169
+ GIC_FDT_IRQ_TYPE_PPI,
153
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
170
+ INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ), irqflags,
154
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
171
+ GIC_FDT_IRQ_TYPE_PPI,
155
-
172
+ INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ), irqflags,
156
- if (is_store) {
173
+ GIC_FDT_IRQ_TYPE_PPI,
157
- do_gpr_st(s, tcg_rt, clean_addr, memop,
174
+ INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ), irqflags);
158
- true, rt, iss_sf, false);
175
+ }
159
- } else {
176
}
160
- do_gpr_ld(s, tcg_rt, clean_addr, memop,
177
161
- is_extended, true, rt, iss_sf, false);
178
static void fdt_add_cpu_nodes(const VirtMachineState *vms)
162
- }
179
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
163
+ if (extract32(a->opt, 1, 1) == 0) {
180
[GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
164
+ return false;
181
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
182
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
183
+ [GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
184
};
185
186
for (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
187
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
188
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
189
object_unref(cpuobj);
165
}
190
}
166
+
191
+
167
+ memop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
192
+ /* Now we've created the CPUs we can see if they have the hypvirt timer */
168
+ op_addr_ldst_pre(s, a, &clean_addr, &dirty_addr, false, memop);
193
+ vms->ns_el2_virt_timer_irq = ns_el2_virt_timer_present() &&
169
+ tcg_rt = cpu_reg(s, a->rt);
194
+ !vmc->no_ns_el2_virt_timer_irq;
170
+ do_gpr_ld(s, tcg_rt, clean_addr, memop,
195
+
171
+ a->ext, true, a->rt, iss_sf, false);
196
fdt_add_timer_nodes(vms);
172
+ return true;
197
fdt_add_cpu_nodes(vms);
173
+}
198
174
+
199
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(9, 0)
175
+static bool trans_STR(DisasContext *s, arg_ldst *a)
200
176
+{
201
static void virt_machine_8_2_options(MachineClass *mc)
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
{
202
{
234
int rt = extract32(insn, 0, 5);
203
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
235
- int opc = extract32(insn, 22, 2);
204
+
236
bool is_vector = extract32(insn, 26, 1);
205
virt_machine_9_0_options(mc);
237
int size = extract32(insn, 30, 2);
206
compat_props_add(mc->compat_props, hw_compat_8_2, hw_compat_8_2_len);
238
207
+ /*
239
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
208
+ * Don't expose NS_EL2_VIRT timer IRQ in DTB on ACPI on 8.2 and
240
disas_ldst_atomic(s, insn, size, rt, is_vector);
209
+ * earlier machines. (Exposing it tickles a bug in older EDK2
241
return;
210
+ * guest BIOS binaries.)
242
case 2:
211
+ */
243
- disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector);
212
+ vmc->no_ns_el2_virt_timer_irq = true;
244
- return;
213
}
245
+ break;
214
DEFINE_VIRT_MACHINE(8, 2)
246
default:
215
247
disas_ldst_pac(s, insn, size, rt, is_vector);
248
return;
249
--
216
--
250
2.34.1
217
2.34.1
diff view generated by jsdifflib
1
Convert the load and store instructions which use a 9-bit
1
Update the virt golden reference files to say that the FACP is ACPI
2
immediate offset to decodetree.
2
v6.3, and the GTDT table is a revision 3 table with space for the
3
virtual EL2 timer.
4
5
Diffs from iasl:
6
7
@@ -XXX,XX +XXX,XX @@
8
/*
9
* Intel ACPI Component Architecture
10
* AML/ASL+ Disassembler version 20200925 (64-bit version)
11
* Copyright (c) 2000 - 2020 Intel Corporation
12
*
13
- * Disassembly of tests/data/acpi/virt/FACP, Mon Jan 22 13:48:40 2024
14
+ * Disassembly of /tmp/aml-W8RZH2, Mon Jan 22 13:48:40 2024
15
*
16
* ACPI Data Table [FACP]
17
*
18
* Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue
19
*/
20
21
[000h 0000 4] Signature : "FACP" [Fixed ACPI Description Table (FADT)]
22
[004h 0004 4] Table Length : 00000114
23
[008h 0008 1] Revision : 06
24
-[009h 0009 1] Checksum : 15
25
+[009h 0009 1] Checksum : 12
26
[00Ah 0010 6] Oem ID : "BOCHS "
27
[010h 0016 8] Oem Table ID : "BXPC "
28
[018h 0024 4] Oem Revision : 00000001
29
[01Ch 0028 4] Asl Compiler ID : "BXPC"
30
[020h 0032 4] Asl Compiler Revision : 00000001
31
32
[024h 0036 4] FACS Address : 00000000
33
[028h 0040 4] DSDT Address : 00000000
34
[02Ch 0044 1] Model : 00
35
[02Dh 0045 1] PM Profile : 00 [Unspecified]
36
[02Eh 0046 2] SCI Interrupt : 0000
37
[030h 0048 4] SMI Command Port : 00000000
38
[034h 0052 1] ACPI Enable Value : 00
39
[035h 0053 1] ACPI Disable Value : 00
40
[036h 0054 1] S4BIOS Command : 00
41
[037h 0055 1] P-State Control : 00
42
@@ -XXX,XX +XXX,XX @@
43
Use APIC Physical Destination Mode (V4) : 0
44
Hardware Reduced (V5) : 1
45
Low Power S0 Idle (V5) : 0
46
47
[074h 0116 12] Reset Register : [Generic Address Structure]
48
[074h 0116 1] Space ID : 00 [SystemMemory]
49
[075h 0117 1] Bit Width : 00
50
[076h 0118 1] Bit Offset : 00
51
[077h 0119 1] Encoded Access Width : 00 [Undefined/Legacy]
52
[078h 0120 8] Address : 0000000000000000
53
54
[080h 0128 1] Value to cause reset : 00
55
[081h 0129 2] ARM Flags (decoded below) : 0003
56
PSCI Compliant : 1
57
Must use HVC for PSCI : 1
58
59
-[083h 0131 1] FADT Minor Revision : 00
60
+[083h 0131 1] FADT Minor Revision : 03
61
[084h 0132 8] FACS Address : 0000000000000000
62
[08Ch 0140 8] DSDT Address : 0000000000000000
63
[094h 0148 12] PM1A Event Block : [Generic Address Structure]
64
[094h 0148 1] Space ID : 00 [SystemMemory]
65
[095h 0149 1] Bit Width : 00
66
[096h 0150 1] Bit Offset : 00
67
[097h 0151 1] Encoded Access Width : 00 [Undefined/Legacy]
68
[098h 0152 8] Address : 0000000000000000
69
70
[0A0h 0160 12] PM1B Event Block : [Generic Address Structure]
71
[0A0h 0160 1] Space ID : 00 [SystemMemory]
72
[0A1h 0161 1] Bit Width : 00
73
[0A2h 0162 1] Bit Offset : 00
74
[0A3h 0163 1] Encoded Access Width : 00 [Undefined/Legacy]
75
[0A4h 0164 8] Address : 0000000000000000
76
77
@@ -XXX,XX +XXX,XX @@
78
[0F5h 0245 1] Bit Width : 00
79
[0F6h 0246 1] Bit Offset : 00
80
[0F7h 0247 1] Encoded Access Width : 00 [Undefined/Legacy]
81
[0F8h 0248 8] Address : 0000000000000000
82
83
[100h 0256 12] Sleep Status Register : [Generic Address Structure]
84
[100h 0256 1] Space ID : 00 [SystemMemory]
85
[101h 0257 1] Bit Width : 00
86
[102h 0258 1] Bit Offset : 00
87
[103h 0259 1] Encoded Access Width : 00 [Undefined/Legacy]
88
[104h 0260 8] Address : 0000000000000000
89
90
[10Ch 0268 8] Hypervisor ID : 00000000554D4551
91
92
Raw Table Data: Length 276 (0x114)
93
94
- 0000: 46 41 43 50 14 01 00 00 06 15 42 4F 43 48 53 20 // FACP......BOCHS
95
+ 0000: 46 41 43 50 14 01 00 00 06 12 42 4F 43 48 53 20 // FACP......BOCHS
96
0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC
97
0020: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
98
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
99
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
100
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
101
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
102
0070: 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
103
- 0080: 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
104
+ 0080: 00 03 00 03 00 00 00 00 00 00 00 00 00 00 00 00 // ................
105
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
106
00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
107
00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
108
00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
109
00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
110
00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
111
00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
112
0100: 00 00 00 00 00 00 00 00 00 00 00 00 51 45 4D 55 // ............QEMU
113
0110: 00 00 00 00 // ....
114
115
@@ -XXX,XX +XXX,XX @@
116
/*
117
* Intel ACPI Component Architecture
118
* AML/ASL+ Disassembler version 20200925 (64-bit version)
119
* Copyright (c) 2000 - 2020 Intel Corporation
120
*
121
- * Disassembly of tests/data/acpi/virt/GTDT, Mon Jan 22 13:48:40 2024
122
+ * Disassembly of /tmp/aml-XDSZH2, Mon Jan 22 13:48:40 2024
123
*
124
* ACPI Data Table [GTDT]
125
*
126
* Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue
127
*/
128
129
[000h 0000 4] Signature : "GTDT" [Generic Timer Description Table]
130
-[004h 0004 4] Table Length : 00000060
131
-[008h 0008 1] Revision : 02
132
-[009h 0009 1] Checksum : 9C
133
+[004h 0004 4] Table Length : 00000068
134
+[008h 0008 1] Revision : 03
135
+[009h 0009 1] Checksum : 93
136
[00Ah 0010 6] Oem ID : "BOCHS "
137
[010h 0016 8] Oem Table ID : "BXPC "
138
[018h 0024 4] Oem Revision : 00000001
139
[01Ch 0028 4] Asl Compiler ID : "BXPC"
140
[020h 0032 4] Asl Compiler Revision : 00000001
141
142
[024h 0036 8] Counter Block Address : FFFFFFFFFFFFFFFF
143
[02Ch 0044 4] Reserved : 00000000
144
145
[030h 0048 4] Secure EL1 Interrupt : 0000001D
146
[034h 0052 4] EL1 Flags (decoded below) : 00000000
147
Trigger Mode : 0
148
Polarity : 0
149
Always On : 0
150
151
[038h 0056 4] Non-Secure EL1 Interrupt : 0000001E
152
@@ -XXX,XX +XXX,XX @@
153
154
[040h 0064 4] Virtual Timer Interrupt : 0000001B
155
[044h 0068 4] VT Flags (decoded below) : 00000000
156
Trigger Mode : 0
157
Polarity : 0
158
Always On : 0
159
160
[048h 0072 4] Non-Secure EL2 Interrupt : 0000001A
161
[04Ch 0076 4] NEL2 Flags (decoded below) : 00000000
162
Trigger Mode : 0
163
Polarity : 0
164
Always On : 0
165
[050h 0080 8] Counter Read Block Address : FFFFFFFFFFFFFFFF
166
167
[058h 0088 4] Platform Timer Count : 00000000
168
[05Ch 0092 4] Platform Timer Offset : 00000000
169
+[060h 0096 4] Virtual EL2 Timer GSIV : 00000000
170
+[064h 0100 4] Virtual EL2 Timer Flags : 00000000
171
172
-Raw Table Data: Length 96 (0x60)
173
+Raw Table Data: Length 104 (0x68)
174
175
- 0000: 47 54 44 54 60 00 00 00 02 9C 42 4F 43 48 53 20 // GTDT`.....BOCHS
176
+ 0000: 47 54 44 54 68 00 00 00 03 93 42 4F 43 48 53 20 // GTDTh.....BOCHS
177
0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC
178
0020: 01 00 00 00 FF FF FF FF FF FF FF FF 00 00 00 00 // ................
179
0030: 1D 00 00 00 00 00 00 00 1E 00 00 00 04 00 00 00 // ................
180
0040: 1B 00 00 00 00 00 00 00 1A 00 00 00 00 00 00 00 // ................
181
0050: FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 // ................
182
+ 0060: 00 00 00 00 00 00 00 00 // ........
3
183
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
184
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
185
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
6
Message-id: 20230602155223.2040685-13-peter.maydell@linaro.org
186
Message-id: 20240122143537.233498-4-peter.maydell@linaro.org
7
---
187
---
8
target/arm/tcg/a64.decode | 69 +++++++++++
188
tests/qtest/bios-tables-test-allowed-diff.h | 2 --
9
target/arm/tcg/translate-a64.c | 206 ++++++++++++++-------------------
189
tests/data/acpi/virt/FACP | Bin 276 -> 276 bytes
10
2 files changed, 153 insertions(+), 122 deletions(-)
190
tests/data/acpi/virt/GTDT | Bin 96 -> 104 bytes
11
191
3 files changed, 2 deletions(-)
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
192
193
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
13
index XXXXXXX..XXXXXXX 100644
194
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
195
--- a/tests/qtest/bios-tables-test-allowed-diff.h
15
+++ b/target/arm/tcg/a64.decode
196
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
16
@@ -XXX,XX +XXX,XX @@ LDP_v 10 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p
197
@@ -1,3 +1 @@
17
STGP 01 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
198
/* List of comma-separated changed AML files to ignore */
18
STGP 01 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
199
-"tests/data/acpi/virt/FACP",
19
STGP 01 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
200
-"tests/data/acpi/virt/GTDT",
20
+
201
diff --git a/tests/data/acpi/virt/FACP b/tests/data/acpi/virt/FACP
21
+# Load/store register (unscaled immediate)
22
+&ldst_imm rt rn imm sz sign w p unpriv ext
23
+@ldst_imm .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=0
24
+@ldst_imm_pre .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=1
25
+@ldst_imm_post .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=1 w=1
26
+@ldst_imm_user .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=1 p=0 w=0
27
+
28
+STR_i sz:2 111 0 00 00 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
29
+LDR_i 00 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=0
30
+LDR_i 01 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=1
31
+LDR_i 10 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=2
32
+LDR_i 11 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=3
33
+LDR_i 00 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=0
34
+LDR_i 01 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=1
35
+LDR_i 10 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=2
36
+LDR_i 00 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=1 sz=0
37
+LDR_i 01 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=1 sz=1
38
+
39
+STR_i sz:2 111 0 00 00 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
40
+LDR_i 00 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=0
41
+LDR_i 01 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=1
42
+LDR_i 10 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=2
43
+LDR_i 11 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=3
44
+LDR_i 00 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=0
45
+LDR_i 01 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=1
46
+LDR_i 10 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=2
47
+LDR_i 00 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=1 sz=0
48
+LDR_i 01 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=1 sz=1
49
+
50
+STR_i sz:2 111 0 00 00 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=0
51
+LDR_i 00 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=0
52
+LDR_i 01 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=1
53
+LDR_i 10 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=2
54
+LDR_i 11 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=0 sz=3
55
+LDR_i 00 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=0
56
+LDR_i 01 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=1
57
+LDR_i 10 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=2
58
+LDR_i 00 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=1 sz=0
59
+LDR_i 01 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=1 sz=1
60
+
61
+STR_i sz:2 111 0 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
62
+LDR_i 00 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=0
63
+LDR_i 01 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=1
64
+LDR_i 10 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=2
65
+LDR_i 11 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=3
66
+LDR_i 00 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=0
67
+LDR_i 01 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=1
68
+LDR_i 10 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=2
69
+LDR_i 00 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=1 sz=0
70
+LDR_i 01 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=1 sz=1
71
+
72
+# PRFM : prefetch memory: a no-op for QEMU
73
+NOP 11 111 0 00 10 0 --------- 00 ----- -----
74
+
75
+STR_v_i sz:2 111 1 00 00 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
76
+STR_v_i 00 111 1 00 10 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=4
77
+LDR_v_i sz:2 111 1 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
78
+LDR_v_i 00 111 1 00 11 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=4
79
+
80
+STR_v_i sz:2 111 1 00 00 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
81
+STR_v_i 00 111 1 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=4
82
+LDR_v_i sz:2 111 1 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
83
+LDR_v_i 00 111 1 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=4
84
+
85
+STR_v_i sz:2 111 1 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
86
+STR_v_i 00 111 1 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
87
+LDR_v_i sz:2 111 1 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
88
+LDR_v_i 00 111 1 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
89
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
202
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/tcg/translate-a64.c
203
GIT binary patch
92
+++ b/target/arm/tcg/translate-a64.c
204
delta 25
93
@@ -XXX,XX +XXX,XX @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
205
gcmbQjG=+)F&CxkPgpq-PO=u!l<;2F$$vli407<0<)c^nh
94
return true;
206
95
}
207
delta 28
96
208
kcmbQjG=+)F&CxkPgpq-PO>`nx<-|!<6Akz$^DuG%0AAS!ssI20
97
-/*
209
98
- * Load/store (immediate post-indexed)
210
diff --git a/tests/data/acpi/virt/GTDT b/tests/data/acpi/virt/GTDT
99
- * Load/store (immediate pre-indexed)
211
index XXXXXXX..XXXXXXX 100644
100
- * Load/store (unscaled immediate)
212
GIT binary patch
101
- *
213
delta 25
102
- * 31 30 29 27 26 25 24 23 22 21 20 12 11 10 9 5 4 0
214
bcmYeu;BpUf3CUn!U|^m+kt>V?$N&QXMtB4L
103
- * +----+-------+---+-----+-----+---+--------+-----+------+------+
215
104
- * |size| 1 1 1 | V | 0 0 | opc | 0 | imm9 | idx | Rn | Rt |
216
delta 16
105
- * +----+-------+---+-----+-----+---+--------+-----+------+------+
217
Xcmc~u;BpUf2}xjJU|^avkt+-UB60)u
106
- *
218
107
- * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
108
- 10 -> unprivileged
109
- * V = 0 -> non-vector
110
- * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
111
- * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
112
- */
113
-static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
114
- int opc,
115
- int size,
116
- int rt,
117
- bool is_vector)
118
+static void op_addr_ldst_imm_pre(DisasContext *s, arg_ldst_imm *a,
119
+ TCGv_i64 *clean_addr, TCGv_i64 *dirty_addr,
120
+ uint64_t offset, bool is_store, MemOp mop)
121
{
122
- int rn = extract32(insn, 5, 5);
123
- int imm9 = sextract32(insn, 12, 9);
124
- int idx = extract32(insn, 10, 2);
125
- bool is_signed = false;
126
- bool is_store = false;
127
- bool is_extended = false;
128
- bool is_unpriv = (idx == 2);
129
- bool iss_valid;
130
- bool post_index;
131
- bool writeback;
132
int memidx;
133
- MemOp memop;
134
- TCGv_i64 clean_addr, dirty_addr;
135
136
- if (is_vector) {
137
- size |= (opc & 2) << 1;
138
- if (size > 4 || is_unpriv) {
139
- unallocated_encoding(s);
140
- return;
141
- }
142
- is_store = ((opc & 1) == 0);
143
- if (!fp_access_check(s)) {
144
- return;
145
- }
146
- memop = finalize_memop_asimd(s, size);
147
- } else {
148
- if (size == 3 && opc == 2) {
149
- /* PRFM - prefetch */
150
- if (idx != 0) {
151
- unallocated_encoding(s);
152
- return;
153
- }
154
- return;
155
- }
156
- if (opc == 3 && size > 1) {
157
- unallocated_encoding(s);
158
- return;
159
- }
160
- is_store = (opc == 0);
161
- is_signed = !is_store && extract32(opc, 1, 1);
162
- is_extended = (size < 3) && extract32(opc, 0, 1);
163
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
164
- }
165
-
166
- switch (idx) {
167
- case 0:
168
- case 2:
169
- post_index = false;
170
- writeback = false;
171
- break;
172
- case 1:
173
- post_index = true;
174
- writeback = true;
175
- break;
176
- case 3:
177
- post_index = false;
178
- writeback = true;
179
- break;
180
- default:
181
- g_assert_not_reached();
182
- }
183
-
184
- iss_valid = !is_vector && !writeback;
185
-
186
- if (rn == 31) {
187
+ if (a->rn == 31) {
188
gen_check_sp_alignment(s);
189
}
190
191
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
192
- if (!post_index) {
193
- tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
194
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
195
+ if (!a->p) {
196
+ tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
197
}
198
+ memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
199
+ *clean_addr = gen_mte_check1_mmuidx(s, *dirty_addr, is_store,
200
+ a->w || a->rn != 31,
201
+ mop, a->unpriv, memidx);
202
+}
203
204
- memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
205
-
206
- clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
207
- writeback || rn != 31,
208
- memop, is_unpriv, memidx);
209
-
210
- if (is_vector) {
211
- if (is_store) {
212
- do_fp_st(s, rt, clean_addr, memop);
213
- } else {
214
- do_fp_ld(s, rt, clean_addr, memop);
215
- }
216
- } else {
217
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
218
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
219
-
220
- if (is_store) {
221
- do_gpr_st_memidx(s, tcg_rt, clean_addr, memop, memidx,
222
- iss_valid, rt, iss_sf, false);
223
- } else {
224
- do_gpr_ld_memidx(s, tcg_rt, clean_addr, memop,
225
- is_extended, memidx,
226
- iss_valid, rt, iss_sf, false);
227
+static void op_addr_ldst_imm_post(DisasContext *s, arg_ldst_imm *a,
228
+ TCGv_i64 dirty_addr, uint64_t offset)
229
+{
230
+ if (a->w) {
231
+ if (a->p) {
232
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
233
}
234
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
235
}
236
+}
237
238
- if (writeback) {
239
- TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
240
- if (post_index) {
241
- tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
242
- }
243
- tcg_gen_mov_i64(tcg_rn, dirty_addr);
244
+static bool trans_STR_i(DisasContext *s, arg_ldst_imm *a)
245
+{
246
+ bool iss_sf, iss_valid = !a->w;
247
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
248
+ int memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
249
+ MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
250
+
251
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, true, mop);
252
+
253
+ tcg_rt = cpu_reg(s, a->rt);
254
+ iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
255
+
256
+ do_gpr_st_memidx(s, tcg_rt, clean_addr, mop, memidx,
257
+ iss_valid, a->rt, iss_sf, false);
258
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
259
+ return true;
260
+}
261
+
262
+static bool trans_LDR_i(DisasContext *s, arg_ldst_imm *a)
263
+{
264
+ bool iss_sf, iss_valid = !a->w;
265
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
266
+ int memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
267
+ MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
268
+
269
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, false, mop);
270
+
271
+ tcg_rt = cpu_reg(s, a->rt);
272
+ iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
273
+
274
+ do_gpr_ld_memidx(s, tcg_rt, clean_addr, mop,
275
+ a->ext, memidx, iss_valid, a->rt, iss_sf, false);
276
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
277
+ return true;
278
+}
279
+
280
+static bool trans_STR_v_i(DisasContext *s, arg_ldst_imm *a)
281
+{
282
+ TCGv_i64 clean_addr, dirty_addr;
283
+ MemOp mop;
284
+
285
+ if (!fp_access_check(s)) {
286
+ return true;
287
}
288
+ mop = finalize_memop_asimd(s, a->sz);
289
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, true, mop);
290
+ do_fp_st(s, a->rt, clean_addr, mop);
291
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
292
+ return true;
293
+}
294
+
295
+static bool trans_LDR_v_i(DisasContext *s, arg_ldst_imm *a)
296
+{
297
+ TCGv_i64 clean_addr, dirty_addr;
298
+ MemOp mop;
299
+
300
+ if (!fp_access_check(s)) {
301
+ return true;
302
+ }
303
+ mop = finalize_memop_asimd(s, a->sz);
304
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, false, mop);
305
+ do_fp_ld(s, a->rt, clean_addr, mop);
306
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
307
+ return true;
308
}
309
310
/*
311
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
312
switch (extract32(insn, 24, 2)) {
313
case 0:
314
if (extract32(insn, 21, 1) == 0) {
315
- /* Load/store register (unscaled immediate)
316
- * Load/store immediate pre/post-indexed
317
- * Load/store register unprivileged
318
- */
319
- disas_ldst_reg_imm9(s, insn, opc, size, rt, is_vector);
320
- return;
321
+ break;
322
}
323
switch (extract32(insn, 10, 2)) {
324
case 0:
325
--
219
--
326
2.34.1
220
2.34.1
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
The patchset adding the GMAC ethernet to this SoC crossed in the
2
mail with the patchset cleaning up the NIC handling. When we
3
create the GMAC modules we must call qemu_configure_nic_device()
4
so that the user has the opportunity to use the -nic commandline
5
option to create a network backend and connect it to the GMACs.
2
6
3
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
Add the missing call.
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
8
5
Message-id: 20230607092112.655098-1-marcin.juszkiewicz@linaro.org
9
Fixes: 21e5326a7c ("hw/arm: Add GMAC devices to NPCM7XX SoC")
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
12
Message-id: 20240206171231.396392-2-peter.maydell@linaro.org
7
---
13
---
8
hw/arm/Kconfig | 1 +
14
hw/arm/npcm7xx.c | 1 +
9
1 file changed, 1 insertion(+)
15
1 file changed, 1 insertion(+)
10
16
11
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
17
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/Kconfig
19
--- a/hw/arm/npcm7xx.c
14
+++ b/hw/arm/Kconfig
20
+++ b/hw/arm/npcm7xx.c
15
@@ -XXX,XX +XXX,XX @@ config SBSA_REF
21
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
16
select PL061 # GPIO
22
for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
17
select USB_EHCI_SYSBUS
23
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->gmac[i]);
18
select WDT_SBSA
24
19
+ select BOCHS_DISPLAY
25
+ qemu_configure_nic_device(DEVICE(sbd), false, NULL);
20
26
/*
21
config SABRELITE
27
* The device exists regardless of whether it's connected to a QEMU
22
bool
28
* netdev backend. So always instantiate it even if there is no
23
--
29
--
24
2.34.1
30
2.34.1
diff view generated by jsdifflib
1
Convert the "Load register (literal)" instruction class to
1
Currently QEMU will warn if there is a NIC on the board that
2
decodetree.
2
is not connected to a backend. By default the '-nic user' will
3
get used for all NICs, but if you manually connect a specific
4
NIC to a specific backend, then the other NICs on the board
5
have no backend and will be warned about:
6
7
qemu-system-arm: warning: nic npcm7xx-emc.1 has no peer
8
qemu-system-arm: warning: nic npcm-gmac.0 has no peer
9
qemu-system-arm: warning: nic npcm-gmac.1 has no peer
10
11
So suppress those warnings by manually connecting every NIC
12
on the board to some backend.
3
13
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
6
Message-id: 20230602155223.2040685-11-peter.maydell@linaro.org
16
Reviewed-by: Thomas Huth <thuth@redhat.com>
17
Message-id: 20240206171231.396392-3-peter.maydell@linaro.org
7
---
18
---
8
target/arm/tcg/a64.decode | 13 ++++++
19
tests/qtest/npcm7xx_emc-test.c | 5 ++++-
9
target/arm/tcg/translate-a64.c | 76 ++++++++++------------------------
20
1 file changed, 4 insertions(+), 1 deletion(-)
10
2 files changed, 35 insertions(+), 54 deletions(-)
11
21
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
22
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
13
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
24
--- a/tests/qtest/npcm7xx_emc-test.c
15
+++ b/target/arm/tcg/a64.decode
25
+++ b/tests/qtest/npcm7xx_emc-test.c
16
@@ -XXX,XX +XXX,XX @@ LDXP 1 . 001000 011 ..... . ..... ..... ..... @stxp # inc LDAXP
26
@@ -XXX,XX +XXX,XX @@ static int *packet_test_init(int module_num, GString *cmd_line)
17
CASP 0 . 001000 0 - 1 rs:5 - 11111 rn:5 rt:5 sz=%imm1_30_p2
27
* KISS and use -nic. The driver accepts 'emc0' and 'emc1' as aliases
18
# CAS, CASA, CASAL, CASL
28
* in the 'model' field to specify the device to match.
19
CAS sz:2 001000 1 - 1 rs:5 - 11111 rn:5 rt:5
29
*/
20
+
30
- g_string_append_printf(cmd_line, " -nic socket,fd=%d,model=emc%d ",
21
+&ldlit rt imm sz sign
31
+ g_string_append_printf(cmd_line, " -nic socket,fd=%d,model=emc%d "
22
+@ldlit .. ... . .. ................... rt:5 &ldlit imm=%imm19
32
+ "-nic user,model=npcm7xx-emc "
23
+
33
+ "-nic user,model=npcm-gmac "
24
+LD_lit 00 011 0 00 ................... ..... @ldlit sz=2 sign=0
34
+ "-nic user,model=npcm-gmac",
25
+LD_lit 01 011 0 00 ................... ..... @ldlit sz=3 sign=0
35
test_sockets[1], module_num);
26
+LD_lit 10 011 0 00 ................... ..... @ldlit sz=2 sign=1
36
27
+LD_lit_v 00 011 1 00 ................... ..... @ldlit sz=2 sign=0
37
g_test_queue_destroy(packet_test_clear, test_sockets);
28
+LD_lit_v 01 011 1 00 ................... ..... @ldlit sz=3 sign=0
29
+LD_lit_v 10 011 1 00 ................... ..... @ldlit sz=4 sign=0
30
+
31
+# PRFM
32
+NOP 11 011 0 00 ------------------- -----
33
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/tcg/translate-a64.c
36
+++ b/target/arm/tcg/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ static bool trans_CAS(DisasContext *s, arg_CAS *a)
38
return true;
39
}
40
41
-/*
42
- * Load register (literal)
43
- *
44
- * 31 30 29 27 26 25 24 23 5 4 0
45
- * +-----+-------+---+-----+-------------------+-------+
46
- * | opc | 0 1 1 | V | 0 0 | imm19 | Rt |
47
- * +-----+-------+---+-----+-------------------+-------+
48
- *
49
- * V: 1 -> vector (simd/fp)
50
- * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
51
- * 10-> 32 bit signed, 11 -> prefetch
52
- * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
53
- */
54
-static void disas_ld_lit(DisasContext *s, uint32_t insn)
55
+static bool trans_LD_lit(DisasContext *s, arg_ldlit *a)
56
{
57
- int rt = extract32(insn, 0, 5);
58
- int64_t imm = sextract32(insn, 5, 19) << 2;
59
- bool is_vector = extract32(insn, 26, 1);
60
- int opc = extract32(insn, 30, 2);
61
- bool is_signed = false;
62
- int size = 2;
63
- TCGv_i64 tcg_rt, clean_addr;
64
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, false);
65
+ TCGv_i64 tcg_rt = cpu_reg(s, a->rt);
66
+ TCGv_i64 clean_addr = tcg_temp_new_i64();
67
+ MemOp memop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
68
+
69
+ gen_pc_plus_diff(s, clean_addr, a->imm);
70
+ do_gpr_ld(s, tcg_rt, clean_addr, memop,
71
+ false, true, a->rt, iss_sf, false);
72
+ return true;
73
+}
74
+
75
+static bool trans_LD_lit_v(DisasContext *s, arg_ldlit *a)
76
+{
77
+ /* Load register (literal), vector version */
78
+ TCGv_i64 clean_addr;
79
MemOp memop;
80
81
- if (is_vector) {
82
- if (opc == 3) {
83
- unallocated_encoding(s);
84
- return;
85
- }
86
- size = 2 + opc;
87
- if (!fp_access_check(s)) {
88
- return;
89
- }
90
- memop = finalize_memop_asimd(s, size);
91
- } else {
92
- if (opc == 3) {
93
- /* PRFM (literal) : prefetch */
94
- return;
95
- }
96
- size = 2 + extract32(opc, 0, 1);
97
- is_signed = extract32(opc, 1, 1);
98
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
99
+ if (!fp_access_check(s)) {
100
+ return true;
101
}
102
-
103
- tcg_rt = cpu_reg(s, rt);
104
-
105
+ memop = finalize_memop_asimd(s, a->sz);
106
clean_addr = tcg_temp_new_i64();
107
- gen_pc_plus_diff(s, clean_addr, imm);
108
-
109
- if (is_vector) {
110
- do_fp_ld(s, rt, clean_addr, memop);
111
- } else {
112
- /* Only unsigned 32bit loads target 32bit registers. */
113
- bool iss_sf = opc != 0;
114
- do_gpr_ld(s, tcg_rt, clean_addr, memop, false, true, rt, iss_sf, false);
115
- }
116
+ gen_pc_plus_diff(s, clean_addr, a->imm);
117
+ do_fp_ld(s, a->rt, clean_addr, memop);
118
+ return true;
119
}
120
121
/*
122
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
123
static void disas_ldst(DisasContext *s, uint32_t insn)
124
{
125
switch (extract32(insn, 24, 6)) {
126
- case 0x18: case 0x1c: /* Load register (literal) */
127
- disas_ld_lit(s, insn);
128
- break;
129
case 0x28: case 0x29:
130
case 0x2c: case 0x2d: /* Load/store pair (all forms) */
131
disas_ldst_pair(s, insn);
132
--
38
--
133
2.34.1
39
2.34.1
diff view generated by jsdifflib
1
QEMU allows qemu_irq lines to transfer arbitrary integers. However
1
It doesn't make sense to read the value of MDCR_EL2 on a non-A-profile
2
the convention is that for a simple IRQ line the values transferred
2
CPU, and in fact if you try to do it we will assert:
3
are always 0 and 1. The A10 SD controller device instead assumes a
4
0-vs-non-0 convention, which happens to work with the interrupt
5
controller it is wired up to.
6
3
7
Coerce the value to boolean to follow our usual convention.
4
#6 0x00007ffff4b95e96 in __GI___assert_fail
5
(assertion=0x5555565a8c70 "!arm_feature(env, ARM_FEATURE_M)", file=0x5555565a6e5c "../../target/arm/helper.c", line=12600, function=0x5555565a9560 <__PRETTY_FUNCTION__.0> "arm_security_space_below_el3") at ./assert/assert.c:101
6
#7 0x0000555555ebf412 in arm_security_space_below_el3 (env=0x555557bc8190) at ../../target/arm/helper.c:12600
7
#8 0x0000555555ea6f89 in arm_is_el2_enabled (env=0x555557bc8190) at ../../target/arm/cpu.h:2595
8
#9 0x0000555555ea942f in arm_mdcr_el2_eff (env=0x555557bc8190) at ../../target/arm/internals.h:1512
8
9
10
We might call pmu_counter_enabled() on an M-profile CPU (for example
11
from the migration pre/post hooks in machine.c); this should always
12
return false because these CPUs don't set ARM_FEATURE_PMU.
13
14
Avoid the assertion by not calling arm_mdcr_el2_eff() before we
15
have done the early return for "PMU not present".
16
17
This fixes an assertion failure if you try to do a loadvm or
18
savevm for an M-profile board.
19
20
Cc: qemu-stable@nongnu.org
21
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2155
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
23
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Tested-by: Guenter Roeck <linux@roeck-us.net>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20230606104609.3692557-3-peter.maydell@linaro.org
25
Message-id: 20240208153346.970021-1-peter.maydell@linaro.org
13
---
26
---
14
hw/sd/allwinner-sdhost.c | 2 +-
27
target/arm/helper.c | 12 ++++++++++--
15
1 file changed, 1 insertion(+), 1 deletion(-)
28
1 file changed, 10 insertions(+), 2 deletions(-)
16
29
17
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/sd/allwinner-sdhost.c
32
--- a/target/arm/helper.c
20
+++ b/hw/sd/allwinner-sdhost.c
33
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_update_irq(AwSdHostState *s)
34
@@ -XXX,XX +XXX,XX @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
35
bool enabled, prohibited = false, filtered;
36
bool secure = arm_is_secure(env);
37
int el = arm_current_el(env);
38
- uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
39
- uint8_t hpmn = mdcr_el2 & MDCR_HPMN;
40
+ uint64_t mdcr_el2;
41
+ uint8_t hpmn;
42
43
+ /*
44
+ * We might be called for M-profile cores where MDCR_EL2 doesn't
45
+ * exist and arm_mdcr_el2_eff() will assert, so this early-exit check
46
+ * must be before we read that value.
47
+ */
48
if (!arm_feature(env, ARM_FEATURE_PMU)) {
49
return false;
22
}
50
}
23
51
24
trace_allwinner_sdhost_update_irq(irq);
52
+ mdcr_el2 = arm_mdcr_el2_eff(env);
25
- qemu_set_irq(s->irq, irq);
53
+ hpmn = mdcr_el2 & MDCR_HPMN;
26
+ qemu_set_irq(s->irq, !!irq);
54
+
27
}
55
if (!arm_feature(env, ARM_FEATURE_EL2) ||
28
56
(counter < hpmn || counter == 31)) {
29
static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,
57
e = env->cp15.c9_pmcr & PMCRE;
30
--
58
--
31
2.34.1
59
2.34.1
32
60
33
61
diff view generated by jsdifflib
1
Convert the instructions in the LDAPR/STLR (unscaled immediate)
1
From: Nabih Estefan <nabihestefan@google.com>
2
group to decodetree.
3
2
3
Fix the nocm_gmac-test.c file to run on a nuvoton 7xx machine instead
4
of 8xx. Also fix comments referencing this and values expecting 8xx.
5
6
Change-Id: Iabd0fba14910c3f1e883c4a9521350f3db9ffab8
7
Signed-Off-By: Nabih Estefan <nabihestefan@google.com>
8
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
9
Message-id: 20240208194759.2858582-2-nabihestefan@google.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: commit message tweaks]
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-18-peter.maydell@linaro.org
7
---
13
---
8
target/arm/tcg/a64.decode | 10 +++
14
tests/qtest/npcm_gmac-test.c | 84 +-----------------------------------
9
target/arm/tcg/translate-a64.c | 132 ++++++++++++---------------------
15
tests/qtest/meson.build | 3 +-
10
2 files changed, 56 insertions(+), 86 deletions(-)
16
2 files changed, 4 insertions(+), 83 deletions(-)
11
17
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
18
diff --git a/tests/qtest/npcm_gmac-test.c b/tests/qtest/npcm_gmac-test.c
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
20
--- a/tests/qtest/npcm_gmac-test.c
15
+++ b/target/arm/tcg/a64.decode
21
+++ b/tests/qtest/npcm_gmac-test.c
16
@@ -XXX,XX +XXX,XX @@ LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
22
@@ -XXX,XX +XXX,XX @@ typedef struct TestData {
17
%ldra_imm 22:s1 12:9 !function=times_2
23
const GMACModule *module;
18
24
} TestData;
19
LDRA 11 111 0 00 m:1 . 1 ......... w:1 1 rn:5 rt:5 imm=%ldra_imm
25
20
+
26
-/* Values extracted from hw/arm/npcm8xx.c */
21
+&ldapr_stlr_i rn rt imm sz sign ext
27
+/* Values extracted from hw/arm/npcm7xx.c */
22
+@ldapr_stlr_i .. ...... .. . imm:9 .. rn:5 rt:5 &ldapr_stlr_i
28
static const GMACModule gmac_module_list[] = {
23
+STLR_i sz:2 011001 00 0 ......... 00 ..... ..... @ldapr_stlr_i sign=0 ext=0
29
{
24
+LDAPR_i sz:2 011001 01 0 ......... 00 ..... ..... @ldapr_stlr_i sign=0 ext=0
30
.irq = 14,
25
+LDAPR_i 00 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=0
31
@@ -XXX,XX +XXX,XX @@ static const GMACModule gmac_module_list[] = {
26
+LDAPR_i 01 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=1
32
.irq = 15,
27
+LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=2
33
.base_addr = 0xf0804000
28
+LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
34
},
29
+LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
35
- {
30
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
36
- .irq = 16,
31
index XXXXXXX..XXXXXXX 100644
37
- .base_addr = 0xf0806000
32
--- a/target/arm/tcg/translate-a64.c
38
- },
33
+++ b/target/arm/tcg/translate-a64.c
39
- {
34
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
40
- .irq = 17,
35
}
41
- .base_addr = 0xf0808000
42
- }
43
};
44
45
/* Returns the index of the GMAC module. */
46
@@ -XXX,XX +XXX,XX @@ static uint32_t gmac_read(QTestState *qts, const GMACModule *mod,
47
return qtest_readl(qts, mod->base_addr + regno);
36
}
48
}
37
49
38
-/* Update the Sixty-Four bit (SF) registersize. This logic is derived
50
-static uint16_t pcs_read(QTestState *qts, const GMACModule *mod,
39
+/*
51
- NPCMRegister regno)
40
+ * Compute the ISS.SF bit for syndrome information if an exception
41
+ * is taken on a load or store. This indicates whether the instruction
42
+ * is accessing a 32-bit or 64-bit register. This logic is derived
43
* from the ARMv8 specs for LDR (Shared decode for all encodings).
44
*/
45
-static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
46
-{
52
-{
47
- int opc0 = extract32(opc, 0, 1);
53
- uint32_t write_value = (regno & 0x3ffe00) >> 9;
48
- int regsize;
54
- qtest_writel(qts, PCS_BASE_ADDRESS + NPCM_PCS_IND_AC_BA, write_value);
49
-
55
- uint32_t read_offset = regno & 0x1ff;
50
- if (is_signed) {
56
- return qtest_readl(qts, PCS_BASE_ADDRESS + read_offset);
51
- regsize = opc0 ? 32 : 64;
52
- } else {
53
- regsize = size == 3 ? 64 : 32;
54
- }
55
- return regsize == 64;
56
-}
57
-}
57
-
58
-
58
static bool ldst_iss_sf(int size, bool sign, bool ext)
59
/* Check that GMAC registers are reset to default value */
60
static void test_init(gconstpointer test_data)
59
{
61
{
60
62
const TestData *td = test_data;
61
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRA(DisasContext *s, arg_LDRA *a)
63
const GMACModule *mod = td->module;
62
return true;
64
- QTestState *qts = qtest_init("-machine npcm845-evb");
63
}
65
+ QTestState *qts = qtest_init("-machine npcm750-evb");
64
66
65
-/*
67
#define CHECK_REG32(regno, value) \
66
- * LDAPR/STLR (unscaled immediate)
68
do { \
67
- *
69
g_assert_cmphex(gmac_read(qts, mod, (regno)), ==, (value)); \
68
- * 31 30 24 22 21 12 10 5 0
70
} while (0)
69
- * +------+-------------+-----+---+--------+-----+----+-----+
71
70
- * | size | 0 1 1 0 0 1 | opc | 0 | imm9 | 0 0 | Rn | Rt |
72
-#define CHECK_REG_PCS(regno, value) \
71
- * +------+-------------+-----+---+--------+-----+----+-----+
73
- do { \
72
- *
74
- g_assert_cmphex(pcs_read(qts, mod, (regno)), ==, (value)); \
73
- * Rt: source or destination register
75
- } while (0)
74
- * Rn: base register
76
-
75
- * imm9: unscaled immediate offset
77
CHECK_REG32(NPCM_DMA_BUS_MODE, 0x00020100);
76
- * opc: 00: STLUR*, 01/10/11: various LDAPUR*
78
CHECK_REG32(NPCM_DMA_XMT_POLL_DEMAND, 0);
77
- * size: size of load/store
79
CHECK_REG32(NPCM_DMA_RCV_POLL_DEMAND, 0);
78
- */
80
@@ -XXX,XX +XXX,XX @@ static void test_init(gconstpointer test_data)
79
-static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
81
CHECK_REG32(NPCM_GMAC_PTP_TAR, 0);
80
+static bool trans_LDAPR_i(DisasContext *s, arg_ldapr_stlr_i *a)
82
CHECK_REG32(NPCM_GMAC_PTP_TTSR, 0);
81
{
83
82
- int rt = extract32(insn, 0, 5);
84
- /* TODO Add registers PCS */
83
- int rn = extract32(insn, 5, 5);
85
- if (mod->base_addr == 0xf0802000) {
84
- int offset = sextract32(insn, 12, 9);
86
- CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID1, 0x699e);
85
- int opc = extract32(insn, 22, 2);
87
- CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID2, 0);
86
- int size = extract32(insn, 30, 2);
88
- CHECK_REG_PCS(NPCM_PCS_SR_CTL_STS, 0x8000);
87
TCGv_i64 clean_addr, dirty_addr;
89
-
88
- bool is_store = false;
90
- CHECK_REG_PCS(NPCM_PCS_SR_MII_CTRL, 0x1140);
89
- bool extend = false;
91
- CHECK_REG_PCS(NPCM_PCS_SR_MII_STS, 0x0109);
90
- bool iss_sf;
92
- CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID1, 0x699e);
91
- MemOp mop = size;
93
- CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID2, 0x0ced0);
92
+ MemOp mop = a->sz | (a->sign ? MO_SIGN : 0);
94
- CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_ADV, 0x0020);
93
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
95
- CHECK_REG_PCS(NPCM_PCS_SR_MII_LP_BABL, 0);
94
96
- CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_EXPN, 0);
95
if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
97
- CHECK_REG_PCS(NPCM_PCS_SR_MII_EXT_STS, 0xc000);
96
- unallocated_encoding(s);
98
-
97
- return;
99
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_ABL, 0x0003);
98
+ return false;
100
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_LWR, 0x0038);
99
}
101
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_UPR, 0);
100
102
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_LWR, 0x0038);
101
- switch (opc) {
103
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_UPR, 0);
102
- case 0: /* STLURB */
104
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_LWR, 0x0058);
103
- is_store = true;
105
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_UPR, 0);
104
- break;
106
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_LWR, 0x0048);
105
- case 1: /* LDAPUR* */
107
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_UPR, 0);
106
- break;
108
-
107
- case 2: /* LDAPURS* 64-bit variant */
109
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MMD_DIG_CTRL1, 0x2400);
108
- if (size == 3) {
110
- CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_CTRL, 0);
109
- unallocated_encoding(s);
111
- CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_INTR_STS, 0x000a);
110
- return;
112
- CHECK_REG_PCS(NPCM_PCS_VR_MII_TC, 0);
111
- }
113
- CHECK_REG_PCS(NPCM_PCS_VR_MII_DBG_CTRL, 0);
112
- mop |= MO_SIGN;
114
- CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL0, 0x899c);
113
- break;
115
- CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_TXTIMER, 0);
114
- case 3: /* LDAPURS* 32-bit variant */
116
- CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_RXTIMER, 0);
115
- if (size > 1) {
117
- CHECK_REG_PCS(NPCM_PCS_VR_MII_LINK_TIMER_CTRL, 0);
116
- unallocated_encoding(s);
118
- CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL1, 0);
117
- return;
119
- CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_STS, 0x0010);
118
- }
120
- CHECK_REG_PCS(NPCM_PCS_VR_MII_ICG_ERRCNT1, 0);
119
- mop |= MO_SIGN;
121
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MISC_STS, 0);
120
- extend = true; /* zero-extend 32->64 after signed load */
122
- CHECK_REG_PCS(NPCM_PCS_VR_MII_RX_LSTS, 0);
121
- break;
123
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_BSTCTRL0, 0x00a);
122
- default:
124
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_LVLCTRL0, 0x007f);
123
- g_assert_not_reached();
125
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_GENCTRL0, 0x0001);
126
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_GENCTRL1, 0);
127
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_STS, 0);
128
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_GENCTRL0, 0x0100);
129
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_GENCTRL1, 0x1100);
130
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_LOS_CTRL0, 0x000e);
131
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_CTRL0, 0x0100);
132
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_CTRL1, 0x0032);
133
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_STS, 0x0001);
134
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL2, 0);
135
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_LVL_CTRL, 0x0019);
136
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL0, 0);
137
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL1, 0);
138
- CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_CTRL2, 0);
139
- CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_ERRCNT_SEL, 0);
124
- }
140
- }
125
-
141
-
126
- iss_sf = disas_ldst_compute_iss_sf(size, (mop & MO_SIGN) != 0, opc);
142
qtest_quit(qts);
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
}
143
}
190
144
191
/* AdvSIMD load/store multiple structures
145
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
192
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
146
index XXXXXXX..XXXXXXX 100644
193
case 0x19:
147
--- a/tests/qtest/meson.build
194
if (extract32(insn, 21, 1) != 0) {
148
+++ b/tests/qtest/meson.build
195
disas_ldst_tag(s, insn);
149
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
196
- } else if (extract32(insn, 10, 2) == 0) {
150
'npcm7xx_sdhci-test',
197
- disas_ldst_ldapr_stlr(s, insn);
151
'npcm7xx_smbus-test',
198
} else {
152
'npcm7xx_timer-test',
199
unallocated_encoding(s);
153
- 'npcm7xx_watchdog_timer-test'] + \
200
}
154
+ 'npcm7xx_watchdog_timer-test',
155
+ 'npcm_gmac-test'] + \
156
(slirp.found() ? ['npcm7xx_emc-test'] : [])
157
qtests_aspeed = \
158
['aspeed_hace-test',
201
--
159
--
202
2.34.1
160
2.34.1
diff view generated by jsdifflib
1
The atomic memory operations are supposed to return the old memory
1
From: Luc Michel <luc.michel@amd.com>
2
data value in the destination register. This value is not
3
sign-extended, even if the operation is the signed minimum or
4
maximum. (In the pseudocode for the instructions the returned data
5
value is passed to ZeroExtend() to create the value in the register.)
6
2
7
We got this wrong because we were doing a 32-to-64 zero extend on the
3
An access fault is raised when the Access Flag is not set in the
8
result for 8 and 16 bit data values, rather than the correct amount
4
looked-up PTE and the AFFD field is not set in the corresponding context
9
of zero extension.
5
descriptor. This was already implemented for stage 2. Implement it for
6
stage 1 as well.
10
7
11
Fix the bug by using ext8u and ext16u for the MO_8 and MO_16 data
8
Signed-off-by: Luc Michel <luc.michel@amd.com>
12
sizes rather than ext32u.
9
Reviewed-by: Mostafa Saleh <smostafa@google.com>
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
11
Tested-by: Mostafa Saleh <smostafa@google.com>
12
Message-id: 20240213082211.3330400-1-luc.michel@amd.com
13
[PMM: tweaked comment text]
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
hw/arm/smmuv3-internal.h | 1 +
17
include/hw/arm/smmu-common.h | 1 +
18
hw/arm/smmu-common.c | 11 +++++++++++
19
hw/arm/smmuv3.c | 1 +
20
4 files changed, 14 insertions(+)
13
21
14
Cc: qemu-stable@nongnu.org
22
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20230602155223.2040685-2-peter.maydell@linaro.org
18
---
19
target/arm/tcg/translate-a64.c | 18 ++++++++++++++++--
20
1 file changed, 16 insertions(+), 2 deletions(-)
21
22
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
23
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/tcg/translate-a64.c
24
--- a/hw/arm/smmuv3-internal.h
25
+++ b/target/arm/tcg/translate-a64.c
25
+++ b/hw/arm/smmuv3-internal.h
26
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
26
@@ -XXX,XX +XXX,XX @@ static inline int pa_range(STE *ste)
27
*/
27
#define CD_EPD(x, sel) extract32((x)->word[0], (16 * (sel)) + 14, 1)
28
fn(tcg_rt, clean_addr, tcg_rs, get_mem_index(s), mop);
28
#define CD_ENDI(x) extract32((x)->word[0], 15, 1)
29
29
#define CD_IPS(x) extract32((x)->word[1], 0 , 3)
30
- if ((mop & MO_SIGN) && size != MO_64) {
30
+#define CD_AFFD(x) extract32((x)->word[1], 3 , 1)
31
- tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
31
#define CD_TBI(x) extract32((x)->word[1], 6 , 2)
32
+ if (mop & MO_SIGN) {
32
#define CD_HD(x) extract32((x)->word[1], 10 , 1)
33
+ switch (size) {
33
#define CD_HA(x) extract32((x)->word[1], 11 , 1)
34
+ case MO_8:
34
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
35
+ tcg_gen_ext8u_i64(tcg_rt, tcg_rt);
35
index XXXXXXX..XXXXXXX 100644
36
+ break;
36
--- a/include/hw/arm/smmu-common.h
37
+ case MO_16:
37
+++ b/include/hw/arm/smmu-common.h
38
+ tcg_gen_ext16u_i64(tcg_rt, tcg_rt);
38
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUTransCfg {
39
+ break;
39
bool disabled; /* smmu is disabled */
40
+ case MO_32:
40
bool bypassed; /* translation is bypassed */
41
+ tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
41
bool aborted; /* translation is aborted */
42
+ break;
42
+ bool affd; /* AF fault disable */
43
+ case MO_64:
43
uint32_t iotlb_hits; /* counts IOTLB hits */
44
+ break;
44
uint32_t iotlb_misses; /* counts IOTLB misses*/
45
+ default:
45
/* Used by stage-1 only. */
46
+ g_assert_not_reached();
46
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/smmu-common.c
49
+++ b/hw/arm/smmu-common.c
50
@@ -XXX,XX +XXX,XX @@ static int smmu_ptw_64_s1(SMMUTransCfg *cfg,
51
pte_addr, pte, iova, gpa,
52
block_size >> 20);
53
}
54
+
55
+ /*
56
+ * QEMU does not currently implement HTTU, so if AFFD and PTE.AF
57
+ * are 0 we take an Access flag fault. (5.4. Context Descriptor)
58
+ * An Access flag fault takes priority over a Permission fault.
59
+ */
60
+ if (!PTE_AF(pte) && !cfg->affd) {
61
+ info->type = SMMU_PTW_ERR_ACCESS;
62
+ goto error;
47
+ }
63
+ }
48
}
64
+
49
}
65
ap = PTE_AP(pte);
66
if (is_permission_fault(ap, perm)) {
67
info->type = SMMU_PTW_ERR_PERMISSION;
68
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/arm/smmuv3.c
71
+++ b/hw/arm/smmuv3.c
72
@@ -XXX,XX +XXX,XX @@ static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event)
73
cfg->oas = MIN(oas2bits(SMMU_IDR5_OAS), cfg->oas);
74
cfg->tbi = CD_TBI(cd);
75
cfg->asid = CD_ASID(cd);
76
+ cfg->affd = CD_AFFD(cd);
77
78
trace_smmuv3_decode_cd(cfg->oas);
50
79
51
--
80
--
52
2.34.1
81
2.34.1
diff view generated by jsdifflib
1
Convert MSR (reg), MRS, SYS, SYSL to decodetree. For QEMU these are
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
all essentially the same instruction (system register access).
3
2
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20240213155214.13619-2-philmd@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-7-peter.maydell@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
---
7
---
9
target/arm/tcg/a64.decode | 8 ++++++++
8
hw/arm/stellaris.c | 6 ++++--
10
target/arm/tcg/translate-a64.c | 32 +++++---------------------------
9
1 file changed, 4 insertions(+), 2 deletions(-)
11
2 files changed, 13 insertions(+), 27 deletions(-)
12
10
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
13
--- a/hw/arm/stellaris.c
16
+++ b/target/arm/tcg/a64.decode
14
+++ b/hw/arm/stellaris.c
17
@@ -XXX,XX +XXX,XX @@ MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
15
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_trigger(void *opaque, int irq, int level)
18
MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
19
MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
20
MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
21
+
22
+# MRS, MSR (register), SYS, SYSL. These are all essentially the
23
+# same instruction as far as QEMU is concerned.
24
+# NB: op0 is bits [20:19], but op0=0b00 is other insns, so we have
25
+# to hand-decode it.
26
+SYS 1101 0101 00 l:1 01 op1:3 crn:4 crm:4 op2:3 rt:5 op0=1
27
+SYS 1101 0101 00 l:1 10 op1:3 crn:4 crm:4 op2:3 rt:5 op0=2
28
+SYS 1101 0101 00 l:1 11 op1:3 crn:4 crm:4 op2:3 rt:5 op0=3
29
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/tcg/translate-a64.c
32
+++ b/target/arm/tcg/translate-a64.c
33
@@ -XXX,XX +XXX,XX @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
34
* These are all essentially the same insn in 'read' and 'write'
35
* versions, with varying op0 fields.
36
*/
37
-static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
38
+static void handle_sys(DisasContext *s, bool isread,
39
unsigned int op0, unsigned int op1, unsigned int op2,
40
unsigned int crn, unsigned int crm, unsigned int rt)
41
{
42
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
43
}
16
}
44
}
17
}
45
18
46
-/* System
19
-static void stellaris_adc_reset(StellarisADCState *s)
47
- * 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
20
+static void stellaris_adc_reset_hold(Object *obj)
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)
54
{
21
{
55
- unsigned int l, op0, op1, crn, crm, op2, rt;
22
+ StellarisADCState *s = STELLARIS_ADC(obj);
56
- l = extract32(insn, 21, 1);
23
int n;
57
- op0 = extract32(insn, 19, 2);
24
58
- op1 = extract32(insn, 16, 3);
25
for (n = 0; n < 4; n++) {
59
- crn = extract32(insn, 12, 4);
26
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_init(Object *obj)
60
- crm = extract32(insn, 8, 4);
27
memory_region_init_io(&s->iomem, obj, &stellaris_adc_ops, s,
61
- op2 = extract32(insn, 5, 3);
28
"adc", 0x1000);
62
- rt = extract32(insn, 0, 5);
29
sysbus_init_mmio(sbd, &s->iomem);
63
-
30
- stellaris_adc_reset(s);
64
- if (op0 == 0) {
31
qdev_init_gpio_in(dev, stellaris_adc_trigger, 1);
65
- unallocated_encoding(s);
66
- return;
67
- }
68
- handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
69
+ handle_sys(s, a->l, a->op0, a->op1, a->op2, a->crn, a->crm, a->rt);
70
+ return true;
71
}
32
}
72
33
73
/* Exception generation
34
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stellaris_i2c_info = {
74
@@ -XXX,XX +XXX,XX @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
35
static void stellaris_adc_class_init(ObjectClass *klass, void *data)
75
switch (extract32(insn, 25, 7)) {
36
{
76
case 0x6a: /* Exception generation / System */
37
DeviceClass *dc = DEVICE_CLASS(klass);
77
if (insn & (1 << 24)) {
38
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
78
- if (extract32(insn, 22, 2) == 0) {
39
79
- disas_system(s, insn);
40
+ rc->phases.hold = stellaris_adc_reset_hold;
80
- } else {
41
dc->vmsd = &vmstate_stellaris_adc;
81
- unallocated_encoding(s);
42
}
82
- }
43
83
+ unallocated_encoding(s);
84
} else {
85
disas_exc(s, insn);
86
}
87
--
44
--
88
2.34.1
45
2.34.1
89
46
90
47
diff view generated by jsdifflib
1
Convert the load/store exclusive pair (LDXP, STXP, LDAXP, STLXP),
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
compare-and-swap pair (CASP, CASPA, CASPAL, CASPL), and compare-and
3
swap (CAS, CASA, CASAL, CASL) instructions to decodetree.
4
2
3
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Message-id: 20240213155214.13619-3-philmd@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230602155223.2040685-10-peter.maydell@linaro.org
8
---
8
---
9
target/arm/tcg/a64.decode | 11 +++
9
hw/arm/stellaris.c | 26 ++++++++++++++++++++++----
10
target/arm/tcg/translate-a64.c | 121 ++++++++++++---------------------
10
1 file changed, 22 insertions(+), 4 deletions(-)
11
2 files changed, 53 insertions(+), 79 deletions(-)
12
11
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
12
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
14
--- a/hw/arm/stellaris.c
16
+++ b/target/arm/tcg/a64.decode
15
+++ b/hw/arm/stellaris.c
17
@@ -XXX,XX +XXX,XX @@ HLT 1101 0100 010 ................ 000 00 @i16
16
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_instance_init(Object *obj)
18
&stlr rn rt sz lasr
17
s->sysclk = qdev_init_clock_out(DEVICE(s), "SYSCLK");
19
@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
18
}
20
@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
19
21
+%imm1_30_p2 30:1 !function=plus_2
20
-/* I2C controller. */
22
+@stxp .. ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=%imm1_30_p2
21
+/*
23
STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
22
+ * I2C controller.
24
LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
23
+ * ??? For now we only implement the master interface.
25
STLR .. 001000 100 11111 . 11111 ..... ..... @stlr # inc STLLR
24
+ */
26
LDAR .. 001000 110 11111 . 11111 ..... ..... @stlr # inc LDLAR
25
26
#define TYPE_STELLARIS_I2C "stellaris-i2c"
27
OBJECT_DECLARE_SIMPLE_TYPE(stellaris_i2c_state, STELLARIS_I2C)
28
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_write(void *opaque, hwaddr offset,
29
stellaris_i2c_update(s);
30
}
31
32
-static void stellaris_i2c_reset(stellaris_i2c_state *s)
33
+static void stellaris_i2c_reset_enter(Object *obj, ResetType type)
34
{
35
+ stellaris_i2c_state *s = STELLARIS_I2C(obj);
27
+
36
+
28
+STXP 1 . 001000 001 ..... . ..... ..... ..... @stxp # inc STLXP
37
if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
29
+LDXP 1 . 001000 011 ..... . ..... ..... ..... @stxp # inc LDAXP
38
i2c_end_transfer(s->bus);
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
+}
39
+}
131
+
40
+
132
+static bool trans_LDXP(DisasContext *s, arg_stxr *a)
41
+static void stellaris_i2c_reset_hold(Object *obj)
133
+{
42
+{
134
+ if (a->rn == 31) {
43
+ stellaris_i2c_state *s = STELLARIS_I2C(obj);
135
+ gen_check_sp_alignment(s);
44
136
+ }
45
s->msa = 0;
137
+ gen_load_exclusive(s, a->rt, a->rt2, a->rn, a->sz, true);
46
s->mcs = 0;
138
+ if (a->lasr) {
47
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_reset(stellaris_i2c_state *s)
139
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
48
s->mimr = 0;
140
+ }
49
s->mris = 0;
141
+ return true;
50
s->mcr = 0;
142
+}
51
+}
143
+
52
+
144
+static bool trans_CASP(DisasContext *s, arg_CASP *a)
53
+static void stellaris_i2c_reset_exit(Object *obj)
145
+{
54
+{
146
+ if (!dc_isar_feature(aa64_atomics, s)) {
55
+ stellaris_i2c_state *s = STELLARIS_I2C(obj);
147
+ return false;
148
+ }
149
+ if (((a->rt | a->rs) & 1) != 0) {
150
+ return false;
151
+ }
152
+
56
+
153
+ gen_compare_and_swap_pair(s, a->rs, a->rt, a->rn, a->sz);
57
stellaris_i2c_update(s);
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
}
58
}
165
59
166
/*
60
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_init(Object *obj)
167
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
61
memory_region_init_io(&s->iomem, obj, &stellaris_i2c_ops, s,
168
static void disas_ldst(DisasContext *s, uint32_t insn)
62
"i2c", 0x1000);
63
sysbus_init_mmio(sbd, &s->iomem);
64
- /* ??? For now we only implement the master interface. */
65
- stellaris_i2c_reset(s);
66
}
67
68
/* Analogue to Digital Converter. This is only partially implemented,
69
@@ -XXX,XX +XXX,XX @@ type_init(stellaris_machine_init)
70
static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
169
{
71
{
170
switch (extract32(insn, 24, 6)) {
72
DeviceClass *dc = DEVICE_CLASS(klass);
171
- case 0x08: /* Load/store exclusive */
73
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
172
- disas_ldst_excl(s, insn);
74
173
- break;
75
+ rc->phases.enter = stellaris_i2c_reset_enter;
174
case 0x18: case 0x1c: /* Load register (literal) */
76
+ rc->phases.hold = stellaris_i2c_reset_hold;
175
disas_ld_lit(s, insn);
77
+ rc->phases.exit = stellaris_i2c_reset_exit;
176
break;
78
dc->vmsd = &vmstate_stellaris_i2c;
79
}
80
177
--
81
--
178
2.34.1
82
2.34.1
83
84
diff view generated by jsdifflib
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
3
QDev objects created with qdev_new() need to manually add
4
their parent relationship with object_property_add_child().
5
6
This commit plug the devices which aren't part of the SoC;
7
they will be plugged into a SoC container in the next one.
8
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20230612223456.33824-4-philmd@linaro.org
11
Message-id: 20240213155214.13619-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>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
include/hw/arm/raspi_platform.h | 5 +++++
14
hw/arm/stellaris.c | 4 ++++
13
hw/misc/bcm2835_property.c | 8 +++++---
15
1 file changed, 4 insertions(+)
14
2 files changed, 10 insertions(+), 3 deletions(-)
15
16
16
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
17
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/raspi_platform.h
19
--- a/hw/arm/stellaris.c
19
+++ b/include/hw/arm/raspi_platform.h
20
+++ b/hw/arm/stellaris.c
20
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
21
#define INTERRUPT_ILLEGAL_TYPE0 6
22
&error_fatal);
22
#define INTERRUPT_ILLEGAL_TYPE1 7
23
23
24
ssddev = qdev_new("ssd0323");
24
+/* Clock rates */
25
+ object_property_add_child(OBJECT(ms), "oled", OBJECT(ssddev));
25
+#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
26
qdev_prop_set_uint8(ssddev, "cs", 1);
26
+#define RPI_FIRMWARE_UART_CLK_RATE 3000000
27
qdev_realize_and_unref(ssddev, bus, &error_fatal);
27
+#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
28
28
+
29
gpio_d_splitter = qdev_new(TYPE_SPLIT_IRQ);
29
#endif
30
+ object_property_add_child(OBJECT(ms), "splitter",
30
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
31
+ OBJECT(gpio_d_splitter));
31
index XXXXXXX..XXXXXXX 100644
32
qdev_prop_set_uint32(gpio_d_splitter, "num-lines", 2);
32
--- a/hw/misc/bcm2835_property.c
33
qdev_realize_and_unref(gpio_d_splitter, NULL, &error_fatal);
33
+++ b/hw/misc/bcm2835_property.c
34
qdev_connect_gpio_out(
34
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
35
#include "qemu/log.h"
36
DeviceState *gpad;
36
#include "qemu/module.h"
37
37
#include "trace.h"
38
gpad = qdev_new(TYPE_STELLARIS_GAMEPAD);
38
+#include "hw/arm/raspi_platform.h"
39
+ object_property_add_child(OBJECT(ms), "gamepad", OBJECT(gpad));
39
40
for (i = 0; i < ARRAY_SIZE(gpad_keycode); i++) {
40
/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
41
qlist_append_int(gpad_keycode_list, gpad_keycode[i]);
41
42
}
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
43
case RPI_FWREQ_GET_MIN_CLOCK_RATE:
44
switch (ldl_le_phys(&s->dma_as, value + 12)) {
45
case RPI_FIRMWARE_EMMC_CLK_ID:
46
- stl_le_phys(&s->dma_as, value + 16, 50000000);
47
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_EMMC_CLK_RATE);
48
break;
49
case RPI_FIRMWARE_UART_CLK_ID:
50
- stl_le_phys(&s->dma_as, value + 16, 3000000);
51
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE);
52
break;
53
default:
54
- stl_le_phys(&s->dma_as, value + 16, 700000000);
55
+ stl_le_phys(&s->dma_as, value + 16,
56
+ RPI_FIRMWARE_DEFAULT_CLK_RATE);
57
break;
58
}
59
resplen = 8;
60
--
43
--
61
2.34.1
44
2.34.1
62
45
63
46
diff view generated by jsdifflib
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Replace magic property values by a proper definition,
3
QDev objects created with qdev_new() need to manually add
4
removing redundant comments.
4
their parent relationship with object_property_add_child().
5
5
6
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
6
Since we don't model the SoC, just use a QOM container.
7
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20230612223456.33824-3-philmd@linaro.org
10
Message-id: 20240213155214.13619-5-philmd@linaro.org
10
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
11
[PMD: Split from bigger patch: 2/4]
12
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
12
---
15
hw/misc/bcm2835_property.c | 101 +++++++++++++++++++------------------
13
hw/arm/stellaris.c | 11 ++++++++++-
16
1 file changed, 51 insertions(+), 50 deletions(-)
14
1 file changed, 10 insertions(+), 1 deletion(-)
17
15
18
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
16
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/bcm2835_property.c
18
--- a/hw/arm/stellaris.c
21
+++ b/hw/misc/bcm2835_property.c
19
+++ b/hw/arm/stellaris.c
22
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
23
#include "migration/vmstate.h"
21
* 400fe000 system control
24
#include "hw/irq.h"
22
*/
25
#include "hw/misc/bcm2835_mbox_defs.h"
23
26
+#include "hw/misc/raspberrypi-fw-defs.h"
24
+ Object *soc_container;
27
#include "sysemu/dma.h"
25
DeviceState *gpio_dev[7], *nvic;
28
#include "qemu/log.h"
26
qemu_irq gpio_in[7][8];
29
#include "qemu/module.h"
27
qemu_irq gpio_out[7][8];
30
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
28
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
31
/* @(value + 8) : Request/response indicator */
29
flash_size = (((board->dc0 & 0xffff) + 1) << 1) * 1024;
32
resplen = 0;
30
sram_size = ((board->dc0 >> 18) + 1) * 1024;
33
switch (tag) {
31
34
- case 0x00000000: /* End tag */
32
+ soc_container = object_new("container");
35
+ case RPI_FWREQ_PROPERTY_END:
33
+ object_property_add_child(OBJECT(ms), "soc", soc_container);
36
break;
34
+
37
- case 0x00000001: /* Get firmware revision */
35
/* Flash programming is done via the SCU, so pretend it is ROM. */
38
+ case RPI_FWREQ_GET_FIRMWARE_REVISION:
36
memory_region_init_rom(flash, NULL, "stellaris.flash", flash_size,
39
stl_le_phys(&s->dma_as, value + 12, 346337);
37
&error_fatal);
40
resplen = 4;
38
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
41
break;
39
* need its sysclk output.
42
- case 0x00010001: /* Get board model */
40
*/
43
+ case RPI_FWREQ_GET_BOARD_MODEL:
41
ssys_dev = qdev_new(TYPE_STELLARIS_SYS);
44
qemu_log_mask(LOG_UNIMP,
42
+ object_property_add_child(soc_container, "sys", OBJECT(ssys_dev));
45
"bcm2835_property: 0x%08x get board model NYI\n",
43
46
tag);
44
/*
47
resplen = 4;
45
* Most devices come preprogrammed with a MAC address in the user data.
48
break;
46
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
49
- case 0x00010002: /* Get board revision */
47
sysbus_realize_and_unref(SYS_BUS_DEVICE(ssys_dev), &error_fatal);
50
+ case RPI_FWREQ_GET_BOARD_REVISION:
48
51
stl_le_phys(&s->dma_as, value + 12, s->board_rev);
49
nvic = qdev_new(TYPE_ARMV7M);
52
resplen = 4;
50
+ object_property_add_child(soc_container, "v7m", OBJECT(nvic));
53
break;
51
qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES);
54
- case 0x00010003: /* Get board MAC address */
52
qdev_prop_set_uint8(nvic, "num-prio-bits", NUM_PRIO_BITS);
55
+ case RPI_FWREQ_GET_BOARD_MAC_ADDRESS:
53
qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type);
56
resplen = sizeof(s->macaddr.a);
54
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
57
dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen,
55
58
MEMTXATTRS_UNSPECIFIED);
56
dev = qdev_new(TYPE_STELLARIS_GPTM);
59
break;
57
sbd = SYS_BUS_DEVICE(dev);
60
- case 0x00010004: /* Get board serial */
58
+ object_property_add_child(soc_container, "gptm[*]", OBJECT(dev));
61
+ case RPI_FWREQ_GET_BOARD_SERIAL:
59
qdev_connect_clock_in(dev, "clk",
62
qemu_log_mask(LOG_UNIMP,
60
qdev_get_clock_out(ssys_dev, "SYSCLK"));
63
"bcm2835_property: 0x%08x get board serial NYI\n",
61
sysbus_realize_and_unref(sbd, &error_fatal);
64
tag);
62
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
65
resplen = 8;
63
66
break;
64
if (board->dc1 & (1 << 3)) { /* watchdog present */
67
- case 0x00010005: /* Get ARM memory */
65
dev = qdev_new(TYPE_LUMINARY_WATCHDOG);
68
+ case RPI_FWREQ_GET_ARM_MEMORY:
66
-
69
/* base */
67
+ object_property_add_child(soc_container, "wdg", OBJECT(dev));
70
stl_le_phys(&s->dma_as, value + 12, 0);
68
qdev_connect_clock_in(dev, "WDOGCLK",
71
/* size */
69
qdev_get_clock_out(ssys_dev, "SYSCLK"));
72
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_base);
70
73
resplen = 8;
71
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
74
break;
72
SysBusDevice *sbd;
75
- case 0x00010006: /* Get VC memory */
73
76
+ case RPI_FWREQ_GET_VC_MEMORY:
74
dev = qdev_new("pl011_luminary");
77
/* base */
75
+ object_property_add_child(soc_container, "uart[*]", OBJECT(dev));
78
stl_le_phys(&s->dma_as, value + 12, s->fbdev->vcram_base);
76
sbd = SYS_BUS_DEVICE(dev);
79
/* size */
77
qdev_prop_set_chr(dev, "chardev", serial_hd(i));
80
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_size);
78
sysbus_realize_and_unref(sbd, &error_fatal);
81
resplen = 8;
79
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
82
break;
80
DeviceState *enet;
83
- case 0x00028001: /* Set power state */
81
84
+ case RPI_FWREQ_SET_POWER_STATE:
82
enet = qdev_new("stellaris_enet");
85
/* Assume that whatever device they asked for exists,
83
+ object_property_add_child(soc_container, "enet", OBJECT(enet));
86
* and we'll just claim we set it to the desired state
84
if (nd) {
87
*/
85
qdev_set_nic_properties(enet, nd);
88
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
86
} else {
89
90
/* Clocks */
91
92
- case 0x00030001: /* Get clock state */
93
+ case RPI_FWREQ_GET_CLOCK_STATE:
94
stl_le_phys(&s->dma_as, value + 16, 0x1);
95
resplen = 8;
96
break;
97
98
- case 0x00038001: /* Set clock state */
99
+ case RPI_FWREQ_SET_CLOCK_STATE:
100
qemu_log_mask(LOG_UNIMP,
101
"bcm2835_property: 0x%08x set clock state NYI\n",
102
tag);
103
resplen = 8;
104
break;
105
106
- case 0x00030002: /* Get clock rate */
107
- case 0x00030004: /* Get max clock rate */
108
- case 0x00030007: /* Get min clock rate */
109
+ case RPI_FWREQ_GET_CLOCK_RATE:
110
+ case RPI_FWREQ_GET_MAX_CLOCK_RATE:
111
+ case RPI_FWREQ_GET_MIN_CLOCK_RATE:
112
switch (ldl_le_phys(&s->dma_as, value + 12)) {
113
- case 1: /* EMMC */
114
+ case RPI_FIRMWARE_EMMC_CLK_ID:
115
stl_le_phys(&s->dma_as, value + 16, 50000000);
116
break;
117
- case 2: /* UART */
118
+ case RPI_FIRMWARE_UART_CLK_ID:
119
stl_le_phys(&s->dma_as, value + 16, 3000000);
120
break;
121
default:
122
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
123
resplen = 8;
124
break;
125
126
- case 0x00038002: /* Set clock rate */
127
- case 0x00038004: /* Set max clock rate */
128
- case 0x00038007: /* Set min clock rate */
129
+ case RPI_FWREQ_SET_CLOCK_RATE:
130
+ case RPI_FWREQ_SET_MAX_CLOCK_RATE:
131
+ case RPI_FWREQ_SET_MIN_CLOCK_RATE:
132
qemu_log_mask(LOG_UNIMP,
133
"bcm2835_property: 0x%08x set clock rate NYI\n",
134
tag);
135
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
136
137
/* Temperature */
138
139
- case 0x00030006: /* Get temperature */
140
+ case RPI_FWREQ_GET_TEMPERATURE:
141
stl_le_phys(&s->dma_as, value + 16, 25000);
142
resplen = 8;
143
break;
144
145
- case 0x0003000A: /* Get max temperature */
146
+ case RPI_FWREQ_GET_MAX_TEMPERATURE:
147
stl_le_phys(&s->dma_as, value + 16, 99000);
148
resplen = 8;
149
break;
150
151
/* Frame buffer */
152
153
- case 0x00040001: /* Allocate buffer */
154
+ case RPI_FWREQ_FRAMEBUFFER_ALLOCATE:
155
stl_le_phys(&s->dma_as, value + 12, fbconfig.base);
156
stl_le_phys(&s->dma_as, value + 16,
157
bcm2835_fb_get_size(&fbconfig));
158
resplen = 8;
159
break;
160
- case 0x00048001: /* Release buffer */
161
+ case RPI_FWREQ_FRAMEBUFFER_RELEASE:
162
resplen = 0;
163
break;
164
- case 0x00040002: /* Blank screen */
165
+ case RPI_FWREQ_FRAMEBUFFER_BLANK:
166
resplen = 4;
167
break;
168
- case 0x00044003: /* Test physical display width/height */
169
- case 0x00044004: /* Test virtual display width/height */
170
+ case RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT:
171
+ case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT:
172
resplen = 8;
173
break;
174
- case 0x00048003: /* Set physical display width/height */
175
+ case RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT:
176
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
177
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
178
bcm2835_fb_validate_config(&fbconfig);
179
fbconfig_updated = true;
180
/* fall through */
181
- case 0x00040003: /* Get physical display width/height */
182
+ case RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT:
183
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
184
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
185
resplen = 8;
186
break;
187
- case 0x00048004: /* Set virtual display width/height */
188
+ case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT:
189
fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
190
fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
191
bcm2835_fb_validate_config(&fbconfig);
192
fbconfig_updated = true;
193
/* fall through */
194
- case 0x00040004: /* Get virtual display width/height */
195
+ case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT:
196
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
197
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
198
resplen = 8;
199
break;
200
- case 0x00044005: /* Test depth */
201
+ case RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH:
202
resplen = 4;
203
break;
204
- case 0x00048005: /* Set depth */
205
+ case RPI_FWREQ_FRAMEBUFFER_SET_DEPTH:
206
fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12);
207
bcm2835_fb_validate_config(&fbconfig);
208
fbconfig_updated = true;
209
/* fall through */
210
- case 0x00040005: /* Get depth */
211
+ case RPI_FWREQ_FRAMEBUFFER_GET_DEPTH:
212
stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
213
resplen = 4;
214
break;
215
- case 0x00044006: /* Test pixel order */
216
+ case RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER:
217
resplen = 4;
218
break;
219
- case 0x00048006: /* Set pixel order */
220
+ case RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER:
221
fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12);
222
bcm2835_fb_validate_config(&fbconfig);
223
fbconfig_updated = true;
224
/* fall through */
225
- case 0x00040006: /* Get pixel order */
226
+ case RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER:
227
stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
228
resplen = 4;
229
break;
230
- case 0x00044007: /* Test pixel alpha */
231
+ case RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE:
232
resplen = 4;
233
break;
234
- case 0x00048007: /* Set alpha */
235
+ case RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE:
236
fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12);
237
bcm2835_fb_validate_config(&fbconfig);
238
fbconfig_updated = true;
239
/* fall through */
240
- case 0x00040007: /* Get alpha */
241
+ case RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE:
242
stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
243
resplen = 4;
244
break;
245
- case 0x00040008: /* Get pitch */
246
+ case RPI_FWREQ_FRAMEBUFFER_GET_PITCH:
247
stl_le_phys(&s->dma_as, value + 12,
248
bcm2835_fb_get_pitch(&fbconfig));
249
resplen = 4;
250
break;
251
- case 0x00044009: /* Test virtual offset */
252
+ case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET:
253
resplen = 8;
254
break;
255
- case 0x00048009: /* Set virtual offset */
256
+ case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET:
257
fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12);
258
fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16);
259
bcm2835_fb_validate_config(&fbconfig);
260
fbconfig_updated = true;
261
/* fall through */
262
- case 0x00040009: /* Get virtual offset */
263
+ case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET:
264
stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
265
stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
266
resplen = 8;
267
break;
268
- case 0x0004000a: /* Get/Test/Set overscan */
269
- case 0x0004400a:
270
- case 0x0004800a:
271
+ case RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN:
272
+ case RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN:
273
+ case RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN:
274
stl_le_phys(&s->dma_as, value + 12, 0);
275
stl_le_phys(&s->dma_as, value + 16, 0);
276
stl_le_phys(&s->dma_as, value + 20, 0);
277
stl_le_phys(&s->dma_as, value + 24, 0);
278
resplen = 16;
279
break;
280
- case 0x0004800b: /* Set palette */
281
+ case RPI_FWREQ_FRAMEBUFFER_SET_PALETTE:
282
offset = ldl_le_phys(&s->dma_as, value + 12);
283
length = ldl_le_phys(&s->dma_as, value + 16);
284
n = 0;
285
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
286
stl_le_phys(&s->dma_as, value + 12, 0);
287
resplen = 4;
288
break;
289
- case 0x00040013: /* Get number of displays */
290
+ case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
291
stl_le_phys(&s->dma_as, value + 12, 1);
292
resplen = 4;
293
break;
294
295
- case 0x00060001: /* Get DMA channels */
296
+ case RPI_FWREQ_GET_DMA_CHANNELS:
297
/* channels 2-5 */
298
stl_le_phys(&s->dma_as, value + 12, 0x003C);
299
resplen = 4;
300
break;
301
302
- case 0x00050001: /* Get command line */
303
+ case RPI_FWREQ_GET_COMMAND_LINE:
304
/*
305
* We follow the firmware behaviour: no NUL terminator is
306
* written to the buffer, and if the buffer is too short
307
--
87
--
308
2.34.1
88
2.34.1
309
89
310
90
diff view generated by jsdifflib
1
Convert the exception generation instructions SVC, HVC, SMC, BRK and
1
We support two different encodings for the AArch32 IMPDEF
2
HLT to decodetree.
2
CBAR register -- older cores like the Cortex A9, A7, A15
3
have this at 4, c15, c0, 0; newer cores like the
4
Cortex A35, A53, A57 and A72 have it at 1 c15 c0 0.
3
5
4
The old decoder decoded the halting-debug insnns DCPS1, DCPS2 and
6
When we implemented this we picked which encoding to
5
DCPS3 just in order to then make them UNDEF; as with DRPS, we don't
7
use based on whether the CPU set ARM_FEATURE_AARCH64.
6
bother to decode them, but document the patterns in a64.decode.
8
However this isn't right for three cases:
9
* the qemu-system-arm 'max' CPU, which is supposed to be
10
a variant on a Cortex-A57; it ought to use the same
11
encoding the A57 does and which the AArch64 'max'
12
exposes to AArch32 guest code
13
* the Cortex-R52, which is AArch32-only but has the CBAR
14
at the newer encoding (and where we incorrectly are
15
not yet setting ARM_FEATURE_CBAR_RO anyway)
16
* any possible future support for other v8 AArch32
17
only CPUs, or for supporting "boot the CPU into
18
AArch32 mode" on our existing cores like the A57 etc
19
20
Make the decision of the encoding be based on whether
21
the CPU implements the ARM_FEATURE_V8 flag instead.
22
23
This changes the behaviour only for the qemu-system-arm
24
'-cpu max'. We don't expect anybody to be relying on the
25
old behaviour because:
26
* it's not what the real hardware Cortex-A57 does
27
(and that's what our ID register claims we are)
28
* we don't implement the memory-mapped GICv3 support
29
which is the only thing that exists at the peripheral
30
base address pointed to by the register
7
31
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
33
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20230602155223.2040685-8-peter.maydell@linaro.org
34
Message-id: 20240206132931.38376-2-peter.maydell@linaro.org
11
---
35
---
12
target/arm/tcg/a64.decode | 15 +++
36
target/arm/helper.c | 2 +-
13
target/arm/tcg/translate-a64.c | 173 ++++++++++++---------------------
37
1 file changed, 1 insertion(+), 1 deletion(-)
14
2 files changed, 79 insertions(+), 109 deletions(-)
15
38
16
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
39
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/tcg/a64.decode
41
--- a/target/arm/helper.c
19
+++ b/target/arm/tcg/a64.decode
42
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
43
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
21
SYS 1101 0101 00 l:1 01 op1:3 crn:4 crm:4 op2:3 rt:5 op0=1
44
* AArch64 cores we might need to add a specific feature flag
22
SYS 1101 0101 00 l:1 10 op1:3 crn:4 crm:4 op2:3 rt:5 op0=2
45
* to indicate cores with "flavour 2" CBAR.
23
SYS 1101 0101 00 l:1 11 op1:3 crn:4 crm:4 op2:3 rt:5 op0=3
46
*/
24
+
47
- if (arm_feature(env, ARM_FEATURE_AARCH64)) {
25
+# Exception generation
48
+ if (arm_feature(env, ARM_FEATURE_V8)) {
26
+
49
/* 32 bit view is [31:18] 0...0 [43:32]. */
27
+@i16 .... .... ... imm:16 ... .. &i
50
uint32_t cbar32 = (extract64(cpu->reset_cbar, 18, 14) << 18)
28
+SVC 1101 0100 000 ................ 000 01 @i16
51
| extract64(cpu->reset_cbar, 32, 12);
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
--
52
--
238
2.34.1
53
2.34.1
diff view generated by jsdifflib
1
Convert the CFINV, XAFLAG and AXFLAG insns to decodetree.
1
The Cortex-R52 implements the Configuration Base Address Register
2
The old decoder handles these in handle_msr_i(), but
2
(CBAR), as a read-only register. Add ARM_FEATURE_CBAR_RO to this CPU
3
the architecture defines them as separate instructions
3
type, so that our implementation provides the register and the
4
from MSR (immediate).
4
associated qdev property.
5
5
6
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>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230602155223.2040685-5-peter.maydell@linaro.org
8
Message-id: 20240206132931.38376-3-peter.maydell@linaro.org
9
---
9
---
10
target/arm/tcg/a64.decode | 6 ++++
10
target/arm/tcg/cpu32.c | 1 +
11
target/arm/tcg/translate-a64.c | 53 +++++++++++++++++-----------------
11
1 file changed, 1 insertion(+)
12
2 files changed, 32 insertions(+), 27 deletions(-)
13
12
14
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/tcg/a64.decode
15
--- a/target/arm/tcg/cpu32.c
17
+++ b/target/arm/tcg/a64.decode
16
+++ b/target/arm/tcg/cpu32.c
18
@@ -XXX,XX +XXX,XX @@ CLREX 1101 0101 0000 0011 0011 ---- 010 11111
17
@@ -XXX,XX +XXX,XX @@ static void cortex_r52_initfn(Object *obj)
19
DSB_DMB 1101 0101 0000 0011 0011 domain:2 types:2 10- 11111
18
set_feature(&cpu->env, ARM_FEATURE_PMSA);
20
ISB 1101 0101 0000 0011 0011 ---- 110 11111
19
set_feature(&cpu->env, ARM_FEATURE_NEON);
21
SB 1101 0101 0000 0011 0011 0000 111 11111
20
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
22
+
21
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
23
+# PSTATE
22
cpu->midr = 0x411fd133; /* r1p3 */
24
+
23
cpu->revidr = 0x00000000;
25
+CFINV 1101 0101 0000 0 000 0100 0000 000 11111
24
cpu->reset_fpsid = 0x41034023;
26
+XAFLAG 1101 0101 0000 0 000 0100 0000 001 11111
27
+AXFLAG 1101 0101 0000 0 000 0100 0000 010 11111
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/tcg/translate-a64.c
31
+++ b/target/arm/tcg/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_SB(DisasContext *s, arg_SB *a)
33
return true;
34
}
35
36
-static void gen_xaflag(void)
37
+static bool trans_CFINV(DisasContext *s, arg_CFINV *a)
38
{
39
- TCGv_i32 z = tcg_temp_new_i32();
40
+ if (!dc_isar_feature(aa64_condm_4, s)) {
41
+ return false;
42
+ }
43
+ tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
44
+ return true;
45
+}
46
+
47
+static bool trans_XAFLAG(DisasContext *s, arg_XAFLAG *a)
48
+{
49
+ TCGv_i32 z;
50
+
51
+ if (!dc_isar_feature(aa64_condm_5, s)) {
52
+ return false;
53
+ }
54
+
55
+ z = tcg_temp_new_i32();
56
57
tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
58
59
@@ -XXX,XX +XXX,XX @@ static void gen_xaflag(void)
60
61
/* C | Z */
62
tcg_gen_or_i32(cpu_CF, cpu_CF, z);
63
+
64
+ return true;
65
}
66
67
-static void gen_axflag(void)
68
+static bool trans_AXFLAG(DisasContext *s, arg_AXFLAG *a)
69
{
70
+ if (!dc_isar_feature(aa64_condm_5, s)) {
71
+ return false;
72
+ }
73
+
74
tcg_gen_sari_i32(cpu_VF, cpu_VF, 31); /* V ? -1 : 0 */
75
tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF); /* C & !V */
76
77
@@ -XXX,XX +XXX,XX @@ static void gen_axflag(void)
78
79
tcg_gen_movi_i32(cpu_NF, 0);
80
tcg_gen_movi_i32(cpu_VF, 0);
81
+
82
+ return true;
83
}
84
85
/* MSR (immediate) - move immediate to processor state field */
86
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
87
s->base.is_jmp = DISAS_TOO_MANY;
88
89
switch (op) {
90
- case 0x00: /* CFINV */
91
- if (crm != 0 || !dc_isar_feature(aa64_condm_4, s)) {
92
- goto do_unallocated;
93
- }
94
- tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
95
- s->base.is_jmp = DISAS_NEXT;
96
- break;
97
-
98
- case 0x01: /* XAFlag */
99
- if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
100
- goto do_unallocated;
101
- }
102
- gen_xaflag();
103
- s->base.is_jmp = DISAS_NEXT;
104
- break;
105
-
106
- case 0x02: /* AXFlag */
107
- if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
108
- goto do_unallocated;
109
- }
110
- gen_axflag();
111
- s->base.is_jmp = DISAS_NEXT;
112
- break;
113
-
114
case 0x03: /* UAO */
115
if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
116
goto do_unallocated;
117
--
25
--
118
2.34.1
26
2.34.1
diff view generated by jsdifflib
1
Convert the various instructions in the hint instruction space
1
Add the Cortex-R52 IMPDEF sysregs, by defining them here and
2
to decodetree.
2
also by enabling the AUXCR feature which defines the ACTLR
3
and HACTLR registers. As is our usual practice, we make these
4
simple reads-as-zero stubs for now.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-3-peter.maydell@linaro.org
8
Message-id: 20240206132931.38376-4-peter.maydell@linaro.org
7
---
9
---
8
target/arm/tcg/a64.decode | 31 ++++
10
target/arm/tcg/cpu32.c | 108 +++++++++++++++++++++++++++++++++++++++++
9
target/arm/tcg/translate-a64.c | 277 ++++++++++++++++++---------------
11
1 file changed, 108 insertions(+)
10
2 files changed, 185 insertions(+), 123 deletions(-)
11
12
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
--- a/target/arm/tcg/cpu32.c
15
+++ b/target/arm/tcg/a64.decode
16
+++ b/target/arm/tcg/cpu32.c
16
@@ -XXX,XX +XXX,XX @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
17
@@ -XXX,XX +XXX,XX @@ static void cortex_r5_initfn(Object *obj)
17
# the processor is in halting debug state (which we don't implement).
18
define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
18
# The pattern is listed here as documentation.
19
}
19
# DRPS 1101011 0101 11111 000000 11111 00000
20
21
+static const ARMCPRegInfo cortex_r52_cp_reginfo[] = {
22
+ { .name = "CPUACTLR", .cp = 15, .opc1 = 0, .crm = 15,
23
+ .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
24
+ { .name = "IMP_ATCMREGIONR",
25
+ .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
26
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
27
+ { .name = "IMP_BTCMREGIONR",
28
+ .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
29
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
30
+ { .name = "IMP_CTCMREGIONR",
31
+ .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 2,
32
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
33
+ { .name = "IMP_CSCTLR",
34
+ .cp = 15, .opc1 = 1, .crn = 9, .crm = 1, .opc2 = 0,
35
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
36
+ { .name = "IMP_BPCTLR",
37
+ .cp = 15, .opc1 = 1, .crn = 9, .crm = 1, .opc2 = 1,
38
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
39
+ { .name = "IMP_MEMPROTCLR",
40
+ .cp = 15, .opc1 = 1, .crn = 9, .crm = 1, .opc2 = 2,
41
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
42
+ { .name = "IMP_SLAVEPCTLR",
43
+ .cp = 15, .opc1 = 0, .crn = 11, .crm = 0, .opc2 = 0,
44
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
45
+ { .name = "IMP_PERIPHREGIONR",
46
+ .cp = 15, .opc1 = 0, .crn = 15, .crm = 0, .opc2 = 0,
47
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
48
+ { .name = "IMP_FLASHIFREGIONR",
49
+ .cp = 15, .opc1 = 0, .crn = 15, .crm = 0, .opc2 = 1,
50
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
51
+ { .name = "IMP_BUILDOPTR",
52
+ .cp = 15, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 0,
53
+ .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
54
+ { .name = "IMP_PINOPTR",
55
+ .cp = 15, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 7,
56
+ .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
57
+ { .name = "IMP_QOSR",
58
+ .cp = 15, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 1,
59
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
60
+ { .name = "IMP_BUSTIMEOUTR",
61
+ .cp = 15, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 2,
62
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
63
+ { .name = "IMP_INTMONR",
64
+ .cp = 15, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 4,
65
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
66
+ { .name = "IMP_ICERR0",
67
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 0, .opc2 = 0,
68
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
69
+ { .name = "IMP_ICERR1",
70
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 0, .opc2 = 1,
71
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
72
+ { .name = "IMP_DCERR0",
73
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 1, .opc2 = 0,
74
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
75
+ { .name = "IMP_DCERR1",
76
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 1, .opc2 = 1,
77
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
78
+ { .name = "IMP_TCMERR0",
79
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 2, .opc2 = 0,
80
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
81
+ { .name = "IMP_TCMERR1",
82
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 2, .opc2 = 1,
83
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
84
+ { .name = "IMP_TCMSYNDR0",
85
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 2, .opc2 = 2,
86
+ .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
87
+ { .name = "IMP_TCMSYNDR1",
88
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 2, .opc2 = 3,
89
+ .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
90
+ { .name = "IMP_FLASHERR0",
91
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 3, .opc2 = 0,
92
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
93
+ { .name = "IMP_FLASHERR1",
94
+ .cp = 15, .opc1 = 2, .crn = 15, .crm = 3, .opc2 = 1,
95
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
96
+ { .name = "IMP_CDBGDR0",
97
+ .cp = 15, .opc1 = 3, .crn = 15, .crm = 0, .opc2 = 0,
98
+ .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
99
+ { .name = "IMP_CBDGBR1",
100
+ .cp = 15, .opc1 = 3, .crn = 15, .crm = 0, .opc2 = 1,
101
+ .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
102
+ { .name = "IMP_TESTR0",
103
+ .cp = 15, .opc1 = 4, .crn = 15, .crm = 0, .opc2 = 0,
104
+ .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
105
+ { .name = "IMP_TESTR1",
106
+ .cp = 15, .opc1 = 4, .crn = 15, .crm = 0, .opc2 = 1,
107
+ .access = PL1_W, .type = ARM_CP_NOP, .resetvalue = 0 },
108
+ { .name = "IMP_CDBGDCI",
109
+ .cp = 15, .opc1 = 0, .crn = 15, .crm = 15, .opc2 = 0,
110
+ .access = PL1_W, .type = ARM_CP_NOP, .resetvalue = 0 },
111
+ { .name = "IMP_CDBGDCT",
112
+ .cp = 15, .opc1 = 3, .crn = 15, .crm = 2, .opc2 = 0,
113
+ .access = PL1_W, .type = ARM_CP_NOP, .resetvalue = 0 },
114
+ { .name = "IMP_CDBGICT",
115
+ .cp = 15, .opc1 = 3, .crn = 15, .crm = 2, .opc2 = 1,
116
+ .access = PL1_W, .type = ARM_CP_NOP, .resetvalue = 0 },
117
+ { .name = "IMP_CDBGDCD",
118
+ .cp = 15, .opc1 = 3, .crn = 15, .crm = 4, .opc2 = 0,
119
+ .access = PL1_W, .type = ARM_CP_NOP, .resetvalue = 0 },
120
+ { .name = "IMP_CDBGICD",
121
+ .cp = 15, .opc1 = 3, .crn = 15, .crm = 4, .opc2 = 1,
122
+ .access = PL1_W, .type = ARM_CP_NOP, .resetvalue = 0 },
123
+};
20
+
124
+
21
+# Hint instruction group
125
+
22
+{
126
static void cortex_r52_initfn(Object *obj)
23
+ [
127
{
24
+ YIELD 1101 0101 0000 0011 0010 0000 001 11111
128
ARMCPU *cpu = ARM_CPU(obj);
25
+ WFE 1101 0101 0000 0011 0010 0000 010 11111
129
@@ -XXX,XX +XXX,XX @@ static void cortex_r52_initfn(Object *obj)
26
+ WFI 1101 0101 0000 0011 0010 0000 011 11111
130
set_feature(&cpu->env, ARM_FEATURE_NEON);
27
+ # We implement WFE to never block, so our SEV/SEVL are NOPs
131
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
28
+ # SEV 1101 0101 0000 0011 0010 0000 100 11111
132
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
29
+ # SEVL 1101 0101 0000 0011 0010 0000 101 11111
133
+ set_feature(&cpu->env, ARM_FEATURE_AUXCR);
30
+ # Our DGL is a NOP because we don't merge memory accesses anyway.
134
cpu->midr = 0x411fd133; /* r1p3 */
31
+ # DGL 1101 0101 0000 0011 0010 0000 110 11111
135
cpu->revidr = 0x00000000;
32
+ XPACLRI 1101 0101 0000 0011 0010 0000 111 11111
136
cpu->reset_fpsid = 0x41034023;
33
+ PACIA1716 1101 0101 0000 0011 0010 0001 000 11111
137
@@ -XXX,XX +XXX,XX @@ static void cortex_r52_initfn(Object *obj)
34
+ PACIB1716 1101 0101 0000 0011 0010 0001 010 11111
138
35
+ AUTIA1716 1101 0101 0000 0011 0010 0001 100 11111
139
cpu->pmsav7_dregion = 16;
36
+ AUTIB1716 1101 0101 0000 0011 0010 0001 110 11111
140
cpu->pmsav8r_hdregion = 16;
37
+ ESB 1101 0101 0000 0011 0010 0010 000 11111
141
+
38
+ PACIAZ 1101 0101 0000 0011 0010 0011 000 11111
142
+ define_arm_cp_regs(cpu, cortex_r52_cp_reginfo);
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
}
143
}
58
144
59
-/* HINT instruction group, including various allocated HINTs */
145
static void cortex_r5f_initfn(Object *obj)
60
-static void handle_hint(DisasContext *s, uint32_t insn,
61
- unsigned int op1, unsigned int op2, unsigned int crm)
62
+static bool trans_NOP(DisasContext *s, arg_NOP *a)
63
{
64
- unsigned int selector = crm << 3 | op2;
65
+ return true;
66
+}
67
68
- if (op1 != 3) {
69
- unallocated_encoding(s);
70
- return;
71
+static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
72
+{
73
+ /*
74
+ * When running in MTTCG we don't generate jumps to the yield and
75
+ * WFE helpers as it won't affect the scheduling of other vCPUs.
76
+ * If we wanted to more completely model WFE/SEV so we don't busy
77
+ * spin unnecessarily we would need to do something more involved.
78
+ */
79
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
80
+ s->base.is_jmp = DISAS_YIELD;
81
}
82
+ return true;
83
+}
84
85
- switch (selector) {
86
- case 0b00000: /* NOP */
87
- break;
88
- case 0b00011: /* WFI */
89
- s->base.is_jmp = DISAS_WFI;
90
- break;
91
- case 0b00001: /* YIELD */
92
- /* When running in MTTCG we don't generate jumps to the yield and
93
- * WFE helpers as it won't affect the scheduling of other vCPUs.
94
- * If we wanted to more completely model WFE/SEV so we don't busy
95
- * spin unnecessarily we would need to do something more involved.
96
+static bool trans_WFI(DisasContext *s, arg_WFI *a)
97
+{
98
+ s->base.is_jmp = DISAS_WFI;
99
+ return true;
100
+}
101
+
102
+static bool trans_WFE(DisasContext *s, arg_WFI *a)
103
+{
104
+ /*
105
+ * When running in MTTCG we don't generate jumps to the yield and
106
+ * WFE helpers as it won't affect the scheduling of other vCPUs.
107
+ * If we wanted to more completely model WFE/SEV so we don't busy
108
+ * spin unnecessarily we would need to do something more involved.
109
+ */
110
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
111
+ s->base.is_jmp = DISAS_WFE;
112
+ }
113
+ return true;
114
+}
115
+
116
+static bool trans_XPACLRI(DisasContext *s, arg_XPACLRI *a)
117
+{
118
+ if (s->pauth_active) {
119
+ gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
120
+ }
121
+ return true;
122
+}
123
+
124
+static bool trans_PACIA1716(DisasContext *s, arg_PACIA1716 *a)
125
+{
126
+ if (s->pauth_active) {
127
+ gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
128
+ }
129
+ return true;
130
+}
131
+
132
+static bool trans_PACIB1716(DisasContext *s, arg_PACIB1716 *a)
133
+{
134
+ if (s->pauth_active) {
135
+ gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
136
+ }
137
+ return true;
138
+}
139
+
140
+static bool trans_AUTIA1716(DisasContext *s, arg_AUTIA1716 *a)
141
+{
142
+ if (s->pauth_active) {
143
+ gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
144
+ }
145
+ return true;
146
+}
147
+
148
+static bool trans_AUTIB1716(DisasContext *s, arg_AUTIB1716 *a)
149
+{
150
+ if (s->pauth_active) {
151
+ gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
152
+ }
153
+ return true;
154
+}
155
+
156
+static bool trans_ESB(DisasContext *s, arg_ESB *a)
157
+{
158
+ /* Without RAS, we must implement this as NOP. */
159
+ if (dc_isar_feature(aa64_ras, s)) {
160
+ /*
161
+ * QEMU does not have a source of physical SErrors,
162
+ * so we are only concerned with virtual SErrors.
163
+ * The pseudocode in the ARM for this case is
164
+ * if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
165
+ * AArch64.vESBOperation();
166
+ * Most of the condition can be evaluated at translation time.
167
+ * Test for EL2 present, and defer test for SEL2 to runtime.
168
*/
169
- if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
170
- s->base.is_jmp = DISAS_YIELD;
171
+ if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
172
+ gen_helper_vesb(cpu_env);
173
}
174
- break;
175
- case 0b00010: /* WFE */
176
- if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
177
- s->base.is_jmp = DISAS_WFE;
178
- }
179
- break;
180
- case 0b00100: /* SEV */
181
- case 0b00101: /* SEVL */
182
- case 0b00110: /* DGH */
183
- /* we treat all as NOP at least for now */
184
- break;
185
- case 0b00111: /* XPACLRI */
186
- if (s->pauth_active) {
187
- gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
188
- }
189
- break;
190
- case 0b01000: /* PACIA1716 */
191
- if (s->pauth_active) {
192
- gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
193
- }
194
- break;
195
- case 0b01010: /* PACIB1716 */
196
- if (s->pauth_active) {
197
- gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
198
- }
199
- break;
200
- case 0b01100: /* AUTIA1716 */
201
- if (s->pauth_active) {
202
- gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
203
- }
204
- break;
205
- case 0b01110: /* AUTIB1716 */
206
- if (s->pauth_active) {
207
- gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
208
- }
209
- break;
210
- case 0b10000: /* ESB */
211
- /* Without RAS, we must implement this as NOP. */
212
- if (dc_isar_feature(aa64_ras, s)) {
213
- /*
214
- * QEMU does not have a source of physical SErrors,
215
- * so we are only concerned with virtual SErrors.
216
- * The pseudocode in the ARM for this case is
217
- * if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
218
- * AArch64.vESBOperation();
219
- * Most of the condition can be evaluated at translation time.
220
- * Test for EL2 present, and defer test for SEL2 to runtime.
221
- */
222
- if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
223
- gen_helper_vesb(cpu_env);
224
- }
225
- }
226
- break;
227
- case 0b11000: /* PACIAZ */
228
- if (s->pauth_active) {
229
- gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30],
230
- tcg_constant_i64(0));
231
- }
232
- break;
233
- case 0b11001: /* PACIASP */
234
- if (s->pauth_active) {
235
- gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
236
- }
237
- break;
238
- case 0b11010: /* PACIBZ */
239
- if (s->pauth_active) {
240
- gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30],
241
- tcg_constant_i64(0));
242
- }
243
- break;
244
- case 0b11011: /* PACIBSP */
245
- if (s->pauth_active) {
246
- gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
247
- }
248
- break;
249
- case 0b11100: /* AUTIAZ */
250
- if (s->pauth_active) {
251
- gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30],
252
- tcg_constant_i64(0));
253
- }
254
- break;
255
- case 0b11101: /* AUTIASP */
256
- if (s->pauth_active) {
257
- gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
258
- }
259
- break;
260
- case 0b11110: /* AUTIBZ */
261
- if (s->pauth_active) {
262
- gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30],
263
- tcg_constant_i64(0));
264
- }
265
- break;
266
- case 0b11111: /* AUTIBSP */
267
- if (s->pauth_active) {
268
- gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
269
- }
270
- break;
271
- default:
272
- /* default specified as NOP equivalent */
273
- break;
274
}
275
+ return true;
276
+}
277
+
278
+static bool trans_PACIAZ(DisasContext *s, arg_PACIAZ *a)
279
+{
280
+ if (s->pauth_active) {
281
+ gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
282
+ }
283
+ return true;
284
+}
285
+
286
+static bool trans_PACIASP(DisasContext *s, arg_PACIASP *a)
287
+{
288
+ if (s->pauth_active) {
289
+ gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
290
+ }
291
+ return true;
292
+}
293
+
294
+static bool trans_PACIBZ(DisasContext *s, arg_PACIBZ *a)
295
+{
296
+ if (s->pauth_active) {
297
+ gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
298
+ }
299
+ return true;
300
+}
301
+
302
+static bool trans_PACIBSP(DisasContext *s, arg_PACIBSP *a)
303
+{
304
+ if (s->pauth_active) {
305
+ gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
306
+ }
307
+ return true;
308
+}
309
+
310
+static bool trans_AUTIAZ(DisasContext *s, arg_AUTIAZ *a)
311
+{
312
+ if (s->pauth_active) {
313
+ gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
314
+ }
315
+ return true;
316
+}
317
+
318
+static bool trans_AUTIASP(DisasContext *s, arg_AUTIASP *a)
319
+{
320
+ if (s->pauth_active) {
321
+ gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
322
+ }
323
+ return true;
324
+}
325
+
326
+static bool trans_AUTIBZ(DisasContext *s, arg_AUTIBZ *a)
327
+{
328
+ if (s->pauth_active) {
329
+ gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
330
+ }
331
+ return true;
332
+}
333
+
334
+static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
335
+{
336
+ if (s->pauth_active) {
337
+ gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
338
+ }
339
+ return true;
340
}
341
342
static void gen_clrex(DisasContext *s, uint32_t insn)
343
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
344
return;
345
}
346
switch (crn) {
347
- case 2: /* HINT (including allocated hints like NOP, YIELD, etc) */
348
- handle_hint(s, insn, op1, op2, crm);
349
- break;
350
case 3: /* CLREX, DSB, DMB, ISB */
351
handle_sync(s, insn, op1, op2, crm);
352
break;
353
--
146
--
354
2.34.1
147
2.34.1
diff view generated by jsdifflib
1
Convert the LDR and STR instructions which use a 12-bit immediate
1
Architecturally, the AArch32 MSR/MRS to/from banked register
2
offset to decodetree. We can reuse the existing LDR and STR
2
instructions are UNPREDICTABLE for attempts to access a banked
3
trans functions for these.
3
register that the guest could access in a more direct way (e.g.
4
using this insn to access r8_fiq when already in FIQ mode). QEMU has
5
chosen to UNDEF on all of these.
6
7
However, for the case of accessing SPSR_hyp from hyp mode, it turns
8
out that real hardware permits this, with the same effect as if the
9
guest had directly written to SPSR. Further, there is some
10
guest code out there that assumes it can do this, because it
11
happens to work on hardware: an example Cortex-R52 startup code
12
fragment uses this, and it got copied into various other places,
13
including Zephyr. Zephyr was fixed to not use this:
14
https://github.com/zephyrproject-rtos/zephyr/issues/47330
15
but other examples are still out there, like the selftest
16
binary for the MPS3-AN536.
17
18
For convenience of being able to run guest code, permit
19
this UNPREDICTABLE access instead of UNDEFing it.
4
20
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230602155223.2040685-14-peter.maydell@linaro.org
23
Message-id: 20240206132931.38376-5-peter.maydell@linaro.org
8
---
24
---
9
target/arm/tcg/a64.decode | 25 ++++++++
25
target/arm/tcg/op_helper.c | 43 ++++++++++++++++++++++++++------------
10
target/arm/tcg/translate-a64.c | 104 +++++----------------------------
26
target/arm/tcg/translate.c | 19 +++++++++++------
11
2 files changed, 41 insertions(+), 88 deletions(-)
27
2 files changed, 43 insertions(+), 19 deletions(-)
12
28
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
29
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
14
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
31
--- a/target/arm/tcg/op_helper.c
16
+++ b/target/arm/tcg/a64.decode
32
+++ b/target/arm/tcg/op_helper.c
17
@@ -XXX,XX +XXX,XX @@ STR_v_i sz:2 111 1 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0
33
@@ -XXX,XX +XXX,XX @@ static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
18
STR_v_i 00 111 1 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
34
*/
19
LDR_v_i sz:2 111 1 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
35
int curmode = env->uncached_cpsr & CPSR_M;
20
LDR_v_i 00 111 1 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
36
21
+
37
- if (regno == 17) {
22
+# Load/store with an unsigned 12 bit immediate, which is scaled by the
38
- /* ELR_Hyp: a special case because access from tgtmode is OK */
23
+# element size. The function gets the sz:imm and returns the scaled immediate.
39
- if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
24
+%uimm_scaled 10:12 sz:3 !function=uimm_scaled
40
- goto undef;
25
+
41
+ if (tgtmode == ARM_CPU_MODE_HYP) {
26
+@ldst_uimm .. ... . .. .. ............ rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=0 imm=%uimm_scaled
42
+ /*
27
+
43
+ * Handle Hyp target regs first because some are special cases
28
+STR_i sz:2 111 0 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=0
44
+ * which don't want the usual "not accessible from tgtmode" check.
29
+LDR_i 00 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=0
45
+ */
30
+LDR_i 01 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=1
46
+ switch (regno) {
31
+LDR_i 10 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=2
47
+ case 16 ... 17: /* ELR_Hyp, SPSR_Hyp */
32
+LDR_i 11 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=3
48
+ if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
33
+LDR_i 00 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=0
49
+ goto undef;
34
+LDR_i 01 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=1
50
+ }
35
+LDR_i 10 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=2
51
+ break;
36
+LDR_i 00 111 0 01 11 ............ ..... ..... @ldst_uimm sign=1 ext=1 sz=0
52
+ case 13:
37
+LDR_i 01 111 0 01 11 ............ ..... ..... @ldst_uimm sign=1 ext=1 sz=1
53
+ if (curmode != ARM_CPU_MODE_MON) {
38
+
54
+ goto undef;
39
+# PRFM
55
+ }
40
+NOP 11 111 0 01 10 ------------ ----- -----
56
+ break;
41
+
57
+ default:
42
+STR_v_i sz:2 111 1 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=0
58
+ g_assert_not_reached();
43
+STR_v_i 00 111 1 01 10 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
59
}
44
+LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0
60
return;
45
+LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
46
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/tcg/translate-a64.c
49
+++ b/target/arm/tcg/translate-a64.c
50
@@ -XXX,XX +XXX,XX @@ enum a64_shift_type {
51
A64_SHIFT_TYPE_ROR = 3
52
};
53
54
+/*
55
+ * Helpers for extracting complex instruction fields
56
+ */
57
+
58
+/*
59
+ * For load/store with an unsigned 12 bit immediate scaled by the element
60
+ * size. The input has the immediate field in bits [14:3] and the element
61
+ * size in [2:0].
62
+ */
63
+static int uimm_scaled(DisasContext *s, int x)
64
+{
65
+ unsigned imm = x >> 3;
66
+ unsigned scale = extract32(x, 0, 3);
67
+ return imm << scale;
68
+}
69
+
70
/*
71
* Include the generated decoders.
72
*/
73
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
74
}
61
}
75
}
62
@@ -XXX,XX +XXX,XX @@ static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
76
63
}
77
-/*
64
}
78
- * Load/store (unsigned immediate)
65
79
- *
66
- if (tgtmode == ARM_CPU_MODE_HYP) {
80
- * 31 30 29 27 26 25 24 23 22 21 10 9 5
67
- /* SPSR_Hyp, r13_hyp: accessible from Monitor mode only */
81
- * +----+-------+---+-----+-----+------------+-------+------+
68
- if (curmode != ARM_CPU_MODE_MON) {
82
- * |size| 1 1 1 | V | 0 1 | opc | imm12 | Rn | Rt |
69
- goto undef;
83
- * +----+-------+---+-----+-----+------------+-------+------+
84
- *
85
- * For non-vector:
86
- * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
87
- * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
88
- * For vector:
89
- * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
90
- * opc<0>: 0 -> store, 1 -> load
91
- * Rn: base address register (inc SP)
92
- * Rt: target register
93
- */
94
-static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
95
- int opc,
96
- int size,
97
- int rt,
98
- bool is_vector)
99
-{
100
- int rn = extract32(insn, 5, 5);
101
- unsigned int imm12 = extract32(insn, 10, 12);
102
- unsigned int offset;
103
- TCGv_i64 clean_addr, dirty_addr;
104
- bool is_store;
105
- bool is_signed = false;
106
- bool is_extended = false;
107
- MemOp memop;
108
-
109
- if (is_vector) {
110
- size |= (opc & 2) << 1;
111
- if (size > 4) {
112
- unallocated_encoding(s);
113
- return;
114
- }
70
- }
115
- is_store = !extract32(opc, 0, 1);
116
- if (!fp_access_check(s)) {
117
- return;
118
- }
119
- memop = finalize_memop_asimd(s, size);
120
- } else {
121
- if (size == 3 && opc == 2) {
122
- /* PRFM - prefetch */
123
- return;
124
- }
125
- if (opc == 3 && size > 1) {
126
- unallocated_encoding(s);
127
- return;
128
- }
129
- is_store = (opc == 0);
130
- is_signed = !is_store && extract32(opc, 1, 1);
131
- is_extended = (size < 3) && extract32(opc, 0, 1);
132
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
133
- }
71
- }
134
-
72
-
135
- if (rn == 31) {
73
return;
136
- gen_check_sp_alignment(s);
74
137
- }
75
undef:
138
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
76
@@ -XXX,XX +XXX,XX @@ void HELPER(msr_banked)(CPUARMState *env, uint32_t value, uint32_t tgtmode,
139
- offset = imm12 << size;
77
140
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
78
switch (regno) {
141
-
79
case 16: /* SPSRs */
142
- clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, memop);
80
- env->banked_spsr[bank_number(tgtmode)] = value;
143
-
81
+ if (tgtmode == (env->uncached_cpsr & CPSR_M)) {
144
- if (is_vector) {
82
+ /* Only happens for SPSR_Hyp access in Hyp mode */
145
- if (is_store) {
83
+ env->spsr = value;
146
- do_fp_st(s, rt, clean_addr, memop);
84
+ } else {
147
- } else {
85
+ env->banked_spsr[bank_number(tgtmode)] = value;
148
- do_fp_ld(s, rt, clean_addr, memop);
86
+ }
149
- }
87
break;
150
- } else {
88
case 17: /* ELR_Hyp */
151
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
89
env->elr_el[2] = value;
152
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
90
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(mrs_banked)(CPUARMState *env, uint32_t tgtmode, uint32_t regno)
153
- if (is_store) {
91
154
- do_gpr_st(s, tcg_rt, clean_addr, memop, true, rt, iss_sf, false);
92
switch (regno) {
155
- } else {
93
case 16: /* SPSRs */
156
- do_gpr_ld(s, tcg_rt, clean_addr, memop,
94
- return env->banked_spsr[bank_number(tgtmode)];
157
- is_extended, true, rt, iss_sf, false);
95
+ if (tgtmode == (env->uncached_cpsr & CPSR_M)) {
158
- }
96
+ /* Only happens for SPSR_Hyp access in Hyp mode */
159
- }
97
+ return env->spsr;
160
-}
98
+ } else {
161
-
99
+ return env->banked_spsr[bank_number(tgtmode)];
162
/* Atomic memory operations
100
+ }
163
*
101
case 17: /* ELR_Hyp */
164
* 31 30 27 26 24 22 21 16 15 12 10 5 0
102
return env->elr_el[2];
165
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
103
case 13:
166
return;
104
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/target/arm/tcg/translate.c
107
+++ b/target/arm/tcg/translate.c
108
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
109
break;
110
case ARM_CPU_MODE_HYP:
111
/*
112
- * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
113
- * (and so we can forbid accesses from EL2 or below). elr_hyp
114
- * can be accessed also from Hyp mode, so forbid accesses from
115
- * EL0 or EL1.
116
+ * r13_hyp can only be accessed from Monitor mode, and so we
117
+ * can forbid accesses from EL2 or below.
118
+ * elr_hyp can be accessed also from Hyp mode, so forbid
119
+ * accesses from EL0 or EL1.
120
+ * SPSR_hyp is supposed to be in the same category as r13_hyp
121
+ * and UNPREDICTABLE if accessed from anything except Monitor
122
+ * mode. However there is some real-world code that will do
123
+ * it because at least some hardware happens to permit the
124
+ * access. (Notably a standard Cortex-R52 startup code fragment
125
+ * does this.) So we permit SPSR_hyp from Hyp mode also, to allow
126
+ * this (incorrect) guest code to run.
127
*/
128
- if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
129
- (s->current_el < 3 && *regno != 17)) {
130
+ if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2
131
+ || (s->current_el < 3 && *regno != 16 && *regno != 17)) {
132
goto undef;
167
}
133
}
168
break;
134
break;
169
- case 1:
170
- disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector);
171
- return;
172
}
173
unallocated_encoding(s);
174
}
175
--
135
--
176
2.34.1
136
2.34.1
diff view generated by jsdifflib
1
In commit 2c5fa0778c3b430 we fixed an endianness bug in the Allwinner
1
We currently guard the CFG3 register read with
2
A10 PIC model; however in the process we introduced a regression.
2
(scc_partno(s) == 0x524 && scc_partno(s) == 0x547)
3
This is because the old code was robust against the incoming 'level'
3
which is clearly wrong as it is never true.
4
argument being something other than 0 or 1, whereas the new code was
5
not.
6
4
7
In particular, the allwinner-sdhost code treats its IRQ line
5
This register is present on all board types except AN524
8
as 0-vs-non-0 rather than 0-vs-1, so when the SD controller
6
and AN527; correct the condition.
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
7
13
Handle level values other than 0 or 1, to restore the old
8
Fixes: 6ac80818941829c0 ("hw/misc/mps2-scc: Implement changes for AN547")
14
behaviour.
15
16
Fixes: 2c5fa0778c3b430 ("hw/intc/allwinner-a10-pic: Don't use set_bit()/clear_bit()")
17
Cc: qemu-stable@nongnu.org
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Tested-by: Guenter Roeck <linux@roeck-us.net>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20230606104609.3692557-2-peter.maydell@linaro.org
12
Message-id: 20240206132931.38376-6-peter.maydell@linaro.org
22
---
13
---
23
hw/intc/allwinner-a10-pic.c | 2 +-
14
hw/misc/mps2-scc.c | 2 +-
24
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
25
16
26
diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
17
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
27
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/intc/allwinner-a10-pic.c
19
--- a/hw/misc/mps2-scc.c
29
+++ b/hw/intc/allwinner-a10-pic.c
20
+++ b/hw/misc/mps2-scc.c
30
@@ -XXX,XX +XXX,XX @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
21
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
31
AwA10PICState *s = opaque;
22
r = s->cfg2;
32
uint32_t *pending_reg = &s->irq_pending[irq / 32];
23
break;
33
24
case A_CFG3:
34
- *pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
25
- if (scc_partno(s) == 0x524 && scc_partno(s) == 0x547) {
35
+ *pending_reg = deposit32(*pending_reg, irq % 32, 1, !!level);
26
+ if (scc_partno(s) == 0x524 || scc_partno(s) == 0x547) {
36
aw_a10_pic_update(s);
27
/* CFG3 reserved on AN524 */
37
}
28
goto bad_offset;
38
29
}
39
--
30
--
40
2.34.1
31
2.34.1
41
32
42
33
diff view generated by jsdifflib
1
Convert the instructions in the load/store exclusive (STXR,
1
The MPS SCC device has a lot of different flavours for the various
2
STLXR, LDXR, LDAXR) and load/store ordered (STLR, STLLR,
2
different MPS FPGA images, which look mostly similar but have
3
LDAR, LDLAR) to decodetree.
3
differences in how particular registers are handled. Currently we
4
deal with this with a lot of open-coded checks on scc_partno(), but
5
as we add more board types this is getting a bit hard to read.
4
6
5
Note that for STLR, STLLR, LDAR, LDLAR this fixes an under-decoding
7
Factor out the conditions into some functions which we can
6
in the legacy decoder where we were not checking that the RES1 bits
8
give more descriptive names to.
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
9
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20230602155223.2040685-9-peter.maydell@linaro.org
13
Message-id: 20240206132931.38376-7-peter.maydell@linaro.org
19
---
14
---
20
target/arm/tcg/a64.decode | 11 +++
15
hw/misc/mps2-scc.c | 45 +++++++++++++++++++++++++++++++--------------
21
target/arm/tcg/translate-a64.c | 154 ++++++++++++++++++++-------------
16
1 file changed, 31 insertions(+), 14 deletions(-)
22
2 files changed, 103 insertions(+), 62 deletions(-)
23
17
24
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
18
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
25
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/tcg/a64.decode
20
--- a/hw/misc/mps2-scc.c
27
+++ b/target/arm/tcg/a64.decode
21
+++ b/hw/misc/mps2-scc.c
28
@@ -XXX,XX +XXX,XX @@ HLT 1101 0100 010 ................ 000 00 @i16
22
@@ -XXX,XX +XXX,XX @@ static int scc_partno(MPS2SCC *s)
29
# DCPS1 1101 0100 101 ................ 000 01 @i16
23
return extract32(s->id, 4, 8);
30
# DCPS2 1101 0100 101 ................ 000 10 @i16
31
# DCPS3 1101 0100 101 ................ 000 11 @i16
32
+
33
+# Loads and stores
34
+
35
+&stxr rn rt rt2 rs sz lasr
36
+&stlr rn rt sz lasr
37
+@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
38
+@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
39
+STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
40
+LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
41
+STLR .. 001000 100 11111 . 11111 ..... ..... @stlr # inc STLLR
42
+LDAR .. 001000 110 11111 . 11111 ..... ..... @stlr # inc LDLAR
43
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/tcg/translate-a64.c
46
+++ b/target/arm/tcg/translate-a64.c
47
@@ -XXX,XX +XXX,XX @@ static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
48
return regsize == 64;
49
}
24
}
50
25
51
+static bool ldst_iss_sf(int size, bool sign, bool ext)
26
+/* Is CFG_REG2 present? */
27
+static bool have_cfg2(MPS2SCC *s)
52
+{
28
+{
53
+
29
+ return scc_partno(s) == 0x524 || scc_partno(s) == 0x547;
54
+ if (sign) {
55
+ /*
56
+ * Signed loads are 64 bit results if we are not going to
57
+ * do a zero-extend from 32 to 64 after the load.
58
+ * (For a store, sign and ext are always false.)
59
+ */
60
+ return !ext;
61
+ } else {
62
+ /* Unsigned loads/stores work at the specified size */
63
+ return size == MO_64;
64
+ }
65
+}
30
+}
66
+
31
+
67
+static bool trans_STXR(DisasContext *s, arg_stxr *a)
32
+/* Is CFG_REG3 present? */
33
+static bool have_cfg3(MPS2SCC *s)
68
+{
34
+{
69
+ if (a->rn == 31) {
35
+ return scc_partno(s) != 0x524 && scc_partno(s) != 0x547;
70
+ gen_check_sp_alignment(s);
71
+ }
72
+ if (a->lasr) {
73
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
74
+ }
75
+ gen_store_exclusive(s, a->rs, a->rt, a->rt2, a->rn, a->sz, false);
76
+ return true;
77
+}
36
+}
78
+
37
+
79
+static bool trans_LDXR(DisasContext *s, arg_stxr *a)
38
+/* Is CFG_REG5 present? */
39
+static bool have_cfg5(MPS2SCC *s)
80
+{
40
+{
81
+ if (a->rn == 31) {
41
+ return scc_partno(s) == 0x524 || scc_partno(s) == 0x547;
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
+}
42
+}
90
+
43
+
91
+static bool trans_STLR(DisasContext *s, arg_stlr *a)
44
+/* Is CFG_REG6 present? */
45
+static bool have_cfg6(MPS2SCC *s)
92
+{
46
+{
93
+ TCGv_i64 clean_addr;
47
+ return scc_partno(s) == 0x524;
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
+}
48
+}
116
+
49
+
117
+static bool trans_LDAR(DisasContext *s, arg_stlr *a)
50
/* Handle a write via the SYS_CFG channel to the specified function/device.
118
+{
51
* Return false on error (reported to guest via SYS_CFGCTRL ERROR bit).
119
+ TCGv_i64 clean_addr;
52
*/
120
+ MemOp memop;
53
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
121
+ bool iss_sf = ldst_iss_sf(a->sz, false, false);
54
r = s->cfg1;
122
+
55
break;
123
+ /* LoadLOAcquire is the same as Load-Acquire for QEMU. */
56
case A_CFG2:
124
+ if (!a->lasr && !dc_isar_feature(aa64_lor, s)) {
57
- if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
125
+ return false;
58
- /* CFG2 reserved on other boards */
126
+ }
59
+ if (!have_cfg2(s)) {
127
+ /* Generate ISS for non-exclusive accesses including LASR. */
60
goto bad_offset;
128
+ if (a->rn == 31) {
61
}
129
+ gen_check_sp_alignment(s);
62
r = s->cfg2;
130
+ }
63
break;
131
+ memop = check_ordered_align(s, a->rn, 0, false, a->sz);
64
case A_CFG3:
132
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, a->rn),
65
- if (scc_partno(s) == 0x524 || scc_partno(s) == 0x547) {
133
+ false, a->rn != 31, memop);
66
- /* CFG3 reserved on AN524 */
134
+ do_gpr_ld(s, cpu_reg(s, a->rt), clean_addr, memop, false, true,
67
+ if (!have_cfg3(s)) {
135
+ a->rt, iss_sf, a->lasr);
68
goto bad_offset;
136
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
69
}
137
+ return true;
70
/* These are user-settable DIP switches on the board. We don't
138
+}
71
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
139
+
72
r = s->cfg4;
140
/* Load/store exclusive
73
break;
141
*
74
case A_CFG5:
142
* 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
75
- if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
143
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
76
- /* CFG5 reserved on other boards */
144
int is_lasr = extract32(insn, 15, 1);
77
+ if (!have_cfg5(s)) {
145
int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
78
goto bad_offset;
146
int size = extract32(insn, 30, 2);
79
}
147
- TCGv_i64 clean_addr;
80
r = s->cfg5;
148
- MemOp memop;
81
break;
149
82
case A_CFG6:
150
switch (o2_L_o1_o0) {
83
- if (scc_partno(s) != 0x524) {
151
- case 0x0: /* STXR */
84
- /* CFG6 reserved on other boards */
152
- case 0x1: /* STLXR */
85
+ if (!have_cfg6(s)) {
153
- if (rn == 31) {
86
goto bad_offset;
154
- gen_check_sp_alignment(s);
87
}
155
- }
88
r = s->cfg6;
156
- if (is_lasr) {
89
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
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
}
90
}
217
break;
91
break;
218
+ default:
92
case A_CFG2:
219
+ /* Handled in decodetree */
93
- if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
220
+ break;
94
- /* CFG2 reserved on other boards */
221
}
95
+ if (!have_cfg2(s)) {
222
unallocated_encoding(s);
96
goto bad_offset;
223
}
97
}
98
/* AN524: QSPI Select signal */
99
s->cfg2 = value;
100
break;
101
case A_CFG5:
102
- if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
103
- /* CFG5 reserved on other boards */
104
+ if (!have_cfg5(s)) {
105
goto bad_offset;
106
}
107
/* AN524: ACLK frequency in Hz */
108
s->cfg5 = value;
109
break;
110
case A_CFG6:
111
- if (scc_partno(s) != 0x524) {
112
- /* CFG6 reserved on other boards */
113
+ if (!have_cfg6(s)) {
114
goto bad_offset;
115
}
116
/* AN524: Clock divider for BRAM */
224
--
117
--
225
2.34.1
118
2.34.1
119
120
diff view generated by jsdifflib
1
In disas_ldst_reg_imm9() we missed one place where a call to
1
The MPS2 SCC device is broadly the same for all FPGA images, but has
2
a gen_mte_check* function should now be passed the memop we
2
minor differences in the behaviour of the CFG registers depending on
3
have created rather than just being passed the size. Fix this.
3
the image. In many cases we don't really care about the functionality
4
4
controlled by these registers and a reads-as-written or similar
5
Fixes: 0a9091424d ("target/arm: Pass memop to gen_mte_check1*")
5
behaviour is sufficient for the moment.
6
7
For the AN536 the required behaviour is:
8
9
* A_CFG0 has CPU reset and halt bits
10
- implement as reads-as-written for the moment
11
* A_CFG1 has flash or ATCM address 0 remap handling
12
- QEMU doesn't model this; implement as reads-as-written
13
* A_CFG2 has QSPI select (like AN524)
14
- implemented (no behaviour, as with AN524)
15
* A_CFG3 is MCC_MSB_ADDR "additional MCC addressing bits"
16
- QEMU doesn't care about these, so use the existing
17
RAZ behaviour for convenience
18
* A_CFG4 is board rev (like all other images)
19
- no change needed
20
* A_CFG5 is ACLK frq in hz (like AN524)
21
- implemented as reads-as-written, as for other boards
22
* A_CFG6 is core 0 vector table base address
23
- implemented as reads-as-written for the moment
24
* A_CFG7 is core 1 vector table base address
25
- implemented as reads-as-written for the moment
26
27
Make the changes necessary for this; leave TODO comments where
28
appropriate to indicate where we might want to come back and
29
implement things like CPU reset.
30
31
The other aspects of the device specific to this FPGA image (like the
32
values of the board ID and similar registers) will be set via the
33
device's qdev properties.
34
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
37
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
38
Message-id: 20240206132931.38376-8-peter.maydell@linaro.org
9
---
39
---
10
target/arm/tcg/translate-a64.c | 2 +-
40
include/hw/misc/mps2-scc.h | 1 +
11
1 file changed, 1 insertion(+), 1 deletion(-)
41
hw/misc/mps2-scc.c | 101 +++++++++++++++++++++++++++++++++----
12
42
2 files changed, 92 insertions(+), 10 deletions(-)
13
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
43
44
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
14
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/translate-a64.c
46
--- a/include/hw/misc/mps2-scc.h
16
+++ b/target/arm/tcg/translate-a64.c
47
+++ b/include/hw/misc/mps2-scc.h
17
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
48
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
18
49
uint32_t cfg4;
19
clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
50
uint32_t cfg5;
20
writeback || rn != 31,
51
uint32_t cfg6;
21
- size, is_unpriv, memidx);
52
+ uint32_t cfg7;
22
+ memop, is_unpriv, memidx);
53
uint32_t cfgdata_rtn;
23
54
uint32_t cfgdata_out;
24
if (is_vector) {
55
uint32_t cfgctrl;
25
if (is_store) {
56
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/misc/mps2-scc.c
59
+++ b/hw/misc/mps2-scc.c
60
@@ -XXX,XX +XXX,XX @@ REG32(CFG3, 0xc)
61
REG32(CFG4, 0x10)
62
REG32(CFG5, 0x14)
63
REG32(CFG6, 0x18)
64
+REG32(CFG7, 0x1c)
65
REG32(CFGDATA_RTN, 0xa0)
66
REG32(CFGDATA_OUT, 0xa4)
67
REG32(CFGCTRL, 0xa8)
68
@@ -XXX,XX +XXX,XX @@ static int scc_partno(MPS2SCC *s)
69
/* Is CFG_REG2 present? */
70
static bool have_cfg2(MPS2SCC *s)
71
{
72
- return scc_partno(s) == 0x524 || scc_partno(s) == 0x547;
73
+ return scc_partno(s) == 0x524 || scc_partno(s) == 0x547 ||
74
+ scc_partno(s) == 0x536;
75
}
76
77
/* Is CFG_REG3 present? */
78
static bool have_cfg3(MPS2SCC *s)
79
{
80
- return scc_partno(s) != 0x524 && scc_partno(s) != 0x547;
81
+ return scc_partno(s) != 0x524 && scc_partno(s) != 0x547 &&
82
+ scc_partno(s) != 0x536;
83
}
84
85
/* Is CFG_REG5 present? */
86
static bool have_cfg5(MPS2SCC *s)
87
{
88
- return scc_partno(s) == 0x524 || scc_partno(s) == 0x547;
89
+ return scc_partno(s) == 0x524 || scc_partno(s) == 0x547 ||
90
+ scc_partno(s) == 0x536;
91
}
92
93
/* Is CFG_REG6 present? */
94
static bool have_cfg6(MPS2SCC *s)
95
{
96
- return scc_partno(s) == 0x524;
97
+ return scc_partno(s) == 0x524 || scc_partno(s) == 0x536;
98
+}
99
+
100
+/* Is CFG_REG7 present? */
101
+static bool have_cfg7(MPS2SCC *s)
102
+{
103
+ return scc_partno(s) == 0x536;
104
+}
105
+
106
+/* Does CFG_REG0 drive the 'remap' GPIO output? */
107
+static bool cfg0_is_remap(MPS2SCC *s)
108
+{
109
+ return scc_partno(s) != 0x536;
110
+}
111
+
112
+/* Is CFG_REG1 driving a set of LEDs? */
113
+static bool cfg1_is_leds(MPS2SCC *s)
114
+{
115
+ return scc_partno(s) != 0x536;
116
}
117
118
/* Handle a write via the SYS_CFG channel to the specified function/device.
119
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
120
if (!have_cfg3(s)) {
121
goto bad_offset;
122
}
123
- /* These are user-settable DIP switches on the board. We don't
124
+ /*
125
+ * These are user-settable DIP switches on the board. We don't
126
* model that, so just return zeroes.
127
+ *
128
+ * TODO: for AN536 this is MCC_MSB_ADDR "additional MCC addressing
129
+ * bits". These change which part of the DDR4 the motherboard
130
+ * configuration controller can see in its memory map (see the
131
+ * appnote section 2.4). QEMU doesn't model the MCC at all, so these
132
+ * bits are not interesting to us; read-as-zero is as good as anything
133
+ * else.
134
*/
135
r = 0;
136
break;
137
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
138
}
139
r = s->cfg6;
140
break;
141
+ case A_CFG7:
142
+ if (!have_cfg7(s)) {
143
+ goto bad_offset;
144
+ }
145
+ r = s->cfg7;
146
+ break;
147
case A_CFGDATA_RTN:
148
r = s->cfgdata_rtn;
149
break;
150
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
151
* we always reflect bit 0 in the 'remap' GPIO output line,
152
* and let the board wire it up or not as it chooses.
153
* TODO on some boards bit 1 is CPU_WAIT.
154
+ *
155
+ * TODO: on the AN536 this register controls reset and halt
156
+ * for both CPUs. For the moment we don't implement this, so the
157
+ * register just reads as written.
158
*/
159
s->cfg0 = value;
160
- qemu_set_irq(s->remap, s->cfg0 & 1);
161
+ if (cfg0_is_remap(s)) {
162
+ qemu_set_irq(s->remap, s->cfg0 & 1);
163
+ }
164
break;
165
case A_CFG1:
166
s->cfg1 = value;
167
- for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) {
168
- led_set_state(s->led[i], extract32(value, i, 1));
169
+ /*
170
+ * On most boards this register drives LEDs.
171
+ *
172
+ * TODO: for AN536 this controls whether flash and ATCM are
173
+ * enabled or disabled on reset. QEMU doesn't model this, and
174
+ * always wires up RAM in the ATCM area and ROM in the flash area.
175
+ */
176
+ if (cfg1_is_leds(s)) {
177
+ for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) {
178
+ led_set_state(s->led[i], extract32(value, i, 1));
179
+ }
180
}
181
break;
182
case A_CFG2:
183
if (!have_cfg2(s)) {
184
goto bad_offset;
185
}
186
- /* AN524: QSPI Select signal */
187
+ /* AN524, AN536: QSPI Select signal */
188
s->cfg2 = value;
189
break;
190
case A_CFG5:
191
if (!have_cfg5(s)) {
192
goto bad_offset;
193
}
194
- /* AN524: ACLK frequency in Hz */
195
+ /* AN524, AN536: ACLK frequency in Hz */
196
s->cfg5 = value;
197
break;
198
case A_CFG6:
199
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
200
goto bad_offset;
201
}
202
/* AN524: Clock divider for BRAM */
203
+ /* AN536: Core 0 vector table base address */
204
+ s->cfg6 = value;
205
+ break;
206
+ case A_CFG7:
207
+ if (!have_cfg7(s)) {
208
+ goto bad_offset;
209
+ }
210
+ /* AN536: Core 1 vector table base address */
211
s->cfg6 = value;
212
break;
213
case A_CFGDATA_OUT:
214
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_finalize(Object *obj)
215
g_free(s->oscclk_reset);
216
}
217
218
+static bool cfg7_needed(void *opaque)
219
+{
220
+ MPS2SCC *s = opaque;
221
+
222
+ return have_cfg7(s);
223
+}
224
+
225
+static const VMStateDescription vmstate_cfg7 = {
226
+ .name = "mps2-scc/cfg7",
227
+ .version_id = 1,
228
+ .minimum_version_id = 1,
229
+ .needed = cfg7_needed,
230
+ .fields = (const VMStateField[]) {
231
+ VMSTATE_UINT32(cfg7, MPS2SCC),
232
+ VMSTATE_END_OF_LIST()
233
+ }
234
+};
235
+
236
static const VMStateDescription mps2_scc_vmstate = {
237
.name = "mps2-scc",
238
.version_id = 3,
239
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_scc_vmstate = {
240
VMSTATE_VARRAY_UINT32(oscclk, MPS2SCC, num_oscclk,
241
0, vmstate_info_uint32, uint32_t),
242
VMSTATE_END_OF_LIST()
243
+ },
244
+ .subsections = (const VMStateDescription * const []) {
245
+ &vmstate_cfg7,
246
+ NULL
247
}
248
};
249
26
--
250
--
27
2.34.1
251
2.34.1
28
252
29
253
diff view generated by jsdifflib
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
1
The AN536 is another FPGA image for the MPS3 development board. Unlike
2
2
the existing FPGA images we already model, this board uses a Cortex-R
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
3
family CPU, and it does not use any equivalent to the M-profile
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
"Subsystem for Embedded" SoC-equivalent that we model in hw/arm/armsse.c.
5
Acked-by: Richard Henderson <richard.henderson@linaro.org>
5
It's therefore more convenient for us to model it as a completely
6
Message-id: 20230612223456.33824-2-philmd@linaro.org
6
separate C file.
7
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
7
8
[PMD: Split from bigger patch: 1/4]
8
This commit adds the basic skeleton of the board model, and the
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
code to create all the RAM and ROM. We assume that we're probably
10
going to want to add more images in future, so use the same
11
base class/subclass setup that mps2-tz.c uses, even though at
12
the moment there's only a single subclass.
13
14
Following commits will add the CPUs and the peripherals.
15
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
18
Message-id: 20240206132931.38376-9-peter.maydell@linaro.org
11
---
19
---
12
include/hw/misc/raspberrypi-fw-defs.h | 163 ++++++++++++++++++++++++++
20
MAINTAINERS | 3 +-
13
1 file changed, 163 insertions(+)
21
configs/devices/arm-softmmu/default.mak | 1 +
14
create mode 100644 include/hw/misc/raspberrypi-fw-defs.h
22
hw/arm/mps3r.c | 239 ++++++++++++++++++++++++
15
23
hw/arm/Kconfig | 5 +
16
diff --git a/include/hw/misc/raspberrypi-fw-defs.h b/include/hw/misc/raspberrypi-fw-defs.h
24
hw/arm/meson.build | 1 +
25
5 files changed, 248 insertions(+), 1 deletion(-)
26
create mode 100644 hw/arm/mps3r.c
27
28
diff --git a/MAINTAINERS b/MAINTAINERS
29
index XXXXXXX..XXXXXXX 100644
30
--- a/MAINTAINERS
31
+++ b/MAINTAINERS
32
@@ -XXX,XX +XXX,XX @@ F: include/hw/misc/imx7_*.h
33
F: hw/pci-host/designware.c
34
F: include/hw/pci-host/designware.h
35
36
-MPS2
37
+MPS2 / MPS3
38
M: Peter Maydell <peter.maydell@linaro.org>
39
L: qemu-arm@nongnu.org
40
S: Maintained
41
F: hw/arm/mps2.c
42
F: hw/arm/mps2-tz.c
43
+F: hw/arm/mps3r.c
44
F: hw/misc/mps2-*.c
45
F: include/hw/misc/mps2-*.h
46
F: hw/arm/armsse.c
47
diff --git a/configs/devices/arm-softmmu/default.mak b/configs/devices/arm-softmmu/default.mak
48
index XXXXXXX..XXXXXXX 100644
49
--- a/configs/devices/arm-softmmu/default.mak
50
+++ b/configs/devices/arm-softmmu/default.mak
51
@@ -XXX,XX +XXX,XX @@ CONFIG_ARM_VIRT=y
52
# CONFIG_INTEGRATOR=n
53
# CONFIG_FSL_IMX31=n
54
# CONFIG_MUSICPAL=n
55
+# CONFIG_MPS3R=n
56
# CONFIG_MUSCA=n
57
# CONFIG_CHEETAH=n
58
# CONFIG_SX1=n
59
diff --git a/hw/arm/mps3r.c b/hw/arm/mps3r.c
17
new file mode 100644
60
new file mode 100644
18
index XXXXXXX..XXXXXXX
61
index XXXXXXX..XXXXXXX
19
--- /dev/null
62
--- /dev/null
20
+++ b/include/hw/misc/raspberrypi-fw-defs.h
63
+++ b/hw/arm/mps3r.c
21
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@
22
+/*
65
+/*
23
+ * Raspberry Pi firmware definitions
66
+ * Arm MPS3 board emulation for Cortex-R-based FPGA images.
67
+ * (For M-profile images see mps2.c and mps2tz.c.)
24
+ *
68
+ *
25
+ * Copyright (C) 2022 Auriga LLC, based on Linux kernel
69
+ * Copyright (c) 2017 Linaro Limited
26
+ * `include/soc/bcm2835/raspberrypi-firmware.h` (Copyright © 2015 Broadcom)
70
+ * Written by Peter Maydell
27
+ *
71
+ *
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
72
+ * This program is free software; you can redistribute it and/or modify
73
+ * it under the terms of the GNU General Public License version 2 or
74
+ * (at your option) any later version.
29
+ */
75
+ */
30
+
76
+
31
+#ifndef INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
77
+/*
32
+#define INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
78
+ * The MPS3 is an FPGA based dev board. This file handles FPGA images
79
+ * which use the Cortex-R CPUs. We model these separately from the
80
+ * M-profile images, because on M-profile the FPGA image is based on
81
+ * a "Subsystem for Embedded" which is similar to an SoC, whereas
82
+ * the R-profile FPGA images don't have that abstraction layer.
83
+ *
84
+ * We model the following FPGA images here:
85
+ * "mps3-an536" -- dual Cortex-R52 as documented in Arm Application Note AN536
86
+ *
87
+ * Application Note AN536:
88
+ * https://developer.arm.com/documentation/dai0536/latest/
89
+ */
33
+
90
+
34
+#include "qemu/osdep.h"
91
+#include "qemu/osdep.h"
35
+
92
+#include "qemu/units.h"
36
+enum rpi_firmware_property_tag {
93
+#include "qapi/error.h"
37
+ RPI_FWREQ_PROPERTY_END = 0,
94
+#include "exec/address-spaces.h"
38
+ RPI_FWREQ_GET_FIRMWARE_REVISION = 0x00000001,
95
+#include "cpu.h"
39
+ RPI_FWREQ_GET_FIRMWARE_VARIANT = 0x00000002,
96
+#include "hw/boards.h"
40
+ RPI_FWREQ_GET_FIRMWARE_HASH = 0x00000003,
97
+#include "hw/arm/boot.h"
41
+
98
+
42
+ RPI_FWREQ_SET_CURSOR_INFO = 0x00008010,
99
+/* Define the layout of RAM and ROM in a board */
43
+ RPI_FWREQ_SET_CURSOR_STATE = 0x00008011,
100
+typedef struct RAMInfo {
44
+
101
+ const char *name;
45
+ RPI_FWREQ_GET_BOARD_MODEL = 0x00010001,
102
+ hwaddr base;
46
+ RPI_FWREQ_GET_BOARD_REVISION = 0x00010002,
103
+ hwaddr size;
47
+ RPI_FWREQ_GET_BOARD_MAC_ADDRESS = 0x00010003,
104
+ int mrindex; /* index into rams[]; -1 for the system RAM block */
48
+ RPI_FWREQ_GET_BOARD_SERIAL = 0x00010004,
105
+ int flags;
49
+ RPI_FWREQ_GET_ARM_MEMORY = 0x00010005,
106
+} RAMInfo;
50
+ RPI_FWREQ_GET_VC_MEMORY = 0x00010006,
107
+
51
+ RPI_FWREQ_GET_CLOCKS = 0x00010007,
108
+/*
52
+ RPI_FWREQ_GET_POWER_STATE = 0x00020001,
109
+ * The MPS3 DDR is 3GiB, but on a 32-bit host QEMU doesn't permit
53
+ RPI_FWREQ_GET_TIMING = 0x00020002,
110
+ * emulation of that much guest RAM, so artificially make it smaller.
54
+ RPI_FWREQ_SET_POWER_STATE = 0x00028001,
111
+ */
55
+ RPI_FWREQ_GET_CLOCK_STATE = 0x00030001,
112
+#if HOST_LONG_BITS == 32
56
+ RPI_FWREQ_GET_CLOCK_RATE = 0x00030002,
113
+#define MPS3_DDR_SIZE (1 * GiB)
57
+ RPI_FWREQ_GET_VOLTAGE = 0x00030003,
114
+#else
58
+ RPI_FWREQ_GET_MAX_CLOCK_RATE = 0x00030004,
115
+#define MPS3_DDR_SIZE (3 * GiB)
59
+ RPI_FWREQ_GET_MAX_VOLTAGE = 0x00030005,
116
+#endif
60
+ RPI_FWREQ_GET_TEMPERATURE = 0x00030006,
117
+
61
+ RPI_FWREQ_GET_MIN_CLOCK_RATE = 0x00030007,
118
+/*
62
+ RPI_FWREQ_GET_MIN_VOLTAGE = 0x00030008,
119
+ * Flag values:
63
+ RPI_FWREQ_GET_TURBO = 0x00030009,
120
+ * IS_MAIN: this is the main machine RAM
64
+ RPI_FWREQ_GET_MAX_TEMPERATURE = 0x0003000a,
121
+ * IS_ROM: this area is read-only
65
+ RPI_FWREQ_GET_STC = 0x0003000b,
122
+ */
66
+ RPI_FWREQ_ALLOCATE_MEMORY = 0x0003000c,
123
+#define IS_MAIN 1
67
+ RPI_FWREQ_LOCK_MEMORY = 0x0003000d,
124
+#define IS_ROM 2
68
+ RPI_FWREQ_UNLOCK_MEMORY = 0x0003000e,
125
+
69
+ RPI_FWREQ_RELEASE_MEMORY = 0x0003000f,
126
+#define MPS3R_RAM_MAX 9
70
+ RPI_FWREQ_EXECUTE_CODE = 0x00030010,
127
+
71
+ RPI_FWREQ_EXECUTE_QPU = 0x00030011,
128
+typedef enum MPS3RFPGAType {
72
+ RPI_FWREQ_SET_ENABLE_QPU = 0x00030012,
129
+ FPGA_AN536,
73
+ RPI_FWREQ_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
130
+} MPS3RFPGAType;
74
+ RPI_FWREQ_GET_EDID_BLOCK = 0x00030020,
131
+
75
+ RPI_FWREQ_GET_CUSTOMER_OTP = 0x00030021,
132
+struct MPS3RMachineClass {
76
+ RPI_FWREQ_GET_EDID_BLOCK_DISPLAY = 0x00030023,
133
+ MachineClass parent;
77
+ RPI_FWREQ_GET_DOMAIN_STATE = 0x00030030,
134
+ MPS3RFPGAType fpga_type;
78
+ RPI_FWREQ_GET_THROTTLED = 0x00030046,
135
+ const RAMInfo *raminfo;
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,
103
+
104
+ /* Dispmanx TAGS */
105
+ RPI_FWREQ_FRAMEBUFFER_ALLOCATE = 0x00040001,
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,
146
+
147
+ RPI_FWREQ_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
148
+ RPI_FWREQ_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
149
+ RPI_FWREQ_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
150
+ RPI_FWREQ_FRAMEBUFFER_SET_LAYER = 0x0004800c,
151
+ RPI_FWREQ_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
152
+ RPI_FWREQ_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
153
+
154
+ RPI_FWREQ_VCHIQ_INIT = 0x00048010,
155
+
156
+ RPI_FWREQ_SET_PLANE = 0x00048015,
157
+ RPI_FWREQ_GET_DISPLAY_TIMING = 0x00040017,
158
+ RPI_FWREQ_SET_TIMING = 0x00048017,
159
+ RPI_FWREQ_GET_DISPLAY_CFG = 0x00040018,
160
+ RPI_FWREQ_SET_DISPLAY_POWER = 0x00048019,
161
+ RPI_FWREQ_GET_COMMAND_LINE = 0x00050001,
162
+ RPI_FWREQ_GET_DMA_CHANNELS = 0x00060001,
163
+};
136
+};
164
+
137
+
165
+enum rpi_firmware_clk_id {
138
+struct MPS3RMachineState {
166
+ RPI_FIRMWARE_EMMC_CLK_ID = 1,
139
+ MachineState parent;
167
+ RPI_FIRMWARE_UART_CLK_ID,
140
+ MemoryRegion ram[MPS3R_RAM_MAX];
168
+ RPI_FIRMWARE_ARM_CLK_ID,
169
+ RPI_FIRMWARE_CORE_CLK_ID,
170
+ RPI_FIRMWARE_V3D_CLK_ID,
171
+ RPI_FIRMWARE_H264_CLK_ID,
172
+ RPI_FIRMWARE_ISP_CLK_ID,
173
+ RPI_FIRMWARE_SDRAM_CLK_ID,
174
+ RPI_FIRMWARE_PIXEL_CLK_ID,
175
+ RPI_FIRMWARE_PWM_CLK_ID,
176
+ RPI_FIRMWARE_HEVC_CLK_ID,
177
+ RPI_FIRMWARE_EMMC2_CLK_ID,
178
+ RPI_FIRMWARE_M2MC_CLK_ID,
179
+ RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
180
+ RPI_FIRMWARE_VEC_CLK_ID,
181
+ RPI_FIRMWARE_NUM_CLK_ID,
182
+};
141
+};
183
+
142
+
184
+#endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */
143
+#define TYPE_MPS3R_MACHINE "mps3r"
144
+#define TYPE_MPS3R_AN536_MACHINE MACHINE_TYPE_NAME("mps3-an536")
145
+
146
+OBJECT_DECLARE_TYPE(MPS3RMachineState, MPS3RMachineClass, MPS3R_MACHINE)
147
+
148
+static const RAMInfo an536_raminfo[] = {
149
+ {
150
+ .name = "ATCM",
151
+ .base = 0x00000000,
152
+ .size = 0x00008000,
153
+ .mrindex = 0,
154
+ }, {
155
+ /* We model the QSPI flash as simple ROM for now */
156
+ .name = "QSPI",
157
+ .base = 0x08000000,
158
+ .size = 0x00800000,
159
+ .flags = IS_ROM,
160
+ .mrindex = 1,
161
+ }, {
162
+ .name = "BRAM",
163
+ .base = 0x10000000,
164
+ .size = 0x00080000,
165
+ .mrindex = 2,
166
+ }, {
167
+ .name = "DDR",
168
+ .base = 0x20000000,
169
+ .size = MPS3_DDR_SIZE,
170
+ .mrindex = -1,
171
+ }, {
172
+ .name = "ATCM0",
173
+ .base = 0xee000000,
174
+ .size = 0x00008000,
175
+ .mrindex = 3,
176
+ }, {
177
+ .name = "BTCM0",
178
+ .base = 0xee100000,
179
+ .size = 0x00008000,
180
+ .mrindex = 4,
181
+ }, {
182
+ .name = "CTCM0",
183
+ .base = 0xee200000,
184
+ .size = 0x00008000,
185
+ .mrindex = 5,
186
+ }, {
187
+ .name = "ATCM1",
188
+ .base = 0xee400000,
189
+ .size = 0x00008000,
190
+ .mrindex = 6,
191
+ }, {
192
+ .name = "BTCM1",
193
+ .base = 0xee500000,
194
+ .size = 0x00008000,
195
+ .mrindex = 7,
196
+ }, {
197
+ .name = "CTCM1",
198
+ .base = 0xee600000,
199
+ .size = 0x00008000,
200
+ .mrindex = 8,
201
+ }, {
202
+ .name = NULL,
203
+ }
204
+};
205
+
206
+static MemoryRegion *mr_for_raminfo(MPS3RMachineState *mms,
207
+ const RAMInfo *raminfo)
208
+{
209
+ /* Return an initialized MemoryRegion for the RAMInfo. */
210
+ MemoryRegion *ram;
211
+
212
+ if (raminfo->mrindex < 0) {
213
+ /* Means this RAMInfo is for QEMU's "system memory" */
214
+ MachineState *machine = MACHINE(mms);
215
+ assert(!(raminfo->flags & IS_ROM));
216
+ return machine->ram;
217
+ }
218
+
219
+ assert(raminfo->mrindex < MPS3R_RAM_MAX);
220
+ ram = &mms->ram[raminfo->mrindex];
221
+
222
+ memory_region_init_ram(ram, NULL, raminfo->name,
223
+ raminfo->size, &error_fatal);
224
+ if (raminfo->flags & IS_ROM) {
225
+ memory_region_set_readonly(ram, true);
226
+ }
227
+ return ram;
228
+}
229
+
230
+static void mps3r_common_init(MachineState *machine)
231
+{
232
+ MPS3RMachineState *mms = MPS3R_MACHINE(machine);
233
+ MPS3RMachineClass *mmc = MPS3R_MACHINE_GET_CLASS(mms);
234
+ MemoryRegion *sysmem = get_system_memory();
235
+
236
+ for (const RAMInfo *ri = mmc->raminfo; ri->name; ri++) {
237
+ MemoryRegion *mr = mr_for_raminfo(mms, ri);
238
+ memory_region_add_subregion(sysmem, ri->base, mr);
239
+ }
240
+}
241
+
242
+static void mps3r_set_default_ram_info(MPS3RMachineClass *mmc)
243
+{
244
+ /*
245
+ * Set mc->default_ram_size and default_ram_id from the
246
+ * information in mmc->raminfo.
247
+ */
248
+ MachineClass *mc = MACHINE_CLASS(mmc);
249
+ const RAMInfo *p;
250
+
251
+ for (p = mmc->raminfo; p->name; p++) {
252
+ if (p->mrindex < 0) {
253
+ /* Found the entry for "system memory" */
254
+ mc->default_ram_size = p->size;
255
+ mc->default_ram_id = p->name;
256
+ return;
257
+ }
258
+ }
259
+ g_assert_not_reached();
260
+}
261
+
262
+static void mps3r_class_init(ObjectClass *oc, void *data)
263
+{
264
+ MachineClass *mc = MACHINE_CLASS(oc);
265
+
266
+ mc->init = mps3r_common_init;
267
+}
268
+
269
+static void mps3r_an536_class_init(ObjectClass *oc, void *data)
270
+{
271
+ MachineClass *mc = MACHINE_CLASS(oc);
272
+ MPS3RMachineClass *mmc = MPS3R_MACHINE_CLASS(oc);
273
+ static const char * const valid_cpu_types[] = {
274
+ ARM_CPU_TYPE_NAME("cortex-r52"),
275
+ NULL
276
+ };
277
+
278
+ mc->desc = "ARM MPS3 with AN536 FPGA image for Cortex-R52";
279
+ mc->default_cpus = 2;
280
+ mc->min_cpus = mc->default_cpus;
281
+ mc->max_cpus = mc->default_cpus;
282
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-r52");
283
+ mc->valid_cpu_types = valid_cpu_types;
284
+ mmc->raminfo = an536_raminfo;
285
+ mps3r_set_default_ram_info(mmc);
286
+}
287
+
288
+static const TypeInfo mps3r_machine_types[] = {
289
+ {
290
+ .name = TYPE_MPS3R_MACHINE,
291
+ .parent = TYPE_MACHINE,
292
+ .abstract = true,
293
+ .instance_size = sizeof(MPS3RMachineState),
294
+ .class_size = sizeof(MPS3RMachineClass),
295
+ .class_init = mps3r_class_init,
296
+ }, {
297
+ .name = TYPE_MPS3R_AN536_MACHINE,
298
+ .parent = TYPE_MPS3R_MACHINE,
299
+ .class_init = mps3r_an536_class_init,
300
+ },
301
+};
302
+
303
+DEFINE_TYPES(mps3r_machine_types);
304
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
305
index XXXXXXX..XXXXXXX 100644
306
--- a/hw/arm/Kconfig
307
+++ b/hw/arm/Kconfig
308
@@ -XXX,XX +XXX,XX @@ config MAINSTONE
309
select PFLASH_CFI01
310
select SMC91C111
311
312
+config MPS3R
313
+ bool
314
+ default y
315
+ depends on TCG && ARM
316
+
317
config MUSCA
318
bool
319
default y
320
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
321
index XXXXXXX..XXXXXXX 100644
322
--- a/hw/arm/meson.build
323
+++ b/hw/arm/meson.build
324
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_HIGHBANK', if_true: files('highbank.c'))
325
arm_ss.add(when: 'CONFIG_INTEGRATOR', if_true: files('integratorcp.c'))
326
arm_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mainstone.c'))
327
arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
328
+arm_ss.add(when: 'CONFIG_MPS3R', if_true: files('mps3r.c'))
329
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
330
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
331
arm_ss.add(when: 'CONFIG_OLIMEX_STM32_H405', if_true: files('olimex-stm32-h405.c'))
185
--
332
--
186
2.34.1
333
2.34.1
187
334
188
335
diff view generated by jsdifflib
1
Convert the MSR (immediate) insn to decodetree. Our implementation
1
Create the CPUs, the GIC, and the per-CPU RAM block for
2
has basically no commonality between the different destinations,
2
the mps3-an536 board.
3
so we decode the destination register in a64.decode.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20240206132931.38376-10-peter.maydell@linaro.org
7
Message-id: 20230602155223.2040685-6-peter.maydell@linaro.org
8
---
6
---
9
target/arm/tcg/a64.decode | 13 ++
7
hw/arm/mps3r.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++-
10
target/arm/tcg/translate-a64.c | 251 ++++++++++++++++-----------------
8
1 file changed, 177 insertions(+), 3 deletions(-)
11
2 files changed, 136 insertions(+), 128 deletions(-)
12
9
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
10
diff --git a/hw/arm/mps3r.c b/hw/arm/mps3r.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
12
--- a/hw/arm/mps3r.c
16
+++ b/target/arm/tcg/a64.decode
13
+++ b/hw/arm/mps3r.c
17
@@ -XXX,XX +XXX,XX @@ SB 1101 0101 0000 0011 0011 0000 111 11111
14
@@ -XXX,XX +XXX,XX @@
18
CFINV 1101 0101 0000 0 000 0100 0000 000 11111
15
#include "qemu/osdep.h"
19
XAFLAG 1101 0101 0000 0 000 0100 0000 001 11111
16
#include "qemu/units.h"
20
AXFLAG 1101 0101 0000 0 000 0100 0000 010 11111
17
#include "qapi/error.h"
21
+
18
+#include "qapi/qmp/qlist.h"
22
+# These are architecturally all "MSR (immediate)"; we decode the destination
19
#include "exec/address-spaces.h"
23
+# register too because there is no commonality in our implementation.
20
#include "cpu.h"
24
+@msr_i .... .... .... . ... .... imm:4 ... .....
21
#include "hw/boards.h"
25
+MSR_i_UAO 1101 0101 0000 0 000 0100 .... 011 11111 @msr_i
22
+#include "hw/qdev-properties.h"
26
+MSR_i_PAN 1101 0101 0000 0 000 0100 .... 100 11111 @msr_i
23
#include "hw/arm/boot.h"
27
+MSR_i_SPSEL 1101 0101 0000 0 000 0100 .... 101 11111 @msr_i
24
+#include "hw/arm/bsa.h"
28
+MSR_i_SBSS 1101 0101 0000 0 011 0100 .... 001 11111 @msr_i
25
+#include "hw/intc/arm_gicv3.h"
29
+MSR_i_DIT 1101 0101 0000 0 011 0100 .... 010 11111 @msr_i
26
30
+MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
27
/* Define the layout of RAM and ROM in a board */
31
+MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
28
typedef struct RAMInfo {
32
+MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
29
@@ -XXX,XX +XXX,XX @@ typedef struct RAMInfo {
33
+MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
30
#define IS_ROM 2
34
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
31
35
index XXXXXXX..XXXXXXX 100644
32
#define MPS3R_RAM_MAX 9
36
--- a/target/arm/tcg/translate-a64.c
33
+#define MPS3R_CPU_MAX 2
37
+++ b/target/arm/tcg/translate-a64.c
34
+
38
@@ -XXX,XX +XXX,XX @@ static bool trans_AXFLAG(DisasContext *s, arg_AXFLAG *a)
35
+#define PERIPHBASE 0xf0000000
39
return true;
36
+#define NUM_SPIS 96
37
38
typedef enum MPS3RFPGAType {
39
FPGA_AN536,
40
@@ -XXX,XX +XXX,XX @@ struct MPS3RMachineClass {
41
MachineClass parent;
42
MPS3RFPGAType fpga_type;
43
const RAMInfo *raminfo;
44
+ hwaddr loader_start;
45
};
46
47
struct MPS3RMachineState {
48
MachineState parent;
49
+ struct arm_boot_info bootinfo;
50
MemoryRegion ram[MPS3R_RAM_MAX];
51
+ Object *cpu[MPS3R_CPU_MAX];
52
+ MemoryRegion cpu_sysmem[MPS3R_CPU_MAX];
53
+ MemoryRegion sysmem_alias[MPS3R_CPU_MAX];
54
+ MemoryRegion cpu_ram[MPS3R_CPU_MAX];
55
+ GICv3State gic;
56
};
57
58
#define TYPE_MPS3R_MACHINE "mps3r"
59
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS3RMachineState *mms,
60
return ram;
40
}
61
}
41
62
42
-/* MSR (immediate) - move immediate to processor state field */
63
+/*
43
-static void handle_msr_i(DisasContext *s, uint32_t insn,
64
+ * There is no defined secondary boot protocol for Linux for the AN536,
44
- unsigned int op1, unsigned int op2, unsigned int crm)
65
+ * because real hardware has a restriction that atomic operations between
45
+static bool trans_MSR_i_UAO(DisasContext *s, arg_i *a)
66
+ * the two CPUs do not function correctly, and so true SMP is not
46
{
67
+ * possible. Therefore for cases where the user is directly booting
47
- int op = op1 << 3 | op2;
68
+ * a kernel, we treat the system as essentially uniprocessor, and
48
-
69
+ * put the secondary CPU into power-off state (as if the user on the
49
- /* End the TB by default, chaining is ok. */
70
+ * real hardware had configured the secondary to be halted via the
50
- s->base.is_jmp = DISAS_TOO_MANY;
71
+ * SCC config registers).
51
-
72
+ *
52
- switch (op) {
73
+ * Note that the default secondary boot code would not work here anyway
53
- case 0x03: /* UAO */
74
+ * as it assumes a GICv2, and we have a GICv3.
54
- if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
75
+ */
55
- goto do_unallocated;
76
+static void mps3r_write_secondary_boot(ARMCPU *cpu,
56
- }
77
+ const struct arm_boot_info *info)
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
+{
78
+{
175
+ if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
79
+ /*
176
+ return false;
80
+ * Power the secondary CPU off. This means we don't need to write any
177
+ }
81
+ * boot code into guest memory. Note that the 'cpu' argument to this
178
+ if (a->imm & 1) {
82
+ * function is the primary CPU we passed to arm_load_kernel(), not
179
+ set_pstate_bits(PSTATE_PAN);
83
+ * the secondary. Loop around all the other CPUs, as the boot.c
180
+ } else {
84
+ * code does for the "disable secondaries if PSCI is enabled" case.
181
+ clear_pstate_bits(PSTATE_PAN);
85
+ */
182
+ }
86
+ for (CPUState *cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
183
+ gen_rebuild_hflags(s);
87
+ if (cs != first_cpu) {
184
+ s->base.is_jmp = DISAS_TOO_MANY;
88
+ object_property_set_bool(OBJECT(cs), "start-powered-off", true,
185
+ return true;
89
+ &error_abort);
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
+ }
90
+ }
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
+ }
91
+ }
248
+}
92
+}
249
+
93
+
250
+static bool trans_MSR_i_DAIFSET(DisasContext *s, arg_i *a)
94
+static void mps3r_secondary_cpu_reset(ARMCPU *cpu,
95
+ const struct arm_boot_info *info)
251
+{
96
+{
252
+ gen_helper_msr_i_daifset(cpu_env, tcg_constant_i32(a->imm));
97
+ /* We don't need to do anything here because the CPU will be off */
253
+ s->base.is_jmp = DISAS_TOO_MANY;
254
+ return true;
255
+}
98
+}
256
+
99
+
257
+static bool trans_MSR_i_DAIFCLEAR(DisasContext *s, arg_i *a)
100
+static void create_gic(MPS3RMachineState *mms, MemoryRegion *sysmem)
258
+{
101
+{
259
+ gen_helper_msr_i_daifclear(cpu_env, tcg_constant_i32(a->imm));
102
+ MachineState *machine = MACHINE(mms);
260
+ /* Exit the cpu loop to re-evaluate pending IRQs. */
103
+ DeviceState *gicdev;
261
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
104
+ QList *redist_region_count;
262
+ return true;
105
+
106
+ object_initialize_child(OBJECT(mms), "gic", &mms->gic, TYPE_ARM_GICV3);
107
+ gicdev = DEVICE(&mms->gic);
108
+ qdev_prop_set_uint32(gicdev, "num-cpu", machine->smp.cpus);
109
+ qdev_prop_set_uint32(gicdev, "num-irq", NUM_SPIS + GIC_INTERNAL);
110
+ redist_region_count = qlist_new();
111
+ qlist_append_int(redist_region_count, machine->smp.cpus);
112
+ qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
113
+ object_property_set_link(OBJECT(&mms->gic), "sysmem",
114
+ OBJECT(sysmem), &error_fatal);
115
+ sysbus_realize(SYS_BUS_DEVICE(&mms->gic), &error_fatal);
116
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->gic), 0, PERIPHBASE);
117
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->gic), 1, PERIPHBASE + 0x100000);
118
+ /*
119
+ * Wire the outputs from each CPU's generic timer and the GICv3
120
+ * maintenance interrupt signal to the appropriate GIC PPI inputs,
121
+ * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
122
+ */
123
+ for (int i = 0; i < machine->smp.cpus; i++) {
124
+ DeviceState *cpudev = DEVICE(mms->cpu[i]);
125
+ SysBusDevice *gicsbd = SYS_BUS_DEVICE(&mms->gic);
126
+ int intidbase = NUM_SPIS + i * GIC_INTERNAL;
127
+ int irq;
128
+ /*
129
+ * Mapping from the output timer irq lines from the CPU to the
130
+ * GIC PPI inputs used for this board. This isn't a BSA board,
131
+ * but it uses the standard convention for the PPI numbers.
132
+ */
133
+ const int timer_irq[] = {
134
+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
135
+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
136
+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
137
+ };
138
+
139
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
140
+ qdev_connect_gpio_out(cpudev, irq,
141
+ qdev_get_gpio_in(gicdev,
142
+ intidbase + timer_irq[irq]));
143
+ }
144
+
145
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
146
+ qdev_get_gpio_in(gicdev,
147
+ intidbase + ARCH_GIC_MAINT_IRQ));
148
+
149
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
150
+ qdev_get_gpio_in(gicdev,
151
+ intidbase + VIRTUAL_PMU_IRQ));
152
+
153
+ sysbus_connect_irq(gicsbd, i,
154
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
155
+ sysbus_connect_irq(gicsbd, i + machine->smp.cpus,
156
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
157
+ sysbus_connect_irq(gicsbd, i + 2 * machine->smp.cpus,
158
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
159
+ sysbus_connect_irq(gicsbd, i + 3 * machine->smp.cpus,
160
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
161
+ }
263
+}
162
+}
264
+
163
+
265
+static bool trans_MSR_i_SVCR(DisasContext *s, arg_MSR_i_SVCR *a)
164
static void mps3r_common_init(MachineState *machine)
266
+{
165
{
267
+ if (!dc_isar_feature(aa64_sme, s) || a->mask == 0) {
166
MPS3RMachineState *mms = MPS3R_MACHINE(machine);
268
+ return false;
167
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
168
MemoryRegion *mr = mr_for_raminfo(mms, ri);
169
memory_region_add_subregion(sysmem, ri->base, mr);
170
}
171
+
172
+ assert(machine->smp.cpus <= MPS3R_CPU_MAX);
173
+ for (int i = 0; i < machine->smp.cpus; i++) {
174
+ g_autofree char *sysmem_name = g_strdup_printf("cpu-%d-memory", i);
175
+ g_autofree char *ramname = g_strdup_printf("cpu-%d-memory", i);
176
+ g_autofree char *alias_name = g_strdup_printf("sysmem-alias-%d", i);
177
+
178
+ /*
179
+ * Each CPU has some private RAM/peripherals, so create the container
180
+ * which will house those, with the whole-machine system memory being
181
+ * used where there's no CPU-specific device. Note that we need the
182
+ * sysmem_alias aliases because we can't put one MR (the original
183
+ * 'sysmem') into more than one other MR.
184
+ */
185
+ memory_region_init(&mms->cpu_sysmem[i], OBJECT(machine),
186
+ sysmem_name, UINT64_MAX);
187
+ memory_region_init_alias(&mms->sysmem_alias[i], OBJECT(machine),
188
+ alias_name, sysmem, 0, UINT64_MAX);
189
+ memory_region_add_subregion_overlap(&mms->cpu_sysmem[i], 0,
190
+ &mms->sysmem_alias[i], -1);
191
+
192
+ mms->cpu[i] = object_new(machine->cpu_type);
193
+ object_property_set_link(mms->cpu[i], "memory",
194
+ OBJECT(&mms->cpu_sysmem[i]), &error_abort);
195
+ object_property_set_int(mms->cpu[i], "reset-cbar",
196
+ PERIPHBASE, &error_abort);
197
+ qdev_realize(DEVICE(mms->cpu[i]), NULL, &error_fatal);
198
+ object_unref(mms->cpu[i]);
199
+
200
+ /* Per-CPU RAM */
201
+ memory_region_init_ram(&mms->cpu_ram[i], NULL, ramname,
202
+ 0x1000, &error_fatal);
203
+ memory_region_add_subregion(&mms->cpu_sysmem[i], 0xe7c01000,
204
+ &mms->cpu_ram[i]);
269
+ }
205
+ }
270
+ if (sme_access_check(s)) {
206
+
271
+ int old = s->pstate_sm | (s->pstate_za << 1);
207
+ create_gic(mms, sysmem);
272
+ int new = a->imm * 3;
208
+
273
+
209
+ mms->bootinfo.ram_size = machine->ram_size;
274
+ if ((old ^ new) & a->mask) {
210
+ mms->bootinfo.board_id = -1;
275
+ /* At least one bit changes. */
211
+ mms->bootinfo.loader_start = mmc->loader_start;
276
+ gen_helper_set_svcr(cpu_env, tcg_constant_i32(new),
212
+ mms->bootinfo.write_secondary_boot = mps3r_write_secondary_boot;
277
+ tcg_constant_i32(a->mask));
213
+ mms->bootinfo.secondary_cpu_reset_hook = mps3r_secondary_cpu_reset;
278
+ s->base.is_jmp = DISAS_TOO_MANY;
214
+ arm_load_kernel(ARM_CPU(mms->cpu[0]), machine, &mms->bootinfo);
279
+ }
280
+ }
281
+ return true;
282
}
215
}
283
216
284
static void gen_get_nzcv(TCGv_i64 tcg_rt)
217
static void mps3r_set_default_ram_info(MPS3RMachineClass *mmc)
285
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
218
@@ -XXX,XX +XXX,XX @@ static void mps3r_set_default_ram_info(MPS3RMachineClass *mmc)
286
rt = extract32(insn, 0, 5);
219
/* Found the entry for "system memory" */
287
220
mc->default_ram_size = p->size;
288
if (op0 == 0) {
221
mc->default_ram_id = p->name;
289
- if (l || rt != 31) {
222
+ mmc->loader_start = p->base;
290
- unallocated_encoding(s);
223
return;
291
- return;
224
}
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
}
225
}
304
handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
226
@@ -XXX,XX +XXX,XX @@ static void mps3r_an536_class_init(ObjectClass *oc, void *data)
227
};
228
229
mc->desc = "ARM MPS3 with AN536 FPGA image for Cortex-R52";
230
- mc->default_cpus = 2;
231
- mc->min_cpus = mc->default_cpus;
232
- mc->max_cpus = mc->default_cpus;
233
+ /*
234
+ * In the real FPGA image there are always two cores, but the standard
235
+ * initial setting for the SCC SYSCON 0x000 register is 0x21, meaning
236
+ * that the second core is held in reset and halted. Many images built for
237
+ * the board do not expect the second core to run at startup (especially
238
+ * since on the real FPGA image it is not possible to use LDREX/STREX
239
+ * in RAM between the two cores, so a true SMP setup isn't supported).
240
+ *
241
+ * As QEMU's equivalent of this, we support both -smp 1 and -smp 2,
242
+ * with the default being -smp 1. This seems a more intuitive UI for
243
+ * QEMU users than, for instance, having a machine property to allow
244
+ * the user to set the initial value of the SYSCON 0x000 register.
245
+ */
246
+ mc->default_cpus = 1;
247
+ mc->min_cpus = 1;
248
+ mc->max_cpus = 2;
249
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-r52");
250
mc->valid_cpu_types = valid_cpu_types;
251
mmc->raminfo = an536_raminfo;
305
--
252
--
306
2.34.1
253
2.34.1
diff view generated by jsdifflib
1
Convert the instructions in the load/store register (pointer
1
This board has a lot of UARTs: there is one UART per CPU in the
2
authentication) group ot decodetree: LDRAA, LDRAB.
2
per-CPU peripheral part of the address map, whose interrupts are
3
connected as per-CPU interrupt lines. Then there are 4 UARTs in the
4
normal part of the peripheral space, whose interrupts are shared
5
peripheral interrupts.
6
7
Connect and wire them all up; this involves some OR gates where
8
multiple overflow interrupts are wired into one GIC input.
3
9
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20240206132931.38376-11-peter.maydell@linaro.org
7
Message-id: 20230602155223.2040685-17-peter.maydell@linaro.org
8
---
13
---
9
target/arm/tcg/a64.decode | 7 +++
14
hw/arm/mps3r.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++
10
target/arm/tcg/translate-a64.c | 83 +++++++---------------------------
15
1 file changed, 94 insertions(+)
11
2 files changed, 23 insertions(+), 67 deletions(-)
12
16
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
17
diff --git a/hw/arm/mps3r.c b/hw/arm/mps3r.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
19
--- a/hw/arm/mps3r.c
16
+++ b/target/arm/tcg/a64.decode
20
+++ b/hw/arm/mps3r.c
17
@@ -XXX,XX +XXX,XX @@ LDUMIN .. 111 0 00 . . 1 ..... 0111 00 ..... ..... @atomic
21
@@ -XXX,XX +XXX,XX @@
18
SWP .. 111 0 00 . . 1 ..... 1000 00 ..... ..... @atomic
22
#include "qapi/qmp/qlist.h"
19
23
#include "exec/address-spaces.h"
20
LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
24
#include "cpu.h"
25
+#include "sysemu/sysemu.h"
26
#include "hw/boards.h"
27
+#include "hw/or-irq.h"
28
#include "hw/qdev-properties.h"
29
#include "hw/arm/boot.h"
30
#include "hw/arm/bsa.h"
31
+#include "hw/char/cmsdk-apb-uart.h"
32
#include "hw/intc/arm_gicv3.h"
33
34
/* Define the layout of RAM and ROM in a board */
35
@@ -XXX,XX +XXX,XX @@ typedef struct RAMInfo {
36
37
#define MPS3R_RAM_MAX 9
38
#define MPS3R_CPU_MAX 2
39
+#define MPS3R_UART_MAX 4 /* shared UART count */
40
41
#define PERIPHBASE 0xf0000000
42
#define NUM_SPIS 96
43
@@ -XXX,XX +XXX,XX @@ struct MPS3RMachineState {
44
MemoryRegion sysmem_alias[MPS3R_CPU_MAX];
45
MemoryRegion cpu_ram[MPS3R_CPU_MAX];
46
GICv3State gic;
47
+ /* per-CPU UARTs followed by the shared UARTs */
48
+ CMSDKAPBUART uart[MPS3R_CPU_MAX + MPS3R_UART_MAX];
49
+ OrIRQState cpu_uart_oflow[MPS3R_CPU_MAX];
50
+ OrIRQState uart_oflow;
51
};
52
53
#define TYPE_MPS3R_MACHINE "mps3r"
54
@@ -XXX,XX +XXX,XX @@ struct MPS3RMachineState {
55
56
OBJECT_DECLARE_TYPE(MPS3RMachineState, MPS3RMachineClass, MPS3R_MACHINE)
57
58
+/*
59
+ * Main clock frequency CLK in Hz (50MHz). In the image there are also
60
+ * ACLK, MCLK, GPUCLK and PERIPHCLK at the same frequency; for our
61
+ * model we just roll them all into one.
62
+ */
63
+#define CLK_FRQ 50000000
21
+
64
+
22
+# Load/store register (pointer authentication)
65
static const RAMInfo an536_raminfo[] = {
23
+
66
{
24
+# LDRA immediate is 10 bits signed and scaled, but the bits aren't all contiguous
67
.name = "ATCM",
25
+%ldra_imm 22:s1 12:9 !function=times_2
68
@@ -XXX,XX +XXX,XX @@ static void create_gic(MPS3RMachineState *mms, MemoryRegion *sysmem)
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,
84
}
85
}
86
87
- /* Form the 10-bit signed, scaled offset. */
88
- offset = (extract32(insn, 22, 1) << 9) | extract32(insn, 12, 9);
89
- offset = sextract32(offset << size, 0, 10 + size);
90
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
91
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, a->imm);
92
93
- memop = finalize_memop(s, size);
94
+ memop = finalize_memop(s, MO_64);
95
96
/* Note that "clean" and "dirty" here refer to TBI not PAC. */
97
clean_addr = gen_mte_check1(s, dirty_addr, false,
98
- is_wback || rn != 31, memop);
99
+ a->w || a->rn != 31, memop);
100
101
- tcg_rt = cpu_reg(s, rt);
102
+ tcg_rt = cpu_reg(s, a->rt);
103
do_gpr_ld(s, tcg_rt, clean_addr, memop,
104
- /* extend */ false, /* iss_valid */ !is_wback,
105
- /* iss_srt */ rt, /* iss_sf */ true, /* iss_ar */ false);
106
+ /* extend */ false, /* iss_valid */ !a->w,
107
+ /* iss_srt */ a->rt, /* iss_sf */ true, /* iss_ar */ false);
108
109
- if (is_wback) {
110
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
111
+ if (a->w) {
112
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
113
}
114
+ return true;
115
}
116
117
/*
118
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
119
}
69
}
120
}
70
}
121
71
122
-/* Load/store register (all forms) */
72
+/*
123
-static void disas_ldst_reg(DisasContext *s, uint32_t insn)
73
+ * Create UART uartno, and map it into the MemoryRegion mem at address baseaddr.
124
-{
74
+ * The qemu_irq arguments are where we connect the various IRQs from the UART.
125
- int rt = extract32(insn, 0, 5);
75
+ */
126
- bool is_vector = extract32(insn, 26, 1);
76
+static void create_uart(MPS3RMachineState *mms, int uartno, MemoryRegion *mem,
127
- int size = extract32(insn, 30, 2);
77
+ hwaddr baseaddr, qemu_irq txirq, qemu_irq rxirq,
128
-
78
+ qemu_irq txoverirq, qemu_irq rxoverirq,
129
- switch (extract32(insn, 24, 2)) {
79
+ qemu_irq combirq)
130
- case 0:
80
+{
131
- if (extract32(insn, 21, 1) == 0) {
81
+ g_autofree char *s = g_strdup_printf("uart%d", uartno);
132
- break;
82
+ SysBusDevice *sbd;
133
- }
83
+
134
- switch (extract32(insn, 10, 2)) {
84
+ assert(uartno < ARRAY_SIZE(mms->uart));
135
- case 0:
85
+ object_initialize_child(OBJECT(mms), s, &mms->uart[uartno],
136
- case 2:
86
+ TYPE_CMSDK_APB_UART);
137
- break;
87
+ qdev_prop_set_uint32(DEVICE(&mms->uart[uartno]), "pclk-frq", CLK_FRQ);
138
- default:
88
+ qdev_prop_set_chr(DEVICE(&mms->uart[uartno]), "chardev", serial_hd(uartno));
139
- disas_ldst_pac(s, insn, size, rt, is_vector);
89
+ sbd = SYS_BUS_DEVICE(&mms->uart[uartno]);
140
- return;
90
+ sysbus_realize(sbd, &error_fatal);
141
- }
91
+ memory_region_add_subregion(mem, baseaddr,
142
- break;
92
+ sysbus_mmio_get_region(sbd, 0));
143
- }
93
+ sysbus_connect_irq(sbd, 0, txirq);
144
- unallocated_encoding(s);
94
+ sysbus_connect_irq(sbd, 1, rxirq);
145
-}
95
+ sysbus_connect_irq(sbd, 2, txoverirq);
146
-
96
+ sysbus_connect_irq(sbd, 3, rxoverirq);
147
/* AdvSIMD load/store multiple structures
97
+ sysbus_connect_irq(sbd, 4, combirq);
148
*
98
+}
149
* 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
99
+
150
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
100
static void mps3r_common_init(MachineState *machine)
151
static void disas_ldst(DisasContext *s, uint32_t insn)
152
{
101
{
153
switch (extract32(insn, 24, 6)) {
102
MPS3RMachineState *mms = MPS3R_MACHINE(machine);
154
- case 0x38: case 0x39:
103
MPS3RMachineClass *mmc = MPS3R_MACHINE_GET_CLASS(mms);
155
- case 0x3c: case 0x3d: /* Load/store register (all forms) */
104
MemoryRegion *sysmem = get_system_memory();
156
- disas_ldst_reg(s, insn);
105
+ DeviceState *gicdev;
157
- break;
106
158
case 0x0c: /* AdvSIMD load/store multiple structures */
107
for (const RAMInfo *ri = mmc->raminfo; ri->name; ri++) {
159
disas_ldst_multiple_struct(s, insn);
108
MemoryRegion *mr = mr_for_raminfo(mms, ri);
160
break;
109
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
110
}
111
112
create_gic(mms, sysmem);
113
+ gicdev = DEVICE(&mms->gic);
114
+
115
+ /*
116
+ * UARTs 0 and 1 are per-CPU; their interrupts are wired to
117
+ * the relevant CPU's PPI 0..3, aka INTID 16..19
118
+ */
119
+ for (int i = 0; i < machine->smp.cpus; i++) {
120
+ int intidbase = NUM_SPIS + i * GIC_INTERNAL;
121
+ g_autofree char *s = g_strdup_printf("cpu-uart-oflow-orgate%d", i);
122
+ DeviceState *orgate;
123
+
124
+ /* The two overflow IRQs from the UART are ORed together into PPI 3 */
125
+ object_initialize_child(OBJECT(mms), s, &mms->cpu_uart_oflow[i],
126
+ TYPE_OR_IRQ);
127
+ orgate = DEVICE(&mms->cpu_uart_oflow[i]);
128
+ qdev_prop_set_uint32(orgate, "num-lines", 2);
129
+ qdev_realize(orgate, NULL, &error_fatal);
130
+ qdev_connect_gpio_out(orgate, 0,
131
+ qdev_get_gpio_in(gicdev, intidbase + 19));
132
+
133
+ create_uart(mms, i, &mms->cpu_sysmem[i], 0xe7c00000,
134
+ qdev_get_gpio_in(gicdev, intidbase + 17), /* tx */
135
+ qdev_get_gpio_in(gicdev, intidbase + 16), /* rx */
136
+ qdev_get_gpio_in(orgate, 0), /* txover */
137
+ qdev_get_gpio_in(orgate, 1), /* rxover */
138
+ qdev_get_gpio_in(gicdev, intidbase + 18) /* combined */);
139
+ }
140
+ /*
141
+ * UARTs 2 to 5 are whole-system; all overflow IRQs are ORed
142
+ * together into IRQ 17
143
+ */
144
+ object_initialize_child(OBJECT(mms), "uart-oflow-orgate",
145
+ &mms->uart_oflow, TYPE_OR_IRQ);
146
+ qdev_prop_set_uint32(DEVICE(&mms->uart_oflow), "num-lines",
147
+ MPS3R_UART_MAX * 2);
148
+ qdev_realize(DEVICE(&mms->uart_oflow), NULL, &error_fatal);
149
+ qdev_connect_gpio_out(DEVICE(&mms->uart_oflow), 0,
150
+ qdev_get_gpio_in(gicdev, 17));
151
+
152
+ for (int i = 0; i < MPS3R_UART_MAX; i++) {
153
+ hwaddr baseaddr = 0xe0205000 + i * 0x1000;
154
+ int rxirq = 5 + i * 2, txirq = 6 + i * 2, combirq = 13 + i;
155
+
156
+ create_uart(mms, i + MPS3R_CPU_MAX, sysmem, baseaddr,
157
+ qdev_get_gpio_in(gicdev, txirq),
158
+ qdev_get_gpio_in(gicdev, rxirq),
159
+ qdev_get_gpio_in(DEVICE(&mms->uart_oflow), i * 2),
160
+ qdev_get_gpio_in(DEVICE(&mms->uart_oflow), i * 2 + 1),
161
+ qdev_get_gpio_in(gicdev, combirq));
162
+ }
163
164
mms->bootinfo.ram_size = machine->ram_size;
165
mms->bootinfo.board_id = -1;
161
--
166
--
162
2.34.1
167
2.34.1
163
168
164
169
diff view generated by jsdifflib
1
Convert the load/store register pair insns (LDP, STP,
1
Add the GPIO, watchdog, dual-timer and I2C devices to the mps3-an536
2
LDNP, STNP, LDPSW, STGP) to decodetree.
2
board. These are all simple devices that just need to be created and
3
wired up.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20230602155223.2040685-12-peter.maydell@linaro.org
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240206132931.38376-12-peter.maydell@linaro.org
7
---
8
---
8
target/arm/tcg/a64.decode | 61 +++++
9
hw/arm/mps3r.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++
9
target/arm/tcg/translate-a64.c | 422 ++++++++++++++++-----------------
10
1 file changed, 59 insertions(+)
10
2 files changed, 268 insertions(+), 215 deletions(-)
11
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
12
diff --git a/hw/arm/mps3r.c b/hw/arm/mps3r.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
14
--- a/hw/arm/mps3r.c
15
+++ b/target/arm/tcg/a64.decode
15
+++ b/hw/arm/mps3r.c
16
@@ -XXX,XX +XXX,XX @@ LD_lit_v 10 011 1 00 ................... ..... @ldlit sz=4 sign=0
16
@@ -XXX,XX +XXX,XX @@
17
17
#include "sysemu/sysemu.h"
18
# PRFM
18
#include "hw/boards.h"
19
NOP 11 011 0 00 ------------------- -----
19
#include "hw/or-irq.h"
20
+#include "hw/qdev-clock.h"
21
#include "hw/qdev-properties.h"
22
#include "hw/arm/boot.h"
23
#include "hw/arm/bsa.h"
24
#include "hw/char/cmsdk-apb-uart.h"
25
+#include "hw/i2c/arm_sbcon_i2c.h"
26
#include "hw/intc/arm_gicv3.h"
27
+#include "hw/misc/unimp.h"
28
+#include "hw/timer/cmsdk-apb-dualtimer.h"
29
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
30
31
/* Define the layout of RAM and ROM in a board */
32
typedef struct RAMInfo {
33
@@ -XXX,XX +XXX,XX @@ struct MPS3RMachineState {
34
CMSDKAPBUART uart[MPS3R_CPU_MAX + MPS3R_UART_MAX];
35
OrIRQState cpu_uart_oflow[MPS3R_CPU_MAX];
36
OrIRQState uart_oflow;
37
+ CMSDKAPBWatchdog watchdog;
38
+ CMSDKAPBDualTimer dualtimer;
39
+ ArmSbconI2CState i2c[5];
40
+ Clock *clk;
41
};
42
43
#define TYPE_MPS3R_MACHINE "mps3r"
44
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
45
MemoryRegion *sysmem = get_system_memory();
46
DeviceState *gicdev;
47
48
+ mms->clk = clock_new(OBJECT(machine), "CLK");
49
+ clock_set_hz(mms->clk, CLK_FRQ);
20
+
50
+
21
+&ldstpair rt2 rt rn imm sz sign w p
51
for (const RAMInfo *ri = mmc->raminfo; ri->name; ri++) {
22
+@ldstpair .. ... . ... . imm:s7 rt2:5 rn:5 rt:5 &ldstpair
52
MemoryRegion *mr = mr_for_raminfo(mms, ri);
23
+
53
memory_region_add_subregion(sysmem, ri->base, mr);
24
+# STNP, LDNP: Signed offset, non-temporal hint. We don't emulate caches
54
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
25
+# so we ignore hints about data access patterns, and handle these like
55
qdev_get_gpio_in(gicdev, combirq));
26
+# plain signed offset.
27
+STP 00 101 0 000 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
28
+LDP 00 101 0 000 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
29
+STP 10 101 0 000 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
30
+LDP 10 101 0 000 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
31
+STP_v 00 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
32
+LDP_v 00 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
33
+STP_v 01 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
34
+LDP_v 01 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
35
+STP_v 10 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
36
+LDP_v 10 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
37
+
38
+# STP and LDP: post-indexed
39
+STP 00 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
40
+LDP 00 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
41
+LDP 01 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=1 w=1
42
+STP 10 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
43
+LDP 10 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
44
+STP_v 00 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
45
+LDP_v 00 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
46
+STP_v 01 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
47
+LDP_v 01 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
48
+STP_v 10 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=1 w=1
49
+LDP_v 10 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=1 w=1
50
+
51
+# STP and LDP: offset
52
+STP 00 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
53
+LDP 00 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
54
+LDP 01 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=0 w=0
55
+STP 10 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
56
+LDP 10 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
57
+STP_v 00 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
58
+LDP_v 00 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
59
+STP_v 01 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
60
+LDP_v 01 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
61
+STP_v 10 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
62
+LDP_v 10 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
63
+
64
+# STP and LDP: pre-indexed
65
+STP 00 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
66
+LDP 00 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
67
+LDP 01 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=0 w=1
68
+STP 10 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
69
+LDP 10 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
70
+STP_v 00 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
71
+LDP_v 00 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
72
+STP_v 01 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
73
+LDP_v 01 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
74
+STP_v 10 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=1
75
+LDP_v 10 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=1
76
+
77
+# STGP: store tag and pair
78
+STGP 01 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
79
+STGP 01 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
80
+STGP 01 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
81
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/tcg/translate-a64.c
84
+++ b/target/arm/tcg/translate-a64.c
85
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_lit_v(DisasContext *s, arg_ldlit *a)
86
return true;
87
}
88
89
-/*
90
- * LDNP (Load Pair - non-temporal hint)
91
- * LDP (Load Pair - non vector)
92
- * LDPSW (Load Pair Signed Word - non vector)
93
- * STNP (Store Pair - non-temporal hint)
94
- * STP (Store Pair - non vector)
95
- * LDNP (Load Pair of SIMD&FP - non-temporal hint)
96
- * LDP (Load Pair of SIMD&FP)
97
- * STNP (Store Pair of SIMD&FP - non-temporal hint)
98
- * STP (Store Pair of SIMD&FP)
99
- *
100
- * 31 30 29 27 26 25 24 23 22 21 15 14 10 9 5 4 0
101
- * +-----+-------+---+---+-------+---+-----------------------------+
102
- * | opc | 1 0 1 | V | 0 | index | L | imm7 | Rt2 | Rn | Rt |
103
- * +-----+-------+---+---+-------+---+-------+-------+------+------+
104
- *
105
- * opc: LDP/STP/LDNP/STNP 00 -> 32 bit, 10 -> 64 bit
106
- * LDPSW/STGP 01
107
- * LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
108
- * V: 0 -> GPR, 1 -> Vector
109
- * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
110
- * 10 -> signed offset, 11 -> pre-index
111
- * L: 0 -> Store 1 -> Load
112
- *
113
- * Rt, Rt2 = GPR or SIMD registers to be stored
114
- * Rn = general purpose register containing address
115
- * imm7 = signed offset (multiple of 4 or 8 depending on size)
116
- */
117
-static void disas_ldst_pair(DisasContext *s, uint32_t insn)
118
+static void op_addr_ldstpair_pre(DisasContext *s, arg_ldstpair *a,
119
+ TCGv_i64 *clean_addr, TCGv_i64 *dirty_addr,
120
+ uint64_t offset, bool is_store, MemOp mop)
121
{
122
- int rt = extract32(insn, 0, 5);
123
- int rn = extract32(insn, 5, 5);
124
- int rt2 = extract32(insn, 10, 5);
125
- uint64_t offset = sextract64(insn, 15, 7);
126
- int index = extract32(insn, 23, 2);
127
- bool is_vector = extract32(insn, 26, 1);
128
- bool is_load = extract32(insn, 22, 1);
129
- int opc = extract32(insn, 30, 2);
130
- bool is_signed = false;
131
- bool postindex = false;
132
- bool wback = false;
133
- bool set_tag = false;
134
- TCGv_i64 clean_addr, dirty_addr;
135
- MemOp mop;
136
- int size;
137
-
138
- if (opc == 3) {
139
- unallocated_encoding(s);
140
- return;
141
- }
142
-
143
- if (is_vector) {
144
- size = 2 + opc;
145
- } else if (opc == 1 && !is_load) {
146
- /* STGP */
147
- if (!dc_isar_feature(aa64_mte_insn_reg, s) || index == 0) {
148
- unallocated_encoding(s);
149
- return;
150
- }
151
- size = 3;
152
- set_tag = true;
153
- } else {
154
- size = 2 + extract32(opc, 1, 1);
155
- is_signed = extract32(opc, 0, 1);
156
- if (!is_load && is_signed) {
157
- unallocated_encoding(s);
158
- return;
159
- }
160
- }
161
-
162
- switch (index) {
163
- case 1: /* post-index */
164
- postindex = true;
165
- wback = true;
166
- break;
167
- case 0:
168
- /* signed offset with "non-temporal" hint. Since we don't emulate
169
- * caches we don't care about hints to the cache system about
170
- * data access patterns, and handle this identically to plain
171
- * signed offset.
172
- */
173
- if (is_signed) {
174
- /* There is no non-temporal-hint version of LDPSW */
175
- unallocated_encoding(s);
176
- return;
177
- }
178
- postindex = false;
179
- break;
180
- case 2: /* signed offset, rn not updated */
181
- postindex = false;
182
- break;
183
- case 3: /* pre-index */
184
- postindex = false;
185
- wback = true;
186
- break;
187
- }
188
-
189
- if (is_vector && !fp_access_check(s)) {
190
- return;
191
- }
192
-
193
- offset <<= (set_tag ? LOG2_TAG_GRANULE : size);
194
-
195
- if (rn == 31) {
196
+ if (a->rn == 31) {
197
gen_check_sp_alignment(s);
198
}
56
}
199
57
200
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
58
+ for (int i = 0; i < 4; i++) {
201
- if (!postindex) {
59
+ /* CMSDK GPIO controllers */
202
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
60
+ g_autofree char *s = g_strdup_printf("gpio%d", i);
203
+ if (!a->p) {
61
+ create_unimplemented_device(s, 0xe0000000 + i * 0x1000, 0x1000);
204
+ tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
205
+ }
62
+ }
206
+
63
+
207
+ *clean_addr = gen_mte_checkN(s, *dirty_addr, is_store,
64
+ object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
208
+ (a->w || a->rn != 31), 2 << a->sz, mop);
65
+ TYPE_CMSDK_APB_WATCHDOG);
209
+}
66
+ qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->clk);
67
+ sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
68
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
69
+ qdev_get_gpio_in(gicdev, 0));
70
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->watchdog), 0, 0xe0100000);
210
+
71
+
211
+static void op_addr_ldstpair_post(DisasContext *s, arg_ldstpair *a,
72
+ object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
212
+ TCGv_i64 dirty_addr, uint64_t offset)
73
+ TYPE_CMSDK_APB_DUALTIMER);
213
+{
74
+ qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->clk);
214
+ if (a->w) {
75
+ sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
215
+ if (a->p) {
76
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
216
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
77
+ qdev_get_gpio_in(gicdev, 3));
217
+ }
78
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 1,
218
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
79
+ qdev_get_gpio_in(gicdev, 1));
219
+ }
80
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 2,
220
+}
81
+ qdev_get_gpio_in(gicdev, 2));
82
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0xe0101000);
221
+
83
+
222
+static bool trans_STP(DisasContext *s, arg_ldstpair *a)
84
+ for (int i = 0; i < ARRAY_SIZE(mms->i2c); i++) {
223
+{
85
+ static const hwaddr i2cbase[] = {0xe0102000, /* Touch */
224
+ uint64_t offset = a->imm << a->sz;
86
+ 0xe0103000, /* Audio */
225
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt, tcg_rt2;
87
+ 0xe0107000, /* Shield0 */
226
+ MemOp mop = finalize_memop(s, a->sz);
88
+ 0xe0108000, /* Shield1 */
89
+ 0xe0109000}; /* DDR4 EEPROM */
90
+ g_autofree char *s = g_strdup_printf("i2c%d", i);
227
+
91
+
228
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, true, mop);
92
+ object_initialize_child(OBJECT(mms), s, &mms->i2c[i],
229
+ tcg_rt = cpu_reg(s, a->rt);
93
+ TYPE_ARM_SBCON_I2C);
230
+ tcg_rt2 = cpu_reg(s, a->rt2);
94
+ sysbus_realize(SYS_BUS_DEVICE(&mms->i2c[i]), &error_fatal);
231
+ /*
95
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->i2c[i]), 0, i2cbase[i]);
232
+ * We built mop above for the single logical access -- rebuild it
96
+ if (i != 2 && i != 3) {
233
+ * now for the paired operation.
97
+ /*
234
+ *
98
+ * internal-only bus: mark it full to avoid user-created
235
+ * With LSE2, non-sign-extending pairs are treated atomically if
99
+ * i2c devices being plugged into it.
236
+ * aligned, and if unaligned one of the pair will be completely
100
+ */
237
+ * within a 16-byte block and that element will be atomic.
101
+ qbus_mark_full(qdev_get_child_bus(DEVICE(&mms->i2c[i]), "i2c"));
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
+ }
102
+ }
318
+ }
103
+ }
319
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
320
+ return true;
321
+}
322
+
104
+
323
+static bool trans_STP_v(DisasContext *s, arg_ldstpair *a)
105
mms->bootinfo.ram_size = machine->ram_size;
324
+{
106
mms->bootinfo.board_id = -1;
325
+ uint64_t offset = a->imm << a->sz;
107
mms->bootinfo.loader_start = mmc->loader_start;
326
+ TCGv_i64 clean_addr, dirty_addr;
327
+ MemOp mop;
328
+
329
+ if (!fp_access_check(s)) {
330
+ return true;
331
+ }
332
+
333
+ /* LSE2 does not merge FP pairs; leave these as separate operations. */
334
+ mop = finalize_memop_asimd(s, a->sz);
335
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, true, mop);
336
+ do_fp_st(s, a->rt, clean_addr, mop);
337
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << a->sz);
338
+ do_fp_st(s, a->rt2, clean_addr, mop);
339
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
340
+ return true;
341
+}
342
+
343
+static bool trans_LDP_v(DisasContext *s, arg_ldstpair *a)
344
+{
345
+ uint64_t offset = a->imm << a->sz;
346
+ TCGv_i64 clean_addr, dirty_addr;
347
+ MemOp mop;
348
+
349
+ if (!fp_access_check(s)) {
350
+ return true;
351
+ }
352
+
353
+ /* LSE2 does not merge FP pairs; leave these as separate operations. */
354
+ mop = finalize_memop_asimd(s, a->sz);
355
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, false, mop);
356
+ do_fp_ld(s, a->rt, clean_addr, mop);
357
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << a->sz);
358
+ do_fp_ld(s, a->rt2, clean_addr, mop);
359
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
360
+ return true;
361
+}
362
+
363
+static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
364
+{
365
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt, tcg_rt2;
366
+ uint64_t offset = a->imm << LOG2_TAG_GRANULE;
367
+ MemOp mop;
368
+ TCGv_i128 tmp;
369
+
370
+ if (!dc_isar_feature(aa64_mte_insn_reg, s)) {
371
+ return false;
372
+ }
373
+
374
+ if (a->rn == 31) {
375
+ gen_check_sp_alignment(s);
376
+ }
377
+
378
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
379
+ if (!a->p) {
380
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
381
}
382
383
- if (set_tag) {
384
- if (!s->ata) {
385
- /*
386
- * TODO: We could rely on the stores below, at least for
387
- * system mode, if we arrange to add MO_ALIGN_16.
388
- */
389
- gen_helper_stg_stub(cpu_env, dirty_addr);
390
- } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
391
- gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
392
- } else {
393
- gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
394
- }
395
- }
396
-
397
- if (is_vector) {
398
- mop = finalize_memop_asimd(s, size);
399
- } else {
400
- mop = finalize_memop(s, size);
401
- }
402
- clean_addr = gen_mte_checkN(s, dirty_addr, !is_load,
403
- (wback || rn != 31) && !set_tag,
404
- 2 << size, mop);
405
-
406
- if (is_vector) {
407
- /* LSE2 does not merge FP pairs; leave these as separate operations. */
408
- if (is_load) {
409
- do_fp_ld(s, rt, clean_addr, mop);
410
- } else {
411
- do_fp_st(s, rt, clean_addr, mop);
412
- }
413
- tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
414
- if (is_load) {
415
- do_fp_ld(s, rt2, clean_addr, mop);
416
- } else {
417
- do_fp_st(s, rt2, clean_addr, mop);
418
- }
419
- } else {
420
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
421
- TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
422
-
423
+ if (!s->ata) {
424
/*
425
- * We built mop above for the single logical access -- rebuild it
426
- * now for the paired operation.
427
- *
428
- * With LSE2, non-sign-extending pairs are treated atomically if
429
- * aligned, and if unaligned one of the pair will be completely
430
- * within a 16-byte block and that element will be atomic.
431
- * Otherwise each element is separately atomic.
432
- * In all cases, issue one operation with the correct atomicity.
433
- *
434
- * This treats sign-extending loads like zero-extending loads,
435
- * since that reuses the most code below.
436
+ * TODO: We could rely on the stores below, at least for
437
+ * system mode, if we arrange to add MO_ALIGN_16.
438
*/
439
- mop = size + 1;
440
- if (s->align_mem) {
441
- mop |= (size == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
442
- }
443
- mop = finalize_memop_pair(s, mop);
444
-
445
- if (is_load) {
446
- if (size == 2) {
447
- int o2 = s->be_data == MO_LE ? 32 : 0;
448
- int o1 = o2 ^ 32;
449
-
450
- tcg_gen_qemu_ld_i64(tcg_rt, clean_addr, get_mem_index(s), mop);
451
- if (is_signed) {
452
- tcg_gen_sextract_i64(tcg_rt2, tcg_rt, o2, 32);
453
- tcg_gen_sextract_i64(tcg_rt, tcg_rt, o1, 32);
454
- } else {
455
- tcg_gen_extract_i64(tcg_rt2, tcg_rt, o2, 32);
456
- tcg_gen_extract_i64(tcg_rt, tcg_rt, o1, 32);
457
- }
458
- } else {
459
- TCGv_i128 tmp = tcg_temp_new_i128();
460
-
461
- tcg_gen_qemu_ld_i128(tmp, clean_addr, get_mem_index(s), mop);
462
- if (s->be_data == MO_LE) {
463
- tcg_gen_extr_i128_i64(tcg_rt, tcg_rt2, tmp);
464
- } else {
465
- tcg_gen_extr_i128_i64(tcg_rt2, tcg_rt, tmp);
466
- }
467
- }
468
- } else {
469
- if (size == 2) {
470
- TCGv_i64 tmp = tcg_temp_new_i64();
471
-
472
- if (s->be_data == MO_LE) {
473
- tcg_gen_concat32_i64(tmp, tcg_rt, tcg_rt2);
474
- } else {
475
- tcg_gen_concat32_i64(tmp, tcg_rt2, tcg_rt);
476
- }
477
- tcg_gen_qemu_st_i64(tmp, clean_addr, get_mem_index(s), mop);
478
- } else {
479
- TCGv_i128 tmp = tcg_temp_new_i128();
480
-
481
- if (s->be_data == MO_LE) {
482
- tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
483
- } else {
484
- tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
485
- }
486
- tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
487
- }
488
- }
489
+ gen_helper_stg_stub(cpu_env, dirty_addr);
490
+ } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
491
+ gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
492
+ } else {
493
+ gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
494
}
495
496
- if (wback) {
497
- if (postindex) {
498
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
499
- }
500
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
501
+ mop = finalize_memop(s, a->sz);
502
+ clean_addr = gen_mte_checkN(s, dirty_addr, true, false, 2 << a->sz, mop);
503
+
504
+ tcg_rt = cpu_reg(s, a->rt);
505
+ tcg_rt2 = cpu_reg(s, a->rt2);
506
+
507
+ assert(a->sz == 3);
508
+
509
+ tmp = tcg_temp_new_i128();
510
+ if (s->be_data == MO_LE) {
511
+ tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
512
+ } else {
513
+ tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
514
}
515
+ tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
516
+
517
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
518
+ return true;
519
}
520
521
/*
522
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
523
static void disas_ldst(DisasContext *s, uint32_t insn)
524
{
525
switch (extract32(insn, 24, 6)) {
526
- case 0x28: case 0x29:
527
- case 0x2c: case 0x2d: /* Load/store pair (all forms) */
528
- disas_ldst_pair(s, insn);
529
- break;
530
case 0x38: case 0x39:
531
case 0x3c: case 0x3d: /* Load/store register (all forms) */
532
disas_ldst_reg(s, insn);
533
--
108
--
534
2.34.1
109
2.34.1
110
111
diff view generated by jsdifflib
1
Convert the instructions in the ASIMD load/store multiple structures
1
Add the remaining devices (or unimplemented-device stubs) for
2
instruction classes to decodetree.
2
this board: SPI controllers, SCC, FPGAIO, I2S, RTC, the
3
QSPI write-config block, and ethernet.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Message-id: 20230602155223.2040685-19-peter.maydell@linaro.org
7
Message-id: 20240206132931.38376-13-peter.maydell@linaro.org
7
---
8
---
8
target/arm/tcg/a64.decode | 20 +++
9
hw/arm/mps3r.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
9
target/arm/tcg/translate-a64.c | 222 ++++++++++++++++-----------------
10
1 file changed, 74 insertions(+)
10
2 files changed, 131 insertions(+), 111 deletions(-)
11
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
12
diff --git a/hw/arm/mps3r.c b/hw/arm/mps3r.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
14
--- a/hw/arm/mps3r.c
15
+++ b/target/arm/tcg/a64.decode
15
+++ b/hw/arm/mps3r.c
16
@@ -XXX,XX +XXX,XX @@ LDAPR_i 01 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext
16
@@ -XXX,XX +XXX,XX @@
17
LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=2
17
#include "hw/char/cmsdk-apb-uart.h"
18
LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
18
#include "hw/i2c/arm_sbcon_i2c.h"
19
LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
19
#include "hw/intc/arm_gicv3.h"
20
+#include "hw/misc/mps2-scc.h"
21
+#include "hw/misc/mps2-fpgaio.h"
22
#include "hw/misc/unimp.h"
23
+#include "hw/net/lan9118.h"
24
+#include "hw/rtc/pl031.h"
25
+#include "hw/ssi/pl022.h"
26
#include "hw/timer/cmsdk-apb-dualtimer.h"
27
#include "hw/watchdog/cmsdk-apb-watchdog.h"
28
29
@@ -XXX,XX +XXX,XX @@ struct MPS3RMachineState {
30
CMSDKAPBWatchdog watchdog;
31
CMSDKAPBDualTimer dualtimer;
32
ArmSbconI2CState i2c[5];
33
+ PL022State spi[3];
34
+ MPS2SCC scc;
35
+ MPS2FPGAIO fpgaio;
36
+ UnimplementedDeviceState i2s_audio;
37
+ PL031State rtc;
38
Clock *clk;
39
};
40
41
@@ -XXX,XX +XXX,XX @@ static const RAMInfo an536_raminfo[] = {
42
}
43
};
44
45
+static const int an536_oscclk[] = {
46
+ 24000000, /* 24MHz reference for RTC and timers */
47
+ 50000000, /* 50MHz ACLK */
48
+ 50000000, /* 50MHz MCLK */
49
+ 50000000, /* 50MHz GPUCLK */
50
+ 24576000, /* 24.576MHz AUDCLK */
51
+ 23750000, /* 23.75MHz HDLCDCLK */
52
+ 100000000, /* 100MHz DDR4_REF_CLK */
53
+};
20
+
54
+
21
+# Load/store multiple structures
55
static MemoryRegion *mr_for_raminfo(MPS3RMachineState *mms,
22
+# The 4-bit opcode in [15:12] encodes repeat count and structure elements
56
const RAMInfo *raminfo)
23
+&ldst_mult rm rn rt sz q p rpt selem
24
+@ldst_mult . q:1 ...... p:1 . . rm:5 .... sz:2 rn:5 rt:5 &ldst_mult
25
+ST_mult 0 . 001100 . 0 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
26
+ST_mult 0 . 001100 . 0 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
27
+ST_mult 0 . 001100 . 0 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
28
+ST_mult 0 . 001100 . 0 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
29
+ST_mult 0 . 001100 . 0 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
30
+ST_mult 0 . 001100 . 0 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
31
+ST_mult 0 . 001100 . 0 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
32
+
33
+LD_mult 0 . 001100 . 1 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
34
+LD_mult 0 . 001100 . 1 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
35
+LD_mult 0 . 001100 . 1 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
36
+LD_mult 0 . 001100 . 1 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
37
+LD_mult 0 . 001100 . 1 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
38
+LD_mult 0 . 001100 . 1 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
39
+LD_mult 0 . 001100 . 1 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
40
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/tcg/translate-a64.c
43
+++ b/target/arm/tcg/translate-a64.c
44
@@ -XXX,XX +XXX,XX @@ static bool trans_STLR_i(DisasContext *s, arg_ldapr_stlr_i *a)
45
return true;
46
}
47
48
-/* AdvSIMD load/store multiple structures
49
- *
50
- * 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
51
- * +---+---+---------------+---+-------------+--------+------+------+------+
52
- * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size | Rn | Rt |
53
- * +---+---+---------------+---+-------------+--------+------+------+------+
54
- *
55
- * AdvSIMD load/store multiple structures (post-indexed)
56
- *
57
- * 31 30 29 23 22 21 20 16 15 12 11 10 9 5 4 0
58
- * +---+---+---------------+---+---+---------+--------+------+------+------+
59
- * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 | Rm | opcode | size | Rn | Rt |
60
- * +---+---+---------------+---+---+---------+--------+------+------+------+
61
- *
62
- * Rt: first (or only) SIMD&FP register to be transferred
63
- * Rn: base address or SP
64
- * Rm (post-index only): post-index register (when !31) or size dependent #imm
65
- */
66
-static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
67
+static bool trans_LD_mult(DisasContext *s, arg_ldst_mult *a)
68
{
57
{
69
- int rt = extract32(insn, 0, 5);
58
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
70
- int rn = extract32(insn, 5, 5);
59
MPS3RMachineClass *mmc = MPS3R_MACHINE_GET_CLASS(mms);
71
- int rm = extract32(insn, 16, 5);
60
MemoryRegion *sysmem = get_system_memory();
72
- int size = extract32(insn, 10, 2);
61
DeviceState *gicdev;
73
- int opcode = extract32(insn, 12, 4);
62
+ QList *oscclk;
74
- bool is_store = !extract32(insn, 22, 1);
63
75
- bool is_postidx = extract32(insn, 23, 1);
64
mms->clk = clock_new(OBJECT(machine), "CLK");
76
- bool is_q = extract32(insn, 30, 1);
65
clock_set_hz(mms->clk, CLK_FRQ);
77
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
66
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
78
MemOp endian, align, mop;
79
80
int total; /* total bytes */
81
int elements; /* elements per vector */
82
- int rpt; /* num iterations */
83
- int selem; /* structure elements */
84
int r;
85
+ int size = a->sz;
86
87
- if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
88
- unallocated_encoding(s);
89
- return;
90
+ if (!a->p && a->rm != 0) {
91
+ /* For non-postindexed accesses the Rm field must be 0 */
92
+ return false;
93
}
94
-
95
- if (!is_postidx && rm != 0) {
96
- unallocated_encoding(s);
97
- return;
98
+ if (size == 3 && !a->q && a->selem != 1) {
99
+ return false;
100
}
101
-
102
- /* From the shared decode logic */
103
- switch (opcode) {
104
- case 0x0:
105
- rpt = 1;
106
- selem = 4;
107
- break;
108
- case 0x2:
109
- rpt = 4;
110
- selem = 1;
111
- break;
112
- case 0x4:
113
- rpt = 1;
114
- selem = 3;
115
- break;
116
- case 0x6:
117
- rpt = 3;
118
- selem = 1;
119
- break;
120
- case 0x7:
121
- rpt = 1;
122
- selem = 1;
123
- break;
124
- case 0x8:
125
- rpt = 1;
126
- selem = 2;
127
- break;
128
- case 0xa:
129
- rpt = 2;
130
- selem = 1;
131
- break;
132
- default:
133
- unallocated_encoding(s);
134
- return;
135
- }
136
-
137
- if (size == 3 && !is_q && selem != 1) {
138
- /* reserved */
139
- unallocated_encoding(s);
140
- return;
141
- }
142
-
143
if (!fp_access_check(s)) {
144
- return;
145
+ return true;
146
}
147
148
- if (rn == 31) {
149
+ if (a->rn == 31) {
150
gen_check_sp_alignment(s);
151
}
152
153
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
154
endian = MO_LE;
155
}
156
157
- total = rpt * selem * (is_q ? 16 : 8);
158
- tcg_rn = cpu_reg_sp(s, rn);
159
+ total = a->rpt * a->selem * (a->q ? 16 : 8);
160
+ tcg_rn = cpu_reg_sp(s, a->rn);
161
162
/*
163
* Issue the MTE check vs the logical repeat count, before we
164
* promote consecutive little-endian elements below.
165
*/
166
- clean_addr = gen_mte_checkN(s, tcg_rn, is_store, is_postidx || rn != 31,
167
- total, finalize_memop_asimd(s, size));
168
+ clean_addr = gen_mte_checkN(s, tcg_rn, false, a->p || a->rn != 31, total,
169
+ finalize_memop_asimd(s, size));
170
171
/*
172
* Consecutive little-endian elements from a single register
173
* can be promoted to a larger little-endian operation.
174
*/
175
align = MO_ALIGN;
176
- if (selem == 1 && endian == MO_LE) {
177
+ if (a->selem == 1 && endian == MO_LE) {
178
align = pow2_align(size);
179
size = 3;
180
}
181
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
182
}
183
mop = endian | size | align;
184
185
- elements = (is_q ? 16 : 8) >> size;
186
+ elements = (a->q ? 16 : 8) >> size;
187
tcg_ebytes = tcg_constant_i64(1 << size);
188
- for (r = 0; r < rpt; r++) {
189
+ for (r = 0; r < a->rpt; r++) {
190
int e;
191
for (e = 0; e < elements; e++) {
192
int xs;
193
- for (xs = 0; xs < selem; xs++) {
194
- int tt = (rt + r + xs) % 32;
195
- if (is_store) {
196
- do_vec_st(s, tt, e, clean_addr, mop);
197
- } else {
198
- do_vec_ld(s, tt, e, clean_addr, mop);
199
- }
200
+ for (xs = 0; xs < a->selem; xs++) {
201
+ int tt = (a->rt + r + xs) % 32;
202
+ do_vec_ld(s, tt, e, clean_addr, mop);
203
tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
204
}
205
}
67
}
206
}
68
}
207
69
208
- if (!is_store) {
70
+ for (int i = 0; i < ARRAY_SIZE(mms->spi); i++) {
209
- /* For non-quad operations, setting a slice of the low
71
+ g_autofree char *s = g_strdup_printf("spi%d", i);
210
- * 64 bits of the register clears the high 64 bits (in
72
+ hwaddr baseaddr = 0xe0104000 + i * 0x1000;
211
- * the ARM ARM pseudocode this is implicit in the fact
73
+
212
- * that 'rval' is a 64 bit wide variable).
74
+ object_initialize_child(OBJECT(mms), s, &mms->spi[i], TYPE_PL022);
213
- * For quad operations, we might still need to zero the
75
+ sysbus_realize(SYS_BUS_DEVICE(&mms->spi[i]), &error_fatal);
214
- * high bits of SVE.
76
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->spi[i]), 0, baseaddr);
215
- */
77
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->spi[i]), 0,
216
- for (r = 0; r < rpt * selem; r++) {
78
+ qdev_get_gpio_in(gicdev, 22 + i));
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
+ }
79
+ }
230
+
80
+
231
+ if (a->p) {
81
+ object_initialize_child(OBJECT(mms), "scc", &mms->scc, TYPE_MPS2_SCC);
232
+ if (a->rm == 31) {
82
+ qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-cfg0", 0);
233
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
83
+ qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-cfg4", 0x2);
234
+ } else {
84
+ qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-aid", 0x00200008);
235
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
85
+ qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-id", 0x41055360);
236
+ }
86
+ oscclk = qlist_new();
87
+ for (int i = 0; i < ARRAY_SIZE(an536_oscclk); i++) {
88
+ qlist_append_int(oscclk, an536_oscclk[i]);
237
+ }
89
+ }
238
+ return true;
90
+ qdev_prop_set_array(DEVICE(&mms->scc), "oscclk", oscclk);
239
+}
91
+ sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
92
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->scc), 0, 0xe0200000);
240
+
93
+
241
+static bool trans_ST_mult(DisasContext *s, arg_ldst_mult *a)
94
+ create_unimplemented_device("i2s-audio", 0xe0201000, 0x1000);
242
+{
243
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
244
+ MemOp endian, align, mop;
245
+
95
+
246
+ int total; /* total bytes */
96
+ object_initialize_child(OBJECT(mms), "fpgaio", &mms->fpgaio,
247
+ int elements; /* elements per vector */
97
+ TYPE_MPS2_FPGAIO);
248
+ int r;
98
+ qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "prescale-clk", an536_oscclk[1]);
249
+ int size = a->sz;
99
+ qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "num-leds", 10);
100
+ qdev_prop_set_bit(DEVICE(&mms->fpgaio), "has-switches", true);
101
+ qdev_prop_set_bit(DEVICE(&mms->fpgaio), "has-dbgctrl", false);
102
+ sysbus_realize(SYS_BUS_DEVICE(&mms->fpgaio), &error_fatal);
103
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->fpgaio), 0, 0xe0202000);
250
+
104
+
251
+ if (!a->p && a->rm != 0) {
105
+ create_unimplemented_device("clcd", 0xe0209000, 0x1000);
252
+ /* For non-postindexed accesses the Rm field must be 0 */
253
+ return false;
254
+ }
255
+ if (size == 3 && !a->q && a->selem != 1) {
256
+ return false;
257
+ }
258
+ if (!fp_access_check(s)) {
259
+ return true;
260
+ }
261
+
106
+
262
+ if (a->rn == 31) {
107
+ object_initialize_child(OBJECT(mms), "rtc", &mms->rtc, TYPE_PL031);
263
+ gen_check_sp_alignment(s);
108
+ sysbus_realize(SYS_BUS_DEVICE(&mms->rtc), &error_fatal);
264
+ }
109
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->rtc), 0, 0xe020a000);
265
+
110
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->rtc), 0,
266
+ /* For our purposes, bytes are always little-endian. */
111
+ qdev_get_gpio_in(gicdev, 4));
267
+ endian = s->be_data;
268
+ if (size == 0) {
269
+ endian = MO_LE;
270
+ }
271
+
272
+ total = a->rpt * a->selem * (a->q ? 16 : 8);
273
+ tcg_rn = cpu_reg_sp(s, a->rn);
274
+
112
+
275
+ /*
113
+ /*
276
+ * Issue the MTE check vs the logical repeat count, before we
114
+ * In hardware this is a LAN9220; the LAN9118 is software compatible
277
+ * promote consecutive little-endian elements below.
115
+ * except that it doesn't support the checksum-offload feature.
278
+ */
116
+ */
279
+ clean_addr = gen_mte_checkN(s, tcg_rn, true, a->p || a->rn != 31, total,
117
+ lan9118_init(0xe0300000,
280
+ finalize_memop_asimd(s, size));
118
+ qdev_get_gpio_in(gicdev, 18));
281
+
119
+
282
+ /*
120
+ create_unimplemented_device("usb", 0xe0301000, 0x1000);
283
+ * Consecutive little-endian elements from a single register
121
+ create_unimplemented_device("qspi-write-config", 0xe0600000, 0x1000);
284
+ * can be promoted to a larger little-endian operation.
285
+ */
286
+ align = MO_ALIGN;
287
+ if (a->selem == 1 && endian == MO_LE) {
288
+ align = pow2_align(size);
289
+ size = 3;
290
+ }
291
+ if (!s->align_mem) {
292
+ align = 0;
293
+ }
294
+ mop = endian | size | align;
295
+
122
+
296
+ elements = (a->q ? 16 : 8) >> size;
123
mms->bootinfo.ram_size = machine->ram_size;
297
+ tcg_ebytes = tcg_constant_i64(1 << size);
124
mms->bootinfo.board_id = -1;
298
+ for (r = 0; r < a->rpt; r++) {
125
mms->bootinfo.loader_start = mmc->loader_start;
299
+ int e;
300
+ for (e = 0; e < elements; e++) {
301
+ int xs;
302
+ for (xs = 0; xs < a->selem; xs++) {
303
+ int tt = (a->rt + r + xs) % 32;
304
+ do_vec_st(s, tt, e, clean_addr, mop);
305
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
306
+ }
307
}
308
}
309
310
- if (is_postidx) {
311
- if (rm == 31) {
312
+ if (a->p) {
313
+ if (a->rm == 31) {
314
tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
315
} else {
316
- tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
317
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
318
}
319
}
320
+ return true;
321
}
322
323
/* AdvSIMD load/store single structure
324
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
325
static void disas_ldst(DisasContext *s, uint32_t insn)
326
{
327
switch (extract32(insn, 24, 6)) {
328
- case 0x0c: /* AdvSIMD load/store multiple structures */
329
- disas_ldst_multiple_struct(s, insn);
330
- break;
331
case 0x0d: /* AdvSIMD load/store single structure */
332
disas_ldst_single_struct(s, insn);
333
break;
334
--
126
--
335
2.34.1
127
2.34.1
128
129
diff view generated by jsdifflib
1
Convert the insns in the "Barriers" instruction class to
1
Add documentation for the mps3-an536 board type.
2
decodetree: CLREX, DSB, DMB, ISB and SB.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-4-peter.maydell@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Message-id: 20240206132931.38376-14-peter.maydell@linaro.org
8
---
6
---
9
target/arm/tcg/a64.decode | 7 +++
7
docs/system/arm/mps2.rst | 37 ++++++++++++++++++++++++++++++++++---
10
target/arm/tcg/translate-a64.c | 92 ++++++++++++++--------------------
8
1 file changed, 34 insertions(+), 3 deletions(-)
11
2 files changed, 46 insertions(+), 53 deletions(-)
12
9
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
10
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
12
--- a/docs/system/arm/mps2.rst
16
+++ b/target/arm/tcg/a64.decode
13
+++ b/docs/system/arm/mps2.rst
17
@@ -XXX,XX +XXX,XX @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
14
@@ -XXX,XX +XXX,XX @@
18
# that isn't specifically allocated to an instruction must NOP
15
-Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``, ``mps3-an547``)
19
NOP 1101 0101 0000 0011 0010 ---- --- 11111
16
-=========================================================================================================================================================
20
}
17
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``, ``mps3-an536``, ``mps3-an547``)
18
+=========================================================================================================================================================================
19
20
-These board models all use Arm M-profile CPUs.
21
+These board models use Arm M-profile or R-profile CPUs.
22
23
The Arm MPS2, MPS2+ and MPS3 dev boards are FPGA based (the 2+ has a
24
bigger FPGA but is otherwise the same as the 2; the 3 has a bigger
25
@@ -XXX,XX +XXX,XX @@ FPGA image.
26
27
QEMU models the following FPGA images:
28
29
+FPGA images using M-profile CPUs:
21
+
30
+
22
+# Barriers
31
``mps2-an385``
32
Cortex-M3 as documented in Arm Application Note AN385
33
``mps2-an386``
34
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
35
``mps3-an547``
36
Cortex-M55 on an MPS3, as documented in Arm Application Note AN547
37
38
+FPGA images using R-profile CPUs:
23
+
39
+
24
+CLREX 1101 0101 0000 0011 0011 ---- 010 11111
40
+``mps3-an536``
25
+DSB_DMB 1101 0101 0000 0011 0011 domain:2 types:2 10- 11111
41
+ Dual Cortex-R52 on an MPS3, as documented in Arm Application Note AN536
26
+ISB 1101 0101 0000 0011 0011 ---- 110 11111
42
+
27
+SB 1101 0101 0000 0011 0011 0000 111 11111
43
Differences between QEMU and real hardware:
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
44
29
index XXXXXXX..XXXXXXX 100644
45
- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
30
--- a/target/arm/tcg/translate-a64.c
46
@@ -XXX,XX +XXX,XX @@ Differences between QEMU and real hardware:
31
+++ b/target/arm/tcg/translate-a64.c
47
flash, but only as simple ROM, so attempting to rewrite the flash
32
@@ -XXX,XX +XXX,XX @@ static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
48
from the guest will fail
33
return true;
49
- QEMU does not model the USB controller in MPS3 boards
34
}
50
+- AN536 does not support runtime control of CPU reset and halt via
35
51
+ the SCC CFG_REG0 register.
36
-static void gen_clrex(DisasContext *s, uint32_t insn)
52
+- AN536 does not support enabling or disabling the flash and ATCM
37
+static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
53
+ interfaces via the SCC CFG_REG1 register.
38
{
54
+- AN536 does not support setting of the initial vector table
39
tcg_gen_movi_i64(cpu_exclusive_addr, -1);
55
+ base address via the SCC CFG_REG6 and CFG_REG7 register config,
40
+ return true;
56
+ and does not provide a mechanism for specifying these values at
41
}
57
+ startup, so all guest images must be built to start from TCM
42
58
+ (i.e. to expect the interrupt vector base at 0 from reset).
43
-/* CLREX, DSB, DMB, ISB */
59
+- AN536 defaults to only creating a single CPU; this is the equivalent
44
-static void handle_sync(DisasContext *s, uint32_t insn,
60
+ of the way the real FPGA image usually runs with the second Cortex-R52
45
- unsigned int op1, unsigned int op2, unsigned int crm)
61
+ held in halt via the initial SCC CFG_REG0 register setting. You can
46
+static bool trans_DSB_DMB(DisasContext *s, arg_DSB_DMB *a)
62
+ create the second CPU with ``-smp 2``; both CPUs will then start
47
{
63
+ execution immediately on startup.
48
+ /* We handle DSB and DMB the same way */
64
+
49
TCGBar bar;
65
+Note that for the AN536 the first UART is accessible only by
50
66
+CPU0, and the second UART is accessible only by CPU1. The
51
- if (op1 != 3) {
67
+first UART accessible shared between both CPUs is the third
52
- unallocated_encoding(s);
68
+UART. Guest software might therefore be built to use either
53
- return;
69
+the first UART or the third UART; if you don't see any output
54
+ switch (a->types) {
70
+from the UART you are looking at, try one of the others.
55
+ case 1: /* MBReqTypes_Reads */
71
+(Even if the AN536 machine is started with a single CPU and so
56
+ bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
72
+no "CPU1-only UART", the UART numbering remains the same,
57
+ break;
73
+with the third UART being the first of the shared ones.)
58
+ case 2: /* MBReqTypes_Writes */
74
59
+ bar = TCG_BAR_SC | TCG_MO_ST_ST;
75
Machine-specific options
60
+ break;
76
""""""""""""""""""""""""
61
+ default: /* MBReqTypes_All */
62
+ bar = TCG_BAR_SC | TCG_MO_ALL;
63
+ break;
64
}
65
+ tcg_gen_mb(bar);
66
+ return true;
67
+}
68
69
- switch (op2) {
70
- case 2: /* CLREX */
71
- gen_clrex(s, insn);
72
- return;
73
- case 4: /* DSB */
74
- case 5: /* DMB */
75
- switch (crm & 3) {
76
- case 1: /* MBReqTypes_Reads */
77
- bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
78
- break;
79
- case 2: /* MBReqTypes_Writes */
80
- bar = TCG_BAR_SC | TCG_MO_ST_ST;
81
- break;
82
- default: /* MBReqTypes_All */
83
- bar = TCG_BAR_SC | TCG_MO_ALL;
84
- break;
85
- }
86
- tcg_gen_mb(bar);
87
- return;
88
- case 6: /* ISB */
89
- /* We need to break the TB after this insn to execute
90
- * a self-modified code correctly and also to take
91
- * any pending interrupts immediately.
92
- */
93
- reset_btype(s);
94
- gen_goto_tb(s, 0, 4);
95
- return;
96
+static bool trans_ISB(DisasContext *s, arg_ISB *a)
97
+{
98
+ /*
99
+ * We need to break the TB after this insn to execute
100
+ * self-modifying code correctly and also to take
101
+ * any pending interrupts immediately.
102
+ */
103
+ reset_btype(s);
104
+ gen_goto_tb(s, 0, 4);
105
+ return true;
106
+}
107
108
- case 7: /* SB */
109
- if (crm != 0 || !dc_isar_feature(aa64_sb, s)) {
110
- goto do_unallocated;
111
- }
112
- /*
113
- * TODO: There is no speculation barrier opcode for TCG;
114
- * MB and end the TB instead.
115
- */
116
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
117
- gen_goto_tb(s, 0, 4);
118
- return;
119
-
120
- default:
121
- do_unallocated:
122
- unallocated_encoding(s);
123
- return;
124
+static bool trans_SB(DisasContext *s, arg_SB *a)
125
+{
126
+ if (!dc_isar_feature(aa64_sb, s)) {
127
+ return false;
128
}
129
+ /*
130
+ * TODO: There is no speculation barrier opcode for TCG;
131
+ * MB and end the TB instead.
132
+ */
133
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
134
+ gen_goto_tb(s, 0, 4);
135
+ return true;
136
}
137
138
static void gen_xaflag(void)
139
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
140
return;
141
}
142
switch (crn) {
143
- case 3: /* CLREX, DSB, DMB, ISB */
144
- handle_sync(s, insn, op1, op2, crm);
145
- break;
146
case 4: /* MSR (immediate) */
147
handle_msr_i(s, insn, op1, op2, crm);
148
break;
149
--
77
--
150
2.34.1
78
2.34.1
151
79
152
80
diff view generated by jsdifflib