1
Hi; here's the latest arm pullreq. This is mostly patches from
1
The following changes since commit 5767815218efd3cbfd409505ed824d5f356044ae:
2
RTH, plus a couple of other more minor things. Switching to
3
PCREL is the big one, hopefully should improve performance.
4
2
5
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)
6
-- PMM
7
8
The following changes since commit 214a8da23651f2472b296b3293e619fd58d9e212:
9
10
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2022-10-18 11:14:31 -0400)
11
4
12
are available in the Git repository at:
5
are available in the Git repository at:
13
6
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20221020
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240215
15
8
16
for you to fetch changes up to 5db899303799e49209016a93289b8694afa1449e:
9
for you to fetch changes up to f780e63fe731b058fe52d43653600d8729a1b5f2:
17
10
18
hw/ide/microdrive: Use device_cold_reset() for self-resets (2022-10-20 12:11:53 +0100)
11
docs: Add documentation for the mps3-an536 board (2024-02-15 14:32:39 +0000)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
target-arm queue:
14
target-arm queue:
22
* Switch to TARGET_TB_PCREL
15
* hw/arm/xilinx_zynq: Wire FIQ between CPU <> GIC
23
* More pagetable-walk refactoring preparatory to HAFDBS
16
* linux-user/aarch64: Choose SYNC as the preferred MTE mode
24
* update the cortex-a15 MIDR to latest rev
17
* Fix some errors in SVE/SME handling of MTE tags
25
* hw/char/pl011: fix baud rate calculation
18
* hw/pci-host/raven.c: Mark raven_io_ops as implementing unaligned accesses
26
* hw/ide/microdrive: Use device_cold_reset() for self-resets
19
* hw/block/tc58128: Don't emit deprecation warning under qtest
20
* tests/qtest: Fix handling of npcm7xx and GMAC tests
21
* hw/arm/virt: Wire up non-secure EL2 virtual timer IRQ
22
* tests/qtest/npcm7xx_emc-test: Connect all NICs to a backend
23
* Don't assert on vmload/vmsave of M-profile CPUs
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)
27
30
28
----------------------------------------------------------------
31
----------------------------------------------------------------
29
Alex Bennée (1):
32
Luc Michel (1):
30
target/arm: update the cortex-a15 MIDR to latest rev
33
hw/arm/smmuv3: add support for stage 1 access fault
31
34
32
Baruch Siach (1):
35
Nabih Estefan (1):
33
hw/char/pl011: fix baud rate calculation
36
tests/qtest: Fix GMAC test to run on a machine in upstream QEMU
34
37
35
Peter Maydell (1):
38
Peter Maydell (22):
36
hw/ide/microdrive: Use device_cold_reset() for self-resets
39
hw/pci-host/raven.c: Mark raven_io_ops as implementing unaligned accesses
40
hw/block/tc58128: Don't emit deprecation warning under qtest
41
tests/qtest/meson.build: Don't include qtests_npcm7xx in qtests_aarch64
42
tests/qtest/bios-tables-test: Allow changes to virt GTDT
43
hw/arm/virt: Wire up non-secure EL2 virtual timer IRQ
44
tests/qtest/bios-tables-tests: Update virt golden reference
45
hw/arm/npcm7xx: Call qemu_configure_nic_device() for GMAC modules
46
tests/qtest/npcm7xx_emc-test: Connect all NICs to a backend
47
target/arm: Don't get MDCR_EL2 in pmu_counter_enabled() before checking ARM_FEATURE_PMU
48
target/arm: Use new CBAR encoding for all v8 CPUs, not all aarch64 CPUs
49
target/arm: The Cortex-R52 has a read-only CBAR
50
target/arm: Add Cortex-R52 IMPDEF sysregs
51
target/arm: Allow access to SPSR_hyp from hyp mode
52
hw/misc/mps2-scc: Fix condition for CFG3 register
53
hw/misc/mps2-scc: Factor out which-board conditionals
54
hw/misc/mps2-scc: Make changes needed for AN536 FPGA image
55
hw/arm/mps3r: Initial skeleton for mps3-an536 board
56
hw/arm/mps3r: Add CPUs, GIC, and per-CPU RAM
57
hw/arm/mps3r: Add UARTs
58
hw/arm/mps3r: Add GPIO, watchdog, dual-timer, I2C devices
59
hw/arm/mps3r: Add remaining devices
60
docs: Add documentation for the mps3-an536 board
37
61
38
Richard Henderson (21):
62
Philippe Mathieu-Daudé (5):
39
target/arm: Enable TARGET_PAGE_ENTRY_EXTRA
63
hw/arm/xilinx_zynq: Wire FIQ between CPU <> GIC
40
target/arm: Use probe_access_full for MTE
64
hw/arm/stellaris: Convert ADC controller to Resettable interface
41
target/arm: Use probe_access_full for BTI
65
hw/arm/stellaris: Convert I2C controller to Resettable interface
42
target/arm: Add ARMMMUIdx_Phys_{S,NS}
66
hw/arm/stellaris: Add missing QOM 'machine' parent
43
target/arm: Move ARMMMUIdx_Stage2 to a real tlb mmu_idx
67
hw/arm/stellaris: Add missing QOM 'SoC' parent
44
target/arm: Restrict tlb flush from vttbr_write to vmid change
45
target/arm: Split out S1Translate type
46
target/arm: Plumb debug into S1Translate
47
target/arm: Move be test for regime into S1TranslateResult
48
target/arm: Use softmmu tlbs for page table walking
49
target/arm: Split out get_phys_addr_twostage
50
target/arm: Use bool consistently for get_phys_addr subroutines
51
target/arm: Introduce curr_insn_len
52
target/arm: Change gen_goto_tb to work on displacements
53
target/arm: Change gen_*set_pc_im to gen_*update_pc
54
target/arm: Change gen_exception_insn* to work on displacements
55
target/arm: Remove gen_exception_internal_insn pc argument
56
target/arm: Change gen_jmp* to work on displacements
57
target/arm: Introduce gen_pc_plus_diff for aarch64
58
target/arm: Introduce gen_pc_plus_diff for aarch32
59
target/arm: Enable TARGET_TB_PCREL
60
68
61
target/arm/cpu-param.h | 17 +-
69
Richard Henderson (6):
62
target/arm/cpu.h | 47 ++--
70
linux-user/aarch64: Choose SYNC as the preferred MTE mode
63
target/arm/internals.h | 1 +
71
target/arm: Fix nregs computation in do_{ld,st}_zpa
64
target/arm/sve_ldst_internal.h | 1 +
72
target/arm: Adjust and validate mtedesc sizem1
65
target/arm/translate-a32.h | 2 +-
73
target/arm: Split out make_svemte_desc
66
target/arm/translate.h | 66 ++++-
74
target/arm: Handle mte in do_ldrq, do_ldro
67
hw/char/pl011.c | 2 +-
75
target/arm: Fix SVE/SME gross MTE suppression checks
68
hw/ide/microdrive.c | 8 +-
69
target/arm/cpu.c | 23 +-
70
target/arm/cpu_tcg.c | 4 +-
71
target/arm/helper.c | 155 +++++++++---
72
target/arm/mte_helper.c | 62 ++---
73
target/arm/ptw.c | 535 +++++++++++++++++++++++++----------------
74
target/arm/sve_helper.c | 54 ++---
75
target/arm/tlb_helper.c | 24 +-
76
target/arm/translate-a64.c | 220 ++++++++++-------
77
target/arm/translate-m-nocp.c | 8 +-
78
target/arm/translate-mve.c | 2 +-
79
target/arm/translate-vfp.c | 10 +-
80
target/arm/translate.c | 284 +++++++++++++---------
81
20 files changed, 918 insertions(+), 607 deletions(-)
82
76
77
MAINTAINERS | 3 +-
78
docs/system/arm/mps2.rst | 37 +-
79
configs/devices/arm-softmmu/default.mak | 1 +
80
hw/arm/smmuv3-internal.h | 1 +
81
include/hw/arm/smmu-common.h | 1 +
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
New patch
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
2
3
Similarly to commits dadbb58f59..5ae79fe825 for other ARM boards,
4
connect FIQ output of the GIC CPU interfaces to the CPU.
5
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20240130152548.17855-1-philmd@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/xilinx_zynq.c | 2 ++
12
1 file changed, 2 insertions(+)
13
14
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/xilinx_zynq.c
17
+++ b/hw/arm/xilinx_zynq.c
18
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
19
sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE);
20
sysbus_connect_irq(busdev, 0,
21
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
22
+ sysbus_connect_irq(busdev, 1,
23
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ));
24
25
for (n = 0; n < 64; n++) {
26
pic[n] = qdev_get_gpio_in(dev, n);
27
--
28
2.34.1
29
30
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not yet used, but add mmu indexes for 1-1 mapping
3
The API does not generate an error for setting ASYNC | SYNC; that merely
4
to physical addresses.
4
constrains the selection vs the per-cpu default. For qemu linux-user,
5
choose SYNC as the default.
5
6
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Cc: qemu-stable@nongnu.org
8
Reported-by: Gustavo Romero <gustavo.romero@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20221011031911.2408754-5-richard.henderson@linaro.org
10
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
11
Message-id: 20240207025210.8837-2-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
target/arm/cpu-param.h | 2 +-
14
linux-user/aarch64/target_prctl.h | 29 +++++++++++++++++------------
12
target/arm/cpu.h | 7 ++++++-
15
1 file changed, 17 insertions(+), 12 deletions(-)
13
target/arm/ptw.c | 19 +++++++++++++++++--
14
3 files changed, 24 insertions(+), 4 deletions(-)
15
16
16
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
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/target/arm/cpu-param.h
19
--- a/linux-user/aarch64/target_prctl.h
19
+++ b/target/arm/cpu-param.h
20
+++ b/linux-user/aarch64/target_prctl.h
20
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_set_tagged_addr_ctrl(CPUArchState *env, abi_long arg2)
21
bool guarded;
22
env->tagged_addr_enable = arg2 & PR_TAGGED_ADDR_ENABLE;
22
#endif
23
23
24
if (cpu_isar_feature(aa64_mte, cpu)) {
24
-#define NB_MMU_MODES 8
25
- switch (arg2 & PR_MTE_TCF_MASK) {
25
+#define NB_MMU_MODES 10
26
- case PR_MTE_TCF_NONE:
26
27
- case PR_MTE_TCF_SYNC:
27
#endif
28
- case PR_MTE_TCF_ASYNC:
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
- break;
29
index XXXXXXX..XXXXXXX 100644
30
- default:
30
--- a/target/arm/cpu.h
31
- return -EINVAL;
31
+++ b/target/arm/cpu.h
32
- }
32
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
33
-
33
* EL2 EL2&0 +PAN
34
/*
34
* EL2 (aka NS PL2)
35
* Write PR_MTE_TCF to SCTLR_EL1[TCF0].
35
* EL3 (aka S PL1)
36
- * Note that the syscall values are consistent with hw.
36
+ * Physical (NS & S)
37
+ *
37
*
38
+ * The kernel has a per-cpu configuration for the sysadmin,
38
- * for a total of 8 different mmu_idx.
39
+ * /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred,
39
+ * for a total of 10 different mmu_idx.
40
+ * which qemu does not implement.
40
*
41
+ *
41
* R profile CPUs have an MPU, but can use the same set of MMU indexes
42
+ * Because there is no performance difference between the modes, and
42
* as A profile. They only need to distinguish EL0 and EL1 (and
43
+ * because SYNC is most useful for debugging MTE errors, choose SYNC
43
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
44
+ * as the preferred mode. With this preference, and the way the API
44
ARMMMUIdx_E2 = 6 | ARM_MMU_IDX_A,
45
+ * uses only two bits, there is no way for the program to select
45
ARMMMUIdx_E3 = 7 | ARM_MMU_IDX_A,
46
+ * ASYMM mode.
46
47
*/
47
+ /* TLBs with 1-1 mapping to the physical address spaces. */
48
- env->cp15.sctlr_el[1] =
48
+ ARMMMUIdx_Phys_NS = 8 | ARM_MMU_IDX_A,
49
- deposit64(env->cp15.sctlr_el[1], 38, 2, arg2 >> PR_MTE_TCF_SHIFT);
49
+ ARMMMUIdx_Phys_S = 9 | ARM_MMU_IDX_A,
50
+ unsigned tcf = 0;
50
+
51
+ if (arg2 & PR_MTE_TCF_SYNC) {
51
/*
52
+ tcf = 1;
52
* These are not allocated TLBs and are used only for AT system
53
+ } else if (arg2 & PR_MTE_TCF_ASYNC) {
53
* instructions or for the first stage of an S12 page table walk.
54
+ tcf = 2;
54
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
55
+ }
55
index XXXXXXX..XXXXXXX 100644
56
+ env->cp15.sctlr_el[1] = deposit64(env->cp15.sctlr_el[1], 38, 2, tcf);
56
--- a/target/arm/ptw.c
57
57
+++ b/target/arm/ptw.c
58
/*
58
@@ -XXX,XX +XXX,XX @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
59
* Write PR_MTE_TAG to GCR_EL1[Exclude].
59
case ARMMMUIdx_E3:
60
break;
61
62
+ case ARMMMUIdx_Phys_NS:
63
+ case ARMMMUIdx_Phys_S:
64
+ /* No translation for physical address spaces. */
65
+ return true;
66
+
67
default:
68
g_assert_not_reached();
69
}
70
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
71
{
72
uint8_t memattr = 0x00; /* Device nGnRnE */
73
uint8_t shareability = 0; /* non-sharable */
74
+ int r_el;
75
76
- if (mmu_idx != ARMMMUIdx_Stage2 && mmu_idx != ARMMMUIdx_Stage2_S) {
77
- int r_el = regime_el(env, mmu_idx);
78
+ switch (mmu_idx) {
79
+ case ARMMMUIdx_Stage2:
80
+ case ARMMMUIdx_Stage2_S:
81
+ case ARMMMUIdx_Phys_NS:
82
+ case ARMMMUIdx_Phys_S:
83
+ break;
84
85
+ default:
86
+ r_el = regime_el(env, mmu_idx);
87
if (arm_el_is_aa64(env, r_el)) {
88
int pamax = arm_pamax(env_archcpu(env));
89
uint64_t tcr = env->cp15.tcr_el[r_el];
90
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
91
shareability = 2; /* outer sharable */
92
}
93
result->cacheattrs.is_s2_format = false;
94
+ break;
95
}
96
97
result->f.phys_addr = address;
98
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
99
is_secure = arm_is_secure_below_el3(env);
100
break;
101
case ARMMMUIdx_Stage2:
102
+ case ARMMMUIdx_Phys_NS:
103
case ARMMMUIdx_MPrivNegPri:
104
case ARMMMUIdx_MUserNegPri:
105
case ARMMMUIdx_MPriv:
106
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
107
break;
108
case ARMMMUIdx_E3:
109
case ARMMMUIdx_Stage2_S:
110
+ case ARMMMUIdx_Phys_S:
111
case ARMMMUIdx_MSPrivNegPri:
112
case ARMMMUIdx_MSUserNegPri:
113
case ARMMMUIdx_MSPriv:
114
--
60
--
115
2.25.1
61
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
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.
4
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
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20221020030641.2066807-7-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
17
---
10
target/arm/translate.c | 37 +++++++++++++++++++++----------------
18
target/arm/tcg/translate-sve.c | 16 ++++++++--------
11
1 file changed, 21 insertions(+), 16 deletions(-)
19
1 file changed, 8 insertions(+), 8 deletions(-)
12
20
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
21
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
23
--- a/target/arm/tcg/translate-sve.c
16
+++ b/target/arm/translate.c
24
+++ b/target/arm/tcg/translate-sve.c
17
@@ -XXX,XX +XXX,XX @@ static uint32_t read_pc(DisasContext *s)
25
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
18
return s->pc_curr + (s->thumb ? 4 : 8);
26
TCGv_ptr t_pg;
27
int desc = 0;
28
29
- /*
30
- * For e.g. LD4, there are not enough arguments to pass all 4
31
- * registers as pointers, so encode the regno into the data field.
32
- * For consistency, do this even for LD1.
33
- */
34
+ assert(mte_n >= 1 && mte_n <= 4);
35
if (s->mte_active[0]) {
36
int msz = dtype_msz(dtype);
37
38
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
39
addr = clean_data_tbi(s, addr);
40
}
41
42
+ /*
43
+ * For e.g. LD4, there are not enough arguments to pass all 4
44
+ * registers as pointers, so encode the regno into the data field.
45
+ * For consistency, do this even for LD1.
46
+ */
47
desc = simd_desc(vsz, vsz, zt | desc);
48
t_pg = tcg_temp_new_ptr();
49
50
@@ -XXX,XX +XXX,XX @@ static void do_ld_zpa(DisasContext *s, int zt, int pg,
51
* accessible via the instruction encoding.
52
*/
53
assert(fn != NULL);
54
- do_mem_zpa(s, zt, pg, addr, dtype, nreg, false, fn);
55
+ do_mem_zpa(s, zt, pg, addr, dtype, nreg + 1, false, fn);
19
}
56
}
20
57
21
+/* The pc_curr difference for an architectural jump. */
58
static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a)
22
+static target_long jmp_diff(DisasContext *s, target_long diff)
59
@@ -XXX,XX +XXX,XX @@ static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
23
+{
60
if (nreg == 0) {
24
+ return diff + (s->thumb ? 4 : 8);
61
/* ST1 */
25
+}
62
fn = fn_single[s->mte_active[0]][be][msz][esz];
26
+
63
- nreg = 1;
27
/* Set a variable to the value of a CPU register. */
64
} else {
28
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
65
/* ST2, ST3, ST4 -- msz == esz, enforced by encoding */
29
{
66
assert(msz == esz);
30
@@ -XXX,XX +XXX,XX @@ static void gen_goto_ptr(void)
67
fn = fn_multiple[s->mte_active[0]][be][nreg - 1][msz];
31
* cpu_loop_exec. Any live exit_requests will be processed as we
68
}
32
* enter the next TB.
69
assert(fn != NULL);
33
*/
70
- do_mem_zpa(s, zt, pg, addr, msz_dtype(s, msz), nreg, true, fn);
34
-static void gen_goto_tb(DisasContext *s, int n, int diff)
71
+ do_mem_zpa(s, zt, pg, addr, msz_dtype(s, msz), nreg + 1, true, fn);
35
+static void gen_goto_tb(DisasContext *s, int n, target_long diff)
36
{
37
target_ulong dest = s->pc_curr + diff;
38
39
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, int diff)
40
}
72
}
41
73
42
/* Jump, specifying which TB number to use if we gen_goto_tb() */
74
static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a)
43
-static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
44
+static void gen_jmp_tb(DisasContext *s, target_long diff, int tbno)
45
{
46
- int diff = dest - s->pc_curr;
47
-
48
if (unlikely(s->ss_active)) {
49
/* An indirect jump so that we still trigger the debug exception. */
50
gen_update_pc(s, diff);
51
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
52
}
53
}
54
55
-static inline void gen_jmp(DisasContext *s, uint32_t dest)
56
+static inline void gen_jmp(DisasContext *s, target_long diff)
57
{
58
- gen_jmp_tb(s, dest, 0);
59
+ gen_jmp_tb(s, diff, 0);
60
}
61
62
static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
63
@@ -XXX,XX +XXX,XX @@ static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
64
65
static bool trans_B(DisasContext *s, arg_i *a)
66
{
67
- gen_jmp(s, read_pc(s) + a->imm);
68
+ gen_jmp(s, jmp_diff(s, a->imm));
69
return true;
70
}
71
72
@@ -XXX,XX +XXX,XX @@ static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
73
return true;
74
}
75
arm_skip_unless(s, a->cond);
76
- gen_jmp(s, read_pc(s) + a->imm);
77
+ gen_jmp(s, jmp_diff(s, a->imm));
78
return true;
79
}
80
81
static bool trans_BL(DisasContext *s, arg_i *a)
82
{
83
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
84
- gen_jmp(s, read_pc(s) + a->imm);
85
+ gen_jmp(s, jmp_diff(s, a->imm));
86
return true;
87
}
88
89
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
90
}
91
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
92
store_cpu_field_constant(!s->thumb, thumb);
93
- gen_jmp(s, (read_pc(s) & ~3) + a->imm);
94
+ /* This jump is computed from an aligned PC: subtract off the low bits. */
95
+ gen_jmp(s, jmp_diff(s, a->imm - (s->pc_curr & 3)));
96
return true;
97
}
98
99
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
100
* when we take this upcoming exit from this TB, so gen_jmp_tb() is OK.
101
*/
102
}
103
- gen_jmp_tb(s, s->base.pc_next, 1);
104
+ gen_jmp_tb(s, curr_insn_len(s), 1);
105
106
gen_set_label(nextlabel);
107
- gen_jmp(s, read_pc(s) + a->imm);
108
+ gen_jmp(s, jmp_diff(s, a->imm));
109
return true;
110
}
111
112
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
113
114
if (a->f) {
115
/* Loop-forever: just jump back to the loop start */
116
- gen_jmp(s, read_pc(s) - a->imm);
117
+ gen_jmp(s, jmp_diff(s, -a->imm));
118
return true;
119
}
120
121
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
122
tcg_temp_free_i32(decr);
123
}
124
/* Jump back to the loop start */
125
- gen_jmp(s, read_pc(s) - a->imm);
126
+ gen_jmp(s, jmp_diff(s, -a->imm));
127
128
gen_set_label(loopend);
129
if (a->tp) {
130
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
131
store_cpu_field(tcg_constant_i32(4), v7m.ltpsize);
132
}
133
/* End TB, continuing to following insn */
134
- gen_jmp_tb(s, s->base.pc_next, 1);
135
+ gen_jmp_tb(s, curr_insn_len(s), 1);
136
return true;
137
}
138
139
@@ -XXX,XX +XXX,XX @@ static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
140
tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
141
tmp, 0, s->condlabel);
142
tcg_temp_free_i32(tmp);
143
- gen_jmp(s, read_pc(s) + a->imm);
144
+ gen_jmp(s, jmp_diff(s, a->imm));
145
return true;
146
}
147
148
--
75
--
149
2.25.1
76
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add a field to TARGET_PAGE_ENTRY_EXTRA to hold the guarded bit.
3
When we added SVE_MTEDESC_SHIFT, we effectively limited the
4
In is_guarded_page, use probe_access_full instead of just guessing
4
maximum size of MTEDESC. Adjust SIZEM1 to consume the remaining
5
that the tlb entry is still present. Also handles the FIXME about
5
bits (32 - 10 - 5 - 12 == 5). Assert that the data to be stored
6
executing from device memory.
6
fits within the field (expecting 8 * 4 - 1 == 31, exact fit).
7
7
8
Cc: qemu-stable@nongnu.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20221011031911.2408754-4-richard.henderson@linaro.org
11
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
12
Message-id: 20240207025210.8837-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
14
---
13
target/arm/cpu-param.h | 9 +++++----
15
target/arm/internals.h | 2 +-
14
target/arm/cpu.h | 13 -------------
16
target/arm/tcg/translate-sve.c | 7 ++++---
15
target/arm/internals.h | 1 +
17
2 files changed, 5 insertions(+), 4 deletions(-)
16
target/arm/ptw.c | 7 ++++---
17
target/arm/translate-a64.c | 21 ++++++++++-----------
18
5 files changed, 20 insertions(+), 31 deletions(-)
19
18
20
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu-param.h
23
+++ b/target/arm/cpu-param.h
24
@@ -XXX,XX +XXX,XX @@
25
*
26
* For ARMMMUIdx_Stage2*, pte_attrs is the S2 descriptor bits [5:2].
27
* Otherwise, pte_attrs is the same as the MAIR_EL1 8-bit format.
28
- * For shareability, as in the SH field of the VMSAv8-64 PTEs.
29
+ * For shareability and guarded, as in the SH and GP fields respectively
30
+ * of the VMSAv8-64 PTEs.
31
*/
32
# define TARGET_PAGE_ENTRY_EXTRA \
33
- uint8_t pte_attrs; \
34
- uint8_t shareability;
35
-
36
+ uint8_t pte_attrs; \
37
+ uint8_t shareability; \
38
+ bool guarded;
39
#endif
40
41
#define NB_MMU_MODES 8
42
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/cpu.h
45
+++ b/target/arm/cpu.h
46
@@ -XXX,XX +XXX,XX @@ static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
47
/* Shared between translate-sve.c and sve_helper.c. */
48
extern const uint64_t pred_esz_masks[5];
49
50
-/* Helper for the macros below, validating the argument type. */
51
-static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
52
-{
53
- return x;
54
-}
55
-
56
-/*
57
- * Lvalue macros for ARM TLB bits that we must cache in the TCG TLB.
58
- * Using these should be a bit more self-documenting than using the
59
- * generic target bits directly.
60
- */
61
-#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
62
-
63
/*
64
* AArch64 usage of the PAGE_TARGET_* bits for linux-user.
65
* Note that with the Linux kernel, PROT_MTE may not be cleared by mprotect
66
diff --git a/target/arm/internals.h b/target/arm/internals.h
19
diff --git a/target/arm/internals.h b/target/arm/internals.h
67
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/internals.h
21
--- a/target/arm/internals.h
69
+++ b/target/arm/internals.h
22
+++ b/target/arm/internals.h
70
@@ -XXX,XX +XXX,XX @@ typedef struct ARMCacheAttrs {
23
@@ -XXX,XX +XXX,XX @@ FIELD(MTEDESC, TBI, 4, 2)
71
unsigned int attrs:8;
24
FIELD(MTEDESC, TCMA, 6, 2)
72
unsigned int shareability:2; /* as in the SH field of the VMSAv8-64 PTEs */
25
FIELD(MTEDESC, WRITE, 8, 1)
73
bool is_s2_format:1;
26
FIELD(MTEDESC, ALIGN, 9, 3)
74
+ bool guarded:1; /* guarded bit of the v8-64 PTE */
27
-FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12) /* size - 1 */
75
} ARMCacheAttrs;
28
+FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - SVE_MTEDESC_SHIFT - 12) /* size - 1 */
76
29
77
/* Fields that are valid upon success. */
30
bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr);
78
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
31
uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra);
32
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
79
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
80
--- a/target/arm/ptw.c
34
--- a/target/arm/tcg/translate-sve.c
81
+++ b/target/arm/ptw.c
35
+++ b/target/arm/tcg/translate-sve.c
82
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
36
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
83
*/
37
{
84
result->f.attrs.secure = false;
38
unsigned vsz = vec_full_reg_size(s);
85
}
39
TCGv_ptr t_pg;
86
- /* When in aarch64 mode, and BTI is enabled, remember GP in the IOTLB. */
40
+ uint32_t sizem1;
87
- if (aarch64 && guarded && cpu_isar_feature(aa64_bti, cpu)) {
41
int desc = 0;
88
- arm_tlb_bti_gp(&result->f.attrs) = true;
42
89
+
43
assert(mte_n >= 1 && mte_n <= 4);
90
+ /* When in aarch64 mode, and BTI is enabled, remember GP in the TLB. */
44
+ sizem1 = (mte_n << dtype_msz(dtype)) - 1;
91
+ if (aarch64 && cpu_isar_feature(aa64_bti, cpu)) {
45
+ assert(sizem1 <= R_MTEDESC_SIZEM1_MASK >> R_MTEDESC_SIZEM1_SHIFT);
92
+ result->f.guarded = guarded;
46
if (s->mte_active[0]) {
93
}
47
- int msz = dtype_msz(dtype);
94
48
-
95
if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
49
desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s));
96
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
50
desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
97
index XXXXXXX..XXXXXXX 100644
51
desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
98
--- a/target/arm/translate-a64.c
52
desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
99
+++ b/target/arm/translate-a64.c
53
- desc = FIELD_DP32(desc, MTEDESC, SIZEM1, (mte_n << msz) - 1);
100
@@ -XXX,XX +XXX,XX @@ static bool is_guarded_page(CPUARMState *env, DisasContext *s)
54
+ desc = FIELD_DP32(desc, MTEDESC, SIZEM1, sizem1);
101
#ifdef CONFIG_USER_ONLY
55
desc <<= SVE_MTEDESC_SHIFT;
102
return page_get_flags(addr) & PAGE_BTI;
56
} else {
103
#else
57
addr = clean_data_tbi(s, addr);
104
+ CPUTLBEntryFull *full;
105
+ void *host;
106
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
107
- unsigned int index = tlb_index(env, mmu_idx, addr);
108
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
109
+ int flags;
110
111
/*
112
* We test this immediately after reading an insn, which means
113
- * that any normal page must be in the TLB. The only exception
114
- * would be for executing from flash or device memory, which
115
- * does not retain the TLB entry.
116
- *
117
- * FIXME: Assume false for those, for now. We could use
118
- * arm_cpu_get_phys_page_attrs_debug to re-read the page
119
- * table entry even for that case.
120
+ * that the TLB entry must be present and valid, and thus this
121
+ * access will never raise an exception.
122
*/
123
- return (tlb_hit(entry->addr_code, addr) &&
124
- arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].fulltlb[index].attrs));
125
+ flags = probe_access_full(env, addr, MMU_INST_FETCH, mmu_idx,
126
+ false, &host, &full, 0);
127
+ assert(!(flags & TLB_INVALID_MASK));
128
+
129
+ return full->guarded;
130
#endif
131
}
132
133
--
58
--
134
2.25.1
59
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Hoist this test out of arm_ld[lq]_ptw into S1_ptw_translate.
3
Share code that creates mtedesc and embeds within simd_desc.
4
4
5
Cc: qemu-stable@nongnu.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20221011031911.2408754-10-richard.henderson@linaro.org
8
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
9
Message-id: 20240207025210.8837-5-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
target/arm/ptw.c | 6 ++++--
12
target/arm/tcg/translate-a64.h | 2 ++
11
1 file changed, 4 insertions(+), 2 deletions(-)
13
target/arm/tcg/translate-sme.c | 15 +++--------
14
target/arm/tcg/translate-sve.c | 47 ++++++++++++++++++----------------
15
3 files changed, 31 insertions(+), 33 deletions(-)
12
16
13
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
17
diff --git a/target/arm/tcg/translate-a64.h b/target/arm/tcg/translate-a64.h
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/ptw.c
19
--- a/target/arm/tcg/translate-a64.h
16
+++ b/target/arm/ptw.c
20
+++ b/target/arm/tcg/translate-a64.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct S1Translate {
21
@@ -XXX,XX +XXX,XX @@ bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
18
bool in_secure;
22
bool sve_access_check(DisasContext *s);
19
bool in_debug;
23
bool sme_enabled_check(DisasContext *s);
20
bool out_secure;
24
bool sme_enabled_check_with_svcr(DisasContext *s, unsigned);
21
+ bool out_be;
25
+uint32_t make_svemte_desc(DisasContext *s, unsigned vsz, uint32_t nregs,
22
hwaddr out_phys;
26
+ uint32_t msz, bool is_write, uint32_t data);
23
} S1Translate;
27
24
28
/* This function corresponds to CheckStreamingSVEEnabled. */
25
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
29
static inline bool sme_sm_enabled_check(DisasContext *s)
26
30
diff --git a/target/arm/tcg/translate-sme.c b/target/arm/tcg/translate-sme.c
27
ptw->out_secure = is_secure;
31
index XXXXXXX..XXXXXXX 100644
28
ptw->out_phys = addr;
32
--- a/target/arm/tcg/translate-sme.c
29
+ ptw->out_be = regime_translation_big_endian(env, ptw->in_mmu_idx);
33
+++ b/target/arm/tcg/translate-sme.c
30
return true;
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));
31
}
153
}
32
154
33
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
34
addr = ptw->out_phys;
35
attrs.secure = ptw->out_secure;
36
as = arm_addressspace(cs, attrs);
37
- if (regime_translation_big_endian(env, ptw->in_mmu_idx)) {
38
+ if (ptw->out_be) {
39
data = address_space_ldl_be(as, addr, attrs, &result);
40
} else {
41
data = address_space_ldl_le(as, addr, attrs, &result);
42
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
43
addr = ptw->out_phys;
44
attrs.secure = ptw->out_secure;
45
as = arm_addressspace(cs, attrs);
46
- if (regime_translation_big_endian(env, ptw->in_mmu_idx)) {
47
+ if (ptw->out_be) {
48
data = address_space_ldq_be(as, addr, attrs, &result);
49
} else {
50
data = address_space_ldq_le(as, addr, attrs, &result);
51
--
155
--
52
2.25.1
156
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
So far, limit the change to S1_ptw_translate, arm_ldl_ptw, and
3
These functions "use the standard load helpers", but
4
arm_ldq_ptw. Use probe_access_full to find the host address,
4
fail to clean_data_tbi or populate mtedesc.
5
and if so use a host load. If the probe fails, we've got our
6
fault info already. On the off chance that page tables are not
7
in RAM, continue to use the address_space_ld* functions.
8
5
6
Cc: qemu-stable@nongnu.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20221011031911.2408754-11-richard.henderson@linaro.org
9
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
10
Message-id: 20240207025210.8837-6-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
12
---
14
target/arm/cpu.h | 5 +
13
target/arm/tcg/translate-sve.c | 15 +++++++++++++--
15
target/arm/ptw.c | 196 +++++++++++++++++++++++++---------------
14
1 file changed, 13 insertions(+), 2 deletions(-)
16
target/arm/tlb_helper.c | 17 +++-
17
3 files changed, 144 insertions(+), 74 deletions(-)
18
15
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
18
--- a/target/arm/tcg/translate-sve.c
22
+++ b/target/arm/cpu.h
19
+++ b/target/arm/tcg/translate-sve.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMTBFlags {
20
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
24
target_ulong flags2;
21
unsigned vsz = vec_full_reg_size(s);
25
} CPUARMTBFlags;
22
TCGv_ptr t_pg;
26
23
int poff;
27
+typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
24
+ uint32_t desc;
28
+
25
29
typedef struct CPUArchState {
26
/* Load the first quadword using the normal predicated load helpers. */
30
/* Regs for current mode. */
27
+ if (!s->mte_active[0]) {
31
uint32_t regs[16];
28
+ addr = clean_data_tbi(s, addr);
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
33
struct CPUBreakpoint *cpu_breakpoint[16];
34
struct CPUWatchpoint *cpu_watchpoint[16];
35
36
+ /* Optional fault info across tlb lookup. */
37
+ ARMMMUFaultInfo *tlb_fi;
38
+
39
/* Fields up to this point are cleared by a CPU reset */
40
struct {} end_reset_fields;
41
42
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/ptw.c
45
+++ b/target/arm/ptw.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "qemu/osdep.h"
48
#include "qemu/log.h"
49
#include "qemu/range.h"
50
+#include "exec/exec-all.h"
51
#include "cpu.h"
52
#include "internals.h"
53
#include "idau.h"
54
@@ -XXX,XX +XXX,XX @@ typedef struct S1Translate {
55
bool out_secure;
56
bool out_be;
57
hwaddr out_phys;
58
+ void *out_host;
59
} S1Translate;
60
61
static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
62
@@ -XXX,XX +XXX,XX @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
63
return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
64
}
65
66
-static bool ptw_attrs_are_device(uint64_t hcr, ARMCacheAttrs cacheattrs)
67
+static bool S2_attrs_are_device(uint64_t hcr, uint8_t attrs)
68
{
69
/*
70
* For an S1 page table walk, the stage 1 attributes are always
71
@@ -XXX,XX +XXX,XX @@ static bool ptw_attrs_are_device(uint64_t hcr, ARMCacheAttrs cacheattrs)
72
* With HCR_EL2.FWB == 1 this is when descriptor bit [4] is 0, ie
73
* when cacheattrs.attrs bit [2] is 0.
74
*/
75
- assert(cacheattrs.is_s2_format);
76
if (hcr & HCR_FWB) {
77
- return (cacheattrs.attrs & 0x4) == 0;
78
+ return (attrs & 0x4) == 0;
79
} else {
80
- return (cacheattrs.attrs & 0xc) == 0;
81
+ return (attrs & 0xc) == 0;
82
}
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
86
hwaddr addr, ARMMMUFaultInfo *fi)
87
{
88
bool is_secure = ptw->in_secure;
89
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
90
ARMMMUIdx s2_mmu_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
91
+ bool s2_phys = false;
92
+ uint8_t pte_attrs;
93
+ bool pte_secure;
94
95
- if (arm_mmu_idx_is_stage1_of_2(ptw->in_mmu_idx) &&
96
- !regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
97
- GetPhysAddrResult s2 = {};
98
- S1Translate s2ptw = {
99
- .in_mmu_idx = s2_mmu_idx,
100
- .in_secure = is_secure,
101
- .in_debug = ptw->in_debug,
102
- };
103
- uint64_t hcr;
104
- int ret;
105
+ if (!arm_mmu_idx_is_stage1_of_2(mmu_idx)
106
+ || regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
107
+ s2_mmu_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
108
+ s2_phys = true;
109
+ }
110
111
- ret = get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
112
- false, &s2, fi);
113
- if (ret) {
114
- assert(fi->type != ARMFault_None);
115
- fi->s2addr = addr;
116
- fi->stage2 = true;
117
- fi->s1ptw = true;
118
- fi->s1ns = !is_secure;
119
- return false;
120
+ if (unlikely(ptw->in_debug)) {
121
+ /*
122
+ * From gdbstub, do not use softmmu so that we don't modify the
123
+ * state of the cpu at all, including softmmu tlb contents.
124
+ */
125
+ if (s2_phys) {
126
+ ptw->out_phys = addr;
127
+ pte_attrs = 0;
128
+ pte_secure = is_secure;
129
+ } else {
130
+ S1Translate s2ptw = {
131
+ .in_mmu_idx = s2_mmu_idx,
132
+ .in_secure = is_secure,
133
+ .in_debug = true,
134
+ };
135
+ GetPhysAddrResult s2 = { };
136
+ if (!get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
137
+ false, &s2, fi)) {
138
+ goto fail;
139
+ }
140
+ ptw->out_phys = s2.f.phys_addr;
141
+ pte_attrs = s2.cacheattrs.attrs;
142
+ pte_secure = s2.f.attrs.secure;
143
}
144
+ ptw->out_host = NULL;
145
+ } else {
146
+ CPUTLBEntryFull *full;
147
+ int flags;
148
149
- hcr = arm_hcr_el2_eff_secstate(env, is_secure);
150
- if ((hcr & HCR_PTW) && ptw_attrs_are_device(hcr, s2.cacheattrs)) {
151
+ env->tlb_fi = fi;
152
+ flags = probe_access_full(env, addr, MMU_DATA_LOAD,
153
+ arm_to_core_mmu_idx(s2_mmu_idx),
154
+ true, &ptw->out_host, &full, 0);
155
+ env->tlb_fi = NULL;
156
+
157
+ if (unlikely(flags & TLB_INVALID_MASK)) {
158
+ goto fail;
159
+ }
160
+ ptw->out_phys = full->phys_addr;
161
+ pte_attrs = full->pte_attrs;
162
+ pte_secure = full->attrs.secure;
163
+ }
29
+ }
164
+
30
+
165
+ if (!s2_phys) {
31
poff = pred_full_reg_offset(s, pg);
166
+ uint64_t hcr = arm_hcr_el2_eff_secstate(env, is_secure);
32
if (vsz > 16) {
167
+
33
/*
168
+ if ((hcr & HCR_PTW) && S2_attrs_are_device(hcr, pte_attrs)) {
34
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
169
/*
35
170
* PTW set and S1 walk touched S2 Device memory:
36
gen_helper_gvec_mem *fn
171
* generate Permission fault.
37
= ldr_fns[s->mte_active[0]][s->be_data == MO_BE][dtype][0];
172
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
38
- fn(tcg_env, t_pg, addr, tcg_constant_i32(simd_desc(16, 16, zt)));
173
fi->s1ns = !is_secure;
39
+ desc = make_svemte_desc(s, 16, 1, dtype_msz(dtype), false, zt);
174
return false;
40
+ fn(tcg_env, t_pg, addr, tcg_constant_i32(desc));
175
}
41
176
-
42
/* Replicate that first quadword. */
177
- if (arm_is_secure_below_el3(env)) {
43
if (vsz > 16) {
178
- /* Check if page table walk is to secure or non-secure PA space. */
44
@@ -XXX,XX +XXX,XX @@ static void do_ldro(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
179
- if (is_secure) {
45
unsigned vsz_r32;
180
- is_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
46
TCGv_ptr t_pg;
181
- } else {
47
int poff, doff;
182
- is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
48
+ uint32_t desc;
183
- }
49
184
- } else {
50
if (vsz < 32) {
185
- assert(!is_secure);
51
/*
186
- }
52
@@ -XXX,XX +XXX,XX @@ static void do_ldro(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
187
-
188
- addr = s2.f.phys_addr;
189
}
53
}
190
54
191
- ptw->out_secure = is_secure;
55
/* Load the first octaword using the normal predicated load helpers. */
192
- ptw->out_phys = addr;
56
+ if (!s->mte_active[0]) {
193
- ptw->out_be = regime_translation_big_endian(env, ptw->in_mmu_idx);
57
+ addr = clean_data_tbi(s, addr);
194
+ /* Check if page table walk is to secure or non-secure PA space. */
195
+ ptw->out_secure = (is_secure
196
+ && !(pte_secure
197
+ ? env->cp15.vstcr_el2 & VSTCR_SW
198
+ : env->cp15.vtcr_el2 & VTCR_NSW));
199
+ ptw->out_be = regime_translation_big_endian(env, mmu_idx);
200
return true;
201
+
202
+ fail:
203
+ assert(fi->type != ARMFault_None);
204
+ fi->s2addr = addr;
205
+ fi->stage2 = true;
206
+ fi->s1ptw = true;
207
+ fi->s1ns = !is_secure;
208
+ return false;
209
}
210
211
/* All loads done in the course of a page table walk go through here. */
212
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
213
ARMMMUFaultInfo *fi)
214
{
215
CPUState *cs = env_cpu(env);
216
- MemTxAttrs attrs = {};
217
- MemTxResult result = MEMTX_OK;
218
- AddressSpace *as;
219
uint32_t data;
220
221
if (!S1_ptw_translate(env, ptw, addr, fi)) {
222
+ /* Failure. */
223
+ assert(fi->s1ptw);
224
return 0;
225
}
226
- addr = ptw->out_phys;
227
- attrs.secure = ptw->out_secure;
228
- as = arm_addressspace(cs, attrs);
229
- if (ptw->out_be) {
230
- data = address_space_ldl_be(as, addr, attrs, &result);
231
+
232
+ if (likely(ptw->out_host)) {
233
+ /* Page tables are in RAM, and we have the host address. */
234
+ if (ptw->out_be) {
235
+ data = ldl_be_p(ptw->out_host);
236
+ } else {
237
+ data = ldl_le_p(ptw->out_host);
238
+ }
239
} else {
240
- data = address_space_ldl_le(as, addr, attrs, &result);
241
+ /* Page tables are in MMIO. */
242
+ MemTxAttrs attrs = { .secure = ptw->out_secure };
243
+ AddressSpace *as = arm_addressspace(cs, attrs);
244
+ MemTxResult result = MEMTX_OK;
245
+
246
+ if (ptw->out_be) {
247
+ data = address_space_ldl_be(as, ptw->out_phys, attrs, &result);
248
+ } else {
249
+ data = address_space_ldl_le(as, ptw->out_phys, attrs, &result);
250
+ }
251
+ if (unlikely(result != MEMTX_OK)) {
252
+ fi->type = ARMFault_SyncExternalOnWalk;
253
+ fi->ea = arm_extabort_type(result);
254
+ return 0;
255
+ }
256
}
257
- if (result == MEMTX_OK) {
258
- return data;
259
- }
260
- fi->type = ARMFault_SyncExternalOnWalk;
261
- fi->ea = arm_extabort_type(result);
262
- return 0;
263
+ return data;
264
}
265
266
static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
267
ARMMMUFaultInfo *fi)
268
{
269
CPUState *cs = env_cpu(env);
270
- MemTxAttrs attrs = {};
271
- MemTxResult result = MEMTX_OK;
272
- AddressSpace *as;
273
uint64_t data;
274
275
if (!S1_ptw_translate(env, ptw, addr, fi)) {
276
+ /* Failure. */
277
+ assert(fi->s1ptw);
278
return 0;
279
}
280
- addr = ptw->out_phys;
281
- attrs.secure = ptw->out_secure;
282
- as = arm_addressspace(cs, attrs);
283
- if (ptw->out_be) {
284
- data = address_space_ldq_be(as, addr, attrs, &result);
285
+
286
+ if (likely(ptw->out_host)) {
287
+ /* Page tables are in RAM, and we have the host address. */
288
+ if (ptw->out_be) {
289
+ data = ldq_be_p(ptw->out_host);
290
+ } else {
291
+ data = ldq_le_p(ptw->out_host);
292
+ }
293
} else {
294
- data = address_space_ldq_le(as, addr, attrs, &result);
295
+ /* Page tables are in MMIO. */
296
+ MemTxAttrs attrs = { .secure = ptw->out_secure };
297
+ AddressSpace *as = arm_addressspace(cs, attrs);
298
+ MemTxResult result = MEMTX_OK;
299
+
300
+ if (ptw->out_be) {
301
+ data = address_space_ldq_be(as, ptw->out_phys, attrs, &result);
302
+ } else {
303
+ data = address_space_ldq_le(as, ptw->out_phys, attrs, &result);
304
+ }
305
+ if (unlikely(result != MEMTX_OK)) {
306
+ fi->type = ARMFault_SyncExternalOnWalk;
307
+ fi->ea = arm_extabort_type(result);
308
+ return 0;
309
+ }
310
}
311
- if (result == MEMTX_OK) {
312
- return data;
313
- }
314
- fi->type = ARMFault_SyncExternalOnWalk;
315
- fi->ea = arm_extabort_type(result);
316
- return 0;
317
+ return data;
318
}
319
320
static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
321
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
322
index XXXXXXX..XXXXXXX 100644
323
--- a/target/arm/tlb_helper.c
324
+++ b/target/arm/tlb_helper.c
325
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
326
bool probe, uintptr_t retaddr)
327
{
328
ARMCPU *cpu = ARM_CPU(cs);
329
- ARMMMUFaultInfo fi = {};
330
GetPhysAddrResult res = {};
331
+ ARMMMUFaultInfo local_fi, *fi;
332
int ret;
333
334
+ /*
335
+ * Allow S1_ptw_translate to see any fault generated here.
336
+ * Since this may recurse, read and clear.
337
+ */
338
+ fi = cpu->env.tlb_fi;
339
+ if (fi) {
340
+ cpu->env.tlb_fi = NULL;
341
+ } else {
342
+ fi = memset(&local_fi, 0, sizeof(local_fi));
343
+ }
58
+ }
344
+
59
60
poff = pred_full_reg_offset(s, pg);
61
if (vsz > 32) {
62
@@ -XXX,XX +XXX,XX @@ static void do_ldro(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype)
63
64
gen_helper_gvec_mem *fn
65
= ldr_fns[s->mte_active[0]][s->be_data == MO_BE][dtype][0];
66
- fn(tcg_env, t_pg, addr, tcg_constant_i32(simd_desc(32, 32, zt)));
67
+ desc = make_svemte_desc(s, 32, 1, dtype_msz(dtype), false, zt);
68
+ fn(tcg_env, t_pg, addr, tcg_constant_i32(desc));
69
345
/*
70
/*
346
* Walk the page table and (if the mapping exists) add the page
71
* Replicate that first octaword.
347
* to the TLB. On success, return true. Otherwise, if probing,
348
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
349
*/
350
ret = get_phys_addr(&cpu->env, address, access_type,
351
core_to_arm_mmu_idx(&cpu->env, mmu_idx),
352
- &res, &fi);
353
+ &res, fi);
354
if (likely(!ret)) {
355
/*
356
* Map a single [sub]page. Regions smaller than our declared
357
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
358
} else {
359
/* now we have a real cpu fault */
360
cpu_restore_state(cs, retaddr, true);
361
- arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi);
362
+ arm_deliver_fault(cpu, address, access_type, mmu_idx, fi);
363
}
364
}
365
#else
366
--
72
--
367
2.25.1
73
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The CPUTLBEntryFull structure now stores the original pte attributes, as
3
The TBI and TCMA bits are located within mtedesc, not desc.
4
well as the physical address. Therefore, we no longer need a separate
5
bit in MemTxAttrs, nor do we need to walk the tree of memory regions.
6
4
5
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20221011031911.2408754-3-richard.henderson@linaro.org
8
Tested-by: Gustavo Romero <gustavo.romero@linaro.org>
9
Message-id: 20240207025210.8837-7-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/cpu.h | 1 -
12
target/arm/tcg/sme_helper.c | 8 ++++----
13
target/arm/sve_ldst_internal.h | 1 +
13
target/arm/tcg/sve_helper.c | 12 ++++++------
14
target/arm/mte_helper.c | 62 ++++++++++------------------------
14
2 files changed, 10 insertions(+), 10 deletions(-)
15
target/arm/sve_helper.c | 54 ++++++++++-------------------
16
target/arm/tlb_helper.c | 4 ---
17
5 files changed, 36 insertions(+), 86 deletions(-)
18
15
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
18
--- a/target/arm/tcg/sme_helper.c
22
+++ b/target/arm/cpu.h
19
+++ b/target/arm/tcg/sme_helper.c
23
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
20
@@ -XXX,XX +XXX,XX @@ void sme_ld1_mte(CPUARMState *env, void *za, uint64_t *vg,
24
* generic target bits directly.
21
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
25
*/
22
26
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
23
/* Perform gross MTE suppression early. */
27
-#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
24
- if (!tbi_check(desc, bit55) ||
28
25
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
29
/*
26
+ if (!tbi_check(mtedesc, bit55) ||
30
* AArch64 usage of the PAGE_TARGET_* bits for linux-user.
27
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
31
diff --git a/target/arm/sve_ldst_internal.h b/target/arm/sve_ldst_internal.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/sve_ldst_internal.h
34
+++ b/target/arm/sve_ldst_internal.h
35
@@ -XXX,XX +XXX,XX @@ typedef struct {
36
void *host;
37
int flags;
38
MemTxAttrs attrs;
39
+ bool tagged;
40
} SVEHostPage;
41
42
bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
43
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/mte_helper.c
46
+++ b/target/arm/mte_helper.c
47
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
48
TARGET_PAGE_BITS - LOG2_TAG_GRANULE - 1);
49
return tags + index;
50
#else
51
- uintptr_t index;
52
CPUTLBEntryFull *full;
53
+ MemTxAttrs attrs;
54
int in_page, flags;
55
- ram_addr_t ptr_ra;
56
hwaddr ptr_paddr, tag_paddr, xlat;
57
MemoryRegion *mr;
58
ARMASIdx tag_asi;
59
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
60
* valid. Indicate to probe_access_flags no-fault, then assert that
61
* we received a valid page.
62
*/
63
- flags = probe_access_flags(env, ptr, ptr_access, ptr_mmu_idx,
64
- ra == 0, &host, ra);
65
+ flags = probe_access_full(env, ptr, ptr_access, ptr_mmu_idx,
66
+ ra == 0, &host, &full, ra);
67
assert(!(flags & TLB_INVALID_MASK));
68
69
- /*
70
- * Find the CPUTLBEntryFull for ptr. This *must* be present in the TLB
71
- * because we just found the mapping.
72
- * TODO: Perhaps there should be a cputlb helper that returns a
73
- * matching tlb entry + iotlb entry.
74
- */
75
- index = tlb_index(env, ptr_mmu_idx, ptr);
76
-# ifdef CONFIG_DEBUG_TCG
77
- {
78
- CPUTLBEntry *entry = tlb_entry(env, ptr_mmu_idx, ptr);
79
- target_ulong comparator = (ptr_access == MMU_DATA_LOAD
80
- ? entry->addr_read
81
- : tlb_addr_write(entry));
82
- g_assert(tlb_hit(comparator, ptr));
83
- }
84
-# endif
85
- full = &env_tlb(env)->d[ptr_mmu_idx].fulltlb[index];
86
-
87
/* If the virtual page MemAttr != Tagged, access unchecked. */
88
- if (!arm_tlb_mte_tagged(&full->attrs)) {
89
+ if (full->pte_attrs != 0xf0) {
90
return NULL;
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
94
return NULL;
95
}
96
97
+ /*
98
+ * Remember these values across the second lookup below,
99
+ * which may invalidate this pointer via tlb resize.
100
+ */
101
+ ptr_paddr = full->phys_addr;
102
+ attrs = full->attrs;
103
+ full = NULL;
104
+
105
/*
106
* The Normal memory access can extend to the next page. E.g. a single
107
* 8-byte access to the last byte of a page will check only the last
108
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
109
*/
110
in_page = -(ptr | TARGET_PAGE_MASK);
111
if (unlikely(ptr_size > in_page)) {
112
- void *ignore;
113
- flags |= probe_access_flags(env, ptr + in_page, ptr_access,
114
- ptr_mmu_idx, ra == 0, &ignore, ra);
115
+ flags |= probe_access_full(env, ptr + in_page, ptr_access,
116
+ ptr_mmu_idx, ra == 0, &host, &full, ra);
117
assert(!(flags & TLB_INVALID_MASK));
118
}
119
120
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
121
if (unlikely(flags & TLB_WATCHPOINT)) {
122
int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE;
123
assert(ra != 0);
124
- cpu_check_watchpoint(env_cpu(env), ptr, ptr_size,
125
- full->attrs, wp, ra);
126
+ cpu_check_watchpoint(env_cpu(env), ptr, ptr_size, attrs, wp, ra);
127
}
128
129
- /*
130
- * Find the physical address within the normal mem space.
131
- * The memory region lookup must succeed because TLB_MMIO was
132
- * not set in the cputlb lookup above.
133
- */
134
- mr = memory_region_from_host(host, &ptr_ra);
135
- tcg_debug_assert(mr != NULL);
136
- tcg_debug_assert(memory_region_is_ram(mr));
137
- ptr_paddr = ptr_ra;
138
- do {
139
- ptr_paddr += mr->addr;
140
- mr = mr->container;
141
- } while (mr);
142
-
143
/* Convert to the physical address in tag space. */
144
tag_paddr = ptr_paddr >> (LOG2_TAG_GRANULE + 1);
145
146
/* Look up the address in tag space. */
147
- tag_asi = full->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
148
+ tag_asi = attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
149
tag_as = cpu_get_address_space(env_cpu(env), tag_asi);
150
mr = address_space_translate(tag_as, tag_paddr, &xlat, NULL,
151
- tag_access == MMU_DATA_STORE,
152
- full->attrs);
153
+ tag_access == MMU_DATA_STORE, attrs);
154
155
/*
156
* Note that @mr will never be NULL. If there is nothing in the address
157
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
158
index XXXXXXX..XXXXXXX 100644
159
--- a/target/arm/sve_helper.c
160
+++ b/target/arm/sve_helper.c
161
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
162
*/
163
addr = useronly_clean_ptr(addr);
164
165
+#ifdef CONFIG_USER_ONLY
166
flags = probe_access_flags(env, addr, access_type, mmu_idx, nofault,
167
&info->host, retaddr);
168
+ memset(&info->attrs, 0, sizeof(info->attrs));
169
+ /* Require both ANON and MTE; see allocation_tag_mem(). */
170
+ info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
171
+#else
172
+ CPUTLBEntryFull *full;
173
+ flags = probe_access_full(env, addr, access_type, mmu_idx, nofault,
174
+ &info->host, &full, retaddr);
175
+ info->attrs = full->attrs;
176
+ info->tagged = full->pte_attrs == 0xf0;
177
+#endif
178
info->flags = flags;
179
180
if (flags & TLB_INVALID_MASK) {
181
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
182
183
/* Ensure that info->host[] is relative to addr, not addr + mem_off. */
184
info->host -= mem_off;
185
-
186
-#ifdef CONFIG_USER_ONLY
187
- memset(&info->attrs, 0, sizeof(info->attrs));
188
- /* Require both MAP_ANON and PROT_MTE -- see allocation_tag_mem. */
189
- arm_tlb_mte_tagged(&info->attrs) =
190
- (flags & PAGE_ANON) && (flags & PAGE_MTE);
191
-#else
192
- /*
193
- * Find the iotlbentry for addr and return the transaction attributes.
194
- * This *must* be present in the TLB because we just found the mapping.
195
- */
196
- {
197
- uintptr_t index = tlb_index(env, mmu_idx, addr);
198
-
199
-# ifdef CONFIG_DEBUG_TCG
200
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
201
- target_ulong comparator = (access_type == MMU_DATA_LOAD
202
- ? entry->addr_read
203
- : tlb_addr_write(entry));
204
- g_assert(tlb_hit(comparator, addr));
205
-# endif
206
-
207
- CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
208
- info->attrs = full->attrs;
209
- }
210
-#endif
211
-
212
return true;
213
}
214
215
@@ -XXX,XX +XXX,XX @@ void sve_cont_ldst_mte_check(SVEContLdSt *info, CPUARMState *env,
216
intptr_t mem_off, reg_off, reg_last;
217
218
/* Process the page only if MemAttr == Tagged. */
219
- if (arm_tlb_mte_tagged(&info->page[0].attrs)) {
220
+ if (info->page[0].tagged) {
221
mem_off = info->mem_off_first[0];
222
reg_off = info->reg_off_first[0];
223
reg_last = info->reg_off_split;
224
@@ -XXX,XX +XXX,XX @@ void sve_cont_ldst_mte_check(SVEContLdSt *info, CPUARMState *env,
225
}
226
227
mem_off = info->mem_off_first[1];
228
- if (mem_off >= 0 && arm_tlb_mte_tagged(&info->page[1].attrs)) {
229
+ if (mem_off >= 0 && info->page[1].tagged) {
230
reg_off = info->reg_off_first[1];
231
reg_last = info->reg_off_last[1];
232
233
@@ -XXX,XX +XXX,XX @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr,
234
* Disable MTE checking if the Tagged bit is not set. Since TBI must
235
* be set within MTEDESC for MTE, !mtedesc => !mte_active.
236
*/
237
- if (!arm_tlb_mte_tagged(&info.page[0].attrs)) {
238
+ if (!info.page[0].tagged) {
239
mtedesc = 0;
28
mtedesc = 0;
240
}
29
}
241
30
242
@@ -XXX,XX +XXX,XX @@ void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
31
@@ -XXX,XX +XXX,XX @@ void sme_st1_mte(CPUARMState *env, void *za, uint64_t *vg, target_ulong addr,
243
cpu_check_watchpoint(env_cpu(env), addr, msize,
32
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
244
info.attrs, BP_MEM_READ, retaddr);
33
245
}
34
/* Perform gross MTE suppression early. */
246
- if (mtedesc && arm_tlb_mte_tagged(&info.attrs)) {
35
- if (!tbi_check(desc, bit55) ||
247
+ if (mtedesc && info.tagged) {
36
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
248
mte_check(env, mtedesc, addr, retaddr);
37
+ if (!tbi_check(mtedesc, bit55) ||
249
}
38
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
250
if (unlikely(info.flags & TLB_MMIO)) {
39
mtedesc = 0;
251
@@ -XXX,XX +XXX,XX @@ void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
40
}
252
msize, info.attrs,
41
253
BP_MEM_READ, retaddr);
42
diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c
254
}
255
- if (mtedesc && arm_tlb_mte_tagged(&info.attrs)) {
256
+ if (mtedesc && info.tagged) {
257
mte_check(env, mtedesc, addr, retaddr);
258
}
259
tlb_fn(env, &scratch, reg_off, addr, retaddr);
260
@@ -XXX,XX +XXX,XX @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
261
(env_cpu(env), addr, msize) & BP_MEM_READ)) {
262
goto fault;
263
}
264
- if (mtedesc &&
265
- arm_tlb_mte_tagged(&info.attrs) &&
266
- !mte_probe(env, mtedesc, addr)) {
267
+ if (mtedesc && info.tagged && !mte_probe(env, mtedesc, addr)) {
268
goto fault;
269
}
270
271
@@ -XXX,XX +XXX,XX @@ void sve_st1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
272
info.attrs, BP_MEM_WRITE, retaddr);
273
}
274
275
- if (mtedesc && arm_tlb_mte_tagged(&info.attrs)) {
276
+ if (mtedesc && info.tagged) {
277
mte_check(env, mtedesc, addr, retaddr);
278
}
279
}
280
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
281
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
282
--- a/target/arm/tlb_helper.c
44
--- a/target/arm/tcg/sve_helper.c
283
+++ b/target/arm/tlb_helper.c
45
+++ b/target/arm/tcg/sve_helper.c
284
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
46
@@ -XXX,XX +XXX,XX @@ void sve_ldN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr,
285
res.f.phys_addr &= TARGET_PAGE_MASK;
47
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
286
address &= TARGET_PAGE_MASK;
48
287
}
49
/* Perform gross MTE suppression early. */
288
- /* Notice and record tagged memory. */
50
- if (!tbi_check(desc, bit55) ||
289
- if (cpu_isar_feature(aa64_mte, cpu) && res.cacheattrs.attrs == 0xf0) {
51
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
290
- arm_tlb_mte_tagged(&res.f.attrs) = true;
52
+ if (!tbi_check(mtedesc, bit55) ||
291
- }
53
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
292
54
mtedesc = 0;
293
res.f.pte_attrs = res.cacheattrs.attrs;
55
}
294
res.f.shareability = res.cacheattrs.shareability;
56
57
@@ -XXX,XX +XXX,XX @@ void sve_ldnfff1_r_mte(CPUARMState *env, void *vg, target_ulong addr,
58
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
59
60
/* Perform gross MTE suppression early. */
61
- if (!tbi_check(desc, bit55) ||
62
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
63
+ if (!tbi_check(mtedesc, bit55) ||
64
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
65
mtedesc = 0;
66
}
67
68
@@ -XXX,XX +XXX,XX @@ void sve_stN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr,
69
desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
70
71
/* Perform gross MTE suppression early. */
72
- if (!tbi_check(desc, bit55) ||
73
- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
74
+ if (!tbi_check(mtedesc, bit55) ||
75
+ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
76
mtedesc = 0;
77
}
78
295
--
79
--
296
2.25.1
80
2.34.1
diff view generated by jsdifflib
New patch
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).
1
10
11
Fortunately raven_io_read() and raven_io_write() will correctly deal
12
with the case of being passed an unaligned address, so we can fix the
13
missing unaligned access support by setting .impl.unaligned in the
14
MemoryRegionOps struct.
15
16
Fixes: 9a1839164c9c8f06 ("raven: Implement non-contiguous I/O region")
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Tested-by: Cédric Le Goater <clg@redhat.com>
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(+)
24
25
diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/pci-host/raven.c
28
+++ b/hw/pci-host/raven.c
29
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps raven_io_ops = {
30
.write = raven_io_write,
31
.endianness = DEVICE_LITTLE_ENDIAN,
32
.impl.max_access_size = 4,
33
+ .impl.unaligned = true,
34
.valid.unaligned = true,
35
};
36
37
--
38
2.34.1
39
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
New patch
1
Allow changes to the virt GTDT -- we are going to add the IRQ
2
entry for a new timer to it.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
6
Message-id: 20240122143537.233498-2-peter.maydell@linaro.org
7
---
8
tests/qtest/bios-tables-test-allowed-diff.h | 2 ++
9
1 file changed, 2 insertions(+)
10
11
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qtest/bios-tables-test-allowed-diff.h
14
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
15
@@ -1 +1,3 @@
16
/* List of comma-separated changed AML files to ignore */
17
+"tests/data/acpi/virt/FACP",
18
+"tests/data/acpi/virt/GTDT",
19
--
20
2.34.1
diff view generated by jsdifflib
New patch
1
1
Armv8.1+ CPUs have the Virtual Host Extension (VHE) which adds a
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.)
31
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
34
Message-id: 20240122143537.233498-3-peter.maydell@linaro.org
35
---
36
include/hw/arm/virt.h | 2 ++
37
hw/arm/virt-acpi-build.c | 20 ++++++++++----
38
hw/arm/virt.c | 60 ++++++++++++++++++++++++++++++++++------
39
3 files changed, 67 insertions(+), 15 deletions(-)
40
41
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/hw/arm/virt.h
44
+++ b/include/hw/arm/virt.h
45
@@ -XXX,XX +XXX,XX @@ struct VirtMachineClass {
46
/* Machines < 6.2 have no support for describing cpu topology to guest */
47
bool no_cpu_topology;
48
bool no_tcg_lpa2;
49
+ bool no_ns_el2_virt_timer_irq;
50
};
51
52
struct VirtMachineState {
53
@@ -XXX,XX +XXX,XX @@ struct VirtMachineState {
54
PCIBus *bus;
55
char *oem_id;
56
char *oem_table_id;
57
+ bool ns_el2_virt_timer_irq;
58
};
59
60
#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
61
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/arm/virt-acpi-build.c
64
+++ b/hw/arm/virt-acpi-build.c
65
@@ -XXX,XX +XXX,XX @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
66
}
67
68
/*
69
- * ACPI spec, Revision 5.1
70
- * 5.2.24 Generic Timer Description Table (GTDT)
71
+ * ACPI spec, Revision 6.5
72
+ * 5.2.25 Generic Timer Description Table (GTDT)
73
*/
74
static void
75
build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
76
@@ -XXX,XX +XXX,XX @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
77
uint32_t irqflags = vmc->claim_edge_triggered_timers ?
78
1 : /* Interrupt is Edge triggered */
79
0; /* Interrupt is Level triggered */
80
- AcpiTable table = { .sig = "GTDT", .rev = 2, .oem_id = vms->oem_id,
81
+ AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
82
.oem_table_id = vms->oem_table_id };
83
84
acpi_table_begin(&table, table_data);
85
@@ -XXX,XX +XXX,XX @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
86
build_append_int_noprefix(table_data, 0, 4);
87
/* Platform Timer Offset */
88
build_append_int_noprefix(table_data, 0, 4);
89
-
90
+ if (vms->ns_el2_virt_timer_irq) {
91
+ /* Virtual EL2 Timer GSIV */
92
+ build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
93
+ /* Virtual EL2 Timer Flags */
94
+ build_append_int_noprefix(table_data, irqflags, 4);
95
+ } else {
96
+ build_append_int_noprefix(table_data, 0, 4);
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)
105
{
106
- /* ACPI v6.0 */
107
+ /* ACPI v6.3 */
108
AcpiFadtData fadt = {
109
.rev = 6,
110
- .minor_ver = 0,
111
+ .minor_ver = 3,
112
.flags = 1 << ACPI_FADT_F_HW_REDUCED_ACPI,
113
.xdsdt_tbl_offset = &dsdt_tbl_offset,
114
};
115
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/hw/arm/virt.c
118
+++ b/hw/arm/virt.c
119
@@ -XXX,XX +XXX,XX @@ static void create_randomness(MachineState *ms, const char *node)
120
qemu_fdt_setprop(ms->fdt, node, "rng-seed", seed.rng, sizeof(seed.rng));
121
}
122
123
+/*
124
+ * The CPU object always exposes the NS EL2 virt timer IRQ line,
125
+ * but we don't want to advertise it to the guest in the dtb or ACPI
126
+ * table unless it's really going to do something.
127
+ */
128
+static bool ns_el2_virt_timer_present(void)
129
+{
130
+ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(0));
131
+ CPUARMState *env = &cpu->env;
132
+
133
+ return arm_feature(env, ARM_FEATURE_AARCH64) &&
134
+ arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu);
135
+}
136
+
137
static void create_fdt(VirtMachineState *vms)
138
{
139
MachineState *ms = MACHINE(vms);
140
@@ -XXX,XX +XXX,XX @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
141
"arm,armv7-timer");
142
}
143
qemu_fdt_setprop(ms->fdt, "/timer", "always-on", NULL, 0);
144
- qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
145
- GIC_FDT_IRQ_TYPE_PPI,
146
- INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ), irqflags,
147
- GIC_FDT_IRQ_TYPE_PPI,
148
- INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ), irqflags,
149
- GIC_FDT_IRQ_TYPE_PPI,
150
- INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ), irqflags,
151
- GIC_FDT_IRQ_TYPE_PPI,
152
- INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ), irqflags);
153
+ if (vms->ns_el2_virt_timer_irq) {
154
+ qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
155
+ GIC_FDT_IRQ_TYPE_PPI,
156
+ INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ), irqflags,
157
+ GIC_FDT_IRQ_TYPE_PPI,
158
+ INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ), irqflags,
159
+ GIC_FDT_IRQ_TYPE_PPI,
160
+ INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ), irqflags,
161
+ GIC_FDT_IRQ_TYPE_PPI,
162
+ INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ), irqflags,
163
+ GIC_FDT_IRQ_TYPE_PPI,
164
+ INTID_TO_PPI(ARCH_TIMER_NS_EL2_VIRT_IRQ), irqflags);
165
+ } else {
166
+ qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
167
+ GIC_FDT_IRQ_TYPE_PPI,
168
+ INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ), irqflags,
169
+ GIC_FDT_IRQ_TYPE_PPI,
170
+ INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ), irqflags,
171
+ GIC_FDT_IRQ_TYPE_PPI,
172
+ INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ), irqflags,
173
+ GIC_FDT_IRQ_TYPE_PPI,
174
+ INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ), irqflags);
175
+ }
176
}
177
178
static void fdt_add_cpu_nodes(const VirtMachineState *vms)
179
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
180
[GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
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);
190
}
191
+
192
+ /* Now we've created the CPUs we can see if they have the hypvirt timer */
193
+ vms->ns_el2_virt_timer_irq = ns_el2_virt_timer_present() &&
194
+ !vmc->no_ns_el2_virt_timer_irq;
195
+
196
fdt_add_timer_nodes(vms);
197
fdt_add_cpu_nodes(vms);
198
199
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(9, 0)
200
201
static void virt_machine_8_2_options(MachineClass *mc)
202
{
203
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
204
+
205
virt_machine_9_0_options(mc);
206
compat_props_add(mc->compat_props, hw_compat_8_2, hw_compat_8_2_len);
207
+ /*
208
+ * Don't expose NS_EL2_VIRT timer IRQ in DTB on ACPI on 8.2 and
209
+ * earlier machines. (Exposing it tickles a bug in older EDK2
210
+ * guest BIOS binaries.)
211
+ */
212
+ vmc->no_ns_el2_virt_timer_irq = true;
213
}
214
DEFINE_VIRT_MACHINE(8, 2)
215
216
--
217
2.34.1
diff view generated by jsdifflib
New patch
1
1
Update the virt golden reference files to say that the FACP is ACPI
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 // ........
183
184
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
185
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
186
Message-id: 20240122143537.233498-4-peter.maydell@linaro.org
187
---
188
tests/qtest/bios-tables-test-allowed-diff.h | 2 --
189
tests/data/acpi/virt/FACP | Bin 276 -> 276 bytes
190
tests/data/acpi/virt/GTDT | Bin 96 -> 104 bytes
191
3 files changed, 2 deletions(-)
192
193
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
194
index XXXXXXX..XXXXXXX 100644
195
--- a/tests/qtest/bios-tables-test-allowed-diff.h
196
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
197
@@ -1,3 +1 @@
198
/* List of comma-separated changed AML files to ignore */
199
-"tests/data/acpi/virt/FACP",
200
-"tests/data/acpi/virt/GTDT",
201
diff --git a/tests/data/acpi/virt/FACP b/tests/data/acpi/virt/FACP
202
index XXXXXXX..XXXXXXX 100644
203
GIT binary patch
204
delta 25
205
gcmbQjG=+)F&CxkPgpq-PO=u!l<;2F$$vli407<0<)c^nh
206
207
delta 28
208
kcmbQjG=+)F&CxkPgpq-PO>`nx<-|!<6Akz$^DuG%0AAS!ssI20
209
210
diff --git a/tests/data/acpi/virt/GTDT b/tests/data/acpi/virt/GTDT
211
index XXXXXXX..XXXXXXX 100644
212
GIT binary patch
213
delta 25
214
bcmYeu;BpUf3CUn!U|^m+kt>V?$N&QXMtB4L
215
216
delta 16
217
Xcmc~u;BpUf2}xjJU|^avkt+-UB60)u
218
219
--
220
2.34.1
diff view generated by jsdifflib
New patch
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.
1
6
7
Add the missing call.
8
9
Fixes: 21e5326a7c ("hw/arm: Add GMAC devices to NPCM7XX SoC")
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
13
---
14
hw/arm/npcm7xx.c | 1 +
15
1 file changed, 1 insertion(+)
16
17
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/npcm7xx.c
20
+++ b/hw/arm/npcm7xx.c
21
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
22
for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
23
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->gmac[i]);
24
25
+ qemu_configure_nic_device(DEVICE(sbd), false, NULL);
26
/*
27
* The device exists regardless of whether it's connected to a QEMU
28
* netdev backend. So always instantiate it even if there is no
29
--
30
2.34.1
diff view generated by jsdifflib
New patch
1
Currently QEMU will warn if there is a NIC on the board that
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:
1
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.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
16
Reviewed-by: Thomas Huth <thuth@redhat.com>
17
Message-id: 20240206171231.396392-3-peter.maydell@linaro.org
18
---
19
tests/qtest/npcm7xx_emc-test.c | 5 ++++-
20
1 file changed, 4 insertions(+), 1 deletion(-)
21
22
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/tests/qtest/npcm7xx_emc-test.c
25
+++ b/tests/qtest/npcm7xx_emc-test.c
26
@@ -XXX,XX +XXX,XX @@ static int *packet_test_init(int module_num, GString *cmd_line)
27
* KISS and use -nic. The driver accepts 'emc0' and 'emc1' as aliases
28
* in the 'model' field to specify the device to match.
29
*/
30
- g_string_append_printf(cmd_line, " -nic socket,fd=%d,model=emc%d ",
31
+ g_string_append_printf(cmd_line, " -nic socket,fd=%d,model=emc%d "
32
+ "-nic user,model=npcm7xx-emc "
33
+ "-nic user,model=npcm-gmac "
34
+ "-nic user,model=npcm-gmac",
35
test_sockets[1], module_num);
36
37
g_test_queue_destroy(packet_test_clear, test_sockets);
38
--
39
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
It doesn't make sense to read the value of MDCR_EL2 on a non-A-profile
2
CPU, and in fact if you try to do it we will assert:
2
3
3
A simple helper to retrieve the length of the current insn.
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
4
9
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
We might call pmu_counter_enabled() on an M-profile CPU (for example
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
from the migration pre/post hooks in machine.c); this should always
7
Message-id: 20221020030641.2066807-2-richard.henderson@linaro.org
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20240208153346.970021-1-peter.maydell@linaro.org
9
---
26
---
10
target/arm/translate.h | 5 +++++
27
target/arm/helper.c | 12 ++++++++++--
11
target/arm/translate-vfp.c | 2 +-
28
1 file changed, 10 insertions(+), 2 deletions(-)
12
target/arm/translate.c | 5 ++---
13
3 files changed, 8 insertions(+), 4 deletions(-)
14
29
15
diff --git a/target/arm/translate.h b/target/arm/translate.h
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.h
32
--- a/target/arm/helper.c
18
+++ b/target/arm/translate.h
33
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
34
@@ -XXX,XX +XXX,XX @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
20
s->insn_start = NULL;
35
bool enabled, prohibited = false, filtered;
21
}
36
bool secure = arm_is_secure(env);
22
37
int el = arm_current_el(env);
23
+static inline int curr_insn_len(DisasContext *s)
38
- uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
24
+{
39
- uint8_t hpmn = mdcr_el2 & MDCR_HPMN;
25
+ return s->base.pc_next - s->pc_curr;
40
+ uint64_t mdcr_el2;
26
+}
41
+ uint8_t hpmn;
27
+
42
28
/* is_jmp field values */
43
+ /*
29
#define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
44
+ * We might be called for M-profile cores where MDCR_EL2 doesn't
30
/* CPU state was modified dynamically; exit to main loop for interrupts. */
45
+ * exist and arm_mdcr_el2_eff() will assert, so this early-exit check
31
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
46
+ * must be before we read that value.
32
index XXXXXXX..XXXXXXX 100644
47
+ */
33
--- a/target/arm/translate-vfp.c
48
if (!arm_feature(env, ARM_FEATURE_PMU)) {
34
+++ b/target/arm/translate-vfp.c
35
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
36
if (s->sme_trap_nonstreaming) {
37
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
38
syn_smetrap(SME_ET_Streaming,
39
- s->base.pc_next - s->pc_curr == 2));
40
+ curr_insn_len(s) == 2));
41
return false;
49
return false;
42
}
50
}
43
51
44
diff --git a/target/arm/translate.c b/target/arm/translate.c
52
+ mdcr_el2 = arm_mdcr_el2_eff(env);
45
index XXXXXXX..XXXXXXX 100644
53
+ hpmn = mdcr_el2 & MDCR_HPMN;
46
--- a/target/arm/translate.c
54
+
47
+++ b/target/arm/translate.c
55
if (!arm_feature(env, ARM_FEATURE_EL2) ||
48
@@ -XXX,XX +XXX,XX @@ static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
56
(counter < hpmn || counter == 31)) {
49
/* ISS not valid if writeback */
57
e = env->cp15.c9_pmcr & PMCRE;
50
if (p && !w) {
51
ret = rd;
52
- if (s->base.pc_next - s->pc_curr == 2) {
53
+ if (curr_insn_len(s) == 2) {
54
ret |= ISSIs16Bit;
55
}
56
} else {
57
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
58
/* nothing more to generate */
59
break;
60
case DISAS_WFI:
61
- gen_helper_wfi(cpu_env,
62
- tcg_constant_i32(dc->base.pc_next - dc->pc_curr));
63
+ gen_helper_wfi(cpu_env, tcg_constant_i32(curr_insn_len(dc)));
64
/*
65
* The helper doesn't necessarily throw an exception, but we
66
* must go back to the main loop to check for interrupts anyway.
67
--
58
--
68
2.25.1
59
2.34.1
69
60
70
61
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Nabih Estefan <nabihestefan@google.com>
2
2
3
The return type of the functions is already bool, but in a few
3
Fix the nocm_gmac-test.c file to run on a nuvoton 7xx machine instead
4
instances we used an integer type with the return statement.
4
of 8xx. Also fix comments referencing this and values expecting 8xx.
5
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
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
[PMM: commit message tweaks]
8
Message-id: 20221011031911.2408754-13-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
target/arm/ptw.c | 7 +++----
14
tests/qtest/npcm_gmac-test.c | 84 +-----------------------------------
12
1 file changed, 3 insertions(+), 4 deletions(-)
15
tests/qtest/meson.build | 3 +-
16
2 files changed, 4 insertions(+), 83 deletions(-)
13
17
14
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
18
diff --git a/tests/qtest/npcm_gmac-test.c b/tests/qtest/npcm_gmac-test.c
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/ptw.c
20
--- a/tests/qtest/npcm_gmac-test.c
17
+++ b/target/arm/ptw.c
21
+++ b/tests/qtest/npcm_gmac-test.c
18
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
22
@@ -XXX,XX +XXX,XX @@ typedef struct TestData {
19
result->f.lg_page_size = TARGET_PAGE_BITS;
23
const GMACModule *module;
20
result->cacheattrs.shareability = shareability;
24
} TestData;
21
result->cacheattrs.attrs = memattr;
25
22
- return 0;
26
-/* Values extracted from hw/arm/npcm8xx.c */
23
+ return false;
27
+/* Values extracted from hw/arm/npcm7xx.c */
28
static const GMACModule gmac_module_list[] = {
29
{
30
.irq = 14,
31
@@ -XXX,XX +XXX,XX @@ static const GMACModule gmac_module_list[] = {
32
.irq = 15,
33
.base_addr = 0xf0804000
34
},
35
- {
36
- .irq = 16,
37
- .base_addr = 0xf0806000
38
- },
39
- {
40
- .irq = 17,
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);
24
}
48
}
25
49
26
static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
50
-static uint16_t pcs_read(QTestState *qts, const GMACModule *mod,
27
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
51
- NPCMRegister regno)
52
-{
53
- uint32_t write_value = (regno & 0x3ffe00) >> 9;
54
- qtest_writel(qts, PCS_BASE_ADDRESS + NPCM_PCS_IND_AC_BA, write_value);
55
- uint32_t read_offset = regno & 0x1ff;
56
- return qtest_readl(qts, PCS_BASE_ADDRESS + read_offset);
57
-}
58
-
59
/* Check that GMAC registers are reset to default value */
60
static void test_init(gconstpointer test_data)
28
{
61
{
29
hwaddr ipa;
62
const TestData *td = test_data;
30
int s1_prot;
63
const GMACModule *mod = td->module;
31
- int ret;
64
- QTestState *qts = qtest_init("-machine npcm845-evb");
32
bool is_secure = ptw->in_secure;
65
+ QTestState *qts = qtest_init("-machine npcm750-evb");
33
- bool ipa_secure, s2walk_secure;
66
34
+ bool ret, ipa_secure, s2walk_secure;
67
#define CHECK_REG32(regno, value) \
35
ARMCacheAttrs cacheattrs1;
68
do { \
36
bool is_el0;
69
g_assert_cmphex(gmac_read(qts, mod, (regno)), ==, (value)); \
37
uint64_t hcr;
70
} while (0)
38
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
71
39
&& (ipa_secure
72
-#define CHECK_REG_PCS(regno, value) \
40
|| !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))));
73
- do { \
41
74
- g_assert_cmphex(pcs_read(qts, mod, (regno)), ==, (value)); \
42
- return 0;
75
- } while (0)
43
+ return false;
76
-
77
CHECK_REG32(NPCM_DMA_BUS_MODE, 0x00020100);
78
CHECK_REG32(NPCM_DMA_XMT_POLL_DEMAND, 0);
79
CHECK_REG32(NPCM_DMA_RCV_POLL_DEMAND, 0);
80
@@ -XXX,XX +XXX,XX @@ static void test_init(gconstpointer test_data)
81
CHECK_REG32(NPCM_GMAC_PTP_TAR, 0);
82
CHECK_REG32(NPCM_GMAC_PTP_TTSR, 0);
83
84
- /* TODO Add registers PCS */
85
- if (mod->base_addr == 0xf0802000) {
86
- CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID1, 0x699e);
87
- CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID2, 0);
88
- CHECK_REG_PCS(NPCM_PCS_SR_CTL_STS, 0x8000);
89
-
90
- CHECK_REG_PCS(NPCM_PCS_SR_MII_CTRL, 0x1140);
91
- CHECK_REG_PCS(NPCM_PCS_SR_MII_STS, 0x0109);
92
- CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID1, 0x699e);
93
- CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID2, 0x0ced0);
94
- CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_ADV, 0x0020);
95
- CHECK_REG_PCS(NPCM_PCS_SR_MII_LP_BABL, 0);
96
- CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_EXPN, 0);
97
- CHECK_REG_PCS(NPCM_PCS_SR_MII_EXT_STS, 0xc000);
98
-
99
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_ABL, 0x0003);
100
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_LWR, 0x0038);
101
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_UPR, 0);
102
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_LWR, 0x0038);
103
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_UPR, 0);
104
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_LWR, 0x0058);
105
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_UPR, 0);
106
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_LWR, 0x0048);
107
- CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_UPR, 0);
108
-
109
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MMD_DIG_CTRL1, 0x2400);
110
- CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_CTRL, 0);
111
- CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_INTR_STS, 0x000a);
112
- CHECK_REG_PCS(NPCM_PCS_VR_MII_TC, 0);
113
- CHECK_REG_PCS(NPCM_PCS_VR_MII_DBG_CTRL, 0);
114
- CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL0, 0x899c);
115
- CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_TXTIMER, 0);
116
- CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_RXTIMER, 0);
117
- CHECK_REG_PCS(NPCM_PCS_VR_MII_LINK_TIMER_CTRL, 0);
118
- CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL1, 0);
119
- CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_STS, 0x0010);
120
- CHECK_REG_PCS(NPCM_PCS_VR_MII_ICG_ERRCNT1, 0);
121
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MISC_STS, 0);
122
- CHECK_REG_PCS(NPCM_PCS_VR_MII_RX_LSTS, 0);
123
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_BSTCTRL0, 0x00a);
124
- CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_LVLCTRL0, 0x007f);
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);
140
- }
141
-
142
qtest_quit(qts);
44
}
143
}
45
144
46
static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
145
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
146
index XXXXXXX..XXXXXXX 100644
147
--- a/tests/qtest/meson.build
148
+++ b/tests/qtest/meson.build
149
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
150
'npcm7xx_sdhci-test',
151
'npcm7xx_smbus-test',
152
'npcm7xx_timer-test',
153
- 'npcm7xx_watchdog_timer-test'] + \
154
+ 'npcm7xx_watchdog_timer-test',
155
+ 'npcm_gmac-test'] + \
156
(slirp.found() ? ['npcm7xx_emc-test'] : [])
157
qtests_aspeed = \
158
['aspeed_hace-test',
47
--
159
--
48
2.25.1
160
2.34.1
diff view generated by jsdifflib
1
From: Baruch Siach <baruch@tkos.co.il>
1
From: Luc Michel <luc.michel@amd.com>
2
2
3
The PL011 TRM says that "UARTIBRD = 0 is invalid and UARTFBRD is ignored
3
An access fault is raised when the Access Flag is not set in the
4
when this is the case". But the code looks at FBRD for the invalid case.
4
looked-up PTE and the AFFD field is not set in the corresponding context
5
Fix this.
5
descriptor. This was already implemented for stage 2. Implement it for
6
stage 1 as well.
6
7
7
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
8
Signed-off-by: Luc Michel <luc.michel@amd.com>
8
Message-id: 1408f62a2e45665816527d4845ffde650957d5ab.1665051588.git.baruchs-c@neureality.ai
9
Reviewed-by: Mostafa Saleh <smostafa@google.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
15
---
12
hw/char/pl011.c | 2 +-
16
hw/arm/smmuv3-internal.h | 1 +
13
1 file changed, 1 insertion(+), 1 deletion(-)
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(+)
14
21
15
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
22
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/char/pl011.c
24
--- a/hw/arm/smmuv3-internal.h
18
+++ b/hw/char/pl011.c
25
+++ b/hw/arm/smmuv3-internal.h
19
@@ -XXX,XX +XXX,XX @@ static unsigned int pl011_get_baudrate(const PL011State *s)
26
@@ -XXX,XX +XXX,XX @@ static inline int pa_range(STE *ste)
20
{
27
#define CD_EPD(x, sel) extract32((x)->word[0], (16 * (sel)) + 14, 1)
21
uint64_t clk;
28
#define CD_ENDI(x) extract32((x)->word[0], 15, 1)
22
29
#define CD_IPS(x) extract32((x)->word[1], 0 , 3)
23
- if (s->fbrd == 0) {
30
+#define CD_AFFD(x) extract32((x)->word[1], 3 , 1)
24
+ if (s->ibrd == 0) {
31
#define CD_TBI(x) extract32((x)->word[1], 6 , 2)
25
return 0;
32
#define CD_HD(x) extract32((x)->word[1], 10 , 1)
26
}
33
#define CD_HA(x) extract32((x)->word[1], 11 , 1)
34
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/smmu-common.h
37
+++ b/include/hw/arm/smmu-common.h
38
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUTransCfg {
39
bool disabled; /* smmu is disabled */
40
bool bypassed; /* translation is bypassed */
41
bool aborted; /* translation is aborted */
42
+ bool affd; /* AF fault disable */
43
uint32_t iotlb_hits; /* counts IOTLB hits */
44
uint32_t iotlb_misses; /* counts IOTLB misses*/
45
/* Used by stage-1 only. */
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;
63
+ }
64
+
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);
27
79
28
--
80
--
29
2.25.1
81
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
In preparation for TARGET_TB_PCREL, reduce reliance on
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
absolute values by passing in pc difference.
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
5
Message-id: 20240213155214.13619-2-philmd@linaro.org
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20221020030641.2066807-4-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
7
---
11
target/arm/translate-a32.h | 2 +-
8
hw/arm/stellaris.c | 6 ++++--
12
target/arm/translate.h | 6 ++--
9
1 file changed, 4 insertions(+), 2 deletions(-)
13
target/arm/translate-a64.c | 32 +++++++++---------
14
target/arm/translate-vfp.c | 2 +-
15
target/arm/translate.c | 68 ++++++++++++++++++++------------------
16
5 files changed, 56 insertions(+), 54 deletions(-)
17
10
18
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
19
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate-a32.h
13
--- a/hw/arm/stellaris.c
21
+++ b/target/arm/translate-a32.h
14
+++ b/hw/arm/stellaris.c
22
@@ -XXX,XX +XXX,XX @@ void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop);
15
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_trigger(void *opaque, int irq, int level)
23
TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs);
24
void gen_set_cpsr(TCGv_i32 var, uint32_t mask);
25
void gen_set_condexec(DisasContext *s);
26
-void gen_set_pc_im(DisasContext *s, target_ulong val);
27
+void gen_update_pc(DisasContext *s, target_long diff);
28
void gen_lookup_tb(DisasContext *s);
29
long vfp_reg_offset(bool dp, unsigned reg);
30
long neon_full_reg_offset(unsigned reg);
31
diff --git a/target/arm/translate.h b/target/arm/translate.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate.h
34
+++ b/target/arm/translate.h
35
@@ -XXX,XX +XXX,XX @@ static inline int curr_insn_len(DisasContext *s)
36
* For instructions which want an immediate exit to the main loop, as opposed
37
* to attempting to use lookup_and_goto_ptr. Unlike DISAS_UPDATE_EXIT, this
38
* doesn't write the PC on exiting the translation loop so you need to ensure
39
- * something (gen_a64_set_pc_im or runtime helper) has done so before we reach
40
+ * something (gen_a64_update_pc or runtime helper) has done so before we reach
41
* return from cpu_tb_exec.
42
*/
43
#define DISAS_EXIT DISAS_TARGET_9
44
@@ -XXX,XX +XXX,XX @@ static inline int curr_insn_len(DisasContext *s)
45
46
#ifdef TARGET_AARCH64
47
void a64_translate_init(void);
48
-void gen_a64_set_pc_im(uint64_t val);
49
+void gen_a64_update_pc(DisasContext *s, target_long diff);
50
extern const TranslatorOps aarch64_translator_ops;
51
#else
52
static inline void a64_translate_init(void)
53
{
54
}
55
56
-static inline void gen_a64_set_pc_im(uint64_t val)
57
+static inline void gen_a64_update_pc(DisasContext *s, target_long diff)
58
{
59
}
60
#endif
61
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/translate-a64.c
64
+++ b/target/arm/translate-a64.c
65
@@ -XXX,XX +XXX,XX @@ static void reset_btype(DisasContext *s)
66
}
16
}
67
}
17
}
68
18
69
-void gen_a64_set_pc_im(uint64_t val)
19
-static void stellaris_adc_reset(StellarisADCState *s)
70
+void gen_a64_update_pc(DisasContext *s, target_long diff)
20
+static void stellaris_adc_reset_hold(Object *obj)
71
{
21
{
72
- tcg_gen_movi_i64(cpu_pc, val);
22
+ StellarisADCState *s = STELLARIS_ADC(obj);
73
+ tcg_gen_movi_i64(cpu_pc, s->pc_curr + diff);
23
int n;
24
25
for (n = 0; n < 4; n++) {
26
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_init(Object *obj)
27
memory_region_init_io(&s->iomem, obj, &stellaris_adc_ops, s,
28
"adc", 0x1000);
29
sysbus_init_mmio(sbd, &s->iomem);
30
- stellaris_adc_reset(s);
31
qdev_init_gpio_in(dev, stellaris_adc_trigger, 1);
74
}
32
}
75
33
76
/*
34
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stellaris_i2c_info = {
77
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal(int excp)
35
static void stellaris_adc_class_init(ObjectClass *klass, void *data)
78
79
static void gen_exception_internal_insn(DisasContext *s, uint64_t pc, int excp)
80
{
36
{
81
- gen_a64_set_pc_im(pc);
37
DeviceClass *dc = DEVICE_CLASS(klass);
82
+ gen_a64_update_pc(s, pc - s->pc_curr);
38
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
83
gen_exception_internal(excp);
39
84
s->base.is_jmp = DISAS_NORETURN;
40
+ rc->phases.hold = stellaris_adc_reset_hold;
41
dc->vmsd = &vmstate_stellaris_adc;
85
}
42
}
86
43
87
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syndrome)
88
{
89
- gen_a64_set_pc_im(s->pc_curr);
90
+ gen_a64_update_pc(s, 0);
91
gen_helper_exception_bkpt_insn(cpu_env, tcg_constant_i32(syndrome));
92
s->base.is_jmp = DISAS_NORETURN;
93
}
94
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, int64_t diff)
95
96
if (use_goto_tb(s, dest)) {
97
tcg_gen_goto_tb(n);
98
- gen_a64_set_pc_im(dest);
99
+ gen_a64_update_pc(s, diff);
100
tcg_gen_exit_tb(s->base.tb, n);
101
s->base.is_jmp = DISAS_NORETURN;
102
} else {
103
- gen_a64_set_pc_im(dest);
104
+ gen_a64_update_pc(s, diff);
105
if (s->ss_active) {
106
gen_step_complete_exception(s);
107
} else {
108
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
109
uint32_t syndrome;
110
111
syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
112
- gen_a64_set_pc_im(s->pc_curr);
113
+ gen_a64_update_pc(s, 0);
114
gen_helper_access_check_cp_reg(cpu_env,
115
tcg_constant_ptr(ri),
116
tcg_constant_i32(syndrome),
117
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
118
* The readfn or writefn might raise an exception;
119
* synchronize the CPU state in case it does.
120
*/
121
- gen_a64_set_pc_im(s->pc_curr);
122
+ gen_a64_update_pc(s, 0);
123
}
124
125
/* Handle special cases first */
126
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
127
/* The pre HVC helper handles cases when HVC gets trapped
128
* as an undefined insn by runtime configuration.
129
*/
130
- gen_a64_set_pc_im(s->pc_curr);
131
+ gen_a64_update_pc(s, 0);
132
gen_helper_pre_hvc(cpu_env);
133
gen_ss_advance(s);
134
gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC,
135
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
136
unallocated_encoding(s);
137
break;
138
}
139
- gen_a64_set_pc_im(s->pc_curr);
140
+ gen_a64_update_pc(s, 0);
141
gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
142
gen_ss_advance(s);
143
gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC,
144
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
145
*/
146
switch (dc->base.is_jmp) {
147
default:
148
- gen_a64_set_pc_im(dc->base.pc_next);
149
+ gen_a64_update_pc(dc, 4);
150
/* fall through */
151
case DISAS_EXIT:
152
case DISAS_JUMP:
153
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
154
break;
155
default:
156
case DISAS_UPDATE_EXIT:
157
- gen_a64_set_pc_im(dc->base.pc_next);
158
+ gen_a64_update_pc(dc, 4);
159
/* fall through */
160
case DISAS_EXIT:
161
tcg_gen_exit_tb(NULL, 0);
162
break;
163
case DISAS_UPDATE_NOCHAIN:
164
- gen_a64_set_pc_im(dc->base.pc_next);
165
+ gen_a64_update_pc(dc, 4);
166
/* fall through */
167
case DISAS_JUMP:
168
tcg_gen_lookup_and_goto_ptr();
169
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
170
case DISAS_SWI:
171
break;
172
case DISAS_WFE:
173
- gen_a64_set_pc_im(dc->base.pc_next);
174
+ gen_a64_update_pc(dc, 4);
175
gen_helper_wfe(cpu_env);
176
break;
177
case DISAS_YIELD:
178
- gen_a64_set_pc_im(dc->base.pc_next);
179
+ gen_a64_update_pc(dc, 4);
180
gen_helper_yield(cpu_env);
181
break;
182
case DISAS_WFI:
183
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
184
* This is a special case because we don't want to just halt
185
* the CPU if trying to debug across a WFI.
186
*/
187
- gen_a64_set_pc_im(dc->base.pc_next);
188
+ gen_a64_update_pc(dc, 4);
189
gen_helper_wfi(cpu_env, tcg_constant_i32(4));
190
/*
191
* The helper doesn't necessarily throw an exception, but we
192
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/target/arm/translate-vfp.c
195
+++ b/target/arm/translate-vfp.c
196
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
197
case ARM_VFP_FPSID:
198
if (s->current_el == 1) {
199
gen_set_condexec(s);
200
- gen_set_pc_im(s, s->pc_curr);
201
+ gen_update_pc(s, 0);
202
gen_helper_check_hcr_el2_trap(cpu_env,
203
tcg_constant_i32(a->rt),
204
tcg_constant_i32(a->reg));
205
diff --git a/target/arm/translate.c b/target/arm/translate.c
206
index XXXXXXX..XXXXXXX 100644
207
--- a/target/arm/translate.c
208
+++ b/target/arm/translate.c
209
@@ -XXX,XX +XXX,XX @@ void gen_set_condexec(DisasContext *s)
210
}
211
}
212
213
-void gen_set_pc_im(DisasContext *s, target_ulong val)
214
+void gen_update_pc(DisasContext *s, target_long diff)
215
{
216
- tcg_gen_movi_i32(cpu_R[15], val);
217
+ tcg_gen_movi_i32(cpu_R[15], s->pc_curr + diff);
218
}
219
220
/* Set PC and Thumb state from var. var is marked as dead. */
221
@@ -XXX,XX +XXX,XX @@ static inline void gen_bxns(DisasContext *s, int rm)
222
223
/* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
224
* we need to sync state before calling it, but:
225
- * - we don't need to do gen_set_pc_im() because the bxns helper will
226
+ * - we don't need to do gen_update_pc() because the bxns helper will
227
* always set the PC itself
228
* - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
229
* unless it's outside an IT block or the last insn in an IT block,
230
@@ -XXX,XX +XXX,XX @@ static inline void gen_blxns(DisasContext *s, int rm)
231
* We do however need to set the PC, because the blxns helper reads it.
232
* The blxns helper may throw an exception.
233
*/
234
- gen_set_pc_im(s, s->base.pc_next);
235
+ gen_update_pc(s, curr_insn_len(s));
236
gen_helper_v7m_blxns(cpu_env, var);
237
tcg_temp_free_i32(var);
238
s->base.is_jmp = DISAS_EXIT;
239
@@ -XXX,XX +XXX,XX @@ static inline void gen_hvc(DisasContext *s, int imm16)
240
* as an undefined insn by runtime configuration (ie before
241
* the insn really executes).
242
*/
243
- gen_set_pc_im(s, s->pc_curr);
244
+ gen_update_pc(s, 0);
245
gen_helper_pre_hvc(cpu_env);
246
/* Otherwise we will treat this as a real exception which
247
* happens after execution of the insn. (The distinction matters
248
@@ -XXX,XX +XXX,XX @@ static inline void gen_hvc(DisasContext *s, int imm16)
249
* for single stepping.)
250
*/
251
s->svc_imm = imm16;
252
- gen_set_pc_im(s, s->base.pc_next);
253
+ gen_update_pc(s, curr_insn_len(s));
254
s->base.is_jmp = DISAS_HVC;
255
}
256
257
@@ -XXX,XX +XXX,XX @@ static inline void gen_smc(DisasContext *s)
258
/* As with HVC, we may take an exception either before or after
259
* the insn executes.
260
*/
261
- gen_set_pc_im(s, s->pc_curr);
262
+ gen_update_pc(s, 0);
263
gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa32_smc()));
264
- gen_set_pc_im(s, s->base.pc_next);
265
+ gen_update_pc(s, curr_insn_len(s));
266
s->base.is_jmp = DISAS_SMC;
267
}
268
269
static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
270
{
271
gen_set_condexec(s);
272
- gen_set_pc_im(s, pc);
273
+ gen_update_pc(s, pc - s->pc_curr);
274
gen_exception_internal(excp);
275
s->base.is_jmp = DISAS_NORETURN;
276
}
277
@@ -XXX,XX +XXX,XX @@ static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
278
uint32_t syn, TCGv_i32 tcg_el)
279
{
280
if (s->aarch64) {
281
- gen_a64_set_pc_im(pc);
282
+ gen_a64_update_pc(s, pc - s->pc_curr);
283
} else {
284
gen_set_condexec(s);
285
- gen_set_pc_im(s, pc);
286
+ gen_update_pc(s, pc - s->pc_curr);
287
}
288
gen_exception_el_v(excp, syn, tcg_el);
289
s->base.is_jmp = DISAS_NORETURN;
290
@@ -XXX,XX +XXX,XX @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
291
void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
292
{
293
if (s->aarch64) {
294
- gen_a64_set_pc_im(pc);
295
+ gen_a64_update_pc(s, pc - s->pc_curr);
296
} else {
297
gen_set_condexec(s);
298
- gen_set_pc_im(s, pc);
299
+ gen_update_pc(s, pc - s->pc_curr);
300
}
301
gen_exception(excp, syn);
302
s->base.is_jmp = DISAS_NORETURN;
303
@@ -XXX,XX +XXX,XX @@ void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
304
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
305
{
306
gen_set_condexec(s);
307
- gen_set_pc_im(s, s->pc_curr);
308
+ gen_update_pc(s, 0);
309
gen_helper_exception_bkpt_insn(cpu_env, tcg_constant_i32(syn));
310
s->base.is_jmp = DISAS_NORETURN;
311
}
312
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, int diff)
313
314
if (translator_use_goto_tb(&s->base, dest)) {
315
tcg_gen_goto_tb(n);
316
- gen_set_pc_im(s, dest);
317
+ gen_update_pc(s, diff);
318
tcg_gen_exit_tb(s->base.tb, n);
319
} else {
320
- gen_set_pc_im(s, dest);
321
+ gen_update_pc(s, diff);
322
gen_goto_ptr();
323
}
324
s->base.is_jmp = DISAS_NORETURN;
325
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, int diff)
326
/* Jump, specifying which TB number to use if we gen_goto_tb() */
327
static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
328
{
329
+ int diff = dest - s->pc_curr;
330
+
331
if (unlikely(s->ss_active)) {
332
/* An indirect jump so that we still trigger the debug exception. */
333
- gen_set_pc_im(s, dest);
334
+ gen_update_pc(s, diff);
335
s->base.is_jmp = DISAS_JUMP;
336
return;
337
}
338
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
339
* gen_jmp();
340
* on the second call to gen_jmp().
341
*/
342
- gen_goto_tb(s, tbno, dest - s->pc_curr);
343
+ gen_goto_tb(s, tbno, diff);
344
break;
345
case DISAS_UPDATE_NOCHAIN:
346
case DISAS_UPDATE_EXIT:
347
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
348
* Avoid using goto_tb so we really do exit back to the main loop
349
* and don't chain to another TB.
350
*/
351
- gen_set_pc_im(s, dest);
352
+ gen_update_pc(s, diff);
353
gen_goto_ptr();
354
s->base.is_jmp = DISAS_NORETURN;
355
break;
356
@@ -XXX,XX +XXX,XX @@ static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
357
358
/* Sync state because msr_banked() can raise exceptions */
359
gen_set_condexec(s);
360
- gen_set_pc_im(s, s->pc_curr);
361
+ gen_update_pc(s, 0);
362
tcg_reg = load_reg(s, rn);
363
gen_helper_msr_banked(cpu_env, tcg_reg,
364
tcg_constant_i32(tgtmode),
365
@@ -XXX,XX +XXX,XX @@ static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
366
367
/* Sync state because mrs_banked() can raise exceptions */
368
gen_set_condexec(s);
369
- gen_set_pc_im(s, s->pc_curr);
370
+ gen_update_pc(s, 0);
371
tcg_reg = tcg_temp_new_i32();
372
gen_helper_mrs_banked(tcg_reg, cpu_env,
373
tcg_constant_i32(tgtmode),
374
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
375
}
376
377
gen_set_condexec(s);
378
- gen_set_pc_im(s, s->pc_curr);
379
+ gen_update_pc(s, 0);
380
gen_helper_access_check_cp_reg(cpu_env,
381
tcg_constant_ptr(ri),
382
tcg_constant_i32(syndrome),
383
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
384
* synchronize the CPU state in case it does.
385
*/
386
gen_set_condexec(s);
387
- gen_set_pc_im(s, s->pc_curr);
388
+ gen_update_pc(s, 0);
389
}
390
391
/* Handle special cases first */
392
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
393
unallocated_encoding(s);
394
return;
395
}
396
- gen_set_pc_im(s, s->base.pc_next);
397
+ gen_update_pc(s, curr_insn_len(s));
398
s->base.is_jmp = DISAS_WFI;
399
return;
400
default:
401
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
402
addr = tcg_temp_new_i32();
403
/* get_r13_banked() will raise an exception if called from System mode */
404
gen_set_condexec(s);
405
- gen_set_pc_im(s, s->pc_curr);
406
+ gen_update_pc(s, 0);
407
gen_helper_get_r13_banked(addr, cpu_env, tcg_constant_i32(mode));
408
switch (amode) {
409
case 0: /* DA */
410
@@ -XXX,XX +XXX,XX @@ static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
411
* scheduling of other vCPUs.
412
*/
413
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
414
- gen_set_pc_im(s, s->base.pc_next);
415
+ gen_update_pc(s, curr_insn_len(s));
416
s->base.is_jmp = DISAS_YIELD;
417
}
418
return true;
419
@@ -XXX,XX +XXX,XX @@ static bool trans_WFE(DisasContext *s, arg_WFE *a)
420
* implemented so we can't sleep like WFI does.
421
*/
422
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
423
- gen_set_pc_im(s, s->base.pc_next);
424
+ gen_update_pc(s, curr_insn_len(s));
425
s->base.is_jmp = DISAS_WFE;
426
}
427
return true;
428
@@ -XXX,XX +XXX,XX @@ static bool trans_WFE(DisasContext *s, arg_WFE *a)
429
static bool trans_WFI(DisasContext *s, arg_WFI *a)
430
{
431
/* For WFI, halt the vCPU until an IRQ. */
432
- gen_set_pc_im(s, s->base.pc_next);
433
+ gen_update_pc(s, curr_insn_len(s));
434
s->base.is_jmp = DISAS_WFI;
435
return true;
436
}
437
@@ -XXX,XX +XXX,XX @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
438
(a->imm == semihost_imm)) {
439
gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
440
} else {
441
- gen_set_pc_im(s, s->base.pc_next);
442
+ gen_update_pc(s, curr_insn_len(s));
443
s->svc_imm = a->imm;
444
s->base.is_jmp = DISAS_SWI;
445
}
446
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
447
case DISAS_TOO_MANY:
448
case DISAS_UPDATE_EXIT:
449
case DISAS_UPDATE_NOCHAIN:
450
- gen_set_pc_im(dc, dc->base.pc_next);
451
+ gen_update_pc(dc, curr_insn_len(dc));
452
/* fall through */
453
default:
454
/* FIXME: Single stepping a WFI insn will not halt the CPU. */
455
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
456
gen_goto_tb(dc, 1, curr_insn_len(dc));
457
break;
458
case DISAS_UPDATE_NOCHAIN:
459
- gen_set_pc_im(dc, dc->base.pc_next);
460
+ gen_update_pc(dc, curr_insn_len(dc));
461
/* fall through */
462
case DISAS_JUMP:
463
gen_goto_ptr();
464
break;
465
case DISAS_UPDATE_EXIT:
466
- gen_set_pc_im(dc, dc->base.pc_next);
467
+ gen_update_pc(dc, curr_insn_len(dc));
468
/* fall through */
469
default:
470
/* indicate that the hash table must be used to find the next TB */
471
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
472
gen_set_label(dc->condlabel);
473
gen_set_condexec(dc);
474
if (unlikely(dc->ss_active)) {
475
- gen_set_pc_im(dc, dc->base.pc_next);
476
+ gen_update_pc(dc, curr_insn_len(dc));
477
gen_singlestep_exception(dc);
478
} else {
479
gen_goto_tb(dc, 1, curr_insn_len(dc));
480
--
44
--
481
2.25.1
45
2.34.1
482
46
483
47
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
3
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
4
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 20240213155214.13619-3-philmd@linaro.org
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20221020030641.2066807-9-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
8
---
10
target/arm/translate.c | 38 +++++++++++++++++++++-----------------
9
hw/arm/stellaris.c | 26 ++++++++++++++++++++++----
11
1 file changed, 21 insertions(+), 17 deletions(-)
10
1 file changed, 22 insertions(+), 4 deletions(-)
12
11
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
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/translate.c
14
--- a/hw/arm/stellaris.c
16
+++ b/target/arm/translate.c
15
+++ b/hw/arm/stellaris.c
17
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
16
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_instance_init(Object *obj)
18
}
17
s->sysclk = qdev_init_clock_out(DEVICE(s), "SYSCLK");
19
}
18
}
20
19
21
-/* The architectural value of PC. */
20
-/* I2C controller. */
22
-static uint32_t read_pc(DisasContext *s)
21
+/*
23
-{
22
+ * I2C controller.
24
- return s->pc_curr + (s->thumb ? 4 : 8);
23
+ * ??? For now we only implement the master interface.
25
-}
24
+ */
26
-
25
27
/* The pc_curr difference for an architectural jump. */
26
#define TYPE_STELLARIS_I2C "stellaris-i2c"
28
static target_long jmp_diff(DisasContext *s, target_long diff)
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)
29
{
34
{
30
return diff + (s->thumb ? 4 : 8);
35
+ stellaris_i2c_state *s = STELLARIS_I2C(obj);
31
}
36
+
32
37
if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
33
+static void gen_pc_plus_diff(DisasContext *s, TCGv_i32 var, target_long diff)
38
i2c_end_transfer(s->bus);
34
+{
35
+ tcg_gen_movi_i32(var, s->pc_curr + diff);
36
+}
39
+}
37
+
40
+
38
/* Set a variable to the value of a CPU register. */
41
+static void stellaris_i2c_reset_hold(Object *obj)
39
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
42
+{
43
+ stellaris_i2c_state *s = STELLARIS_I2C(obj);
44
45
s->msa = 0;
46
s->mcs = 0;
47
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_reset(stellaris_i2c_state *s)
48
s->mimr = 0;
49
s->mris = 0;
50
s->mcr = 0;
51
+}
52
+
53
+static void stellaris_i2c_reset_exit(Object *obj)
54
+{
55
+ stellaris_i2c_state *s = STELLARIS_I2C(obj);
56
+
57
stellaris_i2c_update(s);
58
}
59
60
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_init(Object *obj)
61
memory_region_init_io(&s->iomem, obj, &stellaris_i2c_ops, s,
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)
40
{
71
{
41
if (reg == 15) {
72
DeviceClass *dc = DEVICE_CLASS(klass);
42
- tcg_gen_movi_i32(var, read_pc(s));
73
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
43
+ gen_pc_plus_diff(s, var, jmp_diff(s, 0));
74
44
} else {
75
+ rc->phases.enter = stellaris_i2c_reset_enter;
45
tcg_gen_mov_i32(var, cpu_R[reg]);
76
+ rc->phases.hold = stellaris_i2c_reset_hold;
46
}
77
+ rc->phases.exit = stellaris_i2c_reset_exit;
47
@@ -XXX,XX +XXX,XX @@ TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
78
dc->vmsd = &vmstate_stellaris_i2c;
48
TCGv_i32 tmp = tcg_temp_new_i32();
49
50
if (reg == 15) {
51
- tcg_gen_movi_i32(tmp, (read_pc(s) & ~3) + ofs);
52
+ /*
53
+ * This address is computed from an aligned PC:
54
+ * subtract off the low bits.
55
+ */
56
+ gen_pc_plus_diff(s, tmp, jmp_diff(s, ofs - (s->pc_curr & 3)));
57
} else {
58
tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
59
}
60
@@ -XXX,XX +XXX,XX @@ void unallocated_encoding(DisasContext *s)
61
/* Force a TB lookup after an instruction that changes the CPU state. */
62
void gen_lookup_tb(DisasContext *s)
63
{
64
- tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
65
+ gen_pc_plus_diff(s, cpu_R[15], curr_insn_len(s));
66
s->base.is_jmp = DISAS_EXIT;
67
}
79
}
68
80
69
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
70
return false;
71
}
72
tmp = load_reg(s, a->rm);
73
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
74
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | s->thumb);
75
gen_bx(s, tmp);
76
return true;
77
}
78
@@ -XXX,XX +XXX,XX @@ static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
79
80
static bool trans_BL(DisasContext *s, arg_i *a)
81
{
82
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
83
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | s->thumb);
84
gen_jmp(s, jmp_diff(s, a->imm));
85
return true;
86
}
87
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
88
if (s->thumb && (a->imm & 2)) {
89
return false;
90
}
91
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
92
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | s->thumb);
93
store_cpu_field_constant(!s->thumb, thumb);
94
/* This jump is computed from an aligned PC: subtract off the low bits. */
95
gen_jmp(s, jmp_diff(s, a->imm - (s->pc_curr & 3)));
96
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
97
static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
98
{
99
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
100
- tcg_gen_movi_i32(cpu_R[14], read_pc(s) + (a->imm << 12));
101
+ gen_pc_plus_diff(s, cpu_R[14], jmp_diff(s, a->imm << 12));
102
return true;
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
106
107
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
108
tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
109
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
110
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | 1);
111
gen_bx(s, tmp);
112
return true;
113
}
114
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
115
tmp = tcg_temp_new_i32();
116
tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
117
tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
118
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
119
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | 1);
120
gen_bx(s, tmp);
121
return true;
122
}
123
@@ -XXX,XX +XXX,XX @@ static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
124
tcg_gen_add_i32(addr, addr, tmp);
125
126
gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), half ? MO_UW : MO_UB);
127
- tcg_temp_free_i32(addr);
128
129
tcg_gen_add_i32(tmp, tmp, tmp);
130
- tcg_gen_addi_i32(tmp, tmp, read_pc(s));
131
+ gen_pc_plus_diff(s, addr, jmp_diff(s, 0));
132
+ tcg_gen_add_i32(tmp, tmp, addr);
133
+ tcg_temp_free_i32(addr);
134
store_reg(s, 15, tmp);
135
return true;
136
}
137
--
81
--
138
2.25.1
82
2.34.1
139
83
140
84
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
3
QDev objects created with qdev_new() need to manually add
4
Since we always pass dc->pc_curr, fold the arithmetic to zero displacement.
4
their parent relationship with object_property_add_child().
5
5
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
This commit plug the devices which aren't part of the SoC;
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
they will be plugged into a SoC container in the next one.
8
Message-id: 20221020030641.2066807-6-richard.henderson@linaro.org
8
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20240213155214.13619-4-philmd@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
target/arm/translate-a64.c | 6 +++---
14
hw/arm/stellaris.c | 4 ++++
12
target/arm/translate.c | 10 +++++-----
15
1 file changed, 4 insertions(+)
13
2 files changed, 8 insertions(+), 8 deletions(-)
14
16
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
17
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
19
--- a/hw/arm/stellaris.c
18
+++ b/target/arm/translate-a64.c
20
+++ b/hw/arm/stellaris.c
19
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal(int excp)
21
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
20
gen_helper_exception_internal(cpu_env, tcg_constant_i32(excp));
22
&error_fatal);
21
}
23
22
24
ssddev = qdev_new("ssd0323");
23
-static void gen_exception_internal_insn(DisasContext *s, uint64_t pc, int excp)
25
+ object_property_add_child(OBJECT(ms), "oled", OBJECT(ssddev));
24
+static void gen_exception_internal_insn(DisasContext *s, int excp)
26
qdev_prop_set_uint8(ssddev, "cs", 1);
25
{
27
qdev_realize_and_unref(ssddev, bus, &error_fatal);
26
- gen_a64_update_pc(s, pc - s->pc_curr);
28
27
+ gen_a64_update_pc(s, 0);
29
gpio_d_splitter = qdev_new(TYPE_SPLIT_IRQ);
28
gen_exception_internal(excp);
30
+ object_property_add_child(OBJECT(ms), "splitter",
29
s->base.is_jmp = DISAS_NORETURN;
31
+ OBJECT(gpio_d_splitter));
30
}
32
qdev_prop_set_uint32(gpio_d_splitter, "num-lines", 2);
31
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
33
qdev_realize_and_unref(gpio_d_splitter, NULL, &error_fatal);
32
* Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
34
qdev_connect_gpio_out(
33
*/
35
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
34
if (semihosting_enabled(s->current_el == 0) && imm16 == 0xf000) {
36
DeviceState *gpad;
35
- gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
37
36
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
38
gpad = qdev_new(TYPE_STELLARIS_GAMEPAD);
37
} else {
39
+ object_property_add_child(OBJECT(ms), "gamepad", OBJECT(gpad));
38
unallocated_encoding(s);
40
for (i = 0; i < ARRAY_SIZE(gpad_keycode); i++) {
41
qlist_append_int(gpad_keycode_list, gpad_keycode[i]);
39
}
42
}
40
diff --git a/target/arm/translate.c b/target/arm/translate.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/translate.c
43
+++ b/target/arm/translate.c
44
@@ -XXX,XX +XXX,XX @@ static inline void gen_smc(DisasContext *s)
45
s->base.is_jmp = DISAS_SMC;
46
}
47
48
-static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
49
+static void gen_exception_internal_insn(DisasContext *s, int excp)
50
{
51
gen_set_condexec(s);
52
- gen_update_pc(s, pc - s->pc_curr);
53
+ gen_update_pc(s, 0);
54
gen_exception_internal(excp);
55
s->base.is_jmp = DISAS_NORETURN;
56
}
57
@@ -XXX,XX +XXX,XX @@ static inline void gen_hlt(DisasContext *s, int imm)
58
*/
59
if (semihosting_enabled(s->current_el != 0) &&
60
(imm == (s->thumb ? 0x3c : 0xf000))) {
61
- gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
62
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
63
return;
64
}
65
66
@@ -XXX,XX +XXX,XX @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
67
if (arm_dc_feature(s, ARM_FEATURE_M) &&
68
semihosting_enabled(s->current_el == 0) &&
69
(a->imm == 0xab)) {
70
- gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
71
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
72
} else {
73
gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
74
}
75
@@ -XXX,XX +XXX,XX @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
76
if (!arm_dc_feature(s, ARM_FEATURE_M) &&
77
semihosting_enabled(s->current_el == 0) &&
78
(a->imm == semihost_imm)) {
79
- gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
80
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
81
} else {
82
gen_update_pc(s, curr_insn_len(s));
83
s->svc_imm = a->imm;
84
--
43
--
85
2.25.1
44
2.34.1
86
45
87
46
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
3
QDev objects created with qdev_new() need to manually add
4
their parent relationship with object_property_add_child().
4
5
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Since we don't model the SoC, just use a QOM container.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
7
Message-id: 20221020030641.2066807-5-richard.henderson@linaro.org
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20240213155214.13619-5-philmd@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
target/arm/translate.h | 5 +++--
13
hw/arm/stellaris.c | 11 ++++++++++-
11
target/arm/translate-a64.c | 28 ++++++++++-------------
14
1 file changed, 10 insertions(+), 1 deletion(-)
12
target/arm/translate-m-nocp.c | 6 ++---
13
target/arm/translate-mve.c | 2 +-
14
target/arm/translate-vfp.c | 6 ++---
15
target/arm/translate.c | 42 +++++++++++++++++------------------
16
6 files changed, 43 insertions(+), 46 deletions(-)
17
15
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
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/target/arm/translate.h
18
--- a/hw/arm/stellaris.c
21
+++ b/target/arm/translate.h
19
+++ b/hw/arm/stellaris.c
22
@@ -XXX,XX +XXX,XX @@ void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
20
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
23
void arm_gen_test_cc(int cc, TCGLabel *label);
21
* 400fe000 system control
24
MemOp pow2_align(unsigned i);
22
*/
25
void unallocated_encoding(DisasContext *s);
23
26
-void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
24
+ Object *soc_container;
27
+void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp,
25
DeviceState *gpio_dev[7], *nvic;
28
uint32_t syn, uint32_t target_el);
26
qemu_irq gpio_in[7][8];
29
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn);
27
qemu_irq gpio_out[7][8];
30
+void gen_exception_insn(DisasContext *s, target_long pc_diff,
28
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
31
+ int excp, uint32_t syn);
29
flash_size = (((board->dc0 & 0xffff) + 1) << 1) * 1024;
32
30
sram_size = ((board->dc0 >> 18) + 1) * 1024;
33
/* Return state of Alternate Half-precision flag, caller frees result */
31
34
static inline TCGv_i32 get_ahp_flag(void)
32
+ soc_container = object_new("container");
35
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
33
+ object_property_add_child(OBJECT(ms), "soc", soc_container);
36
index XXXXXXX..XXXXXXX 100644
34
+
37
--- a/target/arm/translate-a64.c
35
/* Flash programming is done via the SCU, so pretend it is ROM. */
38
+++ b/target/arm/translate-a64.c
36
memory_region_init_rom(flash, NULL, "stellaris.flash", flash_size,
39
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check_only(DisasContext *s)
37
&error_fatal);
40
assert(!s->fp_access_checked);
38
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
41
s->fp_access_checked = true;
39
* need its sysclk output.
42
40
*/
43
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
41
ssys_dev = qdev_new(TYPE_STELLARIS_SYS);
44
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
42
+ object_property_add_child(soc_container, "sys", OBJECT(ssys_dev));
45
syn_fp_access_trap(1, 0xe, false, 0),
43
46
s->fp_excp_el);
44
/*
47
return false;
45
* Most devices come preprogrammed with a MAC address in the user data.
48
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
46
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
49
return false;
47
sysbus_realize_and_unref(SYS_BUS_DEVICE(ssys_dev), &error_fatal);
50
}
48
51
if (s->sme_trap_nonstreaming && s->is_nonstreaming) {
49
nvic = qdev_new(TYPE_ARMV7M);
52
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
50
+ object_property_add_child(soc_container, "v7m", OBJECT(nvic));
53
+ gen_exception_insn(s, 0, EXCP_UDEF,
51
qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES);
54
syn_smetrap(SME_ET_Streaming, false));
52
qdev_prop_set_uint8(nvic, "num-prio-bits", NUM_PRIO_BITS);
55
return false;
53
qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type);
56
}
54
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
57
@@ -XXX,XX +XXX,XX @@ bool sve_access_check(DisasContext *s)
55
58
goto fail_exit;
56
dev = qdev_new(TYPE_STELLARIS_GPTM);
59
}
57
sbd = SYS_BUS_DEVICE(dev);
60
} else if (s->sve_excp_el) {
58
+ object_property_add_child(soc_container, "gptm[*]", OBJECT(dev));
61
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
59
qdev_connect_clock_in(dev, "clk",
62
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
60
qdev_get_clock_out(ssys_dev, "SYSCLK"));
63
syn_sve_access_trap(), s->sve_excp_el);
61
sysbus_realize_and_unref(sbd, &error_fatal);
64
goto fail_exit;
62
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
65
}
63
66
@@ -XXX,XX +XXX,XX @@ bool sve_access_check(DisasContext *s)
64
if (board->dc1 & (1 << 3)) { /* watchdog present */
67
static bool sme_access_check(DisasContext *s)
65
dev = qdev_new(TYPE_LUMINARY_WATCHDOG);
68
{
66
-
69
if (s->sme_excp_el) {
67
+ object_property_add_child(soc_container, "wdg", OBJECT(dev));
70
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
68
qdev_connect_clock_in(dev, "WDOGCLK",
71
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
69
qdev_get_clock_out(ssys_dev, "SYSCLK"));
72
syn_smetrap(SME_ET_AccessTrap, false),
70
73
s->sme_excp_el);
71
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
74
return false;
72
SysBusDevice *sbd;
75
@@ -XXX,XX +XXX,XX @@ bool sme_enabled_check_with_svcr(DisasContext *s, unsigned req)
73
76
return false;
74
dev = qdev_new("pl011_luminary");
77
}
75
+ object_property_add_child(soc_container, "uart[*]", OBJECT(dev));
78
if (FIELD_EX64(req, SVCR, SM) && !s->pstate_sm) {
76
sbd = SYS_BUS_DEVICE(dev);
79
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
77
qdev_prop_set_chr(dev, "chardev", serial_hd(i));
80
+ gen_exception_insn(s, 0, EXCP_UDEF,
78
sysbus_realize_and_unref(sbd, &error_fatal);
81
syn_smetrap(SME_ET_NotStreaming, false));
79
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
82
return false;
80
DeviceState *enet;
83
}
81
84
if (FIELD_EX64(req, SVCR, ZA) && !s->pstate_za) {
82
enet = qdev_new("stellaris_enet");
85
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
83
+ object_property_add_child(soc_container, "enet", OBJECT(enet));
86
+ gen_exception_insn(s, 0, EXCP_UDEF,
84
if (nd) {
87
syn_smetrap(SME_ET_InactiveZA, false));
85
qdev_set_nic_properties(enet, nd);
88
return false;
89
}
90
@@ -XXX,XX +XXX,XX @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
91
} else {
92
syndrome = syn_uncategorized();
93
}
94
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome);
95
+ gen_exception_insn(s, 0, EXCP_UDEF, syndrome);
96
}
97
98
/* MRS - move from system register
99
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
100
switch (op2_ll) {
101
case 1: /* SVC */
102
gen_ss_advance(s);
103
- gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
104
- syn_aa64_svc(imm16));
105
+ gen_exception_insn(s, 4, EXCP_SWI, syn_aa64_svc(imm16));
106
break;
107
case 2: /* HVC */
108
if (s->current_el == 0) {
109
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
110
gen_a64_update_pc(s, 0);
111
gen_helper_pre_hvc(cpu_env);
112
gen_ss_advance(s);
113
- gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC,
114
- syn_aa64_hvc(imm16), 2);
115
+ gen_exception_insn_el(s, 4, EXCP_HVC, syn_aa64_hvc(imm16), 2);
116
break;
117
case 3: /* SMC */
118
if (s->current_el == 0) {
119
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
120
gen_a64_update_pc(s, 0);
121
gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
122
gen_ss_advance(s);
123
- gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC,
124
- syn_aa64_smc(imm16), 3);
125
+ gen_exception_insn_el(s, 4, EXCP_SMC, syn_aa64_smc(imm16), 3);
126
break;
127
default:
128
unallocated_encoding(s);
129
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
130
* Illegal execution state. This has priority over BTI
131
* exceptions, but comes after instruction abort exceptions.
132
*/
133
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
134
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_illegalstate());
135
return;
136
}
137
138
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
139
if (s->btype != 0
140
&& s->guarded_page
141
&& !btype_destination_ok(insn, s->bt, s->btype)) {
142
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
143
- syn_btitrap(s->btype));
144
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_btitrap(s->btype));
145
return;
146
}
147
} else {
86
} else {
148
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/target/arm/translate-m-nocp.c
151
+++ b/target/arm/translate-m-nocp.c
152
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
153
tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
154
155
if (s->fp_excp_el != 0) {
156
- gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
157
+ gen_exception_insn_el(s, 0, EXCP_NOCP,
158
syn_uncategorized(), s->fp_excp_el);
159
return true;
160
}
161
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a)
162
}
163
164
if (a->cp != 10) {
165
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized());
166
+ gen_exception_insn(s, 0, EXCP_NOCP, syn_uncategorized());
167
return true;
168
}
169
170
if (s->fp_excp_el != 0) {
171
- gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
172
+ gen_exception_insn_el(s, 0, EXCP_NOCP,
173
syn_uncategorized(), s->fp_excp_el);
174
return true;
175
}
176
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/target/arm/translate-mve.c
179
+++ b/target/arm/translate-mve.c
180
@@ -XXX,XX +XXX,XX @@ bool mve_eci_check(DisasContext *s)
181
return true;
182
default:
183
/* Reserved value: INVSTATE UsageFault */
184
- gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
185
+ gen_exception_insn(s, 0, EXCP_INVSTATE, syn_uncategorized());
186
return false;
187
}
188
}
189
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
190
index XXXXXXX..XXXXXXX 100644
191
--- a/target/arm/translate-vfp.c
192
+++ b/target/arm/translate-vfp.c
193
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
194
int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa;
195
uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc);
196
197
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
198
+ gen_exception_insn_el(s, 0, EXCP_UDEF, syn, s->fp_excp_el);
199
return false;
200
}
201
202
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
203
* appear to be any insns which touch VFP which are allowed.
204
*/
205
if (s->sme_trap_nonstreaming) {
206
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
207
+ gen_exception_insn(s, 0, EXCP_UDEF,
208
syn_smetrap(SME_ET_Streaming,
209
curr_insn_len(s) == 2));
210
return false;
211
@@ -XXX,XX +XXX,XX @@ bool vfp_access_check_m(DisasContext *s, bool skip_context_update)
212
* the encoding space handled by the patterns in m-nocp.decode,
213
* and for them we may need to raise NOCP here.
214
*/
215
- gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
216
+ gen_exception_insn_el(s, 0, EXCP_NOCP,
217
syn_uncategorized(), s->fp_excp_el);
218
return false;
219
}
220
diff --git a/target/arm/translate.c b/target/arm/translate.c
221
index XXXXXXX..XXXXXXX 100644
222
--- a/target/arm/translate.c
223
+++ b/target/arm/translate.c
224
@@ -XXX,XX +XXX,XX @@ static void gen_exception(int excp, uint32_t syndrome)
225
tcg_constant_i32(syndrome));
226
}
227
228
-static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
229
- uint32_t syn, TCGv_i32 tcg_el)
230
+static void gen_exception_insn_el_v(DisasContext *s, target_long pc_diff,
231
+ int excp, uint32_t syn, TCGv_i32 tcg_el)
232
{
233
if (s->aarch64) {
234
- gen_a64_update_pc(s, pc - s->pc_curr);
235
+ gen_a64_update_pc(s, pc_diff);
236
} else {
237
gen_set_condexec(s);
238
- gen_update_pc(s, pc - s->pc_curr);
239
+ gen_update_pc(s, pc_diff);
240
}
241
gen_exception_el_v(excp, syn, tcg_el);
242
s->base.is_jmp = DISAS_NORETURN;
243
}
244
245
-void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
246
+void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp,
247
uint32_t syn, uint32_t target_el)
248
{
249
- gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
250
+ gen_exception_insn_el_v(s, pc_diff, excp, syn,
251
+ tcg_constant_i32(target_el));
252
}
253
254
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
255
+void gen_exception_insn(DisasContext *s, target_long pc_diff,
256
+ int excp, uint32_t syn)
257
{
258
if (s->aarch64) {
259
- gen_a64_update_pc(s, pc - s->pc_curr);
260
+ gen_a64_update_pc(s, pc_diff);
261
} else {
262
gen_set_condexec(s);
263
- gen_update_pc(s, pc - s->pc_curr);
264
+ gen_update_pc(s, pc_diff);
265
}
266
gen_exception(excp, syn);
267
s->base.is_jmp = DISAS_NORETURN;
268
@@ -XXX,XX +XXX,XX @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
269
void unallocated_encoding(DisasContext *s)
270
{
271
/* Unallocated and reserved encodings are uncategorized */
272
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized());
273
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_uncategorized());
274
}
275
276
/* Force a TB lookup after an instruction that changes the CPU state. */
277
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
278
tcg_el = tcg_constant_i32(3);
279
}
280
281
- gen_exception_insn_el_v(s, s->pc_curr, EXCP_UDEF,
282
+ gen_exception_insn_el_v(s, 0, EXCP_UDEF,
283
syn_uncategorized(), tcg_el);
284
tcg_temp_free_i32(tcg_el);
285
return false;
286
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
287
288
undef:
289
/* If we get here then some access check did not pass */
290
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized());
291
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_uncategorized());
292
return false;
293
}
294
295
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
296
* For the UNPREDICTABLE cases we choose to UNDEF.
297
*/
298
if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
299
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
300
- syn_uncategorized(), 3);
301
+ gen_exception_insn_el(s, 0, EXCP_UDEF, syn_uncategorized(), 3);
302
return;
303
}
304
305
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
306
* Do the check-and-raise-exception by hand.
307
*/
308
if (s->fp_excp_el) {
309
- gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
310
+ gen_exception_insn_el(s, 0, EXCP_NOCP,
311
syn_uncategorized(), s->fp_excp_el);
312
return true;
313
}
314
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
315
tmp = load_cpu_field(v7m.ltpsize);
316
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc);
317
tcg_temp_free_i32(tmp);
318
- gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
319
+ gen_exception_insn(s, 0, EXCP_INVSTATE, syn_uncategorized());
320
gen_set_label(skipexc);
321
}
322
323
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
324
* UsageFault exception.
325
*/
326
if (arm_dc_feature(s, ARM_FEATURE_M)) {
327
- gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
328
+ gen_exception_insn(s, 0, EXCP_INVSTATE, syn_uncategorized());
329
return;
330
}
331
332
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
333
* Illegal execution state. This has priority over BTI
334
* exceptions, but comes after instruction abort exceptions.
335
*/
336
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
337
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_illegalstate());
338
return;
339
}
340
341
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
342
* Illegal execution state. This has priority over BTI
343
* exceptions, but comes after instruction abort exceptions.
344
*/
345
- gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF, syn_illegalstate());
346
+ gen_exception_insn(dc, 0, EXCP_UDEF, syn_illegalstate());
347
return;
348
}
349
350
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
351
*/
352
tcg_remove_ops_after(dc->insn_eci_rewind);
353
dc->condjmp = 0;
354
- gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE,
355
- syn_uncategorized());
356
+ gen_exception_insn(dc, 0, EXCP_INVSTATE, syn_uncategorized());
357
}
358
359
arm_post_translate_insn(dc);
360
--
87
--
361
2.25.1
88
2.34.1
362
89
363
90
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
We support two different encodings for the AArch32 IMPDEF
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.
2
5
3
Compare only the VMID field when considering whether we need to flush.
6
When we implemented this we picked which encoding to
7
use based on whether the CPU set ARM_FEATURE_AARCH64.
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
4
19
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20
Make the decision of the encoding be based on whether
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
the CPU implements the ARM_FEATURE_V8 flag instead.
7
Message-id: 20221011031911.2408754-7-richard.henderson@linaro.org
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
31
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
34
Message-id: 20240206132931.38376-2-peter.maydell@linaro.org
9
---
35
---
10
target/arm/helper.c | 4 ++--
36
target/arm/helper.c | 2 +-
11
1 file changed, 2 insertions(+), 2 deletions(-)
37
1 file changed, 1 insertion(+), 1 deletion(-)
12
38
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
39
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
41
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
42
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
43
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
18
* A change in VMID to the stage2 page table (Stage2) invalidates
44
* AArch64 cores we might need to add a specific feature flag
19
* the stage2 and combined stage 1&2 tlbs (EL10_1 and EL10_0).
45
* to indicate cores with "flavour 2" CBAR.
20
*/
46
*/
21
- if (raw_read(env, ri) != value) {
47
- if (arm_feature(env, ARM_FEATURE_AARCH64)) {
22
+ if (extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
48
+ if (arm_feature(env, ARM_FEATURE_V8)) {
23
tlb_flush_by_mmuidx(cs, alle1_tlbmask(env));
49
/* 32 bit view is [31:18] 0...0 [43:32]. */
24
- raw_write(env, ri, value);
50
uint32_t cbar32 = (extract64(cpu->reset_cbar, 18, 14) << 18)
25
}
51
| extract64(cpu->reset_cbar, 32, 12);
26
+ raw_write(env, ri, value);
27
}
28
29
static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
30
--
52
--
31
2.25.1
53
2.34.1
diff view generated by jsdifflib
New patch
1
The Cortex-R52 implements the Configuration Base Address Register
2
(CBAR), as a read-only register. Add ARM_FEATURE_CBAR_RO to this CPU
3
type, so that our implementation provides the register and the
4
associated qdev property.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20240206132931.38376-3-peter.maydell@linaro.org
9
---
10
target/arm/tcg/cpu32.c | 1 +
11
1 file changed, 1 insertion(+)
12
13
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/cpu32.c
16
+++ b/target/arm/tcg/cpu32.c
17
@@ -XXX,XX +XXX,XX @@ static void cortex_r52_initfn(Object *obj)
18
set_feature(&cpu->env, ARM_FEATURE_PMSA);
19
set_feature(&cpu->env, ARM_FEATURE_NEON);
20
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
21
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
22
cpu->midr = 0x411fd133; /* r1p3 */
23
cpu->revidr = 0x00000000;
24
cpu->reset_fpsid = 0x41034023;
25
--
26
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Add the Cortex-R52 IMPDEF sysregs, by defining them here and
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.
2
5
3
Before using softmmu page tables for the ptw, plumb down
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
a debug parameter so that we can query page table entries
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
from gdbstub without modifying cpu state.
8
Message-id: 20240206132931.38376-4-peter.maydell@linaro.org
9
---
10
target/arm/tcg/cpu32.c | 108 +++++++++++++++++++++++++++++++++++++++++
11
1 file changed, 108 insertions(+)
6
12
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20221011031911.2408754-9-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/ptw.c | 55 ++++++++++++++++++++++++++++++++----------------
13
1 file changed, 37 insertions(+), 18 deletions(-)
14
15
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/ptw.c
15
--- a/target/arm/tcg/cpu32.c
18
+++ b/target/arm/ptw.c
16
+++ b/target/arm/tcg/cpu32.c
19
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void cortex_r5_initfn(Object *obj)
20
typedef struct S1Translate {
18
define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
21
ARMMMUIdx in_mmu_idx;
22
bool in_secure;
23
+ bool in_debug;
24
bool out_secure;
25
hwaddr out_phys;
26
} S1Translate;
27
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
28
S1Translate s2ptw = {
29
.in_mmu_idx = s2_mmu_idx,
30
.in_secure = is_secure,
31
+ .in_debug = ptw->in_debug,
32
};
33
uint64_t hcr;
34
int ret;
35
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
36
return 0;
37
}
19
}
38
20
39
-bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
21
+static const ARMCPRegInfo cortex_r52_cp_reginfo[] = {
40
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
22
+ { .name = "CPUACTLR", .cp = 15, .opc1 = 0, .crm = 15,
41
- bool is_secure, GetPhysAddrResult *result,
23
+ .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
42
- ARMMMUFaultInfo *fi)
24
+ { .name = "IMP_ATCMREGIONR",
43
+static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
25
+ .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
44
+ target_ulong address,
26
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
45
+ MMUAccessType access_type,
27
+ { .name = "IMP_BTCMREGIONR",
46
+ GetPhysAddrResult *result,
28
+ .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
47
+ ARMMMUFaultInfo *fi)
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
+};
124
+
125
+
126
static void cortex_r52_initfn(Object *obj)
48
{
127
{
49
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
128
ARMCPU *cpu = ARM_CPU(obj);
50
ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx);
129
@@ -XXX,XX +XXX,XX @@ static void cortex_r52_initfn(Object *obj)
51
- S1Translate ptw;
130
set_feature(&cpu->env, ARM_FEATURE_NEON);
52
+ bool is_secure = ptw->in_secure;
131
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
53
132
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
54
if (mmu_idx != s1_mmu_idx) {
133
+ set_feature(&cpu->env, ARM_FEATURE_AUXCR);
55
/*
134
cpu->midr = 0x411fd133; /* r1p3 */
56
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
135
cpu->revidr = 0x00000000;
57
bool is_el0;
136
cpu->reset_fpsid = 0x41034023;
58
uint64_t hcr;
137
@@ -XXX,XX +XXX,XX @@ static void cortex_r52_initfn(Object *obj)
59
138
60
- ret = get_phys_addr_with_secure(env, address, access_type,
139
cpu->pmsav7_dregion = 16;
61
- s1_mmu_idx, is_secure, result, fi);
140
cpu->pmsav8r_hdregion = 16;
62
+ ptw->in_mmu_idx = s1_mmu_idx;
141
+
63
+ ret = get_phys_addr_with_struct(env, ptw, address, access_type,
142
+ define_arm_cp_regs(cpu, cortex_r52_cp_reginfo);
64
+ result, fi);
65
66
/* If S1 fails or S2 is disabled, return early. */
67
if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2,
68
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
69
s2walk_secure = false;
70
}
71
72
- ptw.in_mmu_idx =
73
+ ptw->in_mmu_idx =
74
s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
75
- ptw.in_secure = s2walk_secure;
76
+ ptw->in_secure = s2walk_secure;
77
is_el0 = mmu_idx == ARMMMUIdx_E10_0;
78
79
/*
80
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
81
cacheattrs1 = result->cacheattrs;
82
memset(result, 0, sizeof(*result));
83
84
- ret = get_phys_addr_lpae(env, &ptw, ipa, access_type,
85
+ ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
86
is_el0, result, fi);
87
fi->s2addr = ipa;
88
89
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
90
is_secure, result, fi);
91
}
92
93
- ptw.in_mmu_idx = mmu_idx;
94
- ptw.in_secure = is_secure;
95
-
96
if (regime_using_lpae_format(env, mmu_idx)) {
97
- return get_phys_addr_lpae(env, &ptw, address, access_type, false,
98
+ return get_phys_addr_lpae(env, ptw, address, access_type, false,
99
result, fi);
100
} else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
101
- return get_phys_addr_v6(env, &ptw, address, access_type, result, fi);
102
+ return get_phys_addr_v6(env, ptw, address, access_type, result, fi);
103
} else {
104
- return get_phys_addr_v5(env, &ptw, address, access_type, result, fi);
105
+ return get_phys_addr_v5(env, ptw, address, access_type, result, fi);
106
}
107
}
143
}
108
144
109
+bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
145
static void cortex_r5f_initfn(Object *obj)
110
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
111
+ bool is_secure, GetPhysAddrResult *result,
112
+ ARMMMUFaultInfo *fi)
113
+{
114
+ S1Translate ptw = {
115
+ .in_mmu_idx = mmu_idx,
116
+ .in_secure = is_secure,
117
+ };
118
+ return get_phys_addr_with_struct(env, &ptw, address, access_type,
119
+ result, fi);
120
+}
121
+
122
bool get_phys_addr(CPUARMState *env, target_ulong address,
123
MMUAccessType access_type, ARMMMUIdx mmu_idx,
124
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
125
@@ -XXX,XX +XXX,XX @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
126
{
127
ARMCPU *cpu = ARM_CPU(cs);
128
CPUARMState *env = &cpu->env;
129
+ S1Translate ptw = {
130
+ .in_mmu_idx = arm_mmu_idx(env),
131
+ .in_secure = arm_is_secure(env),
132
+ .in_debug = true,
133
+ };
134
GetPhysAddrResult res = {};
135
ARMMMUFaultInfo fi = {};
136
- ARMMMUIdx mmu_idx = arm_mmu_idx(env);
137
bool ret;
138
139
- ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &res, &fi);
140
+ ret = get_phys_addr_with_struct(env, &ptw, addr, MMU_DATA_LOAD, &res, &fi);
141
*attrs = res.f.attrs;
142
143
if (ret) {
144
--
146
--
145
2.25.1
147
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Architecturally, the AArch32 MSR/MRS to/from banked register
2
instructions are UNPREDICTABLE for attempts to access a banked
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.
2
6
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
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.
4
17
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
For convenience of being able to run guest code, permit
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
19
this UNPREDICTABLE access instead of UNDEFing it.
7
Message-id: 20221020030641.2066807-3-richard.henderson@linaro.org
20
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20240206132931.38376-5-peter.maydell@linaro.org
9
---
24
---
10
target/arm/translate-a64.c | 40 ++++++++++++++++++++------------------
25
target/arm/tcg/op_helper.c | 43 ++++++++++++++++++++++++++------------
11
target/arm/translate.c | 10 ++++++----
26
target/arm/tcg/translate.c | 19 +++++++++++------
12
2 files changed, 27 insertions(+), 23 deletions(-)
27
2 files changed, 43 insertions(+), 19 deletions(-)
13
28
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
29
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
15
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
31
--- a/target/arm/tcg/op_helper.c
17
+++ b/target/arm/translate-a64.c
32
+++ b/target/arm/tcg/op_helper.c
18
@@ -XXX,XX +XXX,XX @@ static inline bool use_goto_tb(DisasContext *s, uint64_t dest)
33
@@ -XXX,XX +XXX,XX @@ static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
19
return translator_use_goto_tb(&s->base, dest);
34
*/
20
}
35
int curmode = env->uncached_cpsr & CPSR_M;
21
36
22
-static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
37
- if (regno == 17) {
23
+static void gen_goto_tb(DisasContext *s, int n, int64_t diff)
38
- /* ELR_Hyp: a special case because access from tgtmode is OK */
24
{
39
- if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
25
+ uint64_t dest = s->pc_curr + diff;
40
- goto undef;
26
+
41
+ if (tgtmode == ARM_CPU_MODE_HYP) {
27
if (use_goto_tb(s, dest)) {
42
+ /*
28
tcg_gen_goto_tb(n);
43
+ * Handle Hyp target regs first because some are special cases
29
gen_a64_set_pc_im(dest);
44
+ * which don't want the usual "not accessible from tgtmode" check.
30
@@ -XXX,XX +XXX,XX @@ static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
45
+ */
31
*/
46
+ switch (regno) {
32
static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
47
+ case 16 ... 17: /* ELR_Hyp, SPSR_Hyp */
33
{
48
+ if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
34
- uint64_t addr = s->pc_curr + sextract32(insn, 0, 26) * 4;
49
+ goto undef;
35
+ int64_t diff = sextract32(insn, 0, 26) * 4;
50
+ }
36
51
+ break;
37
if (insn & (1U << 31)) {
52
+ case 13:
38
/* BL Branch with link */
53
+ if (curmode != ARM_CPU_MODE_MON) {
39
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
54
+ goto undef;
40
55
+ }
41
/* B Branch / BL Branch with link */
56
+ break;
42
reset_btype(s);
57
+ default:
43
- gen_goto_tb(s, 0, addr);
58
+ g_assert_not_reached();
44
+ gen_goto_tb(s, 0, diff);
59
}
45
}
46
47
/* Compare and branch (immediate)
48
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
49
static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
50
{
51
unsigned int sf, op, rt;
52
- uint64_t addr;
53
+ int64_t diff;
54
TCGLabel *label_match;
55
TCGv_i64 tcg_cmp;
56
57
sf = extract32(insn, 31, 1);
58
op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
59
rt = extract32(insn, 0, 5);
60
- addr = s->pc_curr + sextract32(insn, 5, 19) * 4;
61
+ diff = sextract32(insn, 5, 19) * 4;
62
63
tcg_cmp = read_cpu_reg(s, rt, sf);
64
label_match = gen_new_label();
65
@@ -XXX,XX +XXX,XX @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
66
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
67
tcg_cmp, 0, label_match);
68
69
- gen_goto_tb(s, 0, s->base.pc_next);
70
+ gen_goto_tb(s, 0, 4);
71
gen_set_label(label_match);
72
- gen_goto_tb(s, 1, addr);
73
+ gen_goto_tb(s, 1, diff);
74
}
75
76
/* Test and branch (immediate)
77
@@ -XXX,XX +XXX,XX @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
78
static void disas_test_b_imm(DisasContext *s, uint32_t insn)
79
{
80
unsigned int bit_pos, op, rt;
81
- uint64_t addr;
82
+ int64_t diff;
83
TCGLabel *label_match;
84
TCGv_i64 tcg_cmp;
85
86
bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
87
op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
88
- addr = s->pc_curr + sextract32(insn, 5, 14) * 4;
89
+ diff = sextract32(insn, 5, 14) * 4;
90
rt = extract32(insn, 0, 5);
91
92
tcg_cmp = tcg_temp_new_i64();
93
@@ -XXX,XX +XXX,XX @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
94
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
95
tcg_cmp, 0, label_match);
96
tcg_temp_free_i64(tcg_cmp);
97
- gen_goto_tb(s, 0, s->base.pc_next);
98
+ gen_goto_tb(s, 0, 4);
99
gen_set_label(label_match);
100
- gen_goto_tb(s, 1, addr);
101
+ gen_goto_tb(s, 1, diff);
102
}
103
104
/* Conditional branch (immediate)
105
@@ -XXX,XX +XXX,XX @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
106
static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
107
{
108
unsigned int cond;
109
- uint64_t addr;
110
+ int64_t diff;
111
112
if ((insn & (1 << 4)) || (insn & (1 << 24))) {
113
unallocated_encoding(s);
114
return;
60
return;
115
}
61
}
116
- addr = s->pc_curr + sextract32(insn, 5, 19) * 4;
62
@@ -XXX,XX +XXX,XX @@ static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
117
+ diff = sextract32(insn, 5, 19) * 4;
118
cond = extract32(insn, 0, 4);
119
120
reset_btype(s);
121
@@ -XXX,XX +XXX,XX @@ static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
122
/* genuinely conditional branches */
123
TCGLabel *label_match = gen_new_label();
124
arm_gen_test_cc(cond, label_match);
125
- gen_goto_tb(s, 0, s->base.pc_next);
126
+ gen_goto_tb(s, 0, 4);
127
gen_set_label(label_match);
128
- gen_goto_tb(s, 1, addr);
129
+ gen_goto_tb(s, 1, diff);
130
} else {
131
/* 0xe and 0xf are both "always" conditions */
132
- gen_goto_tb(s, 0, addr);
133
+ gen_goto_tb(s, 0, diff);
134
}
135
}
136
137
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
138
* any pending interrupts immediately.
139
*/
140
reset_btype(s);
141
- gen_goto_tb(s, 0, s->base.pc_next);
142
+ gen_goto_tb(s, 0, 4);
143
return;
144
145
case 7: /* SB */
146
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
147
* MB and end the TB instead.
148
*/
149
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
150
- gen_goto_tb(s, 0, s->base.pc_next);
151
+ gen_goto_tb(s, 0, 4);
152
return;
153
154
default:
155
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
156
switch (dc->base.is_jmp) {
157
case DISAS_NEXT:
158
case DISAS_TOO_MANY:
159
- gen_goto_tb(dc, 1, dc->base.pc_next);
160
+ gen_goto_tb(dc, 1, 4);
161
break;
162
default:
163
case DISAS_UPDATE_EXIT:
164
diff --git a/target/arm/translate.c b/target/arm/translate.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/translate.c
167
+++ b/target/arm/translate.c
168
@@ -XXX,XX +XXX,XX @@ static void gen_goto_ptr(void)
169
* cpu_loop_exec. Any live exit_requests will be processed as we
170
* enter the next TB.
171
*/
172
-static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
173
+static void gen_goto_tb(DisasContext *s, int n, int diff)
174
{
175
+ target_ulong dest = s->pc_curr + diff;
176
+
177
if (translator_use_goto_tb(&s->base, dest)) {
178
tcg_gen_goto_tb(n);
179
gen_set_pc_im(s, dest);
180
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
181
* gen_jmp();
182
* on the second call to gen_jmp().
183
*/
184
- gen_goto_tb(s, tbno, dest);
185
+ gen_goto_tb(s, tbno, dest - s->pc_curr);
186
break;
187
case DISAS_UPDATE_NOCHAIN:
188
case DISAS_UPDATE_EXIT:
189
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
190
switch (dc->base.is_jmp) {
191
case DISAS_NEXT:
192
case DISAS_TOO_MANY:
193
- gen_goto_tb(dc, 1, dc->base.pc_next);
194
+ gen_goto_tb(dc, 1, curr_insn_len(dc));
195
break;
196
case DISAS_UPDATE_NOCHAIN:
197
gen_set_pc_im(dc, dc->base.pc_next);
198
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
199
gen_set_pc_im(dc, dc->base.pc_next);
200
gen_singlestep_exception(dc);
201
} else {
202
- gen_goto_tb(dc, 1, dc->base.pc_next);
203
+ gen_goto_tb(dc, 1, curr_insn_len(dc));
204
}
63
}
205
}
64
}
206
}
65
66
- if (tgtmode == ARM_CPU_MODE_HYP) {
67
- /* SPSR_Hyp, r13_hyp: accessible from Monitor mode only */
68
- if (curmode != ARM_CPU_MODE_MON) {
69
- goto undef;
70
- }
71
- }
72
-
73
return;
74
75
undef:
76
@@ -XXX,XX +XXX,XX @@ void HELPER(msr_banked)(CPUARMState *env, uint32_t value, uint32_t tgtmode,
77
78
switch (regno) {
79
case 16: /* SPSRs */
80
- env->banked_spsr[bank_number(tgtmode)] = value;
81
+ if (tgtmode == (env->uncached_cpsr & CPSR_M)) {
82
+ /* Only happens for SPSR_Hyp access in Hyp mode */
83
+ env->spsr = value;
84
+ } else {
85
+ env->banked_spsr[bank_number(tgtmode)] = value;
86
+ }
87
break;
88
case 17: /* ELR_Hyp */
89
env->elr_el[2] = value;
90
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(mrs_banked)(CPUARMState *env, uint32_t tgtmode, uint32_t regno)
91
92
switch (regno) {
93
case 16: /* SPSRs */
94
- return env->banked_spsr[bank_number(tgtmode)];
95
+ if (tgtmode == (env->uncached_cpsr & CPSR_M)) {
96
+ /* Only happens for SPSR_Hyp access in Hyp mode */
97
+ return env->spsr;
98
+ } else {
99
+ return env->banked_spsr[bank_number(tgtmode)];
100
+ }
101
case 17: /* ELR_Hyp */
102
return env->elr_el[2];
103
case 13:
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;
133
}
134
break;
207
--
135
--
208
2.25.1
136
2.34.1
diff view generated by jsdifflib
New patch
1
We currently guard the CFG3 register read with
2
(scc_partno(s) == 0x524 && scc_partno(s) == 0x547)
3
which is clearly wrong as it is never true.
1
4
5
This register is present on all board types except AN524
6
and AN527; correct the condition.
7
8
Fixes: 6ac80818941829c0 ("hw/misc/mps2-scc: Implement changes for AN547")
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20240206132931.38376-6-peter.maydell@linaro.org
13
---
14
hw/misc/mps2-scc.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/misc/mps2-scc.c
20
+++ b/hw/misc/mps2-scc.c
21
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
22
r = s->cfg2;
23
break;
24
case A_CFG3:
25
- if (scc_partno(s) == 0x524 && scc_partno(s) == 0x547) {
26
+ if (scc_partno(s) == 0x524 || scc_partno(s) == 0x547) {
27
/* CFG3 reserved on AN524 */
28
goto bad_offset;
29
}
30
--
31
2.34.1
32
33
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The MPS SCC device has a lot of different flavours for the various
2
different MPS FPGA images, which look mostly similar but have
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.
2
6
3
We had been marking this ARM_MMU_IDX_NOTLB, move it to a real tlb.
7
Factor out the conditions into some functions which we can
4
Flush the tlb when invalidating stage 1+2 translations. Re-use
8
give more descriptive names to.
5
alle1_tlbmask() for other instances of EL1&0 + Stage2.
6
9
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20221011031911.2408754-6-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20240206132931.38376-7-peter.maydell@linaro.org
11
---
14
---
12
target/arm/cpu-param.h | 2 +-
15
hw/misc/mps2-scc.c | 45 +++++++++++++++++++++++++++++++--------------
13
target/arm/cpu.h | 23 ++++---
16
1 file changed, 31 insertions(+), 14 deletions(-)
14
target/arm/helper.c | 151 ++++++++++++++++++++++++++++++-----------
15
3 files changed, 127 insertions(+), 49 deletions(-)
16
17
17
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
18
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu-param.h
20
--- a/hw/misc/mps2-scc.c
20
+++ b/target/arm/cpu-param.h
21
+++ b/hw/misc/mps2-scc.c
21
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static int scc_partno(MPS2SCC *s)
22
bool guarded;
23
return extract32(s->id, 4, 8);
23
#endif
24
25
-#define NB_MMU_MODES 10
26
+#define NB_MMU_MODES 12
27
28
#endif
29
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu.h
32
+++ b/target/arm/cpu.h
33
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
34
* EL2 (aka NS PL2)
35
* EL3 (aka S PL1)
36
* Physical (NS & S)
37
+ * Stage2 (NS & S)
38
*
39
- * for a total of 10 different mmu_idx.
40
+ * for a total of 12 different mmu_idx.
41
*
42
* R profile CPUs have an MPU, but can use the same set of MMU indexes
43
* as A profile. They only need to distinguish EL0 and EL1 (and
44
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
45
ARMMMUIdx_Phys_NS = 8 | ARM_MMU_IDX_A,
46
ARMMMUIdx_Phys_S = 9 | ARM_MMU_IDX_A,
47
48
+ /*
49
+ * Used for second stage of an S12 page table walk, or for descriptor
50
+ * loads during first stage of an S1 page table walk. Note that both
51
+ * are in use simultaneously for SecureEL2: the security state for
52
+ * the S2 ptw is selected by the NS bit from the S1 ptw.
53
+ */
54
+ ARMMMUIdx_Stage2 = 10 | ARM_MMU_IDX_A,
55
+ ARMMMUIdx_Stage2_S = 11 | ARM_MMU_IDX_A,
56
+
57
/*
58
* These are not allocated TLBs and are used only for AT system
59
* instructions or for the first stage of an S12 page table walk.
60
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
61
ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
62
ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
63
ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
64
- /*
65
- * Not allocated a TLB: used only for second stage of an S12 page
66
- * table walk, or for descriptor loads during first stage of an S1
67
- * page table walk. Note that if we ever want to have a TLB for this
68
- * then various TLB flush insns which currently are no-ops or flush
69
- * only stage 1 MMU indexes will need to change to flush stage 2.
70
- */
71
- ARMMMUIdx_Stage2 = 3 | ARM_MMU_IDX_NOTLB,
72
- ARMMMUIdx_Stage2_S = 4 | ARM_MMU_IDX_NOTLB,
73
74
/*
75
* M-profile.
76
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdxBit {
77
TO_CORE_BIT(E20_2),
78
TO_CORE_BIT(E20_2_PAN),
79
TO_CORE_BIT(E3),
80
+ TO_CORE_BIT(Stage2),
81
+ TO_CORE_BIT(Stage2_S),
82
83
TO_CORE_BIT(MUser),
84
TO_CORE_BIT(MPriv),
85
diff --git a/target/arm/helper.c b/target/arm/helper.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/helper.c
88
+++ b/target/arm/helper.c
89
@@ -XXX,XX +XXX,XX @@ static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
90
raw_write(env, ri, value);
91
}
24
}
92
25
93
+static int alle1_tlbmask(CPUARMState *env)
26
+/* Is CFG_REG2 present? */
27
+static bool have_cfg2(MPS2SCC *s)
94
+{
28
+{
95
+ /*
29
+ return scc_partno(s) == 0x524 || scc_partno(s) == 0x547;
96
+ * Note that the 'ALL' scope must invalidate both stage 1 and
97
+ * stage 2 translations, whereas most other scopes only invalidate
98
+ * stage 1 translations.
99
+ */
100
+ return (ARMMMUIdxBit_E10_1 |
101
+ ARMMMUIdxBit_E10_1_PAN |
102
+ ARMMMUIdxBit_E10_0 |
103
+ ARMMMUIdxBit_Stage2 |
104
+ ARMMMUIdxBit_Stage2_S);
105
+}
30
+}
106
+
31
+
107
+
32
+/* Is CFG_REG3 present? */
108
/* IS variants of TLB operations must affect all cores */
33
+static bool have_cfg3(MPS2SCC *s)
109
static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
110
uint64_t value)
111
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
112
{
113
CPUState *cs = env_cpu(env);
114
115
- tlb_flush_by_mmuidx(cs,
116
- ARMMMUIdxBit_E10_1 |
117
- ARMMMUIdxBit_E10_1_PAN |
118
- ARMMMUIdxBit_E10_0);
119
+ tlb_flush_by_mmuidx(cs, alle1_tlbmask(env));
120
}
121
122
static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
123
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
124
{
125
CPUState *cs = env_cpu(env);
126
127
- tlb_flush_by_mmuidx_all_cpus_synced(cs,
128
- ARMMMUIdxBit_E10_1 |
129
- ARMMMUIdxBit_E10_1_PAN |
130
- ARMMMUIdxBit_E10_0);
131
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, alle1_tlbmask(env));
132
}
133
134
135
@@ -XXX,XX +XXX,XX @@ static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
136
ARMMMUIdxBit_E2);
137
}
138
139
+static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
140
+ uint64_t value)
141
+{
34
+{
142
+ CPUState *cs = env_cpu(env);
35
+ return scc_partno(s) != 0x524 && scc_partno(s) != 0x547;
143
+ uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12;
144
+
145
+ tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
146
+}
36
+}
147
+
37
+
148
+static void tlbiipas2is_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
38
+/* Is CFG_REG5 present? */
149
+ uint64_t value)
39
+static bool have_cfg5(MPS2SCC *s)
150
+{
40
+{
151
+ CPUState *cs = env_cpu(env);
41
+ return scc_partno(s) == 0x524 || scc_partno(s) == 0x547;
152
+ uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12;
153
+
154
+ tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2);
155
+}
42
+}
156
+
43
+
157
static const ARMCPRegInfo cp_reginfo[] = {
44
+/* Is CFG_REG6 present? */
158
/* Define the secure and non-secure FCSE identifier CP registers
45
+static bool have_cfg6(MPS2SCC *s)
159
* separately because there is no secure bank in V8 (no _EL3). This allows
160
@@ -XXX,XX +XXX,XX @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
161
162
/*
163
* A change in VMID to the stage2 page table (Stage2) invalidates
164
- * the combined stage 1&2 tlbs (EL10_1 and EL10_0).
165
+ * the stage2 and combined stage 1&2 tlbs (EL10_1 and EL10_0).
166
*/
167
if (raw_read(env, ri) != value) {
168
- uint16_t mask = ARMMMUIdxBit_E10_1 |
169
- ARMMMUIdxBit_E10_1_PAN |
170
- ARMMMUIdxBit_E10_0;
171
- tlb_flush_by_mmuidx(cs, mask);
172
+ tlb_flush_by_mmuidx(cs, alle1_tlbmask(env));
173
raw_write(env, ri, value);
174
}
175
}
176
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
177
}
178
}
179
180
-static int alle1_tlbmask(CPUARMState *env)
181
-{
182
- /*
183
- * Note that the 'ALL' scope must invalidate both stage 1 and
184
- * stage 2 translations, whereas most other scopes only invalidate
185
- * stage 1 translations.
186
- */
187
- return (ARMMMUIdxBit_E10_1 |
188
- ARMMMUIdxBit_E10_1_PAN |
189
- ARMMMUIdxBit_E10_0);
190
-}
191
-
192
static int e2_tlbmask(CPUARMState *env)
193
{
194
return (ARMMMUIdxBit_E20_0 |
195
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
196
ARMMMUIdxBit_E3, bits);
197
}
198
199
+static int ipas2e1_tlbmask(CPUARMState *env, int64_t value)
200
+{
46
+{
201
+ /*
47
+ return scc_partno(s) == 0x524;
202
+ * The MSB of value is the NS field, which only applies if SEL2
203
+ * is implemented and SCR_EL3.NS is not set (i.e. in secure mode).
204
+ */
205
+ return (value >= 0
206
+ && cpu_isar_feature(aa64_sel2, env_archcpu(env))
207
+ && arm_is_secure_below_el3(env)
208
+ ? ARMMMUIdxBit_Stage2_S
209
+ : ARMMMUIdxBit_Stage2);
210
+}
48
+}
211
+
49
+
212
+static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
50
/* Handle a write via the SYS_CFG channel to the specified function/device.
213
+ uint64_t value)
51
* Return false on error (reported to guest via SYS_CFGCTRL ERROR bit).
214
+{
52
*/
215
+ CPUState *cs = env_cpu(env);
53
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
216
+ int mask = ipas2e1_tlbmask(env, value);
54
r = s->cfg1;
217
+ uint64_t pageaddr = sextract64(value << 12, 0, 56);
55
break;
218
+
56
case A_CFG2:
219
+ if (tlb_force_broadcast(env)) {
57
- if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
220
+ tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
58
- /* CFG2 reserved on other boards */
221
+ } else {
59
+ if (!have_cfg2(s)) {
222
+ tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
60
goto bad_offset;
223
+ }
61
}
224
+}
62
r = s->cfg2;
225
+
63
break;
226
+static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
64
case A_CFG3:
227
+ uint64_t value)
65
- if (scc_partno(s) == 0x524 || scc_partno(s) == 0x547) {
228
+{
66
- /* CFG3 reserved on AN524 */
229
+ CPUState *cs = env_cpu(env);
67
+ if (!have_cfg3(s)) {
230
+ int mask = ipas2e1_tlbmask(env, value);
68
goto bad_offset;
231
+ uint64_t pageaddr = sextract64(value << 12, 0, 56);
69
}
232
+
70
/* These are user-settable DIP switches on the board. We don't
233
+ tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
71
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
234
+}
72
r = s->cfg4;
235
+
73
break;
236
#ifdef TARGET_AARCH64
74
case A_CFG5:
237
typedef struct {
75
- if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
238
uint64_t base;
76
- /* CFG5 reserved on other boards */
239
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_rvae3is_write(CPUARMState *env,
77
+ if (!have_cfg5(s)) {
240
78
goto bad_offset;
241
do_rvae_write(env, value, ARMMMUIdxBit_E3, true);
79
}
242
}
80
r = s->cfg5;
243
+
81
break;
244
+static void tlbi_aa64_ripas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
82
case A_CFG6:
245
+ uint64_t value)
83
- if (scc_partno(s) != 0x524) {
246
+{
84
- /* CFG6 reserved on other boards */
247
+ do_rvae_write(env, value, ipas2e1_tlbmask(env, value),
85
+ if (!have_cfg6(s)) {
248
+ tlb_force_broadcast(env));
86
goto bad_offset;
249
+}
87
}
250
+
88
r = s->cfg6;
251
+static void tlbi_aa64_ripas2e1is_write(CPUARMState *env,
89
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
252
+ const ARMCPRegInfo *ri,
90
}
253
+ uint64_t value)
91
break;
254
+{
92
case A_CFG2:
255
+ do_rvae_write(env, value, ipas2e1_tlbmask(env, value), true);
93
- if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
256
+}
94
- /* CFG2 reserved on other boards */
257
#endif
95
+ if (!have_cfg2(s)) {
258
96
goto bad_offset;
259
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
97
}
260
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
98
/* AN524: QSPI Select signal */
261
.writefn = tlbi_aa64_vae1_write },
99
s->cfg2 = value;
262
{ .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64,
100
break;
263
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
101
case A_CFG5:
264
- .access = PL2_W, .type = ARM_CP_NOP },
102
- if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
265
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
103
- /* CFG5 reserved on other boards */
266
+ .writefn = tlbi_aa64_ipas2e1is_write },
104
+ if (!have_cfg5(s)) {
267
{ .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64,
105
goto bad_offset;
268
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
106
}
269
- .access = PL2_W, .type = ARM_CP_NOP },
107
/* AN524: ACLK frequency in Hz */
270
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
108
s->cfg5 = value;
271
+ .writefn = tlbi_aa64_ipas2e1is_write },
109
break;
272
{ .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64,
110
case A_CFG6:
273
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
111
- if (scc_partno(s) != 0x524) {
274
.access = PL2_W, .type = ARM_CP_NO_RAW,
112
- /* CFG6 reserved on other boards */
275
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
113
+ if (!have_cfg6(s)) {
276
.writefn = tlbi_aa64_alle1is_write },
114
goto bad_offset;
277
{ .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64,
115
}
278
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
116
/* AN524: Clock divider for BRAM */
279
- .access = PL2_W, .type = ARM_CP_NOP },
280
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
281
+ .writefn = tlbi_aa64_ipas2e1_write },
282
{ .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64,
283
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
284
- .access = PL2_W, .type = ARM_CP_NOP },
285
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
286
+ .writefn = tlbi_aa64_ipas2e1_write },
287
{ .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64,
288
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
289
.access = PL2_W, .type = ARM_CP_NO_RAW,
290
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
291
.writefn = tlbimva_hyp_is_write },
292
{ .name = "TLBIIPAS2",
293
.cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
294
- .type = ARM_CP_NOP, .access = PL2_W },
295
+ .type = ARM_CP_NO_RAW, .access = PL2_W,
296
+ .writefn = tlbiipas2_hyp_write },
297
{ .name = "TLBIIPAS2IS",
298
.cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
299
- .type = ARM_CP_NOP, .access = PL2_W },
300
+ .type = ARM_CP_NO_RAW, .access = PL2_W,
301
+ .writefn = tlbiipas2is_hyp_write },
302
{ .name = "TLBIIPAS2L",
303
.cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
304
- .type = ARM_CP_NOP, .access = PL2_W },
305
+ .type = ARM_CP_NO_RAW, .access = PL2_W,
306
+ .writefn = tlbiipas2_hyp_write },
307
{ .name = "TLBIIPAS2LIS",
308
.cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
309
- .type = ARM_CP_NOP, .access = PL2_W },
310
+ .type = ARM_CP_NO_RAW, .access = PL2_W,
311
+ .writefn = tlbiipas2is_hyp_write },
312
/* 32 bit cache operations */
313
{ .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
314
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access },
315
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
316
.writefn = tlbi_aa64_rvae1_write },
317
{ .name = "TLBI_RIPAS2E1IS", .state = ARM_CP_STATE_AA64,
318
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 2,
319
- .access = PL2_W, .type = ARM_CP_NOP },
320
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
321
+ .writefn = tlbi_aa64_ripas2e1is_write },
322
{ .name = "TLBI_RIPAS2LE1IS", .state = ARM_CP_STATE_AA64,
323
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 6,
324
- .access = PL2_W, .type = ARM_CP_NOP },
325
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
326
+ .writefn = tlbi_aa64_ripas2e1is_write },
327
{ .name = "TLBI_RVAE2IS", .state = ARM_CP_STATE_AA64,
328
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 1,
329
.access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
330
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
331
.writefn = tlbi_aa64_rvae2is_write },
332
{ .name = "TLBI_RIPAS2E1", .state = ARM_CP_STATE_AA64,
333
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 2,
334
- .access = PL2_W, .type = ARM_CP_NOP },
335
- { .name = "TLBI_RIPAS2LE1", .state = ARM_CP_STATE_AA64,
336
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
337
+ .writefn = tlbi_aa64_ripas2e1_write },
338
+ { .name = "TLBI_RIPAS2LE1", .state = ARM_CP_STATE_AA64,
339
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 6,
340
- .access = PL2_W, .type = ARM_CP_NOP },
341
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
342
+ .writefn = tlbi_aa64_ripas2e1_write },
343
{ .name = "TLBI_RVAE2OS", .state = ARM_CP_STATE_AA64,
344
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 1,
345
.access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
346
--
117
--
347
2.25.1
118
2.34.1
119
120
diff view generated by jsdifflib
New patch
1
1
The MPS2 SCC device is broadly the same for all FPGA images, but has
2
minor differences in the behaviour of the CFG registers depending on
3
the image. In many cases we don't really care about the functionality
4
controlled by these registers and a reads-as-written or similar
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
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
37
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
38
Message-id: 20240206132931.38376-8-peter.maydell@linaro.org
39
---
40
include/hw/misc/mps2-scc.h | 1 +
41
hw/misc/mps2-scc.c | 101 +++++++++++++++++++++++++++++++++----
42
2 files changed, 92 insertions(+), 10 deletions(-)
43
44
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/misc/mps2-scc.h
47
+++ b/include/hw/misc/mps2-scc.h
48
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
49
uint32_t cfg4;
50
uint32_t cfg5;
51
uint32_t cfg6;
52
+ uint32_t cfg7;
53
uint32_t cfgdata_rtn;
54
uint32_t cfgdata_out;
55
uint32_t cfgctrl;
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
250
--
251
2.34.1
252
253
diff view generated by jsdifflib
New patch
1
1
The AN536 is another FPGA image for the MPS3 development board. Unlike
2
the existing FPGA images we already model, this board uses a Cortex-R
3
family CPU, and it does not use any equivalent to the M-profile
4
"Subsystem for Embedded" SoC-equivalent that we model in hw/arm/armsse.c.
5
It's therefore more convenient for us to model it as a completely
6
separate C file.
7
8
This commit adds the basic skeleton of the board model, and the
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
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
19
---
20
MAINTAINERS | 3 +-
21
configs/devices/arm-softmmu/default.mak | 1 +
22
hw/arm/mps3r.c | 239 ++++++++++++++++++++++++
23
hw/arm/Kconfig | 5 +
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
60
new file mode 100644
61
index XXXXXXX..XXXXXXX
62
--- /dev/null
63
+++ b/hw/arm/mps3r.c
64
@@ -XXX,XX +XXX,XX @@
65
+/*
66
+ * Arm MPS3 board emulation for Cortex-R-based FPGA images.
67
+ * (For M-profile images see mps2.c and mps2tz.c.)
68
+ *
69
+ * Copyright (c) 2017 Linaro Limited
70
+ * Written by Peter Maydell
71
+ *
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.
75
+ */
76
+
77
+/*
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
+ */
90
+
91
+#include "qemu/osdep.h"
92
+#include "qemu/units.h"
93
+#include "qapi/error.h"
94
+#include "exec/address-spaces.h"
95
+#include "cpu.h"
96
+#include "hw/boards.h"
97
+#include "hw/arm/boot.h"
98
+
99
+/* Define the layout of RAM and ROM in a board */
100
+typedef struct RAMInfo {
101
+ const char *name;
102
+ hwaddr base;
103
+ hwaddr size;
104
+ int mrindex; /* index into rams[]; -1 for the system RAM block */
105
+ int flags;
106
+} RAMInfo;
107
+
108
+/*
109
+ * The MPS3 DDR is 3GiB, but on a 32-bit host QEMU doesn't permit
110
+ * emulation of that much guest RAM, so artificially make it smaller.
111
+ */
112
+#if HOST_LONG_BITS == 32
113
+#define MPS3_DDR_SIZE (1 * GiB)
114
+#else
115
+#define MPS3_DDR_SIZE (3 * GiB)
116
+#endif
117
+
118
+/*
119
+ * Flag values:
120
+ * IS_MAIN: this is the main machine RAM
121
+ * IS_ROM: this area is read-only
122
+ */
123
+#define IS_MAIN 1
124
+#define IS_ROM 2
125
+
126
+#define MPS3R_RAM_MAX 9
127
+
128
+typedef enum MPS3RFPGAType {
129
+ FPGA_AN536,
130
+} MPS3RFPGAType;
131
+
132
+struct MPS3RMachineClass {
133
+ MachineClass parent;
134
+ MPS3RFPGAType fpga_type;
135
+ const RAMInfo *raminfo;
136
+};
137
+
138
+struct MPS3RMachineState {
139
+ MachineState parent;
140
+ MemoryRegion ram[MPS3R_RAM_MAX];
141
+};
142
+
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'))
332
--
333
2.34.1
334
335
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Create the CPUs, the GIC, and the per-CPU RAM block for
2
the mps3-an536 board.
2
3
3
Consolidate most of the inputs and outputs of S1_ptw_translate
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
into a single structure. Plumb this through arm_ld*_ptw from
5
Message-id: 20240206132931.38376-10-peter.maydell@linaro.org
5
the controlling get_phys_addr_* routine.
6
---
7
hw/arm/mps3r.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++-
8
1 file changed, 177 insertions(+), 3 deletions(-)
6
9
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
diff --git a/hw/arm/mps3r.c b/hw/arm/mps3r.c
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20221011031911.2408754-8-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/ptw.c | 140 ++++++++++++++++++++++++++---------------------
13
1 file changed, 79 insertions(+), 61 deletions(-)
14
15
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
16
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/ptw.c
12
--- a/hw/arm/mps3r.c
18
+++ b/target/arm/ptw.c
13
+++ b/hw/arm/mps3r.c
19
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@
20
#include "idau.h"
15
#include "qemu/osdep.h"
21
16
#include "qemu/units.h"
22
17
#include "qapi/error.h"
23
-static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
18
+#include "qapi/qmp/qlist.h"
24
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
19
#include "exec/address-spaces.h"
25
- bool is_secure, bool s1_is_el0,
20
#include "cpu.h"
26
+typedef struct S1Translate {
21
#include "hw/boards.h"
27
+ ARMMMUIdx in_mmu_idx;
22
+#include "hw/qdev-properties.h"
28
+ bool in_secure;
23
#include "hw/arm/boot.h"
29
+ bool out_secure;
24
+#include "hw/arm/bsa.h"
30
+ hwaddr out_phys;
25
+#include "hw/intc/arm_gicv3.h"
31
+} S1Translate;
26
32
+
27
/* Define the layout of RAM and ROM in a board */
33
+static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
28
typedef struct RAMInfo {
34
+ uint64_t address,
29
@@ -XXX,XX +XXX,XX @@ typedef struct RAMInfo {
35
+ MMUAccessType access_type, bool s1_is_el0,
30
#define IS_ROM 2
36
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
31
37
__attribute__((nonnull));
32
#define MPS3R_RAM_MAX 9
38
33
+#define MPS3R_CPU_MAX 2
39
@@ -XXX,XX +XXX,XX @@ static bool ptw_attrs_are_device(uint64_t hcr, ARMCacheAttrs cacheattrs)
34
+
35
+#define PERIPHBASE 0xf0000000
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
/* Translate a S1 pagetable walk through S2 if needed. */
63
+/*
43
-static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
64
+ * There is no defined secondary boot protocol for Linux for the AN536,
44
- hwaddr addr, bool *is_secure_ptr,
65
+ * because real hardware has a restriction that atomic operations between
45
- ARMMMUFaultInfo *fi)
66
+ * the two CPUs do not function correctly, and so true SMP is not
46
+static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
67
+ * possible. Therefore for cases where the user is directly booting
47
+ hwaddr addr, ARMMMUFaultInfo *fi)
68
+ * a kernel, we treat the system as essentially uniprocessor, and
69
+ * put the secondary CPU into power-off state (as if the user on the
70
+ * real hardware had configured the secondary to be halted via the
71
+ * SCC config registers).
72
+ *
73
+ * Note that the default secondary boot code would not work here anyway
74
+ * as it assumes a GICv2, and we have a GICv3.
75
+ */
76
+static void mps3r_write_secondary_boot(ARMCPU *cpu,
77
+ const struct arm_boot_info *info)
78
+{
79
+ /*
80
+ * Power the secondary CPU off. This means we don't need to write any
81
+ * boot code into guest memory. Note that the 'cpu' argument to this
82
+ * function is the primary CPU we passed to arm_load_kernel(), not
83
+ * the secondary. Loop around all the other CPUs, as the boot.c
84
+ * code does for the "disable secondaries if PSCI is enabled" case.
85
+ */
86
+ for (CPUState *cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
87
+ if (cs != first_cpu) {
88
+ object_property_set_bool(OBJECT(cs), "start-powered-off", true,
89
+ &error_abort);
90
+ }
91
+ }
92
+}
93
+
94
+static void mps3r_secondary_cpu_reset(ARMCPU *cpu,
95
+ const struct arm_boot_info *info)
96
+{
97
+ /* We don't need to do anything here because the CPU will be off */
98
+}
99
+
100
+static void create_gic(MPS3RMachineState *mms, MemoryRegion *sysmem)
101
+{
102
+ MachineState *machine = MACHINE(mms);
103
+ DeviceState *gicdev;
104
+ QList *redist_region_count;
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
+ }
162
+}
163
+
164
static void mps3r_common_init(MachineState *machine)
48
{
165
{
49
- bool is_secure = *is_secure_ptr;
166
MPS3RMachineState *mms = MPS3R_MACHINE(machine);
50
+ bool is_secure = ptw->in_secure;
167
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
51
ARMMMUIdx s2_mmu_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
168
MemoryRegion *mr = mr_for_raminfo(mms, ri);
52
169
memory_region_add_subregion(sysmem, ri->base, mr);
53
- if (arm_mmu_idx_is_stage1_of_2(mmu_idx) &&
54
+ if (arm_mmu_idx_is_stage1_of_2(ptw->in_mmu_idx) &&
55
!regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
56
GetPhysAddrResult s2 = {};
57
+ S1Translate s2ptw = {
58
+ .in_mmu_idx = s2_mmu_idx,
59
+ .in_secure = is_secure,
60
+ };
61
uint64_t hcr;
62
int ret;
63
64
- ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx,
65
- is_secure, false, &s2, fi);
66
+ ret = get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
67
+ false, &s2, fi);
68
if (ret) {
69
assert(fi->type != ARMFault_None);
70
fi->s2addr = addr;
71
fi->stage2 = true;
72
fi->s1ptw = true;
73
fi->s1ns = !is_secure;
74
- return ~0;
75
+ return false;
76
}
77
78
hcr = arm_hcr_el2_eff_secstate(env, is_secure);
79
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
80
fi->stage2 = true;
81
fi->s1ptw = true;
82
fi->s1ns = !is_secure;
83
- return ~0;
84
+ return false;
85
}
86
87
if (arm_is_secure_below_el3(env)) {
88
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
89
} else {
90
is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
91
}
92
- *is_secure_ptr = is_secure;
93
} else {
94
assert(!is_secure);
95
}
96
97
addr = s2.f.phys_addr;
98
}
170
}
99
- return addr;
171
+
100
+
172
+ assert(machine->smp.cpus <= MPS3R_CPU_MAX);
101
+ ptw->out_secure = is_secure;
173
+ for (int i = 0; i < machine->smp.cpus; i++) {
102
+ ptw->out_phys = addr;
174
+ g_autofree char *sysmem_name = g_strdup_printf("cpu-%d-memory", i);
103
+ return true;
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]);
205
+ }
206
+
207
+ create_gic(mms, sysmem);
208
+
209
+ mms->bootinfo.ram_size = machine->ram_size;
210
+ mms->bootinfo.board_id = -1;
211
+ mms->bootinfo.loader_start = mmc->loader_start;
212
+ mms->bootinfo.write_secondary_boot = mps3r_write_secondary_boot;
213
+ mms->bootinfo.secondary_cpu_reset_hook = mps3r_secondary_cpu_reset;
214
+ arm_load_kernel(ARM_CPU(mms->cpu[0]), machine, &mms->bootinfo);
104
}
215
}
105
216
106
/* All loads done in the course of a page table walk go through here. */
217
static void mps3r_set_default_ram_info(MPS3RMachineClass *mmc)
107
-static uint32_t arm_ldl_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
218
@@ -XXX,XX +XXX,XX @@ static void mps3r_set_default_ram_info(MPS3RMachineClass *mmc)
108
- ARMMMUIdx mmu_idx, ARMMMUFaultInfo *fi)
219
/* Found the entry for "system memory" */
109
+static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
220
mc->default_ram_size = p->size;
110
+ ARMMMUFaultInfo *fi)
221
mc->default_ram_id = p->name;
111
{
222
+ mmc->loader_start = p->base;
112
CPUState *cs = env_cpu(env);
223
return;
113
MemTxAttrs attrs = {};
114
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
115
AddressSpace *as;
116
uint32_t data;
117
118
- addr = S1_ptw_translate(env, mmu_idx, addr, &is_secure, fi);
119
- attrs.secure = is_secure;
120
- as = arm_addressspace(cs, attrs);
121
- if (fi->s1ptw) {
122
+ if (!S1_ptw_translate(env, ptw, addr, fi)) {
123
return 0;
124
}
125
- if (regime_translation_big_endian(env, mmu_idx)) {
126
+ addr = ptw->out_phys;
127
+ attrs.secure = ptw->out_secure;
128
+ as = arm_addressspace(cs, attrs);
129
+ if (regime_translation_big_endian(env, ptw->in_mmu_idx)) {
130
data = address_space_ldl_be(as, addr, attrs, &result);
131
} else {
132
data = address_space_ldl_le(as, addr, attrs, &result);
133
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
134
return 0;
135
}
136
137
-static uint64_t arm_ldq_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
138
- ARMMMUIdx mmu_idx, ARMMMUFaultInfo *fi)
139
+static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
140
+ ARMMMUFaultInfo *fi)
141
{
142
CPUState *cs = env_cpu(env);
143
MemTxAttrs attrs = {};
144
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
145
AddressSpace *as;
146
uint64_t data;
147
148
- addr = S1_ptw_translate(env, mmu_idx, addr, &is_secure, fi);
149
- attrs.secure = is_secure;
150
- as = arm_addressspace(cs, attrs);
151
- if (fi->s1ptw) {
152
+ if (!S1_ptw_translate(env, ptw, addr, fi)) {
153
return 0;
154
}
155
- if (regime_translation_big_endian(env, mmu_idx)) {
156
+ addr = ptw->out_phys;
157
+ attrs.secure = ptw->out_secure;
158
+ as = arm_addressspace(cs, attrs);
159
+ if (regime_translation_big_endian(env, ptw->in_mmu_idx)) {
160
data = address_space_ldq_be(as, addr, attrs, &result);
161
} else {
162
data = address_space_ldq_le(as, addr, attrs, &result);
163
@@ -XXX,XX +XXX,XX @@ static int simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap)
164
return simple_ap_to_rw_prot_is_user(ap, regime_is_user(env, mmu_idx));
165
}
166
167
-static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
168
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
169
- bool is_secure, GetPhysAddrResult *result,
170
- ARMMMUFaultInfo *fi)
171
+static bool get_phys_addr_v5(CPUARMState *env, S1Translate *ptw,
172
+ uint32_t address, MMUAccessType access_type,
173
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
174
{
175
int level = 1;
176
uint32_t table;
177
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
178
179
/* Pagetable walk. */
180
/* Lookup l1 descriptor. */
181
- if (!get_level1_table_address(env, mmu_idx, &table, address)) {
182
+ if (!get_level1_table_address(env, ptw->in_mmu_idx, &table, address)) {
183
/* Section translation fault if page walk is disabled by PD0 or PD1 */
184
fi->type = ARMFault_Translation;
185
goto do_fault;
186
}
187
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
188
+ desc = arm_ldl_ptw(env, ptw, table, fi);
189
if (fi->type != ARMFault_None) {
190
goto do_fault;
191
}
192
type = (desc & 3);
193
domain = (desc >> 5) & 0x0f;
194
- if (regime_el(env, mmu_idx) == 1) {
195
+ if (regime_el(env, ptw->in_mmu_idx) == 1) {
196
dacr = env->cp15.dacr_ns;
197
} else {
198
dacr = env->cp15.dacr_s;
199
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
200
/* Fine pagetable. */
201
table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
202
}
203
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
204
+ desc = arm_ldl_ptw(env, ptw, table, fi);
205
if (fi->type != ARMFault_None) {
206
goto do_fault;
207
}
208
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
209
g_assert_not_reached();
210
}
224
}
211
}
225
}
212
- result->f.prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
226
@@ -XXX,XX +XXX,XX @@ static void mps3r_an536_class_init(ObjectClass *oc, void *data)
213
+ result->f.prot = ap_to_rw_prot(env, ptw->in_mmu_idx, ap, domain_prot);
227
};
214
result->f.prot |= result->f.prot ? PAGE_EXEC : 0;
228
215
if (!(result->f.prot & (1 << access_type))) {
229
mc->desc = "ARM MPS3 with AN536 FPGA image for Cortex-R52";
216
/* Access permission fault. */
230
- mc->default_cpus = 2;
217
@@ -XXX,XX +XXX,XX @@ do_fault:
231
- mc->min_cpus = mc->default_cpus;
218
return true;
232
- mc->max_cpus = mc->default_cpus;
219
}
233
+ /*
220
234
+ * In the real FPGA image there are always two cores, but the standard
221
-static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
235
+ * initial setting for the SCC SYSCON 0x000 register is 0x21, meaning
222
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
236
+ * that the second core is held in reset and halted. Many images built for
223
- bool is_secure, GetPhysAddrResult *result,
237
+ * the board do not expect the second core to run at startup (especially
224
- ARMMMUFaultInfo *fi)
238
+ * since on the real FPGA image it is not possible to use LDREX/STREX
225
+static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
239
+ * in RAM between the two cores, so a true SMP setup isn't supported).
226
+ uint32_t address, MMUAccessType access_type,
240
+ *
227
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
241
+ * As QEMU's equivalent of this, we support both -smp 1 and -smp 2,
228
{
242
+ * with the default being -smp 1. This seems a more intuitive UI for
229
ARMCPU *cpu = env_archcpu(env);
243
+ * QEMU users than, for instance, having a machine property to allow
230
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
244
+ * the user to set the initial value of the SYSCON 0x000 register.
231
int level = 1;
245
+ */
232
uint32_t table;
246
+ mc->default_cpus = 1;
233
uint32_t desc;
247
+ mc->min_cpus = 1;
234
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
248
+ mc->max_cpus = 2;
235
fi->type = ARMFault_Translation;
249
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-r52");
236
goto do_fault;
250
mc->valid_cpu_types = valid_cpu_types;
237
}
251
mmc->raminfo = an536_raminfo;
238
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
239
+ desc = arm_ldl_ptw(env, ptw, table, fi);
240
if (fi->type != ARMFault_None) {
241
goto do_fault;
242
}
243
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
244
ns = extract32(desc, 3, 1);
245
/* Lookup l2 entry. */
246
table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
247
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
248
+ desc = arm_ldl_ptw(env, ptw, table, fi);
249
if (fi->type != ARMFault_None) {
250
goto do_fault;
251
}
252
@@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
253
* the WnR bit is never set (the caller must do this).
254
*
255
* @env: CPUARMState
256
+ * @ptw: Current and next stage parameters for the walk.
257
* @address: virtual address to get physical address for
258
* @access_type: MMU_DATA_LOAD, MMU_DATA_STORE or MMU_INST_FETCH
259
- * @mmu_idx: MMU index indicating required translation regime
260
- * @s1_is_el0: if @mmu_idx is ARMMMUIdx_Stage2 (so this is a stage 2 page
261
- * table walk), must be true if this is stage 2 of a stage 1+2
262
+ * @s1_is_el0: if @ptw->in_mmu_idx is ARMMMUIdx_Stage2
263
+ * (so this is a stage 2 page table walk),
264
+ * must be true if this is stage 2 of a stage 1+2
265
* walk for an EL0 access. If @mmu_idx is anything else,
266
* @s1_is_el0 is ignored.
267
* @result: set on translation success,
268
* @fi: set to fault info if the translation fails
269
*/
270
-static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
271
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
272
- bool is_secure, bool s1_is_el0,
273
+static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
274
+ uint64_t address,
275
+ MMUAccessType access_type, bool s1_is_el0,
276
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
277
{
278
ARMCPU *cpu = env_archcpu(env);
279
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
280
+ bool is_secure = ptw->in_secure;
281
/* Read an LPAE long-descriptor translation table. */
282
ARMFaultType fault_type = ARMFault_Translation;
283
uint32_t level;
284
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
285
descaddr |= (address >> (stride * (4 - level))) & indexmask;
286
descaddr &= ~7ULL;
287
nstable = extract32(tableattrs, 4, 1);
288
- descriptor = arm_ldq_ptw(env, descaddr, !nstable, mmu_idx, fi);
289
+ ptw->in_secure = !nstable;
290
+ descriptor = arm_ldq_ptw(env, ptw, descaddr, fi);
291
if (fi->type != ARMFault_None) {
292
goto do_fault;
293
}
294
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
295
ARMMMUFaultInfo *fi)
296
{
297
ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx);
298
+ S1Translate ptw;
299
300
if (mmu_idx != s1_mmu_idx) {
301
/*
302
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
303
int ret;
304
bool ipa_secure, s2walk_secure;
305
ARMCacheAttrs cacheattrs1;
306
- ARMMMUIdx s2_mmu_idx;
307
bool is_el0;
308
uint64_t hcr;
309
310
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
311
s2walk_secure = false;
312
}
313
314
- s2_mmu_idx = (s2walk_secure
315
- ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2);
316
+ ptw.in_mmu_idx =
317
+ s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
318
+ ptw.in_secure = s2walk_secure;
319
is_el0 = mmu_idx == ARMMMUIdx_E10_0;
320
321
/*
322
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
323
cacheattrs1 = result->cacheattrs;
324
memset(result, 0, sizeof(*result));
325
326
- ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx,
327
- s2walk_secure, is_el0, result, fi);
328
+ ret = get_phys_addr_lpae(env, &ptw, ipa, access_type,
329
+ is_el0, result, fi);
330
fi->s2addr = ipa;
331
332
/* Combine the S1 and S2 perms. */
333
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
334
return get_phys_addr_disabled(env, address, access_type, mmu_idx,
335
is_secure, result, fi);
336
}
337
+
338
+ ptw.in_mmu_idx = mmu_idx;
339
+ ptw.in_secure = is_secure;
340
+
341
if (regime_using_lpae_format(env, mmu_idx)) {
342
- return get_phys_addr_lpae(env, address, access_type, mmu_idx,
343
- is_secure, false, result, fi);
344
+ return get_phys_addr_lpae(env, &ptw, address, access_type, false,
345
+ result, fi);
346
} else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
347
- return get_phys_addr_v6(env, address, access_type, mmu_idx,
348
- is_secure, result, fi);
349
+ return get_phys_addr_v6(env, &ptw, address, access_type, result, fi);
350
} else {
351
- return get_phys_addr_v5(env, address, access_type, mmu_idx,
352
- is_secure, result, fi);
353
+ return get_phys_addr_v5(env, &ptw, address, access_type, result, fi);
354
}
355
}
356
357
--
252
--
358
2.25.1
253
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
This board has a lot of UARTs: there is one UART per CPU in the
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.
2
6
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
7
Connect and wire them all up; this involves some OR gates where
8
multiple overflow interrupts are wired into one GIC input.
4
9
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20221020030641.2066807-8-richard.henderson@linaro.org
8
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>
12
Message-id: 20240206132931.38376-11-peter.maydell@linaro.org
9
---
13
---
10
target/arm/translate-a64.c | 41 +++++++++++++++++++++++++++-----------
14
hw/arm/mps3r.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++
11
1 file changed, 29 insertions(+), 12 deletions(-)
15
1 file changed, 94 insertions(+)
12
16
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
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/translate-a64.c
19
--- a/hw/arm/mps3r.c
16
+++ b/target/arm/translate-a64.c
20
+++ b/hw/arm/mps3r.c
17
@@ -XXX,XX +XXX,XX @@ static void reset_btype(DisasContext *s)
21
@@ -XXX,XX +XXX,XX @@
22
#include "qapi/qmp/qlist.h"
23
#include "exec/address-spaces.h"
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
64
+
65
static const RAMInfo an536_raminfo[] = {
66
{
67
.name = "ATCM",
68
@@ -XXX,XX +XXX,XX @@ static void create_gic(MPS3RMachineState *mms, MemoryRegion *sysmem)
18
}
69
}
19
}
70
}
20
71
21
+static void gen_pc_plus_diff(DisasContext *s, TCGv_i64 dest, target_long diff)
72
+/*
73
+ * Create UART uartno, and map it into the MemoryRegion mem at address baseaddr.
74
+ * The qemu_irq arguments are where we connect the various IRQs from the UART.
75
+ */
76
+static void create_uart(MPS3RMachineState *mms, int uartno, MemoryRegion *mem,
77
+ hwaddr baseaddr, qemu_irq txirq, qemu_irq rxirq,
78
+ qemu_irq txoverirq, qemu_irq rxoverirq,
79
+ qemu_irq combirq)
22
+{
80
+{
23
+ tcg_gen_movi_i64(dest, s->pc_curr + diff);
81
+ g_autofree char *s = g_strdup_printf("uart%d", uartno);
82
+ SysBusDevice *sbd;
83
+
84
+ assert(uartno < ARRAY_SIZE(mms->uart));
85
+ object_initialize_child(OBJECT(mms), s, &mms->uart[uartno],
86
+ TYPE_CMSDK_APB_UART);
87
+ qdev_prop_set_uint32(DEVICE(&mms->uart[uartno]), "pclk-frq", CLK_FRQ);
88
+ qdev_prop_set_chr(DEVICE(&mms->uart[uartno]), "chardev", serial_hd(uartno));
89
+ sbd = SYS_BUS_DEVICE(&mms->uart[uartno]);
90
+ sysbus_realize(sbd, &error_fatal);
91
+ memory_region_add_subregion(mem, baseaddr,
92
+ sysbus_mmio_get_region(sbd, 0));
93
+ sysbus_connect_irq(sbd, 0, txirq);
94
+ sysbus_connect_irq(sbd, 1, rxirq);
95
+ sysbus_connect_irq(sbd, 2, txoverirq);
96
+ sysbus_connect_irq(sbd, 3, rxoverirq);
97
+ sysbus_connect_irq(sbd, 4, combirq);
24
+}
98
+}
25
+
99
+
26
void gen_a64_update_pc(DisasContext *s, target_long diff)
100
static void mps3r_common_init(MachineState *machine)
27
{
101
{
28
- tcg_gen_movi_i64(cpu_pc, s->pc_curr + diff);
102
MPS3RMachineState *mms = MPS3R_MACHINE(machine);
29
+ gen_pc_plus_diff(s, cpu_pc, diff);
103
MPS3RMachineClass *mmc = MPS3R_MACHINE_GET_CLASS(mms);
30
}
104
MemoryRegion *sysmem = get_system_memory();
31
105
+ DeviceState *gicdev;
32
/*
106
33
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
107
for (const RAMInfo *ri = mmc->raminfo; ri->name; ri++) {
34
108
MemoryRegion *mr = mr_for_raminfo(mms, ri);
35
if (insn & (1U << 31)) {
109
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
36
/* BL Branch with link */
37
- tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
38
+ gen_pc_plus_diff(s, cpu_reg(s, 30), curr_insn_len(s));
39
}
110
}
40
111
41
/* B Branch / BL Branch with link */
112
create_gic(mms, sysmem);
42
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
113
+ gicdev = DEVICE(&mms->gic);
43
default:
114
+
44
goto do_unallocated;
115
+ /*
45
}
116
+ * UARTs 0 and 1 are per-CPU; their interrupts are wired to
46
- gen_a64_set_pc(s, dst);
117
+ * the relevant CPU's PPI 0..3, aka INTID 16..19
47
/* BLR also needs to load return address */
118
+ */
48
if (opc == 1) {
119
+ for (int i = 0; i < machine->smp.cpus; i++) {
49
- tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
120
+ int intidbase = NUM_SPIS + i * GIC_INTERNAL;
50
+ TCGv_i64 lr = cpu_reg(s, 30);
121
+ g_autofree char *s = g_strdup_printf("cpu-uart-oflow-orgate%d", i);
51
+ if (dst == lr) {
122
+ DeviceState *orgate;
52
+ TCGv_i64 tmp = new_tmp_a64(s);
123
+
53
+ tcg_gen_mov_i64(tmp, dst);
124
+ /* The two overflow IRQs from the UART are ORed together into PPI 3 */
54
+ dst = tmp;
125
+ object_initialize_child(OBJECT(mms), s, &mms->cpu_uart_oflow[i],
55
+ }
126
+ TYPE_OR_IRQ);
56
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
127
+ orgate = DEVICE(&mms->cpu_uart_oflow[i]);
57
}
128
+ qdev_prop_set_uint32(orgate, "num-lines", 2);
58
+ gen_a64_set_pc(s, dst);
129
+ qdev_realize(orgate, NULL, &error_fatal);
59
break;
130
+ qdev_connect_gpio_out(orgate, 0,
60
131
+ qdev_get_gpio_in(gicdev, intidbase + 19));
61
case 8: /* BRAA */
132
+
62
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
133
+ create_uart(mms, i, &mms->cpu_sysmem[i], 0xe7c00000,
63
} else {
134
+ qdev_get_gpio_in(gicdev, intidbase + 17), /* tx */
64
dst = cpu_reg(s, rn);
135
+ qdev_get_gpio_in(gicdev, intidbase + 16), /* rx */
65
}
136
+ qdev_get_gpio_in(orgate, 0), /* txover */
66
- gen_a64_set_pc(s, dst);
137
+ qdev_get_gpio_in(orgate, 1), /* rxover */
67
/* BLRAA also needs to load return address */
138
+ qdev_get_gpio_in(gicdev, intidbase + 18) /* combined */);
68
if (opc == 9) {
139
+ }
69
- tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
140
+ /*
70
+ TCGv_i64 lr = cpu_reg(s, 30);
141
+ * UARTs 2 to 5 are whole-system; all overflow IRQs are ORed
71
+ if (dst == lr) {
142
+ * together into IRQ 17
72
+ TCGv_i64 tmp = new_tmp_a64(s);
143
+ */
73
+ tcg_gen_mov_i64(tmp, dst);
144
+ object_initialize_child(OBJECT(mms), "uart-oflow-orgate",
74
+ dst = tmp;
145
+ &mms->uart_oflow, TYPE_OR_IRQ);
75
+ }
146
+ qdev_prop_set_uint32(DEVICE(&mms->uart_oflow), "num-lines",
76
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
147
+ MPS3R_UART_MAX * 2);
77
}
148
+ qdev_realize(DEVICE(&mms->uart_oflow), NULL, &error_fatal);
78
+ gen_a64_set_pc(s, dst);
149
+ qdev_connect_gpio_out(DEVICE(&mms->uart_oflow), 0,
79
break;
150
+ qdev_get_gpio_in(gicdev, 17));
80
151
+
81
case 4: /* ERET */
152
+ for (int i = 0; i < MPS3R_UART_MAX; i++) {
82
@@ -XXX,XX +XXX,XX @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
153
+ hwaddr baseaddr = 0xe0205000 + i * 0x1000;
83
154
+ int rxirq = 5 + i * 2, txirq = 6 + i * 2, combirq = 13 + i;
84
tcg_rt = cpu_reg(s, rt);
155
+
85
156
+ create_uart(mms, i + MPS3R_CPU_MAX, sysmem, baseaddr,
86
- clean_addr = tcg_constant_i64(s->pc_curr + imm);
157
+ qdev_get_gpio_in(gicdev, txirq),
87
+ clean_addr = new_tmp_a64(s);
158
+ qdev_get_gpio_in(gicdev, rxirq),
88
+ gen_pc_plus_diff(s, clean_addr, imm);
159
+ qdev_get_gpio_in(DEVICE(&mms->uart_oflow), i * 2),
89
if (is_vector) {
160
+ qdev_get_gpio_in(DEVICE(&mms->uart_oflow), i * 2 + 1),
90
do_fp_ld(s, rt, clean_addr, size);
161
+ qdev_get_gpio_in(gicdev, combirq));
91
} else {
162
+ }
92
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
163
93
static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
164
mms->bootinfo.ram_size = machine->ram_size;
94
{
165
mms->bootinfo.board_id = -1;
95
unsigned int page, rd;
96
- uint64_t base;
97
- uint64_t offset;
98
+ int64_t offset;
99
100
page = extract32(insn, 31, 1);
101
/* SignExtend(immhi:immlo) -> offset */
102
offset = sextract64(insn, 5, 19);
103
offset = offset << 2 | extract32(insn, 29, 2);
104
rd = extract32(insn, 0, 5);
105
- base = s->pc_curr;
106
107
if (page) {
108
/* ADRP (page based) */
109
- base &= ~0xfff;
110
offset <<= 12;
111
+ /* The page offset is ok for TARGET_TB_PCREL. */
112
+ offset -= s->pc_curr & 0xfff;
113
}
114
115
- tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
116
+ gen_pc_plus_diff(s, cpu_reg(s, rd), offset);
117
}
118
119
/*
120
--
166
--
121
2.25.1
167
2.34.1
168
169
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Add the GPIO, watchdog, dual-timer and I2C devices to the mps3-an536
2
board. These are all simple devices that just need to be created and
3
wired up.
2
4
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20221011031911.2408754-12-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20240206132931.38376-12-peter.maydell@linaro.org
7
---
8
---
8
target/arm/ptw.c | 191 +++++++++++++++++++++++++----------------------
9
hw/arm/mps3r.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++
9
1 file changed, 100 insertions(+), 91 deletions(-)
10
1 file changed, 59 insertions(+)
10
11
11
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
12
diff --git a/hw/arm/mps3r.c b/hw/arm/mps3r.c
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/ptw.c
14
--- a/hw/arm/mps3r.c
14
+++ b/target/arm/ptw.c
15
+++ b/hw/arm/mps3r.c
15
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
16
@@ -XXX,XX +XXX,XX @@
16
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
17
#include "sysemu/sysemu.h"
17
__attribute__((nonnull));
18
#include "hw/boards.h"
18
19
#include "hw/or-irq.h"
19
+static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
20
+#include "hw/qdev-clock.h"
20
+ target_ulong address,
21
#include "hw/qdev-properties.h"
21
+ MMUAccessType access_type,
22
#include "hw/arm/boot.h"
22
+ GetPhysAddrResult *result,
23
#include "hw/arm/bsa.h"
23
+ ARMMMUFaultInfo *fi)
24
#include "hw/char/cmsdk-apb-uart.h"
24
+ __attribute__((nonnull));
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);
25
+
50
+
26
/* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */
51
for (const RAMInfo *ri = mmc->raminfo; ri->name; ri++) {
27
static const uint8_t pamax_map[] = {
52
MemoryRegion *mr = mr_for_raminfo(mms, ri);
28
[0] = 32,
53
memory_region_add_subregion(sysmem, ri->base, mr);
29
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
54
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
30
return 0;
55
qdev_get_gpio_in(gicdev, combirq));
31
}
56
}
32
57
33
+static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
58
+ for (int i = 0; i < 4; i++) {
34
+ target_ulong address,
59
+ /* CMSDK GPIO controllers */
35
+ MMUAccessType access_type,
60
+ g_autofree char *s = g_strdup_printf("gpio%d", i);
36
+ GetPhysAddrResult *result,
61
+ create_unimplemented_device(s, 0xe0000000 + i * 0x1000, 0x1000);
37
+ ARMMMUFaultInfo *fi)
38
+{
39
+ hwaddr ipa;
40
+ int s1_prot;
41
+ int ret;
42
+ bool is_secure = ptw->in_secure;
43
+ bool ipa_secure, s2walk_secure;
44
+ ARMCacheAttrs cacheattrs1;
45
+ bool is_el0;
46
+ uint64_t hcr;
47
+
48
+ ret = get_phys_addr_with_struct(env, ptw, address, access_type, result, fi);
49
+
50
+ /* If S1 fails or S2 is disabled, return early. */
51
+ if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2, is_secure)) {
52
+ return ret;
53
+ }
62
+ }
54
+
63
+
55
+ ipa = result->f.phys_addr;
64
+ object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
56
+ ipa_secure = result->f.attrs.secure;
65
+ TYPE_CMSDK_APB_WATCHDOG);
57
+ if (is_secure) {
66
+ qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->clk);
58
+ /* Select TCR based on the NS bit from the S1 walk. */
67
+ sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
59
+ s2walk_secure = !(ipa_secure
68
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
60
+ ? env->cp15.vstcr_el2 & VSTCR_SW
69
+ qdev_get_gpio_in(gicdev, 0));
61
+ : env->cp15.vtcr_el2 & VTCR_NSW);
70
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->watchdog), 0, 0xe0100000);
62
+ } else {
71
+
63
+ assert(!ipa_secure);
72
+ object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
64
+ s2walk_secure = false;
73
+ TYPE_CMSDK_APB_DUALTIMER);
74
+ qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->clk);
75
+ sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
76
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
77
+ qdev_get_gpio_in(gicdev, 3));
78
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 1,
79
+ qdev_get_gpio_in(gicdev, 1));
80
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 2,
81
+ qdev_get_gpio_in(gicdev, 2));
82
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0xe0101000);
83
+
84
+ for (int i = 0; i < ARRAY_SIZE(mms->i2c); i++) {
85
+ static const hwaddr i2cbase[] = {0xe0102000, /* Touch */
86
+ 0xe0103000, /* Audio */
87
+ 0xe0107000, /* Shield0 */
88
+ 0xe0108000, /* Shield1 */
89
+ 0xe0109000}; /* DDR4 EEPROM */
90
+ g_autofree char *s = g_strdup_printf("i2c%d", i);
91
+
92
+ object_initialize_child(OBJECT(mms), s, &mms->i2c[i],
93
+ TYPE_ARM_SBCON_I2C);
94
+ sysbus_realize(SYS_BUS_DEVICE(&mms->i2c[i]), &error_fatal);
95
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->i2c[i]), 0, i2cbase[i]);
96
+ if (i != 2 && i != 3) {
97
+ /*
98
+ * internal-only bus: mark it full to avoid user-created
99
+ * i2c devices being plugged into it.
100
+ */
101
+ qbus_mark_full(qdev_get_child_bus(DEVICE(&mms->i2c[i]), "i2c"));
102
+ }
65
+ }
103
+ }
66
+
104
+
67
+ is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
105
mms->bootinfo.ram_size = machine->ram_size;
68
+ ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
106
mms->bootinfo.board_id = -1;
69
+ ptw->in_secure = s2walk_secure;
107
mms->bootinfo.loader_start = mmc->loader_start;
70
+
71
+ /*
72
+ * S1 is done, now do S2 translation.
73
+ * Save the stage1 results so that we may merge prot and cacheattrs later.
74
+ */
75
+ s1_prot = result->f.prot;
76
+ cacheattrs1 = result->cacheattrs;
77
+ memset(result, 0, sizeof(*result));
78
+
79
+ ret = get_phys_addr_lpae(env, ptw, ipa, access_type, is_el0, result, fi);
80
+ fi->s2addr = ipa;
81
+
82
+ /* Combine the S1 and S2 perms. */
83
+ result->f.prot &= s1_prot;
84
+
85
+ /* If S2 fails, return early. */
86
+ if (ret) {
87
+ return ret;
88
+ }
89
+
90
+ /* Combine the S1 and S2 cache attributes. */
91
+ hcr = arm_hcr_el2_eff_secstate(env, is_secure);
92
+ if (hcr & HCR_DC) {
93
+ /*
94
+ * HCR.DC forces the first stage attributes to
95
+ * Normal Non-Shareable,
96
+ * Inner Write-Back Read-Allocate Write-Allocate,
97
+ * Outer Write-Back Read-Allocate Write-Allocate.
98
+ * Do not overwrite Tagged within attrs.
99
+ */
100
+ if (cacheattrs1.attrs != 0xf0) {
101
+ cacheattrs1.attrs = 0xff;
102
+ }
103
+ cacheattrs1.shareability = 0;
104
+ }
105
+ result->cacheattrs = combine_cacheattrs(hcr, cacheattrs1,
106
+ result->cacheattrs);
107
+
108
+ /*
109
+ * Check if IPA translates to secure or non-secure PA space.
110
+ * Note that VSTCR overrides VTCR and {N}SW overrides {N}SA.
111
+ */
112
+ result->f.attrs.secure =
113
+ (is_secure
114
+ && !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW))
115
+ && (ipa_secure
116
+ || !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))));
117
+
118
+ return 0;
119
+}
120
+
121
static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
122
target_ulong address,
123
MMUAccessType access_type,
124
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
125
if (mmu_idx != s1_mmu_idx) {
126
/*
127
* Call ourselves recursively to do the stage 1 and then stage 2
128
- * translations if mmu_idx is a two-stage regime.
129
+ * translations if mmu_idx is a two-stage regime, and EL2 present.
130
+ * Otherwise, a stage1+stage2 translation is just stage 1.
131
*/
132
+ ptw->in_mmu_idx = mmu_idx = s1_mmu_idx;
133
if (arm_feature(env, ARM_FEATURE_EL2)) {
134
- hwaddr ipa;
135
- int s1_prot;
136
- int ret;
137
- bool ipa_secure, s2walk_secure;
138
- ARMCacheAttrs cacheattrs1;
139
- bool is_el0;
140
- uint64_t hcr;
141
-
142
- ptw->in_mmu_idx = s1_mmu_idx;
143
- ret = get_phys_addr_with_struct(env, ptw, address, access_type,
144
- result, fi);
145
-
146
- /* If S1 fails or S2 is disabled, return early. */
147
- if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2,
148
- is_secure)) {
149
- return ret;
150
- }
151
-
152
- ipa = result->f.phys_addr;
153
- ipa_secure = result->f.attrs.secure;
154
- if (is_secure) {
155
- /* Select TCR based on the NS bit from the S1 walk. */
156
- s2walk_secure = !(ipa_secure
157
- ? env->cp15.vstcr_el2 & VSTCR_SW
158
- : env->cp15.vtcr_el2 & VTCR_NSW);
159
- } else {
160
- assert(!ipa_secure);
161
- s2walk_secure = false;
162
- }
163
-
164
- ptw->in_mmu_idx =
165
- s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
166
- ptw->in_secure = s2walk_secure;
167
- is_el0 = mmu_idx == ARMMMUIdx_E10_0;
168
-
169
- /*
170
- * S1 is done, now do S2 translation.
171
- * Save the stage1 results so that we may merge
172
- * prot and cacheattrs later.
173
- */
174
- s1_prot = result->f.prot;
175
- cacheattrs1 = result->cacheattrs;
176
- memset(result, 0, sizeof(*result));
177
-
178
- ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
179
- is_el0, result, fi);
180
- fi->s2addr = ipa;
181
-
182
- /* Combine the S1 and S2 perms. */
183
- result->f.prot &= s1_prot;
184
-
185
- /* If S2 fails, return early. */
186
- if (ret) {
187
- return ret;
188
- }
189
-
190
- /* Combine the S1 and S2 cache attributes. */
191
- hcr = arm_hcr_el2_eff_secstate(env, is_secure);
192
- if (hcr & HCR_DC) {
193
- /*
194
- * HCR.DC forces the first stage attributes to
195
- * Normal Non-Shareable,
196
- * Inner Write-Back Read-Allocate Write-Allocate,
197
- * Outer Write-Back Read-Allocate Write-Allocate.
198
- * Do not overwrite Tagged within attrs.
199
- */
200
- if (cacheattrs1.attrs != 0xf0) {
201
- cacheattrs1.attrs = 0xff;
202
- }
203
- cacheattrs1.shareability = 0;
204
- }
205
- result->cacheattrs = combine_cacheattrs(hcr, cacheattrs1,
206
- result->cacheattrs);
207
-
208
- /*
209
- * Check if IPA translates to secure or non-secure PA space.
210
- * Note that VSTCR overrides VTCR and {N}SW overrides {N}SA.
211
- */
212
- result->f.attrs.secure =
213
- (is_secure
214
- && !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW))
215
- && (ipa_secure
216
- || !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))));
217
-
218
- return 0;
219
- } else {
220
- /*
221
- * For non-EL2 CPUs a stage1+stage2 translation is just stage 1.
222
- */
223
- mmu_idx = stage_1_mmu_idx(mmu_idx);
224
+ return get_phys_addr_twostage(env, ptw, address, access_type,
225
+ result, fi);
226
}
227
}
228
229
--
108
--
230
2.25.1
109
2.34.1
110
111
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Add the remaining devices (or unimplemented-device stubs) for
2
this board: SPI controllers, SCC, FPGAIO, I2S, RTC, the
3
QSPI write-config block, and ethernet.
2
4
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20221020030641.2066807-10-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20240206132931.38376-13-peter.maydell@linaro.org
7
---
8
---
8
target/arm/cpu-param.h | 2 +
9
hw/arm/mps3r.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
9
target/arm/translate.h | 50 +++++++++++++++-
10
1 file changed, 74 insertions(+)
10
target/arm/cpu.c | 23 ++++----
11
target/arm/translate-a64.c | 64 +++++++++++++-------
12
target/arm/translate-m-nocp.c | 2 +-
13
target/arm/translate.c | 108 +++++++++++++++++++++++-----------
14
6 files changed, 178 insertions(+), 71 deletions(-)
15
11
16
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
12
diff --git a/hw/arm/mps3r.c b/hw/arm/mps3r.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu-param.h
14
--- a/hw/arm/mps3r.c
19
+++ b/target/arm/cpu-param.h
15
+++ b/hw/arm/mps3r.c
20
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
21
# define TARGET_PAGE_BITS_VARY
17
#include "hw/char/cmsdk-apb-uart.h"
22
# define TARGET_PAGE_BITS_MIN 10
18
#include "hw/i2c/arm_sbcon_i2c.h"
23
19
#include "hw/intc/arm_gicv3.h"
24
+# define TARGET_TB_PCREL 1
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
+};
25
+
54
+
26
/*
55
static MemoryRegion *mr_for_raminfo(MPS3RMachineState *mms,
27
* Cache the attrs and shareability fields from the page table entry.
56
const RAMInfo *raminfo)
28
*
29
diff --git a/target/arm/translate.h b/target/arm/translate.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate.h
32
+++ b/target/arm/translate.h
33
@@ -XXX,XX +XXX,XX @@
34
35
36
/* internal defines */
37
+
38
+/*
39
+ * Save pc_save across a branch, so that we may restore the value from
40
+ * before the branch at the point the label is emitted.
41
+ */
42
+typedef struct DisasLabel {
43
+ TCGLabel *label;
44
+ target_ulong pc_save;
45
+} DisasLabel;
46
+
47
typedef struct DisasContext {
48
DisasContextBase base;
49
const ARMISARegisters *isar;
50
51
/* The address of the current instruction being translated. */
52
target_ulong pc_curr;
53
+ /*
54
+ * For TARGET_TB_PCREL, the full value of cpu_pc is not known
55
+ * (although the page offset is known). For convenience, the
56
+ * translation loop uses the full virtual address that triggered
57
+ * the translation, from base.pc_start through pc_curr.
58
+ * For efficiency, we do not update cpu_pc for every instruction.
59
+ * Instead, pc_save has the value of pc_curr at the time of the
60
+ * last update to cpu_pc, which allows us to compute the addend
61
+ * needed to bring cpu_pc current: pc_curr - pc_save.
62
+ * If cpu_pc now contains the destination of an indirect branch,
63
+ * pc_save contains -1 to indicate that relative updates are no
64
+ * longer possible.
65
+ */
66
+ target_ulong pc_save;
67
target_ulong page_start;
68
uint32_t insn;
69
/* Nonzero if this instruction has been conditionally skipped. */
70
int condjmp;
71
/* The label that will be jumped to when the instruction is skipped. */
72
- TCGLabel *condlabel;
73
+ DisasLabel condlabel;
74
/* Thumb-2 conditional execution bits. */
75
int condexec_mask;
76
int condexec_cond;
77
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
78
* after decode (ie after any UNDEF checks)
79
*/
80
bool eci_handled;
81
- /* TCG op to rewind to if this turns out to be an invalid ECI state */
82
- TCGOp *insn_eci_rewind;
83
int sctlr_b;
84
MemOp be_data;
85
#if !defined(CONFIG_USER_ONLY)
86
@@ -XXX,XX +XXX,XX @@ static inline MemOp finalize_memop(DisasContext *s, MemOp opc)
87
*/
88
uint64_t asimd_imm_const(uint32_t imm, int cmode, int op);
89
90
+/*
91
+ * gen_disas_label:
92
+ * Create a label and cache a copy of pc_save.
93
+ */
94
+static inline DisasLabel gen_disas_label(DisasContext *s)
95
+{
96
+ return (DisasLabel){
97
+ .label = gen_new_label(),
98
+ .pc_save = s->pc_save,
99
+ };
100
+}
101
+
102
+/*
103
+ * set_disas_label:
104
+ * Emit a label and restore the cached copy of pc_save.
105
+ */
106
+static inline void set_disas_label(DisasContext *s, DisasLabel l)
107
+{
108
+ gen_set_label(l.label);
109
+ s->pc_save = l.pc_save;
110
+}
111
+
112
/*
113
* Helpers for implementing sets of trans_* functions.
114
* Defer the implementation of NAME to FUNC, with optional extra arguments.
115
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/target/arm/cpu.c
118
+++ b/target/arm/cpu.c
119
@@ -XXX,XX +XXX,XX @@ static vaddr arm_cpu_get_pc(CPUState *cs)
120
void arm_cpu_synchronize_from_tb(CPUState *cs,
121
const TranslationBlock *tb)
122
{
57
{
123
- ARMCPU *cpu = ARM_CPU(cs);
58
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
124
- CPUARMState *env = &cpu->env;
59
MPS3RMachineClass *mmc = MPS3R_MACHINE_GET_CLASS(mms);
125
-
60
MemoryRegion *sysmem = get_system_memory();
126
- /*
61
DeviceState *gicdev;
127
- * It's OK to look at env for the current mode here, because it's
62
+ QList *oscclk;
128
- * never possible for an AArch64 TB to chain to an AArch32 TB.
63
129
- */
64
mms->clk = clock_new(OBJECT(machine), "CLK");
130
- if (is_a64(env)) {
65
clock_set_hz(mms->clk, CLK_FRQ);
131
- env->pc = tb_pc(tb);
66
@@ -XXX,XX +XXX,XX @@ static void mps3r_common_init(MachineState *machine)
132
- } else {
133
- env->regs[15] = tb_pc(tb);
134
+ /* The program counter is always up to date with TARGET_TB_PCREL. */
135
+ if (!TARGET_TB_PCREL) {
136
+ CPUARMState *env = cs->env_ptr;
137
+ /*
138
+ * It's OK to look at env for the current mode here, because it's
139
+ * never possible for an AArch64 TB to chain to an AArch32 TB.
140
+ */
141
+ if (is_a64(env)) {
142
+ env->pc = tb_pc(tb);
143
+ } else {
144
+ env->regs[15] = tb_pc(tb);
145
+ }
146
}
147
}
148
#endif /* CONFIG_TCG */
149
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/target/arm/translate-a64.c
152
+++ b/target/arm/translate-a64.c
153
@@ -XXX,XX +XXX,XX @@ static void reset_btype(DisasContext *s)
154
155
static void gen_pc_plus_diff(DisasContext *s, TCGv_i64 dest, target_long diff)
156
{
157
- tcg_gen_movi_i64(dest, s->pc_curr + diff);
158
+ assert(s->pc_save != -1);
159
+ if (TARGET_TB_PCREL) {
160
+ tcg_gen_addi_i64(dest, cpu_pc, (s->pc_curr - s->pc_save) + diff);
161
+ } else {
162
+ tcg_gen_movi_i64(dest, s->pc_curr + diff);
163
+ }
164
}
165
166
void gen_a64_update_pc(DisasContext *s, target_long diff)
167
{
168
gen_pc_plus_diff(s, cpu_pc, diff);
169
+ s->pc_save = s->pc_curr + diff;
170
}
171
172
/*
173
@@ -XXX,XX +XXX,XX @@ static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
174
* then loading an address into the PC will clear out any tag.
175
*/
176
gen_top_byte_ignore(s, cpu_pc, src, s->tbii);
177
+ s->pc_save = -1;
178
}
179
180
/*
181
@@ -XXX,XX +XXX,XX @@ static inline bool use_goto_tb(DisasContext *s, uint64_t dest)
182
183
static void gen_goto_tb(DisasContext *s, int n, int64_t diff)
184
{
185
- uint64_t dest = s->pc_curr + diff;
186
-
187
- if (use_goto_tb(s, dest)) {
188
- tcg_gen_goto_tb(n);
189
- gen_a64_update_pc(s, diff);
190
+ if (use_goto_tb(s, s->pc_curr + diff)) {
191
+ /*
192
+ * For pcrel, the pc must always be up-to-date on entry to
193
+ * the linked TB, so that it can use simple additions for all
194
+ * further adjustments. For !pcrel, the linked TB is compiled
195
+ * to know its full virtual address, so we can delay the
196
+ * update to pc to the unlinked path. A long chain of links
197
+ * can thus avoid many updates to the PC.
198
+ */
199
+ if (TARGET_TB_PCREL) {
200
+ gen_a64_update_pc(s, diff);
201
+ tcg_gen_goto_tb(n);
202
+ } else {
203
+ tcg_gen_goto_tb(n);
204
+ gen_a64_update_pc(s, diff);
205
+ }
206
tcg_gen_exit_tb(s->base.tb, n);
207
s->base.is_jmp = DISAS_NORETURN;
208
} else {
209
@@ -XXX,XX +XXX,XX @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
210
{
211
unsigned int sf, op, rt;
212
int64_t diff;
213
- TCGLabel *label_match;
214
+ DisasLabel match;
215
TCGv_i64 tcg_cmp;
216
217
sf = extract32(insn, 31, 1);
218
@@ -XXX,XX +XXX,XX @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
219
diff = sextract32(insn, 5, 19) * 4;
220
221
tcg_cmp = read_cpu_reg(s, rt, sf);
222
- label_match = gen_new_label();
223
-
224
reset_btype(s);
225
- tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
226
- tcg_cmp, 0, label_match);
227
228
+ match = gen_disas_label(s);
229
+ tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
230
+ tcg_cmp, 0, match.label);
231
gen_goto_tb(s, 0, 4);
232
- gen_set_label(label_match);
233
+ set_disas_label(s, match);
234
gen_goto_tb(s, 1, diff);
235
}
236
237
@@ -XXX,XX +XXX,XX @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
238
{
239
unsigned int bit_pos, op, rt;
240
int64_t diff;
241
- TCGLabel *label_match;
242
+ DisasLabel match;
243
TCGv_i64 tcg_cmp;
244
245
bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
246
@@ -XXX,XX +XXX,XX @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
247
248
tcg_cmp = tcg_temp_new_i64();
249
tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
250
- label_match = gen_new_label();
251
252
reset_btype(s);
253
+
254
+ match = gen_disas_label(s);
255
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
256
- tcg_cmp, 0, label_match);
257
+ tcg_cmp, 0, match.label);
258
tcg_temp_free_i64(tcg_cmp);
259
gen_goto_tb(s, 0, 4);
260
- gen_set_label(label_match);
261
+ set_disas_label(s, match);
262
gen_goto_tb(s, 1, diff);
263
}
264
265
@@ -XXX,XX +XXX,XX @@ static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
266
reset_btype(s);
267
if (cond < 0x0e) {
268
/* genuinely conditional branches */
269
- TCGLabel *label_match = gen_new_label();
270
- arm_gen_test_cc(cond, label_match);
271
+ DisasLabel match = gen_disas_label(s);
272
+ arm_gen_test_cc(cond, match.label);
273
gen_goto_tb(s, 0, 4);
274
- gen_set_label(label_match);
275
+ set_disas_label(s, match);
276
gen_goto_tb(s, 1, diff);
277
} else {
278
/* 0xe and 0xf are both "always" conditions */
279
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
280
281
dc->isar = &arm_cpu->isar;
282
dc->condjmp = 0;
283
-
284
+ dc->pc_save = dc->base.pc_first;
285
dc->aarch64 = true;
286
dc->thumb = false;
287
dc->sctlr_b = 0;
288
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu)
289
static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
290
{
291
DisasContext *dc = container_of(dcbase, DisasContext, base);
292
+ target_ulong pc_arg = dc->base.pc_next;
293
294
- tcg_gen_insn_start(dc->base.pc_next, 0, 0);
295
+ if (TARGET_TB_PCREL) {
296
+ pc_arg &= ~TARGET_PAGE_MASK;
297
+ }
298
+ tcg_gen_insn_start(pc_arg, 0, 0);
299
dc->insn_start = tcg_last_op();
300
}
301
302
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
303
index XXXXXXX..XXXXXXX 100644
304
--- a/target/arm/translate-m-nocp.c
305
+++ b/target/arm/translate-m-nocp.c
306
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
307
tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
308
tcg_gen_or_i32(sfpa, sfpa, aspen);
309
arm_gen_condlabel(s);
310
- tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
311
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel.label);
312
313
if (s->fp_excp_el != 0) {
314
gen_exception_insn_el(s, 0, EXCP_NOCP,
315
diff --git a/target/arm/translate.c b/target/arm/translate.c
316
index XXXXXXX..XXXXXXX 100644
317
--- a/target/arm/translate.c
318
+++ b/target/arm/translate.c
319
@@ -XXX,XX +XXX,XX @@ uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
320
void arm_gen_condlabel(DisasContext *s)
321
{
322
if (!s->condjmp) {
323
- s->condlabel = gen_new_label();
324
+ s->condlabel = gen_disas_label(s);
325
s->condjmp = 1;
326
}
327
}
328
@@ -XXX,XX +XXX,XX @@ static target_long jmp_diff(DisasContext *s, target_long diff)
329
330
static void gen_pc_plus_diff(DisasContext *s, TCGv_i32 var, target_long diff)
331
{
332
- tcg_gen_movi_i32(var, s->pc_curr + diff);
333
+ assert(s->pc_save != -1);
334
+ if (TARGET_TB_PCREL) {
335
+ tcg_gen_addi_i32(var, cpu_R[15], (s->pc_curr - s->pc_save) + diff);
336
+ } else {
337
+ tcg_gen_movi_i32(var, s->pc_curr + diff);
338
+ }
339
}
340
341
/* Set a variable to the value of a CPU register. */
342
@@ -XXX,XX +XXX,XX @@ void store_reg(DisasContext *s, int reg, TCGv_i32 var)
343
*/
344
tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
345
s->base.is_jmp = DISAS_JUMP;
346
+ s->pc_save = -1;
347
} else if (reg == 13 && arm_dc_feature(s, ARM_FEATURE_M)) {
348
/* For M-profile SP bits [1:0] are always zero */
349
tcg_gen_andi_i32(var, var, ~3);
350
@@ -XXX,XX +XXX,XX @@ void gen_set_condexec(DisasContext *s)
351
352
void gen_update_pc(DisasContext *s, target_long diff)
353
{
354
- tcg_gen_movi_i32(cpu_R[15], s->pc_curr + diff);
355
+ gen_pc_plus_diff(s, cpu_R[15], diff);
356
+ s->pc_save = s->pc_curr + diff;
357
}
358
359
/* Set PC and Thumb state from var. var is marked as dead. */
360
@@ -XXX,XX +XXX,XX @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var)
361
tcg_gen_andi_i32(cpu_R[15], var, ~1);
362
tcg_gen_andi_i32(var, var, 1);
363
store_cpu_field(var, thumb);
364
+ s->pc_save = -1;
365
}
366
367
/*
368
@@ -XXX,XX +XXX,XX @@ static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
369
static inline void gen_bx_excret_final_code(DisasContext *s)
370
{
371
/* Generate the code to finish possible exception return and end the TB */
372
- TCGLabel *excret_label = gen_new_label();
373
+ DisasLabel excret_label = gen_disas_label(s);
374
uint32_t min_magic;
375
376
if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
377
@@ -XXX,XX +XXX,XX @@ static inline void gen_bx_excret_final_code(DisasContext *s)
378
}
379
380
/* Is the new PC value in the magic range indicating exception return? */
381
- tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
382
+ tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label.label);
383
/* No: end the TB as we would for a DISAS_JMP */
384
if (s->ss_active) {
385
gen_singlestep_exception(s);
386
} else {
387
tcg_gen_exit_tb(NULL, 0);
388
}
389
- gen_set_label(excret_label);
390
+ set_disas_label(s, excret_label);
391
/* Yes: this is an exception return.
392
* At this point in runtime env->regs[15] and env->thumb will hold
393
* the exception-return magic number, which do_v7m_exception_exit()
394
@@ -XXX,XX +XXX,XX @@ static void gen_goto_ptr(void)
395
*/
396
static void gen_goto_tb(DisasContext *s, int n, target_long diff)
397
{
398
- target_ulong dest = s->pc_curr + diff;
399
-
400
- if (translator_use_goto_tb(&s->base, dest)) {
401
- tcg_gen_goto_tb(n);
402
- gen_update_pc(s, diff);
403
+ if (translator_use_goto_tb(&s->base, s->pc_curr + diff)) {
404
+ /*
405
+ * For pcrel, the pc must always be up-to-date on entry to
406
+ * the linked TB, so that it can use simple additions for all
407
+ * further adjustments. For !pcrel, the linked TB is compiled
408
+ * to know its full virtual address, so we can delay the
409
+ * update to pc to the unlinked path. A long chain of links
410
+ * can thus avoid many updates to the PC.
411
+ */
412
+ if (TARGET_TB_PCREL) {
413
+ gen_update_pc(s, diff);
414
+ tcg_gen_goto_tb(n);
415
+ } else {
416
+ tcg_gen_goto_tb(n);
417
+ gen_update_pc(s, diff);
418
+ }
419
tcg_gen_exit_tb(s->base.tb, n);
420
} else {
421
gen_update_pc(s, diff);
422
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
423
static void arm_skip_unless(DisasContext *s, uint32_t cond)
424
{
425
arm_gen_condlabel(s);
426
- arm_gen_test_cc(cond ^ 1, s->condlabel);
427
+ arm_gen_test_cc(cond ^ 1, s->condlabel.label);
428
}
429
430
431
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
432
{
433
/* M-profile low-overhead while-loop start */
434
TCGv_i32 tmp;
435
- TCGLabel *nextlabel;
436
+ DisasLabel nextlabel;
437
438
if (!dc_isar_feature(aa32_lob, s)) {
439
return false;
440
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
441
}
67
}
442
}
68
}
443
69
444
- nextlabel = gen_new_label();
70
+ for (int i = 0; i < ARRAY_SIZE(mms->spi); i++) {
445
- tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
71
+ g_autofree char *s = g_strdup_printf("spi%d", i);
446
+ nextlabel = gen_disas_label(s);
72
+ hwaddr baseaddr = 0xe0104000 + i * 0x1000;
447
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel.label);
73
+
448
tmp = load_reg(s, a->rn);
74
+ object_initialize_child(OBJECT(mms), s, &mms->spi[i], TYPE_PL022);
449
store_reg(s, 14, tmp);
75
+ sysbus_realize(SYS_BUS_DEVICE(&mms->spi[i]), &error_fatal);
450
if (a->size != 4) {
76
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->spi[i]), 0, baseaddr);
451
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
77
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->spi[i]), 0,
452
}
78
+ qdev_get_gpio_in(gicdev, 22 + i));
453
gen_jmp_tb(s, curr_insn_len(s), 1);
454
455
- gen_set_label(nextlabel);
456
+ set_disas_label(s, nextlabel);
457
gen_jmp(s, jmp_diff(s, a->imm));
458
return true;
459
}
460
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
461
* any faster.
462
*/
463
TCGv_i32 tmp;
464
- TCGLabel *loopend;
465
+ DisasLabel loopend;
466
bool fpu_active;
467
468
if (!dc_isar_feature(aa32_lob, s)) {
469
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
470
471
if (!a->tp && dc_isar_feature(aa32_mve, s) && fpu_active) {
472
/* Need to do a runtime check for LTPSIZE != 4 */
473
- TCGLabel *skipexc = gen_new_label();
474
+ DisasLabel skipexc = gen_disas_label(s);
475
tmp = load_cpu_field(v7m.ltpsize);
476
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc);
477
+ tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc.label);
478
tcg_temp_free_i32(tmp);
479
gen_exception_insn(s, 0, EXCP_INVSTATE, syn_uncategorized());
480
- gen_set_label(skipexc);
481
+ set_disas_label(s, skipexc);
482
}
483
484
if (a->f) {
485
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
486
* loop decrement value is 1. For LETP we need to calculate the decrement
487
* value from LTPSIZE.
488
*/
489
- loopend = gen_new_label();
490
+ loopend = gen_disas_label(s);
491
if (!a->tp) {
492
- tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, loopend);
493
+ tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, loopend.label);
494
tcg_gen_addi_i32(cpu_R[14], cpu_R[14], -1);
495
} else {
496
/*
497
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
498
tcg_gen_shl_i32(decr, tcg_constant_i32(1), decr);
499
tcg_temp_free_i32(ltpsize);
500
501
- tcg_gen_brcond_i32(TCG_COND_LEU, cpu_R[14], decr, loopend);
502
+ tcg_gen_brcond_i32(TCG_COND_LEU, cpu_R[14], decr, loopend.label);
503
504
tcg_gen_sub_i32(cpu_R[14], cpu_R[14], decr);
505
tcg_temp_free_i32(decr);
506
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
507
/* Jump back to the loop start */
508
gen_jmp(s, jmp_diff(s, -a->imm));
509
510
- gen_set_label(loopend);
511
+ set_disas_label(s, loopend);
512
if (a->tp) {
513
/* Exits from tail-pred loops must reset LTPSIZE to 4 */
514
store_cpu_field(tcg_constant_i32(4), v7m.ltpsize);
515
@@ -XXX,XX +XXX,XX @@ static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
516
517
arm_gen_condlabel(s);
518
tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
519
- tmp, 0, s->condlabel);
520
+ tmp, 0, s->condlabel.label);
521
tcg_temp_free_i32(tmp);
522
gen_jmp(s, jmp_diff(s, a->imm));
523
return true;
524
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
525
526
dc->isar = &cpu->isar;
527
dc->condjmp = 0;
528
-
529
+ dc->pc_save = dc->base.pc_first;
530
dc->aarch64 = false;
531
dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB);
532
dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
533
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
534
*/
535
dc->eci = dc->condexec_mask = dc->condexec_cond = 0;
536
dc->eci_handled = false;
537
- dc->insn_eci_rewind = NULL;
538
if (condexec & 0xf) {
539
dc->condexec_mask = (condexec & 0xf) << 1;
540
dc->condexec_cond = condexec >> 4;
541
@@ -XXX,XX +XXX,XX @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
542
* fields here.
543
*/
544
uint32_t condexec_bits;
545
+ target_ulong pc_arg = dc->base.pc_next;
546
547
+ if (TARGET_TB_PCREL) {
548
+ pc_arg &= ~TARGET_PAGE_MASK;
549
+ }
79
+ }
550
if (dc->eci) {
80
+
551
condexec_bits = dc->eci << 4;
81
+ object_initialize_child(OBJECT(mms), "scc", &mms->scc, TYPE_MPS2_SCC);
552
} else {
82
+ qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-cfg0", 0);
553
condexec_bits = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
83
+ qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-cfg4", 0x2);
554
}
84
+ qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-aid", 0x00200008);
555
- tcg_gen_insn_start(dc->base.pc_next, condexec_bits, 0);
85
+ qdev_prop_set_uint32(DEVICE(&mms->scc), "scc-id", 0x41055360);
556
+ tcg_gen_insn_start(pc_arg, condexec_bits, 0);
86
+ oscclk = qlist_new();
557
dc->insn_start = tcg_last_op();
87
+ for (int i = 0; i < ARRAY_SIZE(an536_oscclk); i++) {
558
}
88
+ qlist_append_int(oscclk, an536_oscclk[i]);
559
89
+ }
560
@@ -XXX,XX +XXX,XX @@ static bool arm_check_ss_active(DisasContext *dc)
90
+ qdev_prop_set_array(DEVICE(&mms->scc), "oscclk", oscclk);
561
91
+ sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
562
static void arm_post_translate_insn(DisasContext *dc)
92
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->scc), 0, 0xe0200000);
563
{
93
+
564
- if (dc->condjmp && !dc->base.is_jmp) {
94
+ create_unimplemented_device("i2s-audio", 0xe0201000, 0x1000);
565
- gen_set_label(dc->condlabel);
95
+
566
+ if (dc->condjmp && dc->base.is_jmp == DISAS_NEXT) {
96
+ object_initialize_child(OBJECT(mms), "fpgaio", &mms->fpgaio,
567
+ if (dc->pc_save != dc->condlabel.pc_save) {
97
+ TYPE_MPS2_FPGAIO);
568
+ gen_update_pc(dc, dc->condlabel.pc_save - dc->pc_save);
98
+ qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "prescale-clk", an536_oscclk[1]);
569
+ }
99
+ qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "num-leds", 10);
570
+ gen_set_label(dc->condlabel.label);
100
+ qdev_prop_set_bit(DEVICE(&mms->fpgaio), "has-switches", true);
571
dc->condjmp = 0;
101
+ qdev_prop_set_bit(DEVICE(&mms->fpgaio), "has-dbgctrl", false);
572
}
102
+ sysbus_realize(SYS_BUS_DEVICE(&mms->fpgaio), &error_fatal);
573
translator_loop_temp_check(&dc->base);
103
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->fpgaio), 0, 0xe0202000);
574
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
104
+
575
uint32_t pc = dc->base.pc_next;
105
+ create_unimplemented_device("clcd", 0xe0209000, 0x1000);
576
uint32_t insn;
106
+
577
bool is_16bit;
107
+ object_initialize_child(OBJECT(mms), "rtc", &mms->rtc, TYPE_PL031);
578
+ /* TCG op to rewind to if this turns out to be an invalid ECI state */
108
+ sysbus_realize(SYS_BUS_DEVICE(&mms->rtc), &error_fatal);
579
+ TCGOp *insn_eci_rewind = NULL;
109
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->rtc), 0, 0xe020a000);
580
+ target_ulong insn_eci_pc_save = -1;
110
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->rtc), 0,
581
111
+ qdev_get_gpio_in(gicdev, 4));
582
/* Misaligned thumb PC is architecturally impossible. */
112
+
583
assert((dc->base.pc_next & 1) == 0);
113
+ /*
584
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
114
+ * In hardware this is a LAN9220; the LAN9118 is software compatible
585
* insn" case. We will rewind to the marker (ie throwing away
115
+ * except that it doesn't support the checksum-offload feature.
586
* all the generated code) and instead emit "take exception".
116
+ */
587
*/
117
+ lan9118_init(0xe0300000,
588
- dc->insn_eci_rewind = tcg_last_op();
118
+ qdev_get_gpio_in(gicdev, 18));
589
+ insn_eci_rewind = tcg_last_op();
119
+
590
+ insn_eci_pc_save = dc->pc_save;
120
+ create_unimplemented_device("usb", 0xe0301000, 0x1000);
591
}
121
+ create_unimplemented_device("qspi-write-config", 0xe0600000, 0x1000);
592
122
+
593
if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
123
mms->bootinfo.ram_size = machine->ram_size;
594
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
124
mms->bootinfo.board_id = -1;
595
* Insn wasn't valid for ECI/ICI at all: undo what we
125
mms->bootinfo.loader_start = mmc->loader_start;
596
* just generated and instead emit an exception
597
*/
598
- tcg_remove_ops_after(dc->insn_eci_rewind);
599
+ tcg_remove_ops_after(insn_eci_rewind);
600
+ dc->pc_save = insn_eci_pc_save;
601
dc->condjmp = 0;
602
gen_exception_insn(dc, 0, EXCP_INVSTATE, syn_uncategorized());
603
}
604
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
605
606
if (dc->condjmp) {
607
/* "Condition failed" instruction codepath for the branch/trap insn */
608
- gen_set_label(dc->condlabel);
609
+ set_disas_label(dc, dc->condlabel);
610
gen_set_condexec(dc);
611
if (unlikely(dc->ss_active)) {
612
gen_update_pc(dc, curr_insn_len(dc));
613
@@ -XXX,XX +XXX,XX @@ void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
614
target_ulong *data)
615
{
616
if (is_a64(env)) {
617
- env->pc = data[0];
618
+ if (TARGET_TB_PCREL) {
619
+ env->pc = (env->pc & TARGET_PAGE_MASK) | data[0];
620
+ } else {
621
+ env->pc = data[0];
622
+ }
623
env->condexec_bits = 0;
624
env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
625
} else {
626
- env->regs[15] = data[0];
627
+ if (TARGET_TB_PCREL) {
628
+ env->regs[15] = (env->regs[15] & TARGET_PAGE_MASK) | data[0];
629
+ } else {
630
+ env->regs[15] = data[0];
631
+ }
632
env->condexec_bits = data[1];
633
env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
634
}
635
--
126
--
636
2.25.1
127
2.34.1
128
129
diff view generated by jsdifflib
1
Currently the microdrive code uses device_legacy_reset() to reset
1
Add documentation for the mps3-an536 board type.
2
itself, and has its reset method call reset on the IDE bus as the
3
last thing it does. Switch to using device_cold_reset().
4
5
The only concrete microdrive device is the TYPE_DSCM1XXXX; it is not
6
command-line pluggable, so it is used only by the old pxa2xx Arm
7
boards 'akita', 'borzoi', 'spitz', 'terrier' and 'tosa'.
8
9
You might think that this would result in the IDE bus being
10
reset automatically, but it does not, because the IDEBus type
11
does not set the BusClass::reset method. Instead the controller
12
must explicitly call ide_bus_reset(). We therefore leave that
13
call in md_reset().
14
15
Note also that because the PCMCIA card device is a direct subclass of
16
TYPE_DEVICE and we don't model the PCMCIA controller-to-card
17
interface as a qbus, PCMCIA cards are not on any qbus and so they
18
don't get reset when the system is reset. The reset only happens via
19
the dscm1xxxx_attach() and dscm1xxxx_detach() functions during
20
machine creation.
21
22
Because our aim here is merely to try to get rid of calls to the
23
device_legacy_reset() function, we leave these other dubious
24
reset-related issues alone. (They all stem from this code being
25
absolutely ancient.)
26
2
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
29
Message-id: 20221013174042.1602926-1-peter.maydell@linaro.org
5
Message-id: 20240206132931.38376-14-peter.maydell@linaro.org
30
---
6
---
31
hw/ide/microdrive.c | 8 ++++----
7
docs/system/arm/mps2.rst | 37 ++++++++++++++++++++++++++++++++++---
32
1 file changed, 4 insertions(+), 4 deletions(-)
8
1 file changed, 34 insertions(+), 3 deletions(-)
33
9
34
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
10
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
35
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/ide/microdrive.c
12
--- a/docs/system/arm/mps2.rst
37
+++ b/hw/ide/microdrive.c
13
+++ b/docs/system/arm/mps2.rst
38
@@ -XXX,XX +XXX,XX @@ static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
14
@@ -XXX,XX +XXX,XX @@
39
case 0x00:    /* Configuration Option Register */
15
-Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``, ``mps3-an547``)
40
s->opt = value & 0xcf;
16
-=========================================================================================================================================================
41
if (value & OPT_SRESET) {
17
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``, ``mps3-an536``, ``mps3-an547``)
42
- device_legacy_reset(DEVICE(s));
18
+=========================================================================================================================================================================
43
+ device_cold_reset(DEVICE(s));
19
44
}
20
-These board models all use Arm M-profile CPUs.
45
md_interrupt_update(s);
21
+These board models use Arm M-profile or R-profile CPUs.
46
break;
22
47
@@ -XXX,XX +XXX,XX @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
23
The Arm MPS2, MPS2+ and MPS3 dev boards are FPGA based (the 2+ has a
48
case 0xe:    /* Device Control */
24
bigger FPGA but is otherwise the same as the 2; the 3 has a bigger
49
s->ctrl = value;
25
@@ -XXX,XX +XXX,XX @@ FPGA image.
50
if (value & CTRL_SRST) {
26
51
- device_legacy_reset(DEVICE(s));
27
QEMU models the following FPGA images:
52
+ device_cold_reset(DEVICE(s));
28
53
}
29
+FPGA images using M-profile CPUs:
54
md_interrupt_update(s);
30
+
55
break;
31
``mps2-an385``
56
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_attach(PCMCIACardState *card)
32
Cortex-M3 as documented in Arm Application Note AN385
57
md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
33
``mps2-an386``
58
md->io_base = 0x0;
34
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
59
35
``mps3-an547``
60
- device_legacy_reset(DEVICE(md));
36
Cortex-M55 on an MPS3, as documented in Arm Application Note AN547
61
+ device_cold_reset(DEVICE(md));
37
62
md_interrupt_update(md);
38
+FPGA images using R-profile CPUs:
63
39
+
64
return 0;
40
+``mps3-an536``
65
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_detach(PCMCIACardState *card)
41
+ Dual Cortex-R52 on an MPS3, as documented in Arm Application Note AN536
66
{
42
+
67
MicroDriveState *md = MICRODRIVE(card);
43
Differences between QEMU and real hardware:
68
44
69
- device_legacy_reset(DEVICE(md));
45
- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
70
+ device_cold_reset(DEVICE(md));
46
@@ -XXX,XX +XXX,XX @@ Differences between QEMU and real hardware:
71
return 0;
47
flash, but only as simple ROM, so attempting to rewrite the flash
72
}
48
from the guest will fail
73
49
- QEMU does not model the USB controller in MPS3 boards
50
+- AN536 does not support runtime control of CPU reset and halt via
51
+ the SCC CFG_REG0 register.
52
+- AN536 does not support enabling or disabling the flash and ATCM
53
+ interfaces via the SCC CFG_REG1 register.
54
+- AN536 does not support setting of the initial vector table
55
+ base address via the SCC CFG_REG6 and CFG_REG7 register config,
56
+ and does not provide a mechanism for specifying these values at
57
+ startup, so all guest images must be built to start from TCM
58
+ (i.e. to expect the interrupt vector base at 0 from reset).
59
+- AN536 defaults to only creating a single CPU; this is the equivalent
60
+ of the way the real FPGA image usually runs with the second Cortex-R52
61
+ held in halt via the initial SCC CFG_REG0 register setting. You can
62
+ create the second CPU with ``-smp 2``; both CPUs will then start
63
+ execution immediately on startup.
64
+
65
+Note that for the AN536 the first UART is accessible only by
66
+CPU0, and the second UART is accessible only by CPU1. The
67
+first UART accessible shared between both CPUs is the third
68
+UART. Guest software might therefore be built to use either
69
+the first UART or the third UART; if you don't see any output
70
+from the UART you are looking at, try one of the others.
71
+(Even if the AN536 machine is started with a single CPU and so
72
+no "CPU1-only UART", the UART numbering remains the same,
73
+with the third UART being the first of the shared ones.)
74
75
Machine-specific options
76
""""""""""""""""""""""""
74
--
77
--
75
2.25.1
78
2.34.1
76
79
77
80
diff view generated by jsdifflib