1
The following changes since commit 4c41341af76cfc85b5a6c0f87de4838672ab9f89:
1
Two small bugfixes, plus most of RTH's refactoring of cpregs
2
handling.
2
3
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into staging (2020-10-20 11:20:36 +0100)
4
-- PMM
5
6
The following changes since commit 1fba9dc71a170b3a05b9d3272dd8ecfe7f26e215:
7
8
Merge tag 'pull-request-2022-05-04' of https://gitlab.com/thuth/qemu into staging (2022-05-04 08:07:02 -0700)
4
9
5
are available in the Git repository at:
10
are available in the Git repository at:
6
11
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201020
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220505
8
13
9
for you to fetch changes up to 6358890cb939192f6169fdf7664d903bf9b1d338:
14
for you to fetch changes up to 99a50d1a67c602126fc2b3a4812d3000eba9bf34:
10
15
11
tests/tcg/aarch64: Add bti smoke tests (2020-10-20 16:12:02 +0100)
16
target/arm: read access to performance counters from EL0 (2022-05-05 09:36:22 +0100)
12
17
13
----------------------------------------------------------------
18
----------------------------------------------------------------
14
target-arm queue:
19
target-arm queue:
15
* Fix AArch32 SMLAD incorrect setting of Q bit
20
* Enable read access to performance counters from EL0
16
* AArch32 VCVT fixed-point to float is always round-to-nearest
21
* Enable SCTLR_EL1.BT0 for aarch64-linux-user
17
* strongarm: Fix 'time to transmit a char' unit comment
22
* Refactoring of cpreg handling
18
* Restrict APEI tables generation to the 'virt' machine
19
* bcm2835: minor code cleanups
20
* correctly flush TLBs when TBI is enabled
21
* tests/qtest: Add npcm7xx timer test
22
* loads-stores.rst: add footnote that clarifies GETPC usage
23
* Fix reported EL for mte_check_fail
24
* Ignore HCR_EL2.ATA when {E2H,TGE} != 11
25
* microbit_i2c: Fix coredump when dump-vmstate
26
* nseries: Fix loading kernel image on n8x0 machines
27
* Implement v8.1M low-overhead-loops
28
* linux-user: Support AArch64 BTI
29
23
30
----------------------------------------------------------------
24
----------------------------------------------------------------
31
Emanuele Giuseppe Esposito (1):
25
Alex Zuepke (1):
32
loads-stores.rst: add footnote that clarifies GETPC usage
26
target/arm: read access to performance counters from EL0
33
27
34
Havard Skinnemoen (1):
28
Richard Henderson (22):
35
tests/qtest: Add npcm7xx timer test
29
target/arm: Enable SCTLR_EL1.BT0 for aarch64-linux-user
30
target/arm: Split out cpregs.h
31
target/arm: Reorg CPAccessResult and access_check_cp_reg
32
target/arm: Replace sentinels with ARRAY_SIZE in cpregs.h
33
target/arm: Make some more cpreg data static const
34
target/arm: Reorg ARMCPRegInfo type field bits
35
target/arm: Avoid bare abort() or assert(0)
36
target/arm: Change cpreg access permissions to enum
37
target/arm: Name CPState type
38
target/arm: Name CPSecureState type
39
target/arm: Drop always-true test in define_arm_vh_e2h_redirects_aliases
40
target/arm: Store cpregs key in the hash table directly
41
target/arm: Merge allocation of the cpreg and its name
42
target/arm: Hoist computation of key in add_cpreg_to_hashtable
43
target/arm: Consolidate cpreg updates in add_cpreg_to_hashtable
44
target/arm: Use bool for is64 and ns in add_cpreg_to_hashtable
45
target/arm: Hoist isbanked computation in add_cpreg_to_hashtable
46
target/arm: Perform override check early in add_cpreg_to_hashtable
47
target/arm: Reformat comments in add_cpreg_to_hashtable
48
target/arm: Remove HOST_BIG_ENDIAN ifdef in add_cpreg_to_hashtable
49
target/arm: Add isar predicates for FEAT_Debugv8p2
50
target/arm: Add isar_feature_{aa64,any}_ras
36
51
37
Peng Liang (1):
52
target/arm/cpregs.h | 453 ++++++++++++++++++++++++++++++++++++++
38
microbit_i2c: Fix coredump when dump-vmstate
53
target/arm/cpu.h | 393 +++------------------------------
39
54
hw/arm/pxa2xx.c | 2 +-
40
Peter Maydell (12):
55
hw/arm/pxa2xx_pic.c | 2 +-
41
target/arm: Fix SMLAD incorrect setting of Q bit
56
hw/intc/arm_gicv3_cpuif.c | 6 +-
42
target/arm: AArch32 VCVT fixed-point to float is always round-to-nearest
57
hw/intc/arm_gicv3_kvm.c | 3 +-
43
decodetree: Fix codegen for non-overlapping group inside overlapping group
58
target/arm/cpu.c | 25 +--
44
target/arm: Implement v8.1M NOCP handling
59
target/arm/cpu64.c | 2 +-
45
target/arm: Implement v8.1M conditional-select insns
60
target/arm/cpu_tcg.c | 5 +-
46
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
61
target/arm/gdbstub.c | 5 +-
47
target/arm: Don't allow BLX imm for M-profile
62
target/arm/helper.c | 358 +++++++++++++-----------------
48
target/arm: Implement v8.1M branch-future insns (as NOPs)
63
target/arm/hvf/hvf.c | 2 +-
49
target/arm: Implement v8.1M low-overhead-loop instructions
64
target/arm/kvm-stub.c | 4 +-
50
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
65
target/arm/kvm.c | 4 +-
51
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
66
target/arm/machine.c | 4 +-
52
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
67
target/arm/op_helper.c | 57 ++---
53
68
target/arm/translate-a64.c | 14 +-
54
Philippe Mathieu-Daudé (10):
69
target/arm/translate-neon.c | 2 +-
55
hw/arm/strongarm: Fix 'time to transmit a char' unit comment
70
target/arm/translate.c | 13 +-
56
hw/arm: Restrict APEI tables generation to the 'virt' machine
71
tests/tcg/aarch64/bti-3.c | 42 ++++
57
hw/timer/bcm2835: Introduce BCM2835_SYSTIMER_COUNT definition
72
tests/tcg/aarch64/Makefile.target | 6 +-
58
hw/timer/bcm2835: Rename variable holding CTRL_STATUS register
73
21 files changed, 738 insertions(+), 664 deletions(-)
59
hw/timer/bcm2835: Support the timer COMPARE registers
74
create mode 100644 target/arm/cpregs.h
60
hw/arm/bcm2835_peripherals: Correctly wire the SYS_timer IRQs
75
create mode 100644 tests/tcg/aarch64/bti-3.c
61
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
62
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
63
hw/arm/nseries: Fix loading kernel image on n8x0 machines
64
linux-user/elfload: Avoid leaking interp_name using GLib memory API
65
66
Richard Henderson (16):
67
accel/tcg: Add tlb_flush_page_bits_by_mmuidx*
68
target/arm: Use tlb_flush_page_bits_by_mmuidx*
69
target/arm: Remove redundant mmu_idx lookup
70
target/arm: Fix reported EL for mte_check_fail
71
target/arm: Ignore HCR_EL2.ATA when {E2H,TGE} != 11
72
linux-user/aarch64: Reset btype for signals
73
linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
74
include/elf: Add defines related to GNU property notes for AArch64
75
linux-user/elfload: Fix coding style in load_elf_image
76
linux-user/elfload: Adjust iteration over phdr
77
linux-user/elfload: Move PT_INTERP detection to first loop
78
linux-user/elfload: Use Error for load_elf_image
79
linux-user/elfload: Use Error for load_elf_interp
80
linux-user/elfload: Parse NT_GNU_PROPERTY_TYPE_0 notes
81
linux-user/elfload: Parse GNU_PROPERTY_AARCH64_FEATURE_1_AND
82
tests/tcg/aarch64: Add bti smoke tests
83
84
docs/devel/loads-stores.rst | 8 +-
85
default-configs/devices/arm-softmmu.mak | 1 -
86
include/elf.h | 22 ++
87
include/exec/cpu-all.h | 2 +
88
include/exec/exec-all.h | 36 ++
89
include/hw/timer/bcm2835_systmr.h | 17 +-
90
linux-user/qemu.h | 4 +
91
linux-user/syscall_defs.h | 4 +
92
target/arm/cpu.h | 13 +
93
target/arm/helper.h | 13 +
94
target/arm/internals.h | 9 +-
95
target/arm/m-nocp.decode | 10 +-
96
target/arm/t32.decode | 50 ++-
97
accel/tcg/cputlb.c | 275 +++++++++++++++-
98
hw/arm/bcm2835_peripherals.c | 13 +-
99
hw/arm/nseries.c | 1 +
100
hw/arm/strongarm.c | 2 +-
101
hw/i2c/microbit_i2c.c | 1 +
102
hw/intc/bcm2835_ic.c | 4 +-
103
hw/intc/bcm2836_control.c | 8 +-
104
hw/timer/bcm2835_systmr.c | 57 ++--
105
linux-user/aarch64/signal.c | 10 +-
106
linux-user/elfload.c | 326 ++++++++++++++----
107
linux-user/mmap.c | 16 +
108
target/arm/cpu.c | 38 ++-
109
target/arm/helper.c | 55 +++-
110
target/arm/mte_helper.c | 13 +-
111
target/arm/translate-a64.c | 6 +-
112
target/arm/translate.c | 239 +++++++++++++-
113
target/arm/vfp_helper.c | 76 +++--
114
tests/qtest/npcm7xx_timer-test.c | 562 ++++++++++++++++++++++++++++++++
115
tests/tcg/aarch64/bti-1.c | 62 ++++
116
tests/tcg/aarch64/bti-2.c | 108 ++++++
117
tests/tcg/aarch64/bti-crt.inc.c | 51 +++
118
hw/arm/Kconfig | 1 +
119
hw/intc/trace-events | 4 +
120
hw/timer/trace-events | 6 +-
121
scripts/decodetree.py | 2 +-
122
target/arm/translate-vfp.c.inc | 41 ++-
123
tests/qtest/meson.build | 1 +
124
tests/tcg/aarch64/Makefile.target | 10 +
125
tests/tcg/configure.sh | 4 +
126
42 files changed, 1973 insertions(+), 208 deletions(-)
127
create mode 100644 tests/qtest/npcm7xx_timer-test.c
128
create mode 100644 tests/tcg/aarch64/bti-1.c
129
create mode 100644 tests/tcg/aarch64/bti-2.c
130
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
131
diff view generated by jsdifflib
Deleted patch
1
The SMLAD instruction is supposed to:
2
* signed multiply Rn[15:0] * Rm[15:0]
3
* signed multiply Rn[31:16] * Rm[31:16]
4
* perform a signed addition of the products and Ra
5
* set Rd to the low 32 bits of the theoretical
6
infinite-precision result
7
* set the Q flag if the sign-extension of Rd
8
would differ from the infinite-precision result
9
(ie on overflow)
10
1
11
Our current implementation doesn't quite do this, though: it performs
12
an addition of the products setting Q on overflow, and then it adds
13
Ra, again possibly setting Q. This sometimes incorrectly sets Q when
14
the architecturally mandated only-check-for-overflow-once algorithm
15
does not. For instance:
16
r1 = 0x80008000; r2 = 0x80008000; r3 = 0xffffffff
17
smlad r0, r1, r2, r3
18
This is (-32768 * -32768) + (-32768 * -32768) - 1
19
20
The products are both 0x4000_0000, so when added together as 32-bit
21
signed numbers they overflow (and QEMU sets Q), but because the
22
addition of Ra == -1 brings the total back down to 0x7fff_ffff
23
there is no overflow for the complete operation and setting Q is
24
incorrect.
25
26
Fix this edge case by resorting to 64-bit arithmetic for the
27
case where we need to add three values together.
28
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
32
---
33
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++--------
34
1 file changed, 48 insertions(+), 10 deletions(-)
35
36
diff --git a/target/arm/translate.c b/target/arm/translate.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate.c
39
+++ b/target/arm/translate.c
40
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
41
gen_smul_dual(t1, t2);
42
43
if (sub) {
44
- /* This subtraction cannot overflow. */
45
+ /*
46
+ * This subtraction cannot overflow, so we can do a simple
47
+ * 32-bit subtraction and then a possible 32-bit saturating
48
+ * addition of Ra.
49
+ */
50
tcg_gen_sub_i32(t1, t1, t2);
51
+ tcg_temp_free_i32(t2);
52
+
53
+ if (a->ra != 15) {
54
+ t2 = load_reg(s, a->ra);
55
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
56
+ tcg_temp_free_i32(t2);
57
+ }
58
+ } else if (a->ra == 15) {
59
+ /* Single saturation-checking addition */
60
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
61
+ tcg_temp_free_i32(t2);
62
} else {
63
/*
64
- * This addition cannot overflow 32 bits; however it may
65
- * overflow considered as a signed operation, in which case
66
- * we must set the Q flag.
67
+ * We need to add the products and Ra together and then
68
+ * determine whether the final result overflowed. Doing
69
+ * this as two separate add-and-check-overflow steps incorrectly
70
+ * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
71
+ * Do all the arithmetic at 64-bits and then check for overflow.
72
*/
73
- gen_helper_add_setq(t1, cpu_env, t1, t2);
74
- }
75
- tcg_temp_free_i32(t2);
76
+ TCGv_i64 p64, q64;
77
+ TCGv_i32 t3, qf, one;
78
79
- if (a->ra != 15) {
80
- t2 = load_reg(s, a->ra);
81
- gen_helper_add_setq(t1, cpu_env, t1, t2);
82
+ p64 = tcg_temp_new_i64();
83
+ q64 = tcg_temp_new_i64();
84
+ tcg_gen_ext_i32_i64(p64, t1);
85
+ tcg_gen_ext_i32_i64(q64, t2);
86
+ tcg_gen_add_i64(p64, p64, q64);
87
+ load_reg_var(s, t2, a->ra);
88
+ tcg_gen_ext_i32_i64(q64, t2);
89
+ tcg_gen_add_i64(p64, p64, q64);
90
+ tcg_temp_free_i64(q64);
91
+
92
+ tcg_gen_extr_i64_i32(t1, t2, p64);
93
+ tcg_temp_free_i64(p64);
94
+ /*
95
+ * t1 is the low half of the result which goes into Rd.
96
+ * We have overflow and must set Q if the high half (t2)
97
+ * is different from the sign-extension of t1.
98
+ */
99
+ t3 = tcg_temp_new_i32();
100
+ tcg_gen_sari_i32(t3, t1, 31);
101
+ qf = load_cpu_field(QF);
102
+ one = tcg_const_i32(1);
103
+ tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
104
+ store_cpu_field(qf, QF);
105
+ tcg_temp_free_i32(one);
106
+ tcg_temp_free_i32(t3);
107
tcg_temp_free_i32(t2);
108
}
109
store_reg(s, a->rd, t1);
110
--
111
2.20.1
112
113
diff view generated by jsdifflib
Deleted patch
1
For AArch32, unlike the VCVT of integer to float, which honours the
2
rounding mode specified by the FPSCR, VCVT of fixed-point to float is
3
always round-to-nearest. (AArch64 fixed-point-to-float conversions
4
always honour the FPCR rounding mode.)
5
1
6
Implement this by providing _round_to_nearest versions of the
7
relevant helpers which set the rounding mode temporarily when making
8
the call to the underlying softfloat function.
9
10
We only need to change the VFP VCVT instructions, because the
11
standard- FPSCR value used by the Neon VCVT is always set to
12
round-to-nearest, so we don't need to do the extra work of saving
13
and restoring the rounding mode.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20201013103532.13391-1-peter.maydell@linaro.org
18
---
19
target/arm/helper.h | 13 +++++++++++++
20
target/arm/vfp_helper.c | 23 ++++++++++++++++++++++-
21
target/arm/translate-vfp.c.inc | 24 ++++++++++++------------
22
3 files changed, 47 insertions(+), 13 deletions(-)
23
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
27
+++ b/target/arm/helper.h
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
29
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
30
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
31
32
+DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr)
33
+DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr)
34
+DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr)
35
+DEF_HELPER_3(vfp_ultos_round_to_nearest, f32, i32, i32, ptr)
36
+DEF_HELPER_3(vfp_shtod_round_to_nearest, f64, i64, i32, ptr)
37
+DEF_HELPER_3(vfp_sltod_round_to_nearest, f64, i64, i32, ptr)
38
+DEF_HELPER_3(vfp_uhtod_round_to_nearest, f64, i64, i32, ptr)
39
+DEF_HELPER_3(vfp_ultod_round_to_nearest, f64, i64, i32, ptr)
40
+DEF_HELPER_3(vfp_shtoh_round_to_nearest, f16, i32, i32, ptr)
41
+DEF_HELPER_3(vfp_uhtoh_round_to_nearest, f16, i32, i32, ptr)
42
+DEF_HELPER_3(vfp_sltoh_round_to_nearest, f16, i32, i32, ptr)
43
+DEF_HELPER_3(vfp_ultoh_round_to_nearest, f16, i32, i32, ptr)
44
+
45
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
46
47
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/vfp_helper.c
51
+++ b/target/arm/vfp_helper.c
52
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
53
return float64_to_float32(x, &env->vfp.fp_status);
54
}
55
56
-/* VFP3 fixed point conversion. */
57
+/*
58
+ * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
59
+ * must always round-to-nearest; the AArch64 ones honour the FPSCR
60
+ * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
61
+ * round-to-nearest so either helper will work.) AArch32 float-to-fix
62
+ * must round-to-zero.
63
+ */
64
#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
65
ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
66
void *fpstp) \
67
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
68
69
+#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
70
+ ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
71
+ uint32_t shift, \
72
+ void *fpstp) \
73
+ { \
74
+ ftype ret; \
75
+ float_status *fpst = fpstp; \
76
+ FloatRoundMode oldmode = fpst->float_rounding_mode; \
77
+ fpst->float_rounding_mode = float_round_nearest_even; \
78
+ ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); \
79
+ fpst->float_rounding_mode = oldmode; \
80
+ return ret; \
81
+ }
82
+
83
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
84
uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
85
void *fpst) \
86
@@ -XXX,XX +XXX,XX @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
87
88
#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
89
VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
90
+VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
91
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
92
float_round_to_zero, _round_to_zero) \
93
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
94
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/translate-vfp.c.inc
97
+++ b/target/arm/translate-vfp.c.inc
98
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
99
/* Switch on op:U:sx bits */
100
switch (a->opc) {
101
case 0:
102
- gen_helper_vfp_shtoh(vd, vd, shift, fpst);
103
+ gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst);
104
break;
105
case 1:
106
- gen_helper_vfp_sltoh(vd, vd, shift, fpst);
107
+ gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst);
108
break;
109
case 2:
110
- gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
111
+ gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst);
112
break;
113
case 3:
114
- gen_helper_vfp_ultoh(vd, vd, shift, fpst);
115
+ gen_helper_vfp_ultoh_round_to_nearest(vd, vd, shift, fpst);
116
break;
117
case 4:
118
gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
120
/* Switch on op:U:sx bits */
121
switch (a->opc) {
122
case 0:
123
- gen_helper_vfp_shtos(vd, vd, shift, fpst);
124
+ gen_helper_vfp_shtos_round_to_nearest(vd, vd, shift, fpst);
125
break;
126
case 1:
127
- gen_helper_vfp_sltos(vd, vd, shift, fpst);
128
+ gen_helper_vfp_sltos_round_to_nearest(vd, vd, shift, fpst);
129
break;
130
case 2:
131
- gen_helper_vfp_uhtos(vd, vd, shift, fpst);
132
+ gen_helper_vfp_uhtos_round_to_nearest(vd, vd, shift, fpst);
133
break;
134
case 3:
135
- gen_helper_vfp_ultos(vd, vd, shift, fpst);
136
+ gen_helper_vfp_ultos_round_to_nearest(vd, vd, shift, fpst);
137
break;
138
case 4:
139
gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
140
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
141
/* Switch on op:U:sx bits */
142
switch (a->opc) {
143
case 0:
144
- gen_helper_vfp_shtod(vd, vd, shift, fpst);
145
+ gen_helper_vfp_shtod_round_to_nearest(vd, vd, shift, fpst);
146
break;
147
case 1:
148
- gen_helper_vfp_sltod(vd, vd, shift, fpst);
149
+ gen_helper_vfp_sltod_round_to_nearest(vd, vd, shift, fpst);
150
break;
151
case 2:
152
- gen_helper_vfp_uhtod(vd, vd, shift, fpst);
153
+ gen_helper_vfp_uhtod_round_to_nearest(vd, vd, shift, fpst);
154
break;
155
case 3:
156
- gen_helper_vfp_ultod(vd, vd, shift, fpst);
157
+ gen_helper_vfp_ultod_round_to_nearest(vd, vd, shift, fpst);
158
break;
159
case 4:
160
gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
161
--
162
2.20.1
163
164
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The time to transmit a char is expressed in nanoseconds, not in ticks.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20201014213601.205222-1-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/arm/strongarm.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/strongarm.c
16
+++ b/hw/arm/strongarm.c
17
@@ -XXX,XX +XXX,XX @@ struct StrongARMUARTState {
18
uint8_t rx_start;
19
uint8_t rx_len;
20
21
- uint64_t char_transmit_time; /* time to transmit a char in ticks*/
22
+ uint64_t char_transmit_time; /* time to transmit a char in nanoseconds */
23
bool wait_break_end;
24
QEMUTimer *rx_timeout_timer;
25
QEMUTimer *tx_timer;
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
1
3
While APEI is a generic ACPI feature (usable by X86 and ARM64), only
4
the 'virt' machine uses it, by enabling the RAS Virtualization. See
5
commit 2afa8c8519: "hw/arm/virt: Introduce a RAS machine option").
6
7
Restrict the APEI tables generation code to the single user: the virt
8
machine. If another machine wants to use it, it simply has to 'select
9
ACPI_APEI' in its Kconfig.
10
11
Fixes: aa16508f1d ("ACPI: Build related register address fields via hardware error fw_cfg blob")
12
Acked-by: Michael S. Tsirkin <mst@redhat.com>
13
Reviewed-by: Dongjiu Geng <gengdongjiu@huawei.com>
14
Acked-by: Laszlo Ersek <lersek@redhat.com>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Message-id: 20201008161414.2672569-1-philmd@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
default-configs/devices/arm-softmmu.mak | 1 -
21
hw/arm/Kconfig | 1 +
22
2 files changed, 1 insertion(+), 1 deletion(-)
23
24
diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak
25
index XXXXXXX..XXXXXXX 100644
26
--- a/default-configs/devices/arm-softmmu.mak
27
+++ b/default-configs/devices/arm-softmmu.mak
28
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX7=y
29
CONFIG_FSL_IMX6UL=y
30
CONFIG_SEMIHOSTING=y
31
CONFIG_ALLWINNER_H3=y
32
-CONFIG_ACPI_APEI=y
33
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/Kconfig
36
+++ b/hw/arm/Kconfig
37
@@ -XXX,XX +XXX,XX @@ config ARM_VIRT
38
select ACPI_MEMORY_HOTPLUG
39
select ACPI_HW_REDUCED
40
select ACPI_NVDIMM
41
+ select ACPI_APEI
42
43
config CHEETAH
44
bool
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Use the BCM2835_SYSTIMER_COUNT definition instead of the
4
magic '4' value.
5
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201010203709.3116542-2-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/timer/bcm2835_systmr.h | 4 +++-
13
hw/timer/bcm2835_systmr.c | 3 ++-
14
2 files changed, 5 insertions(+), 2 deletions(-)
15
16
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/timer/bcm2835_systmr.h
19
+++ b/include/hw/timer/bcm2835_systmr.h
20
@@ -XXX,XX +XXX,XX @@
21
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
22
OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
23
24
+#define BCM2835_SYSTIMER_COUNT 4
25
+
26
struct BCM2835SystemTimerState {
27
/*< private >*/
28
SysBusDevice parent_obj;
29
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
30
31
struct {
32
uint32_t status;
33
- uint32_t compare[4];
34
+ uint32_t compare[BCM2835_SYSTIMER_COUNT];
35
} reg;
36
};
37
38
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/timer/bcm2835_systmr.c
41
+++ b/hw/timer/bcm2835_systmr.c
42
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
43
.minimum_version_id = 1,
44
.fields = (VMStateField[]) {
45
VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
46
- VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
47
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
48
+ BCM2835_SYSTIMER_COUNT),
49
VMSTATE_END_OF_LIST()
50
}
51
};
52
--
53
2.20.1
54
55
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The variable holding the CTRL_STATUS register is misnamed
4
'status'. Rename it 'ctrl_status' to make it more obvious
5
this register is also used to control the peripheral.
6
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-3-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/timer/bcm2835_systmr.h | 2 +-
14
hw/timer/bcm2835_systmr.c | 8 ++++----
15
2 files changed, 5 insertions(+), 5 deletions(-)
16
17
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/bcm2835_systmr.h
20
+++ b/include/hw/timer/bcm2835_systmr.h
21
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
22
qemu_irq irq;
23
24
struct {
25
- uint32_t status;
26
+ uint32_t ctrl_status;
27
uint32_t compare[BCM2835_SYSTIMER_COUNT];
28
} reg;
29
};
30
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/bcm2835_systmr.c
33
+++ b/hw/timer/bcm2835_systmr.c
34
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE3, 0x18)
35
36
static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
37
{
38
- bool enable = !!s->reg.status;
39
+ bool enable = !!s->reg.ctrl_status;
40
41
trace_bcm2835_systmr_irq(enable);
42
qemu_set_irq(s->irq, enable);
43
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
44
45
switch (offset) {
46
case A_CTRL_STATUS:
47
- r = s->reg.status;
48
+ r = s->reg.ctrl_status;
49
break;
50
case A_COMPARE0 ... A_COMPARE3:
51
r = s->reg.compare[(offset - A_COMPARE0) >> 2];
52
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_write(void *opaque, hwaddr offset,
53
trace_bcm2835_systmr_write(offset, value);
54
switch (offset) {
55
case A_CTRL_STATUS:
56
- s->reg.status &= ~value; /* Ack */
57
+ s->reg.ctrl_status &= ~value; /* Ack */
58
bcm2835_systmr_update_irq(s);
59
break;
60
case A_COMPARE0 ... A_COMPARE3:
61
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
62
.version_id = 1,
63
.minimum_version_id = 1,
64
.fields = (VMStateField[]) {
65
- VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
66
+ VMSTATE_UINT32(reg.ctrl_status, BCM2835SystemTimerState),
67
VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
68
BCM2835_SYSTIMER_COUNT),
69
VMSTATE_END_OF_LIST()
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
This peripheral has 1 free-running timer and 4 compare registers.
4
5
Only the free-running timer is implemented. Add support the
6
COMPARE registers (each register is wired to an IRQ).
7
8
Reference: "BCM2835 ARM Peripherals" datasheet [*]
9
chapter 12 "System Timer":
10
11
The System Timer peripheral provides four 32-bit timer channels
12
and a single 64-bit free running counter. Each channel has an
13
output compare register, which is compared against the 32 least
14
significant bits of the free running counter values. When the
15
two values match, the system timer peripheral generates a signal
16
to indicate a match for the appropriate channel. The match signal
17
is then fed into the interrupt controller.
18
19
This peripheral is used since Linux 3.7, commit ee4af5696720
20
("ARM: bcm2835: add system timer").
21
22
[*] https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
23
24
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Luc Michel <luc@lmichel.fr>
26
Message-id: 20201010203709.3116542-4-f4bug@amsat.org
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
29
include/hw/timer/bcm2835_systmr.h | 11 +++++--
30
hw/timer/bcm2835_systmr.c | 48 ++++++++++++++++++++-----------
31
hw/timer/trace-events | 6 ++--
32
3 files changed, 44 insertions(+), 21 deletions(-)
33
34
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/timer/bcm2835_systmr.h
37
+++ b/include/hw/timer/bcm2835_systmr.h
38
@@ -XXX,XX +XXX,XX @@
39
40
#include "hw/sysbus.h"
41
#include "hw/irq.h"
42
+#include "qemu/timer.h"
43
#include "qom/object.h"
44
45
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
46
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
47
48
#define BCM2835_SYSTIMER_COUNT 4
49
50
+typedef struct {
51
+ unsigned id;
52
+ QEMUTimer timer;
53
+ qemu_irq irq;
54
+ BCM2835SystemTimerState *state;
55
+} BCM2835SystemTimerCompare;
56
+
57
struct BCM2835SystemTimerState {
58
/*< private >*/
59
SysBusDevice parent_obj;
60
61
/*< public >*/
62
MemoryRegion iomem;
63
- qemu_irq irq;
64
-
65
struct {
66
uint32_t ctrl_status;
67
uint32_t compare[BCM2835_SYSTIMER_COUNT];
68
} reg;
69
+ BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT];
70
};
71
72
#endif
73
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/timer/bcm2835_systmr.c
76
+++ b/hw/timer/bcm2835_systmr.c
77
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE1, 0x10)
78
REG32(COMPARE2, 0x14)
79
REG32(COMPARE3, 0x18)
80
81
-static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
82
+static void bcm2835_systmr_timer_expire(void *opaque)
83
{
84
- bool enable = !!s->reg.ctrl_status;
85
+ BCM2835SystemTimerCompare *tmr = opaque;
86
87
- trace_bcm2835_systmr_irq(enable);
88
- qemu_set_irq(s->irq, enable);
89
-}
90
-
91
-static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
92
- unsigned timer_index)
93
-{
94
- /* TODO fow now, since neither Linux nor U-boot use these timers. */
95
- qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
96
- timer_index);
97
+ trace_bcm2835_systmr_timer_expired(tmr->id);
98
+ tmr->state->reg.ctrl_status |= 1 << tmr->id;
99
+ qemu_set_irq(tmr->irq, 1);
100
}
101
102
static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
103
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
104
}
105
106
static void bcm2835_systmr_write(void *opaque, hwaddr offset,
107
- uint64_t value, unsigned size)
108
+ uint64_t value64, unsigned size)
109
{
110
BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
111
+ int index;
112
+ uint32_t value = value64;
113
+ uint32_t triggers_delay_us;
114
+ uint64_t now;
115
116
trace_bcm2835_systmr_write(offset, value);
117
switch (offset) {
118
case A_CTRL_STATUS:
119
s->reg.ctrl_status &= ~value; /* Ack */
120
- bcm2835_systmr_update_irq(s);
121
+ for (index = 0; index < ARRAY_SIZE(s->tmr); index++) {
122
+ if (extract32(value, index, 1)) {
123
+ trace_bcm2835_systmr_irq_ack(index);
124
+ qemu_set_irq(s->tmr[index].irq, 0);
125
+ }
126
+ }
127
break;
128
case A_COMPARE0 ... A_COMPARE3:
129
- s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
130
- bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
131
+ index = (offset - A_COMPARE0) >> 2;
132
+ s->reg.compare[index] = value;
133
+ now = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
134
+ /* Compare lower 32-bits of the free-running counter. */
135
+ triggers_delay_us = value - now;
136
+ trace_bcm2835_systmr_run(index, triggers_delay_us);
137
+ timer_mod(&s->tmr[index].timer, now + triggers_delay_us);
138
break;
139
case A_COUNTER_LOW:
140
case A_COUNTER_HIGH:
141
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
142
memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
143
s, "bcm2835-sys-timer", 0x20);
144
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
145
- sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
146
+
147
+ for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) {
148
+ s->tmr[i].id = i;
149
+ s->tmr[i].state = s;
150
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq);
151
+ timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL,
152
+ bcm2835_systmr_timer_expire, &s->tmr[i]);
153
+ }
154
}
155
156
static const VMStateDescription bcm2835_systmr_vmstate = {
157
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
158
index XXXXXXX..XXXXXXX 100644
159
--- a/hw/timer/trace-events
160
+++ b/hw/timer/trace-events
161
@@ -XXX,XX +XXX,XX @@ nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size
162
nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32
163
164
# bcm2835_systmr.c
165
-bcm2835_systmr_irq(bool enable) "timer irq state %u"
166
+bcm2835_systmr_timer_expired(unsigned id) "timer #%u expired"
167
+bcm2835_systmr_irq_ack(unsigned id) "timer #%u acked"
168
bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
169
-bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
170
+bcm2835_systmr_write(uint64_t offset, uint32_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx32
171
+bcm2835_systmr_run(unsigned id, uint64_t delay_us) "timer #%u expiring in %"PRIu64" us"
172
173
# avr_timer16.c
174
avr_timer16_read(uint8_t addr, uint8_t value) "timer16 read addr:%u value:%u"
175
--
176
2.20.1
177
178
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The SYS_timer is not directly wired to the ARM core, but to the
4
SoC (peripheral) interrupt controller.
5
6
Fixes: 0e5bbd74064 ("hw/arm/bcm2835_peripherals: Use the SYS_timer")
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-5-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/bcm2835_peripherals.c | 13 +++++++++++--
14
1 file changed, 11 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/bcm2835_peripherals.c
19
+++ b/hw/arm/bcm2835_peripherals.c
20
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
21
memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
22
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
23
sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
24
- qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
25
- INTERRUPT_ARM_TIMER));
26
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
27
+ INTERRUPT_TIMER0));
28
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 1,
29
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
30
+ INTERRUPT_TIMER1));
31
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 2,
32
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
33
+ INTERRUPT_TIMER2));
34
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 3,
35
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
36
+ INTERRUPT_TIMER3));
37
38
/* UART0 */
39
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
40
--
41
2.20.1
42
43
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 note test requires gcc 10 for -mbranch-protection=standard.
3
This controls whether the PACI{A,B}SP instructions trap with BTYPE=3
4
The mmap test uses PROT_BTI and does not require special compiler support.
4
(indirect branch from register other than x16/x17). The linux kernel
5
sets this in bti_enable().
5
6
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/998
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220427042312.294300-1-richard.henderson@linaro.org
9
Message-id: 20201016184207.786698-13-richard.henderson@linaro.org
11
[PMM: remove stray change to makefile comment]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++
14
target/arm/cpu.c | 2 ++
13
tests/tcg/aarch64/bti-2.c | 108 ++++++++++++++++++++++++++++++
15
tests/tcg/aarch64/bti-3.c | 42 +++++++++++++++++++++++++++++++
14
tests/tcg/aarch64/bti-crt.inc.c | 51 ++++++++++++++
16
tests/tcg/aarch64/Makefile.target | 6 ++---
15
tests/tcg/aarch64/Makefile.target | 10 +++
17
3 files changed, 47 insertions(+), 3 deletions(-)
16
tests/tcg/configure.sh | 4 ++
18
create mode 100644 tests/tcg/aarch64/bti-3.c
17
5 files changed, 235 insertions(+)
18
create mode 100644 tests/tcg/aarch64/bti-1.c
19
create mode 100644 tests/tcg/aarch64/bti-2.c
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
21
19
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
25
/* Enable all PAC keys. */
26
env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB |
27
SCTLR_EnDA | SCTLR_EnDB);
28
+ /* Trap on btype=3 for PACIxSP. */
29
+ env->cp15.sctlr_el[1] |= SCTLR_BT0;
30
/* and to the FP/Neon instructions */
31
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
32
/* and to the SVE instructions */
33
diff --git a/tests/tcg/aarch64/bti-3.c b/tests/tcg/aarch64/bti-3.c
23
new file mode 100644
34
new file mode 100644
24
index XXXXXXX..XXXXXXX
35
index XXXXXXX..XXXXXXX
25
--- /dev/null
36
--- /dev/null
26
+++ b/tests/tcg/aarch64/bti-1.c
37
+++ b/tests/tcg/aarch64/bti-3.c
27
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
28
+/*
39
+/*
29
+ * Branch target identification, basic notskip cases.
40
+ * BTI vs PACIASP
30
+ */
41
+ */
31
+
42
+
32
+#include "bti-crt.inc.c"
43
+#include "bti-crt.inc.c"
33
+
44
+
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
45
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
35
+{
46
+{
36
+ uc->uc_mcontext.pc += 8;
47
+ uc->uc_mcontext.pc += 8;
37
+ uc->uc_mcontext.pstate = 1;
48
+ uc->uc_mcontext.pstate = 1;
38
+}
49
+}
39
+
50
+
40
+#define NOP "nop"
51
+#define BTYPE_1() \
41
+#define BTI_N "hint #32"
52
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: hint #25; mov %0,#0" \
42
+#define BTI_C "hint #34"
43
+#define BTI_J "hint #36"
44
+#define BTI_JC "hint #38"
45
+
46
+#define BTYPE_1(DEST) \
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
48
+ : "=r"(skipped) : : "x16")
49
+
50
+#define BTYPE_2(DEST) \
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
52
+ : "=r"(skipped) : : "x16", "x30")
53
+ : "=r"(skipped) : : "x16", "x30")
53
+
54
+
54
+#define BTYPE_3(DEST) \
55
+#define BTYPE_2() \
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
56
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: hint #25; mov %0,#0" \
56
+ : "=r"(skipped) : : "x15")
57
+ : "=r"(skipped) : : "x16", "x30")
57
+
58
+
58
+#define TEST(WHICH, DEST, EXPECT) \
59
+#define BTYPE_3() \
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
60
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: hint #25; mov %0,#0" \
61
+ : "=r"(skipped) : : "x15", "x30")
60
+
62
+
63
+#define TEST(WHICH, EXPECT) \
64
+ do { WHICH(); fail += skipped ^ EXPECT; } while (0)
61
+
65
+
62
+int main()
66
+int main()
63
+{
67
+{
64
+ int fail = 0;
68
+ int fail = 0;
65
+ int skipped;
69
+ int skipped;
66
+
70
+
67
+ /* Signal-like with SA_SIGINFO. */
71
+ /* Signal-like with SA_SIGINFO. */
68
+ signal_info(SIGILL, skip2_sigill);
72
+ signal_info(SIGILL, skip2_sigill);
69
+
73
+
70
+ TEST(BTYPE_1, NOP, 1);
74
+ /* With SCTLR_EL1.BT0 set, PACIASP is not compatible with type=3. */
71
+ TEST(BTYPE_1, BTI_N, 1);
75
+ TEST(BTYPE_1, 0);
72
+ TEST(BTYPE_1, BTI_C, 0);
76
+ TEST(BTYPE_2, 0);
73
+ TEST(BTYPE_1, BTI_J, 0);
77
+ TEST(BTYPE_3, 1);
74
+ TEST(BTYPE_1, BTI_JC, 0);
75
+
76
+ TEST(BTYPE_2, NOP, 1);
77
+ TEST(BTYPE_2, BTI_N, 1);
78
+ TEST(BTYPE_2, BTI_C, 0);
79
+ TEST(BTYPE_2, BTI_J, 1);
80
+ TEST(BTYPE_2, BTI_JC, 0);
81
+
82
+ TEST(BTYPE_3, NOP, 1);
83
+ TEST(BTYPE_3, BTI_N, 1);
84
+ TEST(BTYPE_3, BTI_C, 1);
85
+ TEST(BTYPE_3, BTI_J, 0);
86
+ TEST(BTYPE_3, BTI_JC, 0);
87
+
78
+
88
+ return fail;
79
+ return fail;
89
+}
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
91
new file mode 100644
92
index XXXXXXX..XXXXXXX
93
--- /dev/null
94
+++ b/tests/tcg/aarch64/bti-2.c
95
@@ -XXX,XX +XXX,XX @@
96
+/*
97
+ * Branch target identification, basic notskip cases.
98
+ */
99
+
100
+#include <stdio.h>
101
+#include <signal.h>
102
+#include <string.h>
103
+#include <unistd.h>
104
+#include <sys/mman.h>
105
+
106
+#ifndef PROT_BTI
107
+#define PROT_BTI 0x10
108
+#endif
109
+
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
111
+{
112
+ ucontext_t *uc = vuc;
113
+ uc->uc_mcontext.pc += 8;
114
+ uc->uc_mcontext.pstate = 1;
115
+}
116
+
117
+#define NOP "nop"
118
+#define BTI_N "hint #32"
119
+#define BTI_C "hint #34"
120
+#define BTI_J "hint #36"
121
+#define BTI_JC "hint #38"
122
+
123
+#define BTYPE_1(DEST) \
124
+ "mov x1, #1\n\t" \
125
+ "adr x16, 1f\n\t" \
126
+ "br x16\n" \
127
+"1: " DEST "\n\t" \
128
+ "mov x1, #0"
129
+
130
+#define BTYPE_2(DEST) \
131
+ "mov x1, #1\n\t" \
132
+ "adr x16, 1f\n\t" \
133
+ "blr x16\n" \
134
+"1: " DEST "\n\t" \
135
+ "mov x1, #0"
136
+
137
+#define BTYPE_3(DEST) \
138
+ "mov x1, #1\n\t" \
139
+ "adr x15, 1f\n\t" \
140
+ "br x15\n" \
141
+"1: " DEST "\n\t" \
142
+ "mov x1, #0"
143
+
144
+#define TEST(WHICH, DEST, EXPECT) \
145
+ WHICH(DEST) "\n" \
146
+ ".if " #EXPECT "\n\t" \
147
+ "eor x1, x1," #EXPECT "\n" \
148
+ ".endif\n\t" \
149
+ "add x0, x0, x1\n\t"
150
+
151
+extern char test_begin[], test_end[];
152
+
153
+asm("\n"
154
+"test_begin:\n\t"
155
+ BTI_C "\n\t"
156
+ "mov x2, x30\n\t"
157
+ "mov x0, #0\n\t"
158
+
159
+ TEST(BTYPE_1, NOP, 1)
160
+ TEST(BTYPE_1, BTI_N, 1)
161
+ TEST(BTYPE_1, BTI_C, 0)
162
+ TEST(BTYPE_1, BTI_J, 0)
163
+ TEST(BTYPE_1, BTI_JC, 0)
164
+
165
+ TEST(BTYPE_2, NOP, 1)
166
+ TEST(BTYPE_2, BTI_N, 1)
167
+ TEST(BTYPE_2, BTI_C, 0)
168
+ TEST(BTYPE_2, BTI_J, 1)
169
+ TEST(BTYPE_2, BTI_JC, 0)
170
+
171
+ TEST(BTYPE_3, NOP, 1)
172
+ TEST(BTYPE_3, BTI_N, 1)
173
+ TEST(BTYPE_3, BTI_C, 1)
174
+ TEST(BTYPE_3, BTI_J, 0)
175
+ TEST(BTYPE_3, BTI_JC, 0)
176
+
177
+ "ret x2\n"
178
+"test_end:"
179
+);
180
+
181
+int main()
182
+{
183
+ struct sigaction sa;
184
+
185
+ void *p = mmap(0, getpagesize(),
186
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
187
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
188
+ if (p == MAP_FAILED) {
189
+ perror("mmap");
190
+ return 1;
191
+ }
192
+
193
+ memset(&sa, 0, sizeof(sa));
194
+ sa.sa_sigaction = skip2_sigill;
195
+ sa.sa_flags = SA_SIGINFO;
196
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
197
+ perror("sigaction");
198
+ return 1;
199
+ }
200
+
201
+ memcpy(p, test_begin, test_end - test_begin);
202
+ return ((int (*)(void))p)();
203
+}
204
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
205
new file mode 100644
206
index XXXXXXX..XXXXXXX
207
--- /dev/null
208
+++ b/tests/tcg/aarch64/bti-crt.inc.c
209
@@ -XXX,XX +XXX,XX @@
210
+/*
211
+ * Minimal user-environment for testing BTI.
212
+ *
213
+ * Normal libc is not (yet) built with BTI support enabled,
214
+ * and so could generate a BTI TRAP before ever reaching main.
215
+ */
216
+
217
+#include <stdlib.h>
218
+#include <signal.h>
219
+#include <ucontext.h>
220
+#include <asm/unistd.h>
221
+
222
+int main(void);
223
+
224
+void _start(void)
225
+{
226
+ exit(main());
227
+}
228
+
229
+void exit(int ret)
230
+{
231
+ register int x0 __asm__("x0") = ret;
232
+ register int x8 __asm__("x8") = __NR_exit;
233
+
234
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
235
+ __builtin_unreachable();
236
+}
237
+
238
+/*
239
+ * Irritatingly, the user API struct sigaction does not match the
240
+ * kernel API struct sigaction. So for simplicity, isolate the
241
+ * kernel ABI here, and make this act like signal.
242
+ */
243
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
244
+{
245
+ struct kernel_sigaction {
246
+ void (*handler)(int, siginfo_t *, ucontext_t *);
247
+ unsigned long flags;
248
+ unsigned long restorer;
249
+ unsigned long mask;
250
+ } sa = { fn, SA_SIGINFO, 0, 0 };
251
+
252
+ register int x0 __asm__("x0") = sig;
253
+ register void *x1 __asm__("x1") = &sa;
254
+ register void *x2 __asm__("x2") = 0;
255
+ register int x3 __asm__("x3") = sizeof(unsigned long);
256
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
257
+
258
+ asm volatile("svc #0"
259
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
260
+}
80
+}
261
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
81
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
262
index XXXXXXX..XXXXXXX 100644
82
index XXXXXXX..XXXXXXX 100644
263
--- a/tests/tcg/aarch64/Makefile.target
83
--- a/tests/tcg/aarch64/Makefile.target
264
+++ b/tests/tcg/aarch64/Makefile.target
84
+++ b/tests/tcg/aarch64/Makefile.target
265
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
85
@@ -XXX,XX +XXX,XX @@ endif
266
run-plugin-pauth-%: QEMU_OPTS += -cpu max
86
# BTI Tests
87
# bti-1 tests the elf notes, so we require special compiler support.
88
ifneq ($(CROSS_CC_HAS_ARMV8_BTI),)
89
-AARCH64_TESTS += bti-1
90
-bti-1: CFLAGS += -mbranch-protection=standard
91
-bti-1: LDFLAGS += -nostdlib
92
+AARCH64_TESTS += bti-1 bti-3
93
+bti-1 bti-3: CFLAGS += -mbranch-protection=standard
94
+bti-1 bti-3: LDFLAGS += -nostdlib
267
endif
95
endif
268
96
# bti-2 tests PROT_BTI, so no special compiler support required.
269
+# BTI Tests
97
AARCH64_TESTS += bti-2
270
+# bti-1 tests the elf notes, so we require special compiler support.
271
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
272
+AARCH64_TESTS += bti-1
273
+bti-1: CFLAGS += -mbranch-protection=standard
274
+bti-1: LDFLAGS += -nostdlib
275
+endif
276
+# bti-2 tests PROT_BTI, so no special compiler support required.
277
+AARCH64_TESTS += bti-2
278
+
279
# Semihosting smoke test for linux-user
280
AARCH64_TESTS += semihosting
281
run-semihosting: semihosting
282
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
283
index XXXXXXX..XXXXXXX 100755
284
--- a/tests/tcg/configure.sh
285
+++ b/tests/tcg/configure.sh
286
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
287
-march=armv8.3-a -o $TMPE $TMPC; then
288
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
289
fi
290
+ if do_compiler "$target_compiler" $target_compiler_cflags \
291
+ -mbranch-protection=standard -o $TMPE $TMPC; then
292
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
293
+ fi
294
;;
295
esac
296
297
--
98
--
298
2.20.1
99
2.25.1
299
300
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This test exercises the various modes of the npcm7xx timer. In
3
Move ARMCPRegInfo and all related declarations to a new
4
particular, it triggers the bug found by the fuzzer, as reported here:
4
internal header, out of the public cpu.h.
5
5
6
https://lists.gnu.org/archive/html/qemu-devel/2020-09/msg02992.html
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
It also found several other bugs, especially related to interrupt
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
handling.
9
Message-id: 20220501055028.646596-2-richard.henderson@linaro.org
10
11
The test exercises all the timers in all the timer modules, which
12
expands to 180 test cases in total.
13
14
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Message-id: 20201008232154.94221-2-hskinnemoen@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
11
---
19
tests/qtest/npcm7xx_timer-test.c | 562 +++++++++++++++++++++++++++++++
12
target/arm/cpregs.h | 413 +++++++++++++++++++++++++++++++++++++
20
tests/qtest/meson.build | 1 +
13
target/arm/cpu.h | 368 ---------------------------------
21
2 files changed, 563 insertions(+)
14
hw/arm/pxa2xx.c | 1 +
22
create mode 100644 tests/qtest/npcm7xx_timer-test.c
15
hw/arm/pxa2xx_pic.c | 1 +
16
hw/intc/arm_gicv3_cpuif.c | 1 +
17
hw/intc/arm_gicv3_kvm.c | 2 +
18
target/arm/cpu.c | 1 +
19
target/arm/cpu64.c | 1 +
20
target/arm/cpu_tcg.c | 1 +
21
target/arm/gdbstub.c | 3 +-
22
target/arm/helper.c | 1 +
23
target/arm/op_helper.c | 1 +
24
target/arm/translate-a64.c | 4 +-
25
target/arm/translate.c | 3 +-
26
14 files changed, 427 insertions(+), 374 deletions(-)
27
create mode 100644 target/arm/cpregs.h
23
28
24
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
29
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
25
new file mode 100644
30
new file mode 100644
26
index XXXXXXX..XXXXXXX
31
index XXXXXXX..XXXXXXX
27
--- /dev/null
32
--- /dev/null
28
+++ b/tests/qtest/npcm7xx_timer-test.c
33
+++ b/target/arm/cpregs.h
29
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@
30
+/*
35
+/*
31
+ * QTest testcase for the Nuvoton NPCM7xx Timer
36
+ * QEMU ARM CP Register access and descriptions
32
+ *
37
+ *
33
+ * Copyright 2020 Google LLC
38
+ * Copyright (c) 2022 Linaro Ltd
34
+ *
39
+ *
35
+ * This program is free software; you can redistribute it and/or modify it
40
+ * This program is free software; you can redistribute it and/or
36
+ * under the terms of the GNU General Public License as published by the
41
+ * modify it under the terms of the GNU General Public License
37
+ * Free Software Foundation; either version 2 of the License, or
42
+ * as published by the Free Software Foundation; either version 2
38
+ * (at your option) any later version.
43
+ * of the License, or (at your option) any later version.
39
+ *
44
+ *
40
+ * This program is distributed in the hope that it will be useful, but WITHOUT
45
+ * This program is distributed in the hope that it will be useful,
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
46
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
47
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43
+ * for more details.
48
+ * GNU General Public License for more details.
44
+ */
49
+ *
45
+
50
+ * You should have received a copy of the GNU General Public License
46
+#include "qemu/osdep.h"
51
+ * along with this program; if not, see
47
+#include "qemu/timer.h"
52
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
48
+#include "libqtest-single.h"
53
+ */
49
+
54
+
50
+#define TIM_REF_HZ (25000000)
55
+#ifndef TARGET_ARM_CPREGS_H
51
+
56
+#define TARGET_ARM_CPREGS_H
52
+/* Bits in TCSRx */
57
+
53
+#define CEN BIT(30)
58
+/*
54
+#define IE BIT(29)
59
+ * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
55
+#define MODE_ONESHOT (0 << 27)
60
+ * special-behaviour cp reg and bits [11..8] indicate what behaviour
56
+#define MODE_PERIODIC (1 << 27)
61
+ * it has. Otherwise it is a simple cp reg, where CONST indicates that
57
+#define CRST BIT(26)
62
+ * TCG can assume the value to be constant (ie load at translate time)
58
+#define CACT BIT(25)
63
+ * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
59
+#define PRESCALE(x) (x)
64
+ * indicates that the TB should not be ended after a write to this register
60
+
65
+ * (the default is that the TB ends after cp writes). OVERRIDE permits
61
+/* Registers shared between all timers in a module. */
66
+ * a register definition to override a previous definition for the
62
+#define TISR 0x18
67
+ * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
63
+#define WTCR 0x1c
68
+ * old must have the OVERRIDE bit set.
64
+# define WTCLK(x) ((x) << 10)
69
+ * ALIAS indicates that this register is an alias view of some underlying
65
+
70
+ * state which is also visible via another register, and that the other
66
+/* Power-on default; used to re-initialize timers before each test. */
71
+ * register is handling migration and reset; registers marked ALIAS will not be
67
+#define TCSR_DEFAULT PRESCALE(5)
72
+ * migrated but may have their state set by syncing of register state from KVM.
68
+
73
+ * NO_RAW indicates that this register has no underlying state and does not
69
+/* Register offsets for a timer within a timer block. */
74
+ * support raw access for state saving/loading; it will not be used for either
70
+typedef struct Timer {
75
+ * migration or KVM state synchronization. (Typically this is for "registers"
71
+ unsigned int tcsr_offset;
76
+ * which are actually used as instructions for cache maintenance and so on.)
72
+ unsigned int ticr_offset;
77
+ * IO indicates that this register does I/O and therefore its accesses
73
+ unsigned int tdr_offset;
78
+ * need to be marked with gen_io_start() and also end the TB. In particular,
74
+} Timer;
79
+ * registers which implement clocks or timers require this.
75
+
80
+ * RAISES_EXC is for when the read or write hook might raise an exception;
76
+/* A timer block containing 5 timers. */
81
+ * the generated code will synchronize the CPU state before calling the hook
77
+typedef struct TimerBlock {
82
+ * so that it is safe for the hook to call raise_exception().
78
+ int irq_base;
83
+ * NEWEL is for writes to registers that might change the exception
79
+ uint64_t base_addr;
84
+ * level - typically on older ARM chips. For those cases we need to
80
+} TimerBlock;
85
+ * re-read the new el when recomputing the translation flags.
81
+
86
+ */
82
+/* Testdata for testing a particular timer within a timer block. */
87
+#define ARM_CP_SPECIAL 0x0001
83
+typedef struct TestData {
88
+#define ARM_CP_CONST 0x0002
84
+ const TimerBlock *tim;
89
+#define ARM_CP_64BIT 0x0004
85
+ const Timer *timer;
90
+#define ARM_CP_SUPPRESS_TB_END 0x0008
86
+} TestData;
91
+#define ARM_CP_OVERRIDE 0x0010
87
+
92
+#define ARM_CP_ALIAS 0x0020
88
+const TimerBlock timer_block[] = {
93
+#define ARM_CP_IO 0x0040
89
+ {
94
+#define ARM_CP_NO_RAW 0x0080
90
+ .irq_base = 32,
95
+#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
91
+ .base_addr = 0xf0008000,
96
+#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
92
+ },
97
+#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
93
+ {
98
+#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
94
+ .irq_base = 37,
99
+#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
95
+ .base_addr = 0xf0009000,
100
+#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
96
+ },
101
+#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
97
+ {
102
+#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
98
+ .irq_base = 42,
103
+#define ARM_CP_FPU 0x1000
99
+ .base_addr = 0xf000a000,
104
+#define ARM_CP_SVE 0x2000
100
+ },
105
+#define ARM_CP_NO_GDB 0x4000
106
+#define ARM_CP_RAISES_EXC 0x8000
107
+#define ARM_CP_NEWEL 0x10000
108
+/* Used only as a terminator for ARMCPRegInfo lists */
109
+#define ARM_CP_SENTINEL 0xfffff
110
+/* Mask of only the flag bits in a type field */
111
+#define ARM_CP_FLAG_MASK 0x1f0ff
112
+
113
+/*
114
+ * Valid values for ARMCPRegInfo state field, indicating which of
115
+ * the AArch32 and AArch64 execution states this register is visible in.
116
+ * If the reginfo doesn't explicitly specify then it is AArch32 only.
117
+ * If the reginfo is declared to be visible in both states then a second
118
+ * reginfo is synthesised for the AArch32 view of the AArch64 register,
119
+ * such that the AArch32 view is the lower 32 bits of the AArch64 one.
120
+ * Note that we rely on the values of these enums as we iterate through
121
+ * the various states in some places.
122
+ */
123
+enum {
124
+ ARM_CP_STATE_AA32 = 0,
125
+ ARM_CP_STATE_AA64 = 1,
126
+ ARM_CP_STATE_BOTH = 2,
101
+};
127
+};
102
+
128
+
103
+const Timer timer[] = {
129
+/*
104
+ {
130
+ * ARM CP register secure state flags. These flags identify security state
105
+ .tcsr_offset = 0x00,
131
+ * attributes for a given CP register entry.
106
+ .ticr_offset = 0x08,
132
+ * The existence of both or neither secure and non-secure flags indicates that
107
+ .tdr_offset = 0x10,
133
+ * the register has both a secure and non-secure hash entry. A single one of
108
+ }, {
134
+ * these flags causes the register to only be hashed for the specified
109
+ .tcsr_offset = 0x04,
135
+ * security state.
110
+ .ticr_offset = 0x0c,
136
+ * Although definitions may have any combination of the S/NS bits, each
111
+ .tdr_offset = 0x14,
137
+ * registered entry will only have one to identify whether the entry is secure
112
+ }, {
138
+ * or non-secure.
113
+ .tcsr_offset = 0x20,
139
+ */
114
+ .ticr_offset = 0x28,
140
+enum {
115
+ .tdr_offset = 0x30,
141
+ ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
116
+ }, {
142
+ ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
117
+ .tcsr_offset = 0x24,
118
+ .ticr_offset = 0x2c,
119
+ .tdr_offset = 0x34,
120
+ }, {
121
+ .tcsr_offset = 0x40,
122
+ .ticr_offset = 0x48,
123
+ .tdr_offset = 0x50,
124
+ },
125
+};
143
+};
126
+
144
+
127
+/* Returns the index of the timer block. */
145
+/*
128
+static int tim_index(const TimerBlock *tim)
146
+ * Return true if cptype is a valid type field. This is used to try to
147
+ * catch errors where the sentinel has been accidentally left off the end
148
+ * of a list of registers.
149
+ */
150
+static inline bool cptype_valid(int cptype)
129
+{
151
+{
130
+ ptrdiff_t diff = tim - timer_block;
152
+ return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
131
+
153
+ || ((cptype & ARM_CP_SPECIAL) &&
132
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
154
+ ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
133
+
134
+ return diff;
135
+}
155
+}
136
+
156
+
137
+/* Returns the index of a timer within a timer block. */
157
+/*
138
+static int timer_index(const Timer *t)
158
+ * Access rights:
159
+ * We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
160
+ * defines as PL0 (user), PL1 (fiq/irq/svc/abt/und/sys, ie privileged), and
161
+ * PL2 (hyp). The other level which has Read and Write bits is Secure PL1
162
+ * (ie any of the privileged modes in Secure state, or Monitor mode).
163
+ * If a register is accessible in one privilege level it's always accessible
164
+ * in higher privilege levels too. Since "Secure PL1" also follows this rule
165
+ * (ie anything visible in PL2 is visible in S-PL1, some things are only
166
+ * visible in S-PL1) but "Secure PL1" is a bit of a mouthful, we bend the
167
+ * terminology a little and call this PL3.
168
+ * In AArch64 things are somewhat simpler as the PLx bits line up exactly
169
+ * with the ELx exception levels.
170
+ *
171
+ * If access permissions for a register are more complex than can be
172
+ * described with these bits, then use a laxer set of restrictions, and
173
+ * do the more restrictive/complex check inside a helper function.
174
+ */
175
+#define PL3_R 0x80
176
+#define PL3_W 0x40
177
+#define PL2_R (0x20 | PL3_R)
178
+#define PL2_W (0x10 | PL3_W)
179
+#define PL1_R (0x08 | PL2_R)
180
+#define PL1_W (0x04 | PL2_W)
181
+#define PL0_R (0x02 | PL1_R)
182
+#define PL0_W (0x01 | PL1_W)
183
+
184
+/*
185
+ * For user-mode some registers are accessible to EL0 via a kernel
186
+ * trap-and-emulate ABI. In this case we define the read permissions
187
+ * as actually being PL0_R. However some bits of any given register
188
+ * may still be masked.
189
+ */
190
+#ifdef CONFIG_USER_ONLY
191
+#define PL0U_R PL0_R
192
+#else
193
+#define PL0U_R PL1_R
194
+#endif
195
+
196
+#define PL3_RW (PL3_R | PL3_W)
197
+#define PL2_RW (PL2_R | PL2_W)
198
+#define PL1_RW (PL1_R | PL1_W)
199
+#define PL0_RW (PL0_R | PL0_W)
200
+
201
+typedef enum CPAccessResult {
202
+ /* Access is permitted */
203
+ CP_ACCESS_OK = 0,
204
+ /*
205
+ * Access fails due to a configurable trap or enable which would
206
+ * result in a categorized exception syndrome giving information about
207
+ * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
208
+ * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
209
+ * PL1 if in EL0, otherwise to the current EL).
210
+ */
211
+ CP_ACCESS_TRAP = 1,
212
+ /*
213
+ * Access fails and results in an exception syndrome 0x0 ("uncategorized").
214
+ * Note that this is not a catch-all case -- the set of cases which may
215
+ * result in this failure is specifically defined by the architecture.
216
+ */
217
+ CP_ACCESS_TRAP_UNCATEGORIZED = 2,
218
+ /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
219
+ CP_ACCESS_TRAP_EL2 = 3,
220
+ CP_ACCESS_TRAP_EL3 = 4,
221
+ /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
222
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
223
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
224
+} CPAccessResult;
225
+
226
+typedef struct ARMCPRegInfo ARMCPRegInfo;
227
+
228
+/*
229
+ * Access functions for coprocessor registers. These cannot fail and
230
+ * may not raise exceptions.
231
+ */
232
+typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
233
+typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
234
+ uint64_t value);
235
+/* Access permission check functions for coprocessor registers. */
236
+typedef CPAccessResult CPAccessFn(CPUARMState *env,
237
+ const ARMCPRegInfo *opaque,
238
+ bool isread);
239
+/* Hook function for register reset */
240
+typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
241
+
242
+#define CP_ANY 0xff
243
+
244
+/* Definition of an ARM coprocessor register */
245
+struct ARMCPRegInfo {
246
+ /* Name of register (useful mainly for debugging, need not be unique) */
247
+ const char *name;
248
+ /*
249
+ * Location of register: coprocessor number and (crn,crm,opc1,opc2)
250
+ * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
251
+ * 'wildcard' field -- any value of that field in the MRC/MCR insn
252
+ * will be decoded to this register. The register read and write
253
+ * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
254
+ * used by the program, so it is possible to register a wildcard and
255
+ * then behave differently on read/write if necessary.
256
+ * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
257
+ * must both be zero.
258
+ * For AArch64-visible registers, opc0 is also used.
259
+ * Since there are no "coprocessors" in AArch64, cp is purely used as a
260
+ * way to distinguish (for KVM's benefit) guest-visible system registers
261
+ * from demuxed ones provided to preserve the "no side effects on
262
+ * KVM register read/write from QEMU" semantics. cp==0x13 is guest
263
+ * visible (to match KVM's encoding); cp==0 will be converted to
264
+ * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
265
+ */
266
+ uint8_t cp;
267
+ uint8_t crn;
268
+ uint8_t crm;
269
+ uint8_t opc0;
270
+ uint8_t opc1;
271
+ uint8_t opc2;
272
+ /* Execution state in which this register is visible: ARM_CP_STATE_* */
273
+ int state;
274
+ /* Register type: ARM_CP_* bits/values */
275
+ int type;
276
+ /* Access rights: PL*_[RW] */
277
+ int access;
278
+ /* Security state: ARM_CP_SECSTATE_* bits/values */
279
+ int secure;
280
+ /*
281
+ * The opaque pointer passed to define_arm_cp_regs_with_opaque() when
282
+ * this register was defined: can be used to hand data through to the
283
+ * register read/write functions, since they are passed the ARMCPRegInfo*.
284
+ */
285
+ void *opaque;
286
+ /*
287
+ * Value of this register, if it is ARM_CP_CONST. Otherwise, if
288
+ * fieldoffset is non-zero, the reset value of the register.
289
+ */
290
+ uint64_t resetvalue;
291
+ /*
292
+ * Offset of the field in CPUARMState for this register.
293
+ * This is not needed if either:
294
+ * 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
295
+ * 2. both readfn and writefn are specified
296
+ */
297
+ ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
298
+
299
+ /*
300
+ * Offsets of the secure and non-secure fields in CPUARMState for the
301
+ * register if it is banked. These fields are only used during the static
302
+ * registration of a register. During hashing the bank associated
303
+ * with a given security state is copied to fieldoffset which is used from
304
+ * there on out.
305
+ *
306
+ * It is expected that register definitions use either fieldoffset or
307
+ * bank_fieldoffsets in the definition but not both. It is also expected
308
+ * that both bank offsets are set when defining a banked register. This
309
+ * use indicates that a register is banked.
310
+ */
311
+ ptrdiff_t bank_fieldoffsets[2];
312
+
313
+ /*
314
+ * Function for making any access checks for this register in addition to
315
+ * those specified by the 'access' permissions bits. If NULL, no extra
316
+ * checks required. The access check is performed at runtime, not at
317
+ * translate time.
318
+ */
319
+ CPAccessFn *accessfn;
320
+ /*
321
+ * Function for handling reads of this register. If NULL, then reads
322
+ * will be done by loading from the offset into CPUARMState specified
323
+ * by fieldoffset.
324
+ */
325
+ CPReadFn *readfn;
326
+ /*
327
+ * Function for handling writes of this register. If NULL, then writes
328
+ * will be done by writing to the offset into CPUARMState specified
329
+ * by fieldoffset.
330
+ */
331
+ CPWriteFn *writefn;
332
+ /*
333
+ * Function for doing a "raw" read; used when we need to copy
334
+ * coprocessor state to the kernel for KVM or out for
335
+ * migration. This only needs to be provided if there is also a
336
+ * readfn and it has side effects (for instance clear-on-read bits).
337
+ */
338
+ CPReadFn *raw_readfn;
339
+ /*
340
+ * Function for doing a "raw" write; used when we need to copy KVM
341
+ * kernel coprocessor state into userspace, or for inbound
342
+ * migration. This only needs to be provided if there is also a
343
+ * writefn and it masks out "unwritable" bits or has write-one-to-clear
344
+ * or similar behaviour.
345
+ */
346
+ CPWriteFn *raw_writefn;
347
+ /*
348
+ * Function for resetting the register. If NULL, then reset will be done
349
+ * by writing resetvalue to the field specified in fieldoffset. If
350
+ * fieldoffset is 0 then no reset will be done.
351
+ */
352
+ CPResetFn *resetfn;
353
+
354
+ /*
355
+ * "Original" writefn and readfn.
356
+ * For ARMv8.1-VHE register aliases, we overwrite the read/write
357
+ * accessor functions of various EL1/EL0 to perform the runtime
358
+ * check for which sysreg should actually be modified, and then
359
+ * forwards the operation. Before overwriting the accessors,
360
+ * the original function is copied here, so that accesses that
361
+ * really do go to the EL1/EL0 version proceed normally.
362
+ * (The corresponding EL2 register is linked via opaque.)
363
+ */
364
+ CPReadFn *orig_readfn;
365
+ CPWriteFn *orig_writefn;
366
+};
367
+
368
+/*
369
+ * Macros which are lvalues for the field in CPUARMState for the
370
+ * ARMCPRegInfo *ri.
371
+ */
372
+#define CPREG_FIELD32(env, ri) \
373
+ (*(uint32_t *)((char *)(env) + (ri)->fieldoffset))
374
+#define CPREG_FIELD64(env, ri) \
375
+ (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
376
+
377
+#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
378
+
379
+void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
380
+ const ARMCPRegInfo *regs, void *opaque);
381
+void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
382
+ const ARMCPRegInfo *regs, void *opaque);
383
+static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
139
+{
384
+{
140
+ ptrdiff_t diff = t - timer;
385
+ define_arm_cp_regs_with_opaque(cpu, regs, 0);
141
+
142
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
143
+
144
+ return diff;
145
+}
386
+}
146
+
387
+static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
147
+/* Returns the irq line for a given timer. */
148
+static int tim_timer_irq(const TestData *td)
149
+{
388
+{
150
+ return td->tim->irq_base + timer_index(td->timer);
389
+ define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
151
+}
390
+}
152
+
391
+const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
153
+/* Register read/write accessors. */
392
+
154
+
393
+/*
155
+static void tim_write(const TestData *td,
394
+ * Definition of an ARM co-processor register as viewed from
156
+ unsigned int offset, uint32_t value)
395
+ * userspace. This is used for presenting sanitised versions of
396
+ * registers to userspace when emulating the Linux AArch64 CPU
397
+ * ID/feature ABI (advertised as HWCAP_CPUID).
398
+ */
399
+typedef struct ARMCPRegUserSpaceInfo {
400
+ /* Name of register */
401
+ const char *name;
402
+
403
+ /* Is the name actually a glob pattern */
404
+ bool is_glob;
405
+
406
+ /* Only some bits are exported to user space */
407
+ uint64_t exported_bits;
408
+
409
+ /* Fixed bits are applied after the mask */
410
+ uint64_t fixed_bits;
411
+} ARMCPRegUserSpaceInfo;
412
+
413
+#define REGUSERINFO_SENTINEL { .name = NULL }
414
+
415
+void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
416
+
417
+/* CPWriteFn that can be used to implement writes-ignored behaviour */
418
+void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
419
+ uint64_t value);
420
+/* CPReadFn that can be used for read-as-zero behaviour */
421
+uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
422
+
423
+/*
424
+ * CPResetFn that does nothing, for use if no reset is required even
425
+ * if fieldoffset is non zero.
426
+ */
427
+void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
428
+
429
+/*
430
+ * Return true if this reginfo struct's field in the cpu state struct
431
+ * is 64 bits wide.
432
+ */
433
+static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
157
+{
434
+{
158
+ writel(td->tim->base_addr + offset, value);
435
+ return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
159
+}
436
+}
160
+
437
+
161
+static uint32_t tim_read(const TestData *td, unsigned int offset)
438
+static inline bool cp_access_ok(int current_el,
439
+ const ARMCPRegInfo *ri, int isread)
162
+{
440
+{
163
+ return readl(td->tim->base_addr + offset);
441
+ return (ri->access >> ((current_el * 2) + isread)) & 1;
164
+}
442
+}
165
+
443
+
166
+static void tim_write_tcsr(const TestData *td, uint32_t value)
444
+/* Raw read of a coprocessor register (as needed for migration, etc) */
167
+{
445
+uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
168
+ tim_write(td, td->timer->tcsr_offset, value);
446
+
169
+}
447
+#endif /* TARGET_ARM_CPREGS_H */
170
+
448
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
171
+static uint32_t tim_read_tcsr(const TestData *td)
449
index XXXXXXX..XXXXXXX 100644
172
+{
450
--- a/target/arm/cpu.h
173
+ return tim_read(td, td->timer->tcsr_offset);
451
+++ b/target/arm/cpu.h
174
+}
452
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
175
+
453
return kvmid;
176
+static void tim_write_ticr(const TestData *td, uint32_t value)
454
}
177
+{
455
178
+ tim_write(td, td->timer->ticr_offset, value);
456
-/* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
179
+}
457
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
180
+
458
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
181
+static uint32_t tim_read_ticr(const TestData *td)
459
- * TCG can assume the value to be constant (ie load at translate time)
182
+{
460
- * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
183
+ return tim_read(td, td->timer->ticr_offset);
461
- * indicates that the TB should not be ended after a write to this register
184
+}
462
- * (the default is that the TB ends after cp writes). OVERRIDE permits
185
+
463
- * a register definition to override a previous definition for the
186
+static uint32_t tim_read_tdr(const TestData *td)
464
- * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
187
+{
465
- * old must have the OVERRIDE bit set.
188
+ return tim_read(td, td->timer->tdr_offset);
466
- * ALIAS indicates that this register is an alias view of some underlying
189
+}
467
- * state which is also visible via another register, and that the other
190
+
468
- * register is handling migration and reset; registers marked ALIAS will not be
191
+/* Returns the number of nanoseconds to count the given number of cycles. */
469
- * migrated but may have their state set by syncing of register state from KVM.
192
+static int64_t tim_calculate_step(uint32_t count, uint32_t prescale)
470
- * NO_RAW indicates that this register has no underlying state and does not
193
+{
471
- * support raw access for state saving/loading; it will not be used for either
194
+ return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
472
- * migration or KVM state synchronization. (Typically this is for "registers"
195
+}
473
- * which are actually used as instructions for cache maintenance and so on.)
196
+
474
- * IO indicates that this register does I/O and therefore its accesses
197
+/* Returns a bitmask corresponding to the timer under test. */
475
- * need to be marked with gen_io_start() and also end the TB. In particular,
198
+static uint32_t tim_timer_bit(const TestData *td)
476
- * registers which implement clocks or timers require this.
199
+{
477
- * RAISES_EXC is for when the read or write hook might raise an exception;
200
+ return BIT(timer_index(td->timer));
478
- * the generated code will synchronize the CPU state before calling the hook
201
+}
479
- * so that it is safe for the hook to call raise_exception().
202
+
480
- * NEWEL is for writes to registers that might change the exception
203
+/* Resets all timers to power-on defaults. */
481
- * level - typically on older ARM chips. For those cases we need to
204
+static void tim_reset(const TestData *td)
482
- * re-read the new el when recomputing the translation flags.
205
+{
483
- */
206
+ int i, j;
484
-#define ARM_CP_SPECIAL 0x0001
207
+
485
-#define ARM_CP_CONST 0x0002
208
+ /* Reset all the timers, in case a previous test left a timer running. */
486
-#define ARM_CP_64BIT 0x0004
209
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
487
-#define ARM_CP_SUPPRESS_TB_END 0x0008
210
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
488
-#define ARM_CP_OVERRIDE 0x0010
211
+ writel(timer_block[i].base_addr + timer[j].tcsr_offset,
489
-#define ARM_CP_ALIAS 0x0020
212
+ CRST | TCSR_DEFAULT);
490
-#define ARM_CP_IO 0x0040
213
+ }
491
-#define ARM_CP_NO_RAW 0x0080
214
+ writel(timer_block[i].base_addr + TISR, -1);
492
-#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
215
+ }
493
-#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
216
+}
494
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
217
+
495
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
218
+/* Verifies the reset state of a timer. */
496
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
219
+static void test_reset(gconstpointer test_data)
497
-#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
220
+{
498
-#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
221
+ const TestData *td = test_data;
499
-#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
222
+
500
-#define ARM_CP_FPU 0x1000
223
+ tim_reset(td);
501
-#define ARM_CP_SVE 0x2000
224
+
502
-#define ARM_CP_NO_GDB 0x4000
225
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
503
-#define ARM_CP_RAISES_EXC 0x8000
226
+ g_assert_cmphex(tim_read_ticr(td), ==, 0);
504
-#define ARM_CP_NEWEL 0x10000
227
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
505
-/* Used only as a terminator for ARMCPRegInfo lists */
228
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
506
-#define ARM_CP_SENTINEL 0xfffff
229
+ g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
507
-/* Mask of only the flag bits in a type field */
230
+}
508
-#define ARM_CP_FLAG_MASK 0x1f0ff
231
+
509
-
232
+/* Verifies that CRST wins if both CEN and CRST are set. */
510
-/* Valid values for ARMCPRegInfo state field, indicating which of
233
+static void test_reset_overrides_enable(gconstpointer test_data)
511
- * the AArch32 and AArch64 execution states this register is visible in.
234
+{
512
- * If the reginfo doesn't explicitly specify then it is AArch32 only.
235
+ const TestData *td = test_data;
513
- * If the reginfo is declared to be visible in both states then a second
236
+
514
- * reginfo is synthesised for the AArch32 view of the AArch64 register,
237
+ tim_reset(td);
515
- * such that the AArch32 view is the lower 32 bits of the AArch64 one.
238
+
516
- * Note that we rely on the values of these enums as we iterate through
239
+ /* CRST should force CEN to 0 */
517
- * the various states in some places.
240
+ tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
518
- */
241
+
519
-enum {
242
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
520
- ARM_CP_STATE_AA32 = 0,
243
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
521
- ARM_CP_STATE_AA64 = 1,
244
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
522
- ARM_CP_STATE_BOTH = 2,
245
+}
523
-};
246
+
524
-
247
+/* Verifies the behavior when CEN is set and then cleared. */
525
-/* ARM CP register secure state flags. These flags identify security state
248
+static void test_oneshot_enable_then_disable(gconstpointer test_data)
526
- * attributes for a given CP register entry.
249
+{
527
- * The existence of both or neither secure and non-secure flags indicates that
250
+ const TestData *td = test_data;
528
- * the register has both a secure and non-secure hash entry. A single one of
251
+
529
- * these flags causes the register to only be hashed for the specified
252
+ tim_reset(td);
530
- * security state.
253
+
531
- * Although definitions may have any combination of the S/NS bits, each
254
+ /* Enable the timer with zero initial count, then disable it again. */
532
- * registered entry will only have one to identify whether the entry is secure
255
+ tim_write_tcsr(td, CEN | TCSR_DEFAULT);
533
- * or non-secure.
256
+ tim_write_tcsr(td, TCSR_DEFAULT);
534
- */
257
+
535
-enum {
258
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
536
- ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
259
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
537
- ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
260
+ /* Timer interrupt flag should be set, but interrupts are not enabled. */
538
-};
261
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
539
-
262
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
540
-/* Return true if cptype is a valid type field. This is used to try to
263
+}
541
- * catch errors where the sentinel has been accidentally left off the end
264
+
542
- * of a list of registers.
265
+/* Verifies that a one-shot timer fires when expected with prescaler 5. */
543
- */
266
+static void test_oneshot_ps5(gconstpointer test_data)
544
-static inline bool cptype_valid(int cptype)
267
+{
545
-{
268
+ const TestData *td = test_data;
546
- return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
269
+ unsigned int count = 256;
547
- || ((cptype & ARM_CP_SPECIAL) &&
270
+ unsigned int ps = 5;
548
- ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
271
+
549
-}
272
+ tim_reset(td);
550
-
273
+
551
-/* Access rights:
274
+ tim_write_ticr(td, count);
552
- * We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
275
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
553
- * defines as PL0 (user), PL1 (fiq/irq/svc/abt/und/sys, ie privileged), and
276
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
554
- * PL2 (hyp). The other level which has Read and Write bits is Secure PL1
277
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
555
- * (ie any of the privileged modes in Secure state, or Monitor mode).
278
+
556
- * If a register is accessible in one privilege level it's always accessible
279
+ clock_step(tim_calculate_step(count, ps) - 1);
557
- * in higher privilege levels too. Since "Secure PL1" also follows this rule
280
+
558
- * (ie anything visible in PL2 is visible in S-PL1, some things are only
281
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
559
- * visible in S-PL1) but "Secure PL1" is a bit of a mouthful, we bend the
282
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
560
- * terminology a little and call this PL3.
283
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
561
- * In AArch64 things are somewhat simpler as the PLx bits line up exactly
284
+
562
- * with the ELx exception levels.
285
+ clock_step(1);
563
- *
286
+
564
- * If access permissions for a register are more complex than can be
287
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
565
- * described with these bits, then use a laxer set of restrictions, and
288
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
566
- * do the more restrictive/complex check inside a helper function.
289
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
567
- */
290
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
568
-#define PL3_R 0x80
291
+
569
-#define PL3_W 0x40
292
+ /* Clear the interrupt flag. */
570
-#define PL2_R (0x20 | PL3_R)
293
+ tim_write(td, TISR, tim_timer_bit(td));
571
-#define PL2_W (0x10 | PL3_W)
294
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
572
-#define PL1_R (0x08 | PL2_R)
295
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
573
-#define PL1_W (0x04 | PL2_W)
296
+
574
-#define PL0_R (0x02 | PL1_R)
297
+ /* Verify that this isn't a periodic timer. */
575
-#define PL0_W (0x01 | PL1_W)
298
+ clock_step(2 * tim_calculate_step(count, ps));
576
-
299
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
577
-/*
300
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
578
- * For user-mode some registers are accessible to EL0 via a kernel
301
+}
579
- * trap-and-emulate ABI. In this case we define the read permissions
302
+
580
- * as actually being PL0_R. However some bits of any given register
303
+/* Verifies that a one-shot timer fires when expected with prescaler 0. */
581
- * may still be masked.
304
+static void test_oneshot_ps0(gconstpointer test_data)
582
- */
305
+{
583
-#ifdef CONFIG_USER_ONLY
306
+ const TestData *td = test_data;
584
-#define PL0U_R PL0_R
307
+ unsigned int count = 1;
585
-#else
308
+ unsigned int ps = 0;
586
-#define PL0U_R PL1_R
309
+
587
-#endif
310
+ tim_reset(td);
588
-
311
+
589
-#define PL3_RW (PL3_R | PL3_W)
312
+ tim_write_ticr(td, count);
590
-#define PL2_RW (PL2_R | PL2_W)
313
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
591
-#define PL1_RW (PL1_R | PL1_W)
314
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
592
-#define PL0_RW (PL0_R | PL0_W)
315
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
593
-
316
+
594
/* Return the highest implemented Exception Level */
317
+ clock_step(tim_calculate_step(count, ps) - 1);
595
static inline int arm_highest_el(CPUARMState *env)
318
+
596
{
319
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
597
@@ -XXX,XX +XXX,XX @@ static inline int arm_current_el(CPUARMState *env)
320
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
598
}
321
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
599
}
322
+
600
323
+ clock_step(1);
601
-typedef struct ARMCPRegInfo ARMCPRegInfo;
324
+
602
-
325
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
603
-typedef enum CPAccessResult {
326
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
604
- /* Access is permitted */
327
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
605
- CP_ACCESS_OK = 0,
328
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
606
- /* Access fails due to a configurable trap or enable which would
329
+}
607
- * result in a categorized exception syndrome giving information about
330
+
608
- * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
331
+/* Verifies that a one-shot timer fires when expected with highest prescaler. */
609
- * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
332
+static void test_oneshot_ps255(gconstpointer test_data)
610
- * PL1 if in EL0, otherwise to the current EL).
333
+{
611
- */
334
+ const TestData *td = test_data;
612
- CP_ACCESS_TRAP = 1,
335
+ unsigned int count = (1U << 24) - 1;
613
- /* Access fails and results in an exception syndrome 0x0 ("uncategorized").
336
+ unsigned int ps = 255;
614
- * Note that this is not a catch-all case -- the set of cases which may
337
+
615
- * result in this failure is specifically defined by the architecture.
338
+ tim_reset(td);
616
- */
339
+
617
- CP_ACCESS_TRAP_UNCATEGORIZED = 2,
340
+ tim_write_ticr(td, count);
618
- /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
341
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
619
- CP_ACCESS_TRAP_EL2 = 3,
342
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
620
- CP_ACCESS_TRAP_EL3 = 4,
343
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
621
- /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
344
+
622
- CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
345
+ clock_step(tim_calculate_step(count, ps) - 1);
623
- CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
346
+
624
-} CPAccessResult;
347
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
625
-
348
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
626
-/* Access functions for coprocessor registers. These cannot fail and
349
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
627
- * may not raise exceptions.
350
+
628
- */
351
+ clock_step(1);
629
-typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
352
+
630
-typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
353
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
631
- uint64_t value);
354
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
632
-/* Access permission check functions for coprocessor registers. */
355
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
633
-typedef CPAccessResult CPAccessFn(CPUARMState *env,
356
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
634
- const ARMCPRegInfo *opaque,
357
+}
635
- bool isread);
358
+
636
-/* Hook function for register reset */
359
+/* Verifies that a oneshot timer fires an interrupt when expected. */
637
-typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
360
+static void test_oneshot_interrupt(gconstpointer test_data)
638
-
361
+{
639
-#define CP_ANY 0xff
362
+ const TestData *td = test_data;
640
-
363
+ unsigned int count = 256;
641
-/* Definition of an ARM coprocessor register */
364
+ unsigned int ps = 7;
642
-struct ARMCPRegInfo {
365
+
643
- /* Name of register (useful mainly for debugging, need not be unique) */
366
+ tim_reset(td);
644
- const char *name;
367
+
645
- /* Location of register: coprocessor number and (crn,crm,opc1,opc2)
368
+ tim_write_ticr(td, count);
646
- * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
369
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
647
- * 'wildcard' field -- any value of that field in the MRC/MCR insn
370
+
648
- * will be decoded to this register. The register read and write
371
+ clock_step_next();
649
- * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
372
+
650
- * used by the program, so it is possible to register a wildcard and
373
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
651
- * then behave differently on read/write if necessary.
374
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
652
- * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
375
+}
653
- * must both be zero.
376
+
654
- * For AArch64-visible registers, opc0 is also used.
377
+/*
655
- * Since there are no "coprocessors" in AArch64, cp is purely used as a
378
+ * Verifies that the timer can be paused and later resumed, and it still fires
656
- * way to distinguish (for KVM's benefit) guest-visible system registers
379
+ * at the right moment.
657
- * from demuxed ones provided to preserve the "no side effects on
380
+ */
658
- * KVM register read/write from QEMU" semantics. cp==0x13 is guest
381
+static void test_pause_resume(gconstpointer test_data)
659
- * visible (to match KVM's encoding); cp==0 will be converted to
382
+{
660
- * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
383
+ const TestData *td = test_data;
661
- */
384
+ unsigned int count = 256;
662
- uint8_t cp;
385
+ unsigned int ps = 1;
663
- uint8_t crn;
386
+
664
- uint8_t crm;
387
+ tim_reset(td);
665
- uint8_t opc0;
388
+
666
- uint8_t opc1;
389
+ tim_write_ticr(td, count);
667
- uint8_t opc2;
390
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
668
- /* Execution state in which this register is visible: ARM_CP_STATE_* */
391
+
669
- int state;
392
+ /* Pause the timer halfway to expiration. */
670
- /* Register type: ARM_CP_* bits/values */
393
+ clock_step(tim_calculate_step(count / 2, ps));
671
- int type;
394
+ tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
672
- /* Access rights: PL*_[RW] */
395
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
673
- int access;
396
+
674
- /* Security state: ARM_CP_SECSTATE_* bits/values */
397
+ /* Counter should not advance during the following step. */
675
- int secure;
398
+ clock_step(2 * tim_calculate_step(count, ps));
676
- /* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
399
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
677
- * this register was defined: can be used to hand data through to the
400
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
678
- * register read/write functions, since they are passed the ARMCPRegInfo*.
401
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
679
- */
402
+
680
- void *opaque;
403
+ /* Resume the timer and run _almost_ to expiration. */
681
- /* Value of this register, if it is ARM_CP_CONST. Otherwise, if
404
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
682
- * fieldoffset is non-zero, the reset value of the register.
405
+ clock_step(tim_calculate_step(count / 2, ps) - 1);
683
- */
406
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
684
- uint64_t resetvalue;
407
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
685
- /* Offset of the field in CPUARMState for this register.
408
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
686
- *
409
+
687
- * This is not needed if either:
410
+ /* Now, run the rest of the way and verify that the interrupt fires. */
688
- * 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
411
+ clock_step(1);
689
- * 2. both readfn and writefn are specified
412
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
690
- */
413
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
691
- ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
414
+}
692
-
415
+
693
- /* Offsets of the secure and non-secure fields in CPUARMState for the
416
+/* Verifies that the prescaler can be changed while the timer is runnin. */
694
- * register if it is banked. These fields are only used during the static
417
+static void test_prescaler_change(gconstpointer test_data)
695
- * registration of a register. During hashing the bank associated
418
+{
696
- * with a given security state is copied to fieldoffset which is used from
419
+ const TestData *td = test_data;
697
- * there on out.
420
+ unsigned int count = 256;
698
- *
421
+ unsigned int ps = 5;
699
- * It is expected that register definitions use either fieldoffset or
422
+
700
- * bank_fieldoffsets in the definition but not both. It is also expected
423
+ tim_reset(td);
701
- * that both bank offsets are set when defining a banked register. This
424
+
702
- * use indicates that a register is banked.
425
+ tim_write_ticr(td, count);
703
- */
426
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
704
- ptrdiff_t bank_fieldoffsets[2];
427
+
705
-
428
+ /* Run a quarter of the way, and change the prescaler. */
706
- /* Function for making any access checks for this register in addition to
429
+ clock_step(tim_calculate_step(count / 4, ps));
707
- * those specified by the 'access' permissions bits. If NULL, no extra
430
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
708
- * checks required. The access check is performed at runtime, not at
431
+ ps = 2;
709
- * translate time.
432
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
710
- */
433
+ /* The counter must not change. */
711
- CPAccessFn *accessfn;
434
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
712
- /* Function for handling reads of this register. If NULL, then reads
435
+
713
- * will be done by loading from the offset into CPUARMState specified
436
+ /* Run another quarter of the way, and change the prescaler again. */
714
- * by fieldoffset.
437
+ clock_step(tim_calculate_step(count / 4, ps));
715
- */
438
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
716
- CPReadFn *readfn;
439
+ ps = 8;
717
- /* Function for handling writes of this register. If NULL, then writes
440
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
718
- * will be done by writing to the offset into CPUARMState specified
441
+ /* The counter must not change. */
719
- * by fieldoffset.
442
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
720
- */
443
+
721
- CPWriteFn *writefn;
444
+ /* Run another quarter of the way, and change the prescaler again. */
722
- /* Function for doing a "raw" read; used when we need to copy
445
+ clock_step(tim_calculate_step(count / 4, ps));
723
- * coprocessor state to the kernel for KVM or out for
446
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
724
- * migration. This only needs to be provided if there is also a
447
+ ps = 0;
725
- * readfn and it has side effects (for instance clear-on-read bits).
448
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
726
- */
449
+ /* The counter must not change. */
727
- CPReadFn *raw_readfn;
450
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
728
- /* Function for doing a "raw" write; used when we need to copy KVM
451
+
729
- * kernel coprocessor state into userspace, or for inbound
452
+ /* Run almost to expiration, and verify the timer didn't fire yet. */
730
- * migration. This only needs to be provided if there is also a
453
+ clock_step(tim_calculate_step(count / 4, ps) - 1);
731
- * writefn and it masks out "unwritable" bits or has write-one-to-clear
454
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
732
- * or similar behaviour.
455
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
733
- */
456
+
734
- CPWriteFn *raw_writefn;
457
+ /* Now, run the rest of the way and verify that the timer fires. */
735
- /* Function for resetting the register. If NULL, then reset will be done
458
+ clock_step(1);
736
- * by writing resetvalue to the field specified in fieldoffset. If
459
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
737
- * fieldoffset is 0 then no reset will be done.
460
+}
738
- */
461
+
739
- CPResetFn *resetfn;
462
+/* Verifies that a periodic timer automatically restarts after expiration. */
740
-
463
+static void test_periodic_no_interrupt(gconstpointer test_data)
741
- /*
464
+{
742
- * "Original" writefn and readfn.
465
+ const TestData *td = test_data;
743
- * For ARMv8.1-VHE register aliases, we overwrite the read/write
466
+ unsigned int count = 2;
744
- * accessor functions of various EL1/EL0 to perform the runtime
467
+ unsigned int ps = 3;
745
- * check for which sysreg should actually be modified, and then
468
+ int i;
746
- * forwards the operation. Before overwriting the accessors,
469
+
747
- * the original function is copied here, so that accesses that
470
+ tim_reset(td);
748
- * really do go to the EL1/EL0 version proceed normally.
471
+
749
- * (The corresponding EL2 register is linked via opaque.)
472
+ tim_write_ticr(td, count);
750
- */
473
+ tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
751
- CPReadFn *orig_readfn;
474
+
752
- CPWriteFn *orig_writefn;
475
+ for (i = 0; i < 4; i++) {
753
-};
476
+ clock_step_next();
754
-
477
+
755
-/* Macros which are lvalues for the field in CPUARMState for the
478
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
756
- * ARMCPRegInfo *ri.
479
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
757
- */
480
+
758
-#define CPREG_FIELD32(env, ri) \
481
+ tim_write(td, TISR, tim_timer_bit(td));
759
- (*(uint32_t *)((char *)(env) + (ri)->fieldoffset))
482
+
760
-#define CPREG_FIELD64(env, ri) \
483
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
761
- (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
484
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
762
-
485
+ }
763
-#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
486
+}
764
-
487
+
765
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
488
+/* Verifies that a periodict timer fires an interrupt every time it expires. */
766
- const ARMCPRegInfo *regs, void *opaque);
489
+static void test_periodic_interrupt(gconstpointer test_data)
767
-void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
490
+{
768
- const ARMCPRegInfo *regs, void *opaque);
491
+ const TestData *td = test_data;
769
-static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
492
+ unsigned int count = 65535;
770
-{
493
+ unsigned int ps = 2;
771
- define_arm_cp_regs_with_opaque(cpu, regs, 0);
494
+ int i;
772
-}
495
+
773
-static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
496
+ tim_reset(td);
774
-{
497
+
775
- define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
498
+ tim_write_ticr(td, count);
776
-}
499
+ tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
777
-const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
500
+
778
-
501
+ for (i = 0; i < 4; i++) {
779
-/*
502
+ clock_step_next();
780
- * Definition of an ARM co-processor register as viewed from
503
+
781
- * userspace. This is used for presenting sanitised versions of
504
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
782
- * registers to userspace when emulating the Linux AArch64 CPU
505
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
783
- * ID/feature ABI (advertised as HWCAP_CPUID).
506
+
784
- */
507
+ tim_write(td, TISR, tim_timer_bit(td));
785
-typedef struct ARMCPRegUserSpaceInfo {
508
+
786
- /* Name of register */
509
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
787
- const char *name;
510
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
788
-
511
+ }
789
- /* Is the name actually a glob pattern */
512
+}
790
- bool is_glob;
513
+
791
-
514
+/*
792
- /* Only some bits are exported to user space */
515
+ * Verifies that the timer behaves correctly when disabled right before and
793
- uint64_t exported_bits;
516
+ * exactly when it's supposed to expire.
794
-
517
+ */
795
- /* Fixed bits are applied after the mask */
518
+static void test_disable_on_expiration(gconstpointer test_data)
796
- uint64_t fixed_bits;
519
+{
797
-} ARMCPRegUserSpaceInfo;
520
+ const TestData *td = test_data;
798
-
521
+ unsigned int count = 8;
799
-#define REGUSERINFO_SENTINEL { .name = NULL }
522
+ unsigned int ps = 255;
800
-
523
+
801
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
524
+ tim_reset(td);
802
-
525
+
803
-/* CPWriteFn that can be used to implement writes-ignored behaviour */
526
+ tim_write_ticr(td, count);
804
-void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
527
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
805
- uint64_t value);
528
+
806
-/* CPReadFn that can be used for read-as-zero behaviour */
529
+ clock_step(tim_calculate_step(count, ps) - 1);
807
-uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
530
+
808
-
531
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
809
-/* CPResetFn that does nothing, for use if no reset is required even
532
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
810
- * if fieldoffset is non zero.
533
+ clock_step(1);
811
- */
534
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
812
-void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
535
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
813
-
536
+}
814
-/* Return true if this reginfo struct's field in the cpu state struct
537
+
815
- * is 64 bits wide.
538
+/*
816
- */
539
+ * Constructs a name that includes the timer block, timer and testcase name,
817
-static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
540
+ * and adds the test to the test suite.
818
-{
541
+ */
819
- return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
542
+static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
820
-}
543
+{
821
-
544
+ g_autofree char *full_name;
822
-static inline bool cp_access_ok(int current_el,
545
+
823
- const ARMCPRegInfo *ri, int isread)
546
+ full_name = g_strdup_printf("npcm7xx_timer/tim[%d]/timer[%d]/%s",
824
-{
547
+ tim_index(td->tim), timer_index(td->timer),
825
- return (ri->access >> ((current_el * 2) + isread)) & 1;
548
+ name);
826
-}
549
+ qtest_add_data_func(full_name, td, fn);
827
-
550
+}
828
-/* Raw read of a coprocessor register (as needed for migration, etc) */
551
+
829
-uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
552
+/* Convenience macro for adding a test with a predictable function name. */
830
-
553
+#define add_test(name, td) tim_add_test(#name, td, test_##name)
831
/**
554
+
832
* write_list_to_cpustate
555
+int main(int argc, char **argv)
833
* @cpu: ARMCPU
556
+{
834
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
557
+ TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
835
index XXXXXXX..XXXXXXX 100644
558
+ int ret;
836
--- a/hw/arm/pxa2xx.c
559
+ int i, j;
837
+++ b/hw/arm/pxa2xx.c
560
+
838
@@ -XXX,XX +XXX,XX @@
561
+ g_test_init(&argc, &argv, NULL);
839
#include "qemu/cutils.h"
562
+ g_test_set_nonfatal_assertions();
840
#include "qemu/log.h"
563
+
841
#include "qom/object.h"
564
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
842
+#include "target/arm/cpregs.h"
565
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
843
566
+ TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
844
static struct {
567
+ td->tim = &timer_block[i];
845
hwaddr io_base;
568
+ td->timer = &timer[j];
846
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
569
+
847
index XXXXXXX..XXXXXXX 100644
570
+ add_test(reset, td);
848
--- a/hw/arm/pxa2xx_pic.c
571
+ add_test(reset_overrides_enable, td);
849
+++ b/hw/arm/pxa2xx_pic.c
572
+ add_test(oneshot_enable_then_disable, td);
850
@@ -XXX,XX +XXX,XX @@
573
+ add_test(oneshot_ps5, td);
851
#include "hw/sysbus.h"
574
+ add_test(oneshot_ps0, td);
852
#include "migration/vmstate.h"
575
+ add_test(oneshot_ps255, td);
853
#include "qom/object.h"
576
+ add_test(oneshot_interrupt, td);
854
+#include "target/arm/cpregs.h"
577
+ add_test(pause_resume, td);
855
578
+ add_test(prescaler_change, td);
856
#define ICIP    0x00    /* Interrupt Controller IRQ Pending register */
579
+ add_test(periodic_no_interrupt, td);
857
#define ICMR    0x04    /* Interrupt Controller Mask register */
580
+ add_test(periodic_interrupt, td);
858
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
581
+ add_test(disable_on_expiration, td);
859
index XXXXXXX..XXXXXXX 100644
582
+ }
860
--- a/hw/intc/arm_gicv3_cpuif.c
583
+ }
861
+++ b/hw/intc/arm_gicv3_cpuif.c
584
+
862
@@ -XXX,XX +XXX,XX @@
585
+ qtest_start("-machine npcm750-evb");
863
#include "gicv3_internal.h"
586
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
864
#include "hw/irq.h"
587
+ ret = g_test_run();
865
#include "cpu.h"
588
+ qtest_end();
866
+#include "target/arm/cpregs.h"
589
+
867
590
+ return ret;
868
/*
591
+}
869
* Special case return value from hppvi_index(); must be larger than
592
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
870
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
593
index XXXXXXX..XXXXXXX 100644
871
index XXXXXXX..XXXXXXX 100644
594
--- a/tests/qtest/meson.build
872
--- a/hw/intc/arm_gicv3_kvm.c
595
+++ b/tests/qtest/meson.build
873
+++ b/hw/intc/arm_gicv3_kvm.c
596
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
874
@@ -XXX,XX +XXX,XX @@
597
['arm-cpu-features',
875
#include "vgic_common.h"
598
'microbit-test',
876
#include "migration/blocker.h"
599
'm25p80-test',
877
#include "qom/object.h"
600
+ 'npcm7xx_timer-test',
878
+#include "target/arm/cpregs.h"
601
'test-arm-mptimer',
879
+
602
'boot-serial-test',
880
603
'hexloader-test']
881
#ifdef DEBUG_GICV3_KVM
882
#define DPRINTF(fmt, ...) \
883
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
884
index XXXXXXX..XXXXXXX 100644
885
--- a/target/arm/cpu.c
886
+++ b/target/arm/cpu.c
887
@@ -XXX,XX +XXX,XX @@
888
#include "kvm_arm.h"
889
#include "disas/capstone.h"
890
#include "fpu/softfloat.h"
891
+#include "cpregs.h"
892
893
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
894
{
895
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
896
index XXXXXXX..XXXXXXX 100644
897
--- a/target/arm/cpu64.c
898
+++ b/target/arm/cpu64.c
899
@@ -XXX,XX +XXX,XX @@
900
#include "hvf_arm.h"
901
#include "qapi/visitor.h"
902
#include "hw/qdev-properties.h"
903
+#include "cpregs.h"
904
905
906
#ifndef CONFIG_USER_ONLY
907
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
908
index XXXXXXX..XXXXXXX 100644
909
--- a/target/arm/cpu_tcg.c
910
+++ b/target/arm/cpu_tcg.c
911
@@ -XXX,XX +XXX,XX @@
912
#if !defined(CONFIG_USER_ONLY)
913
#include "hw/boards.h"
914
#endif
915
+#include "cpregs.h"
916
917
/* CPU models. These are not needed for the AArch64 linux-user build. */
918
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
919
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
920
index XXXXXXX..XXXXXXX 100644
921
--- a/target/arm/gdbstub.c
922
+++ b/target/arm/gdbstub.c
923
@@ -XXX,XX +XXX,XX @@
924
*/
925
#include "qemu/osdep.h"
926
#include "cpu.h"
927
-#include "internals.h"
928
#include "exec/gdbstub.h"
929
+#include "internals.h"
930
+#include "cpregs.h"
931
932
typedef struct RegisterSysregXmlParam {
933
CPUState *cs;
934
diff --git a/target/arm/helper.c b/target/arm/helper.c
935
index XXXXXXX..XXXXXXX 100644
936
--- a/target/arm/helper.c
937
+++ b/target/arm/helper.c
938
@@ -XXX,XX +XXX,XX @@
939
#include "exec/cpu_ldst.h"
940
#include "semihosting/common-semi.h"
941
#endif
942
+#include "cpregs.h"
943
944
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
945
#define PMCR_NUM_COUNTERS 4 /* QEMU IMPDEF choice */
946
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
947
index XXXXXXX..XXXXXXX 100644
948
--- a/target/arm/op_helper.c
949
+++ b/target/arm/op_helper.c
950
@@ -XXX,XX +XXX,XX @@
951
#include "internals.h"
952
#include "exec/exec-all.h"
953
#include "exec/cpu_ldst.h"
954
+#include "cpregs.h"
955
956
#define SIGNBIT (uint32_t)0x80000000
957
#define SIGNBIT64 ((uint64_t)1 << 63)
958
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
959
index XXXXXXX..XXXXXXX 100644
960
--- a/target/arm/translate-a64.c
961
+++ b/target/arm/translate-a64.c
962
@@ -XXX,XX +XXX,XX @@
963
#include "translate.h"
964
#include "internals.h"
965
#include "qemu/host-utils.h"
966
-
967
#include "semihosting/semihost.h"
968
#include "exec/gen-icount.h"
969
-
970
#include "exec/helper-proto.h"
971
#include "exec/helper-gen.h"
972
#include "exec/log.h"
973
-
974
+#include "cpregs.h"
975
#include "translate-a64.h"
976
#include "qemu/atomic128.h"
977
978
diff --git a/target/arm/translate.c b/target/arm/translate.c
979
index XXXXXXX..XXXXXXX 100644
980
--- a/target/arm/translate.c
981
+++ b/target/arm/translate.c
982
@@ -XXX,XX +XXX,XX @@
983
#include "qemu/bitops.h"
984
#include "arm_ldst.h"
985
#include "semihosting/semihost.h"
986
-
987
#include "exec/helper-proto.h"
988
#include "exec/helper-gen.h"
989
-
990
#include "exec/log.h"
991
+#include "cpregs.h"
992
993
994
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
604
--
995
--
605
2.20.1
996
2.25.1
606
997
607
998
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This is a bit clearer than open-coding some of this
3
Rearrange the values of the enumerators of CPAccessResult
4
with a bare c string.
4
so that we may directly extract the target el. For the two
5
special cases in access_check_cp_reg, use CPAccessResult.
5
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20220501055028.646596-3-richard.henderson@linaro.org
8
Message-id: 20201016184207.786698-9-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
13
target/arm/cpregs.h | 26 ++++++++++++--------
12
1 file changed, 20 insertions(+), 17 deletions(-)
14
target/arm/op_helper.c | 56 +++++++++++++++++++++---------------------
15
2 files changed, 44 insertions(+), 38 deletions(-)
13
16
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
17
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
19
--- a/target/arm/cpregs.h
17
+++ b/linux-user/elfload.c
20
+++ b/target/arm/cpregs.h
18
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static inline bool cptype_valid(int cptype)
19
#include "qemu/guest-random.h"
22
typedef enum CPAccessResult {
20
#include "qemu/units.h"
23
/* Access is permitted */
21
#include "qemu/selfmap.h"
24
CP_ACCESS_OK = 0,
22
+#include "qapi/error.h"
25
+
23
26
+ /*
24
#ifdef _ARCH_PPC64
27
+ * Combined with one of the following, the low 2 bits indicate the
25
#undef ARCH_DLINFO
28
+ * target exception level. If 0, the exception is taken to the usual
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
29
+ * target EL (EL1 or PL1 if in EL0, otherwise to the current EL).
27
struct elf_phdr *phdr;
30
+ */
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
31
+ CP_ACCESS_EL_MASK = 3,
29
int i, retval;
32
+
30
- const char *errmsg;
33
/*
31
+ Error *err = NULL;
34
* Access fails due to a configurable trap or enable which would
32
35
* result in a categorized exception syndrome giving information about
33
/* First of all, some simple consistency checks */
36
* the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
34
- errmsg = "Invalid ELF image for this architecture";
37
- * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
35
if (!elf_check_ident(ehdr)) {
38
- * PL1 if in EL0, otherwise to the current EL).
36
+ error_setg(&err, "Invalid ELF image for this architecture");
39
+ * 0xc or 0x18).
37
goto exit_errmsg;
40
*/
41
- CP_ACCESS_TRAP = 1,
42
+ CP_ACCESS_TRAP = (1 << 2),
43
+ CP_ACCESS_TRAP_EL2 = CP_ACCESS_TRAP | 2,
44
+ CP_ACCESS_TRAP_EL3 = CP_ACCESS_TRAP | 3,
45
+
46
/*
47
* Access fails and results in an exception syndrome 0x0 ("uncategorized").
48
* Note that this is not a catch-all case -- the set of cases which may
49
* result in this failure is specifically defined by the architecture.
50
*/
51
- CP_ACCESS_TRAP_UNCATEGORIZED = 2,
52
- /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
53
- CP_ACCESS_TRAP_EL2 = 3,
54
- CP_ACCESS_TRAP_EL3 = 4,
55
- /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
56
- CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
57
- CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
58
+ CP_ACCESS_TRAP_UNCATEGORIZED = (2 << 2),
59
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = CP_ACCESS_TRAP_UNCATEGORIZED | 2,
60
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = CP_ACCESS_TRAP_UNCATEGORIZED | 3,
61
} CPAccessResult;
62
63
typedef struct ARMCPRegInfo ARMCPRegInfo;
64
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/op_helper.c
67
+++ b/target/arm/op_helper.c
68
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
69
uint32_t isread)
70
{
71
const ARMCPRegInfo *ri = rip;
72
+ CPAccessResult res = CP_ACCESS_OK;
73
int target_el;
74
75
if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
76
&& extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) {
77
- raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env));
78
+ res = CP_ACCESS_TRAP;
79
+ goto fail;
38
}
80
}
39
bswap_ehdr(ehdr);
81
40
if (!elf_check_ehdr(ehdr)) {
82
/*
41
+ error_setg(&err, "Invalid ELF image for this architecture");
83
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
42
goto exit_errmsg;
84
mask &= ~((1 << 4) | (1 << 14));
85
86
if (env->cp15.hstr_el2 & mask) {
87
- target_el = 2;
88
- goto exept;
89
+ res = CP_ACCESS_TRAP_EL2;
90
+ goto fail;
91
}
43
}
92
}
44
93
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
94
- if (!ri->accessfn) {
46
g_autofree char *interp_name = NULL;
95
+ if (ri->accessfn) {
47
96
+ res = ri->accessfn(env, ri, isread);
48
if (*pinterp_name) {
97
+ }
49
- errmsg = "Multiple PT_INTERP entries";
98
+ if (likely(res == CP_ACCESS_OK)) {
50
+ error_setg(&err, "Multiple PT_INTERP entries");
99
return;
51
goto exit_errmsg;
100
}
52
}
101
102
- switch (ri->accessfn(env, ri, isread)) {
103
- case CP_ACCESS_OK:
104
- return;
105
+ fail:
106
+ switch (res & ~CP_ACCESS_EL_MASK) {
107
case CP_ACCESS_TRAP:
108
- target_el = exception_target_el(env);
109
- break;
110
- case CP_ACCESS_TRAP_EL2:
111
- /* Requesting a trap to EL2 when we're in EL3 is
112
- * a bug in the access function.
113
- */
114
- assert(arm_current_el(env) != 3);
115
- target_el = 2;
116
- break;
117
- case CP_ACCESS_TRAP_EL3:
118
- target_el = 3;
119
break;
120
case CP_ACCESS_TRAP_UNCATEGORIZED:
121
- target_el = exception_target_el(env);
122
- syndrome = syn_uncategorized();
123
- break;
124
- case CP_ACCESS_TRAP_UNCATEGORIZED_EL2:
125
- target_el = 2;
126
- syndrome = syn_uncategorized();
127
- break;
128
- case CP_ACCESS_TRAP_UNCATEGORIZED_EL3:
129
- target_el = 3;
130
syndrome = syn_uncategorized();
131
break;
132
default:
133
g_assert_not_reached();
134
}
135
136
-exept:
137
+ target_el = res & CP_ACCESS_EL_MASK;
138
+ switch (target_el) {
139
+ case 0:
140
+ target_el = exception_target_el(env);
141
+ break;
142
+ case 2:
143
+ assert(arm_current_el(env) != 3);
144
+ assert(arm_is_el2_enabled(env));
145
+ break;
146
+ case 3:
147
+ assert(arm_feature(env, ARM_FEATURE_EL3));
148
+ break;
149
+ default:
150
+ /* No "direct" traps to EL1 */
151
+ g_assert_not_reached();
152
+ }
53
+
153
+
54
interp_name = g_malloc(eppnt->p_filesz);
154
raise_exception(env, EXCP_UDEF, syndrome, target_el);
55
- if (!interp_name) {
56
- goto exit_perror;
57
- }
58
59
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
60
memcpy(interp_name, bprm_buf + eppnt->p_offset,
61
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
62
retval = pread(image_fd, interp_name, eppnt->p_filesz,
63
eppnt->p_offset);
64
if (retval != eppnt->p_filesz) {
65
- goto exit_perror;
66
+ goto exit_read;
67
}
68
}
69
if (interp_name[eppnt->p_filesz - 1] != 0) {
70
- errmsg = "Invalid PT_INTERP entry";
71
+ error_setg(&err, "Invalid PT_INTERP entry");
72
goto exit_errmsg;
73
}
74
*pinterp_name = g_steal_pointer(&interp_name);
75
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
76
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
77
-1, 0);
78
if (load_addr == -1) {
79
- goto exit_perror;
80
+ goto exit_mmap;
81
}
82
load_bias = load_addr - loaddr;
83
84
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
85
image_fd, eppnt->p_offset - vaddr_po);
86
87
if (error == -1) {
88
- goto exit_perror;
89
+ goto exit_mmap;
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
94
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
95
Mips_elf_abiflags_v0 abiflags;
96
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
97
- errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
98
+ error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
99
goto exit_errmsg;
100
}
101
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
102
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
103
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
104
eppnt->p_offset);
105
if (retval != sizeof(Mips_elf_abiflags_v0)) {
106
- goto exit_perror;
107
+ goto exit_read;
108
}
109
}
110
bswap_mips_abiflags(&abiflags);
111
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
112
113
exit_read:
114
if (retval >= 0) {
115
- errmsg = "Incomplete read of file header";
116
- goto exit_errmsg;
117
+ error_setg(&err, "Incomplete read of file header");
118
+ } else {
119
+ error_setg_errno(&err, errno, "Error reading file header");
120
}
121
- exit_perror:
122
- errmsg = strerror(errno);
123
+ goto exit_errmsg;
124
+ exit_mmap:
125
+ error_setg_errno(&err, errno, "Error mapping file");
126
+ goto exit_errmsg;
127
exit_errmsg:
128
- fprintf(stderr, "%s: %s\n", image_name, errmsg);
129
+ error_reportf_err(err, "%s: ", image_name);
130
exit(-1);
131
}
155
}
132
156
133
--
157
--
134
2.20.1
158
2.25.1
135
159
136
160
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
When TBI is enabled in a given regime, 56 bits of the address
3
Remove a possible source of error by removing REGINFO_SENTINEL
4
are significant and we need to clear out any other matching
4
and using ARRAY_SIZE (convinently hidden inside a macro) to
5
virtual addresses with differing tags.
5
find the end of the set of regs being registered or modified.
6
6
7
The other uses of tlb_flush_page (without mmuidx) in this file
7
The space saved by not having the extra array element reduces
8
are only used by aarch32 mode.
8
the executable's .data.rel.ro section by about 9k.
9
9
10
Fixes: 38d931687fa1
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reported-by: Jordan Frank <jordanfrank@fb.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20220501055028.646596-4-richard.henderson@linaro.org
15
Message-id: 20201016210754.818257-3-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
15
---
18
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++-------
16
target/arm/cpregs.h | 53 +++++++++---------
19
1 file changed, 39 insertions(+), 7 deletions(-)
17
hw/arm/pxa2xx.c | 1 -
18
hw/arm/pxa2xx_pic.c | 1 -
19
hw/intc/arm_gicv3_cpuif.c | 5 --
20
hw/intc/arm_gicv3_kvm.c | 1 -
21
target/arm/cpu64.c | 1 -
22
target/arm/cpu_tcg.c | 4 --
23
target/arm/helper.c | 111 ++++++++------------------------------
24
8 files changed, 48 insertions(+), 129 deletions(-)
20
25
26
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpregs.h
29
+++ b/target/arm/cpregs.h
30
@@ -XXX,XX +XXX,XX @@
31
#define ARM_CP_NO_GDB 0x4000
32
#define ARM_CP_RAISES_EXC 0x8000
33
#define ARM_CP_NEWEL 0x10000
34
-/* Used only as a terminator for ARMCPRegInfo lists */
35
-#define ARM_CP_SENTINEL 0xfffff
36
/* Mask of only the flag bits in a type field */
37
#define ARM_CP_FLAG_MASK 0x1f0ff
38
39
@@ -XXX,XX +XXX,XX @@ enum {
40
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
41
};
42
43
-/*
44
- * Return true if cptype is a valid type field. This is used to try to
45
- * catch errors where the sentinel has been accidentally left off the end
46
- * of a list of registers.
47
- */
48
-static inline bool cptype_valid(int cptype)
49
-{
50
- return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
51
- || ((cptype & ARM_CP_SPECIAL) &&
52
- ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
53
-}
54
-
55
/*
56
* Access rights:
57
* We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
58
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
59
#define CPREG_FIELD64(env, ri) \
60
(*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
61
62
-#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
63
+void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, const ARMCPRegInfo *reg,
64
+ void *opaque);
65
66
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
67
- const ARMCPRegInfo *regs, void *opaque);
68
-void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
69
- const ARMCPRegInfo *regs, void *opaque);
70
-static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
71
-{
72
- define_arm_cp_regs_with_opaque(cpu, regs, 0);
73
-}
74
static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
75
{
76
- define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
77
+ define_one_arm_cp_reg_with_opaque(cpu, regs, NULL);
78
}
79
+
80
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
81
+ void *opaque, size_t len);
82
+
83
+#define define_arm_cp_regs_with_opaque(CPU, REGS, OPAQUE) \
84
+ do { \
85
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(REGS) == 0); \
86
+ define_arm_cp_regs_with_opaque_len(CPU, REGS, OPAQUE, \
87
+ ARRAY_SIZE(REGS)); \
88
+ } while (0)
89
+
90
+#define define_arm_cp_regs(CPU, REGS) \
91
+ define_arm_cp_regs_with_opaque(CPU, REGS, NULL)
92
+
93
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
94
95
/*
96
@@ -XXX,XX +XXX,XX @@ typedef struct ARMCPRegUserSpaceInfo {
97
uint64_t fixed_bits;
98
} ARMCPRegUserSpaceInfo;
99
100
-#define REGUSERINFO_SENTINEL { .name = NULL }
101
+void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
102
+ const ARMCPRegUserSpaceInfo *mods,
103
+ size_t mods_len);
104
105
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
106
+#define modify_arm_cp_regs(REGS, MODS) \
107
+ do { \
108
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(REGS) == 0); \
109
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(MODS) == 0); \
110
+ modify_arm_cp_regs_with_len(REGS, ARRAY_SIZE(REGS), \
111
+ MODS, ARRAY_SIZE(MODS)); \
112
+ } while (0)
113
114
/* CPWriteFn that can be used to implement writes-ignored behaviour */
115
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
116
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/arm/pxa2xx.c
119
+++ b/hw/arm/pxa2xx.c
120
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pxa_cp_reginfo[] = {
121
{ .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
122
.access = PL1_RW, .type = ARM_CP_IO,
123
.readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
124
- REGINFO_SENTINEL
125
};
126
127
static void pxa2xx_setup_cp14(PXA2xxState *s)
128
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/hw/arm/pxa2xx_pic.c
131
+++ b/hw/arm/pxa2xx_pic.c
132
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
133
REGINFO_FOR_PIC_CP("ICLR2", 8),
134
REGINFO_FOR_PIC_CP("ICFP2", 9),
135
REGINFO_FOR_PIC_CP("ICPR2", 0xa),
136
- REGINFO_SENTINEL
137
};
138
139
static const MemoryRegionOps pxa2xx_pic_ops = {
140
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/hw/intc/arm_gicv3_cpuif.c
143
+++ b/hw/intc/arm_gicv3_cpuif.c
144
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
145
.readfn = icc_igrpen1_el3_read,
146
.writefn = icc_igrpen1_el3_write,
147
},
148
- REGINFO_SENTINEL
149
};
150
151
static uint64_t ich_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
152
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_hcr_reginfo[] = {
153
.readfn = ich_vmcr_read,
154
.writefn = ich_vmcr_write,
155
},
156
- REGINFO_SENTINEL
157
};
158
159
static const ARMCPRegInfo gicv3_cpuif_ich_apxr1_reginfo[] = {
160
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_ich_apxr1_reginfo[] = {
161
.readfn = ich_ap_read,
162
.writefn = ich_ap_write,
163
},
164
- REGINFO_SENTINEL
165
};
166
167
static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
168
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
169
.readfn = ich_ap_read,
170
.writefn = ich_ap_write,
171
},
172
- REGINFO_SENTINEL
173
};
174
175
static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
176
@@ -XXX,XX +XXX,XX @@ void gicv3_init_cpuif(GICv3State *s)
177
.readfn = ich_lr_read,
178
.writefn = ich_lr_write,
179
},
180
- REGINFO_SENTINEL
181
};
182
define_arm_cp_regs(cpu, lr_regset);
183
}
184
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/hw/intc/arm_gicv3_kvm.c
187
+++ b/hw/intc/arm_gicv3_kvm.c
188
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
189
*/
190
.resetfn = arm_gicv3_icc_reset,
191
},
192
- REGINFO_SENTINEL
193
};
194
195
/**
196
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/target/arm/cpu64.c
199
+++ b/target/arm/cpu64.c
200
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
201
{ .name = "L2MERRSR",
202
.cp = 15, .opc1 = 3, .crm = 15,
203
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
204
- REGINFO_SENTINEL
205
};
206
207
static void aarch64_a57_initfn(Object *obj)
208
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/target/arm/cpu_tcg.c
211
+++ b/target/arm/cpu_tcg.c
212
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
213
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
214
{ .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
215
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
216
- REGINFO_SENTINEL
217
};
218
219
static void cortex_a8_initfn(Object *obj)
220
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
221
.access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
222
{ .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
223
.access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
224
- REGINFO_SENTINEL
225
};
226
227
static void cortex_a9_initfn(Object *obj)
228
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
229
#endif
230
{ .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
231
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
232
- REGINFO_SENTINEL
233
};
234
235
static void cortex_a7_initfn(Object *obj)
236
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
237
.access = PL1_RW, .type = ARM_CP_CONST },
238
{ .name = "DCACHE_INVAL", .cp = 15, .opc1 = 0, .crn = 15, .crm = 5,
239
.opc2 = 0, .access = PL1_W, .type = ARM_CP_NOP },
240
- REGINFO_SENTINEL
241
};
242
243
static void cortex_r5_initfn(Object *obj)
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
244
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
245
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
246
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
247
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
248
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cp_reginfo[] = {
26
#endif
249
.secure = ARM_CP_SECSTATE_S,
27
250
.fieldoffset = offsetof(CPUARMState, cp15.contextidr_s),
28
static void switch_mode(CPUARMState *env, int mode);
251
.resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
29
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
252
- REGINFO_SENTINEL
30
253
};
31
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
254
32
{
255
static const ARMCPRegInfo not_v8_cp_reginfo[] = {
33
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
256
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v8_cp_reginfo[] = {
257
{ .name = "CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
258
.opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
259
.type = ARM_CP_NOP | ARM_CP_OVERRIDE },
260
- REGINFO_SENTINEL
261
};
262
263
static const ARMCPRegInfo not_v6_cp_reginfo[] = {
264
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v6_cp_reginfo[] = {
265
*/
266
{ .name = "WFI_v5", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = 2,
267
.access = PL1_W, .type = ARM_CP_WFI },
268
- REGINFO_SENTINEL
269
};
270
271
static const ARMCPRegInfo not_v7_cp_reginfo[] = {
272
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v7_cp_reginfo[] = {
273
.opc1 = 0, .opc2 = 0, .access = PL1_RW, .type = ARM_CP_NOP },
274
{ .name = "NMRR", .cp = 15, .crn = 10, .crm = 2,
275
.opc1 = 0, .opc2 = 1, .access = PL1_RW, .type = ARM_CP_NOP },
276
- REGINFO_SENTINEL
277
};
278
279
static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
280
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
281
.crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, .accessfn = cpacr_access,
282
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.cpacr_el1),
283
.resetfn = cpacr_reset, .writefn = cpacr_write, .readfn = cpacr_read },
284
- REGINFO_SENTINEL
285
};
286
287
typedef struct pm_event {
288
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
289
{ .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
290
.type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
291
.writefn = tlbimvaa_write },
292
- REGINFO_SENTINEL
293
};
294
295
static const ARMCPRegInfo v7mp_cp_reginfo[] = {
296
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7mp_cp_reginfo[] = {
297
{ .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
298
.type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
299
.writefn = tlbimvaa_is_write },
300
- REGINFO_SENTINEL
301
};
302
303
static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
304
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
305
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
306
.writefn = pmovsset_write,
307
.raw_writefn = raw_write },
308
- REGINFO_SENTINEL
309
};
310
311
static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri,
312
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo t2ee_cp_reginfo[] = {
313
{ .name = "TEEHBR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
314
.access = PL0_RW, .fieldoffset = offsetof(CPUARMState, teehbr),
315
.accessfn = teehbr_access, .resetvalue = 0 },
316
- REGINFO_SENTINEL
317
};
318
319
static const ARMCPRegInfo v6k_cp_reginfo[] = {
320
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
321
.bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrprw_s),
322
offsetoflow32(CPUARMState, cp15.tpidrprw_ns) },
323
.resetvalue = 0 },
324
- REGINFO_SENTINEL
325
};
326
327
#ifndef CONFIG_USER_ONLY
328
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
329
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cval),
330
.writefn = gt_sec_cval_write, .raw_writefn = raw_write,
331
},
332
- REGINFO_SENTINEL
333
};
334
335
static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
336
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
337
.access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
338
.readfn = gt_virt_cnt_read,
339
},
340
- REGINFO_SENTINEL
341
};
342
343
#endif
344
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vapa_cp_reginfo[] = {
345
.access = PL1_W, .accessfn = ats_access,
346
.writefn = ats_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
347
#endif
348
- REGINFO_SENTINEL
349
};
350
351
/* Return basic MPU access permission bits. */
352
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
353
.fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]),
354
.writefn = pmsav7_rgnr_write,
355
.resetfn = arm_cp_reset_ignore },
356
- REGINFO_SENTINEL
357
};
358
359
static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
360
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
361
{ .name = "946_PRBS7", .cp = 15, .crn = 6, .crm = 7, .opc1 = 0,
362
.opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
363
.fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) },
364
- REGINFO_SENTINEL
365
};
366
367
static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
368
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
369
.access = PL1_RW, .accessfn = access_tvm_trvm,
370
.fieldoffset = offsetof(CPUARMState, cp15.far_el[1]),
371
.resetvalue = 0, },
372
- REGINFO_SENTINEL
373
};
374
375
static const ARMCPRegInfo vmsa_cp_reginfo[] = {
376
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
377
/* No offsetoflow32 -- pass the entire TCR to writefn/raw_writefn. */
378
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.tcr_el[3]),
379
offsetof(CPUARMState, cp15.tcr_el[1])} },
380
- REGINFO_SENTINEL
381
};
382
383
/* Note that unlike TTBCR, writing to TTBCR2 does not require flushing
384
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo omap_cp_reginfo[] = {
385
{ .name = "C9", .cp = 15, .crn = 9,
386
.crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW,
387
.type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 },
388
- REGINFO_SENTINEL
389
};
390
391
static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri,
392
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo xscale_cp_reginfo[] = {
393
{ .name = "XSCALE_UNLOCK_DCACHE",
394
.cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 1,
395
.access = PL1_W, .type = ARM_CP_NOP },
396
- REGINFO_SENTINEL
397
};
398
399
static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
400
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
401
.access = PL1_RW,
402
.type = ARM_CP_CONST | ARM_CP_NO_RAW | ARM_CP_OVERRIDE,
403
.resetvalue = 0 },
404
- REGINFO_SENTINEL
405
};
406
407
static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
408
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
409
{ .name = "CDSR", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 6,
410
.access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
411
.resetvalue = 0 },
412
- REGINFO_SENTINEL
413
};
414
415
static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
416
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
417
.access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
418
{ .name = "CIDCR", .cp = 15, .crm = 14, .opc1 = 0,
419
.access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
420
- REGINFO_SENTINEL
421
};
422
423
static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
424
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
425
{ .name = "TCI_DCACHE", .cp = 15, .crn = 7, .crm = 14, .opc1 = 0, .opc2 = 3,
426
.access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
427
.resetvalue = (1 << 30) },
428
- REGINFO_SENTINEL
429
};
430
431
static const ARMCPRegInfo strongarm_cp_reginfo[] = {
432
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo strongarm_cp_reginfo[] = {
433
.crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
434
.access = PL1_RW, .resetvalue = 0,
435
.type = ARM_CP_CONST | ARM_CP_OVERRIDE | ARM_CP_NO_RAW },
436
- REGINFO_SENTINEL
437
};
438
439
static uint64_t midr_read(CPUARMState *env, const ARMCPRegInfo *ri)
440
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
441
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
442
offsetof(CPUARMState, cp15.ttbr1_ns) },
443
.writefn = vmsa_ttbr_write, },
444
- REGINFO_SENTINEL
445
};
446
447
static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
448
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
449
.access = PL1_RW, .accessfn = access_trap_aa32s_el1,
450
.writefn = sdcr_write,
451
.fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
452
- REGINFO_SENTINEL
453
};
454
455
/* Used to describe the behaviour of EL2 regs when EL2 does not exist. */
456
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
457
.type = ARM_CP_CONST,
458
.cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
459
.access = PL2_RW, .resetvalue = 0 },
460
- REGINFO_SENTINEL
461
};
462
463
/* Ditto, but for registers which exist in ARMv8 but not v7 */
464
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
465
.cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
466
.access = PL2_RW,
467
.type = ARM_CP_CONST, .resetvalue = 0 },
468
- REGINFO_SENTINEL
469
};
470
471
static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
472
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
473
.cp = 15, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
474
.access = PL2_RW,
475
.fieldoffset = offsetof(CPUARMState, cp15.hstr_el2) },
476
- REGINFO_SENTINEL
477
};
478
479
static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
480
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
481
.access = PL2_RW,
482
.fieldoffset = offsetofhigh32(CPUARMState, cp15.hcr_el2),
483
.writefn = hcr_writehigh },
484
- REGINFO_SENTINEL
485
};
486
487
static CPAccessResult sel2_access(CPUARMState *env, const ARMCPRegInfo *ri,
488
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_sec_cp_reginfo[] = {
489
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 6, .opc2 = 2,
490
.access = PL2_RW, .accessfn = sel2_access,
491
.fieldoffset = offsetof(CPUARMState, cp15.vstcr_el2) },
492
- REGINFO_SENTINEL
493
};
494
495
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
496
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
497
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 5,
498
.access = PL3_W, .type = ARM_CP_NO_RAW,
499
.writefn = tlbi_aa64_vae3_write },
500
- REGINFO_SENTINEL
501
};
502
503
#ifndef CONFIG_USER_ONLY
504
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
505
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
506
.access = PL1_RW, .accessfn = access_tda,
507
.type = ARM_CP_NOP },
508
- REGINFO_SENTINEL
509
};
510
511
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
512
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
513
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
514
{ .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0,
515
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
516
- REGINFO_SENTINEL
517
};
518
519
/* Return the exception level to which exceptions should be taken
520
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
521
.fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]),
522
.writefn = dbgbcr_write, .raw_writefn = raw_write
523
},
524
- REGINFO_SENTINEL
525
};
526
define_arm_cp_regs(cpu, dbgregs);
527
}
528
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
529
.fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]),
530
.writefn = dbgwcr_write, .raw_writefn = raw_write
531
},
532
- REGINFO_SENTINEL
533
};
534
define_arm_cp_regs(cpu, dbgregs);
535
}
536
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
537
.type = ARM_CP_IO,
538
.readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
539
.raw_writefn = pmevtyper_rawwrite },
540
- REGINFO_SENTINEL
541
};
542
define_arm_cp_regs(cpu, pmev_regs);
543
g_free(pmevcntr_name);
544
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
545
.cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 5,
546
.access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
547
.resetvalue = extract64(cpu->pmceid1, 32, 32) },
548
- REGINFO_SENTINEL
549
};
550
define_arm_cp_regs(cpu, v81_pmu_regs);
551
}
552
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo lor_reginfo[] = {
553
.opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
554
.access = PL1_R, .accessfn = access_lor_ns,
555
.type = ARM_CP_CONST, .resetvalue = 0 },
556
- REGINFO_SENTINEL
557
};
558
559
#ifdef TARGET_AARCH64
560
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pauth_reginfo[] = {
561
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 1, .opc2 = 3,
562
.access = PL1_RW, .accessfn = access_pauth,
563
.fieldoffset = offsetof(CPUARMState, keys.apib.hi) },
564
- REGINFO_SENTINEL
565
};
566
567
static const ARMCPRegInfo tlbirange_reginfo[] = {
568
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
569
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 5,
570
.access = PL3_W, .type = ARM_CP_NO_RAW,
571
.writefn = tlbi_aa64_rvae3_write },
572
- REGINFO_SENTINEL
573
};
574
575
static const ARMCPRegInfo tlbios_reginfo[] = {
576
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = {
577
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5,
578
.access = PL3_W, .type = ARM_CP_NO_RAW,
579
.writefn = tlbi_aa64_vae3is_write },
580
- REGINFO_SENTINEL
581
};
582
583
static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
584
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo rndr_reginfo[] = {
585
.type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO,
586
.opc0 = 3, .opc1 = 3, .crn = 2, .crm = 4, .opc2 = 1,
587
.access = PL0_R, .readfn = rndr_readfn },
588
- REGINFO_SENTINEL
589
};
590
591
#ifndef CONFIG_USER_ONLY
592
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dcpop_reg[] = {
593
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 1,
594
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
595
.accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
596
- REGINFO_SENTINEL
597
};
598
599
static const ARMCPRegInfo dcpodp_reg[] = {
600
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dcpodp_reg[] = {
601
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 1,
602
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
603
.accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
604
- REGINFO_SENTINEL
605
};
606
#endif /*CONFIG_USER_ONLY*/
607
608
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_reginfo[] = {
609
{ .name = "DC_CIGDSW", .state = ARM_CP_STATE_AA64,
610
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 6,
611
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
612
- REGINFO_SENTINEL
613
};
614
615
static const ARMCPRegInfo mte_tco_ro_reginfo[] = {
616
{ .name = "TCO", .state = ARM_CP_STATE_AA64,
617
.opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
618
.type = ARM_CP_CONST, .access = PL0_RW, },
619
- REGINFO_SENTINEL
620
};
621
622
static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
623
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
624
.accessfn = aa64_zva_access,
625
#endif
626
},
627
- REGINFO_SENTINEL
628
};
629
630
#endif
631
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo predinv_reginfo[] = {
632
{ .name = "CPPRCTX", .state = ARM_CP_STATE_AA32,
633
.cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 7,
634
.type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
635
- REGINFO_SENTINEL
636
};
637
638
static uint64_t ccsidr2_read(CPUARMState *env, const ARMCPRegInfo *ri)
639
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ccsidr2_reginfo[] = {
640
.access = PL1_R,
641
.accessfn = access_aa64_tid2,
642
.readfn = ccsidr2_read, .type = ARM_CP_NO_RAW },
643
- REGINFO_SENTINEL
644
};
645
646
static CPAccessResult access_aa64_tid3(CPUARMState *env, const ARMCPRegInfo *ri,
647
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo jazelle_regs[] = {
648
.cp = 14, .crn = 2, .crm = 0, .opc1 = 7, .opc2 = 0,
649
.accessfn = access_joscr_jmcr,
650
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
651
- REGINFO_SENTINEL
652
};
653
654
static const ARMCPRegInfo vhe_reginfo[] = {
655
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
656
.access = PL2_RW, .accessfn = e2h_access,
657
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
658
#endif
659
- REGINFO_SENTINEL
660
};
661
662
#ifndef CONFIG_USER_ONLY
663
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1e1_reginfo[] = {
664
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
665
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
666
.writefn = ats_write64 },
667
- REGINFO_SENTINEL
668
};
669
670
static const ARMCPRegInfo ats1cp_reginfo[] = {
671
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1cp_reginfo[] = {
672
.cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
673
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
674
.writefn = ats_write },
675
- REGINFO_SENTINEL
676
};
677
#endif
678
679
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
680
.cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
681
.access = PL2_RW, .type = ARM_CP_CONST,
682
.resetvalue = 0 },
683
- REGINFO_SENTINEL
684
};
685
686
void register_cp_regs_for_features(ARMCPU *cpu)
687
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
688
.access = PL1_R, .type = ARM_CP_CONST,
689
.accessfn = access_aa32_tid3,
690
.resetvalue = cpu->isar.id_isar6 },
691
- REGINFO_SENTINEL
692
};
693
define_arm_cp_regs(cpu, v6_idregs);
694
define_arm_cp_regs(cpu, v6_cp_reginfo);
695
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
696
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 7,
697
.access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
698
.resetvalue = cpu->pmceid1 },
699
- REGINFO_SENTINEL
700
};
701
#ifdef CONFIG_USER_ONLY
702
ARMCPRegUserSpaceInfo v8_user_idregs[] = {
703
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
704
.exported_bits = 0x000000f0ffffffff },
705
{ .name = "ID_AA64ISAR*_EL1_RESERVED",
706
.is_glob = true },
707
- REGUSERINFO_SENTINEL
708
};
709
modify_arm_cp_regs(v8_idregs, v8_user_idregs);
710
#endif
711
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
712
.access = PL2_RW,
713
.resetvalue = vmpidr_def,
714
.fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) },
715
- REGINFO_SENTINEL
716
};
717
define_arm_cp_regs(cpu, vpidr_regs);
718
define_arm_cp_regs(cpu, el2_cp_reginfo);
719
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
720
.access = PL2_RW, .accessfn = access_el3_aa32ns,
721
.type = ARM_CP_NO_RAW,
722
.writefn = arm_cp_write_ignore, .readfn = mpidr_read },
723
- REGINFO_SENTINEL
724
};
725
define_arm_cp_regs(cpu, vpidr_regs);
726
define_arm_cp_regs(cpu, el3_no_el2_cp_reginfo);
727
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
728
.raw_writefn = raw_write, .writefn = sctlr_write,
729
.fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[3]),
730
.resetvalue = cpu->reset_sctlr },
731
- REGINFO_SENTINEL
732
};
733
734
define_arm_cp_regs(cpu, el3_regs);
735
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
736
{ .name = "DUMMY",
737
.cp = 15, .crn = 0, .crm = 7, .opc1 = 0, .opc2 = CP_ANY,
738
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
739
- REGINFO_SENTINEL
740
};
741
ARMCPRegInfo id_v8_midr_cp_reginfo[] = {
742
{ .name = "MIDR_EL1", .state = ARM_CP_STATE_BOTH,
743
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
744
.access = PL1_R,
745
.accessfn = access_aa64_tid1,
746
.type = ARM_CP_CONST, .resetvalue = cpu->revidr },
747
- REGINFO_SENTINEL
748
};
749
ARMCPRegInfo id_cp_reginfo[] = {
750
/* These are common to v8 and pre-v8 */
751
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
752
.access = PL1_R,
753
.accessfn = access_aa32_tid1,
754
.type = ARM_CP_CONST, .resetvalue = 0 },
755
- REGINFO_SENTINEL
756
};
757
/* TLBTR is specific to VMSA */
758
ARMCPRegInfo id_tlbtr_reginfo = {
759
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
760
{ .name = "MIDR_EL1",
761
.exported_bits = 0x00000000ffffffff },
762
{ .name = "REVIDR_EL1" },
763
- REGUSERINFO_SENTINEL
764
};
765
modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_reginfo);
766
#endif
767
if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
768
arm_feature(env, ARM_FEATURE_STRONGARM)) {
769
- ARMCPRegInfo *r;
770
+ size_t i;
771
/* Register the blanket "writes ignored" value first to cover the
772
* whole space. Then update the specific ID registers to allow write
773
* access, so that they ignore writes rather than causing them to
774
* UNDEF.
775
*/
776
define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
777
- for (r = id_pre_v8_midr_cp_reginfo;
778
- r->type != ARM_CP_SENTINEL; r++) {
779
- r->access = PL1_RW;
780
+ for (i = 0; i < ARRAY_SIZE(id_pre_v8_midr_cp_reginfo); ++i) {
781
+ id_pre_v8_midr_cp_reginfo[i].access = PL1_RW;
782
}
783
- for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
784
- r->access = PL1_RW;
785
+ for (i = 0; i < ARRAY_SIZE(id_cp_reginfo); ++i) {
786
+ id_cp_reginfo[i].access = PL1_RW;
787
}
788
id_mpuir_reginfo.access = PL1_RW;
789
id_tlbtr_reginfo.access = PL1_RW;
790
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
791
{ .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,
792
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
793
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
794
- REGINFO_SENTINEL
795
};
796
#ifdef CONFIG_USER_ONLY
797
ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
798
{ .name = "MPIDR_EL1",
799
.fixed_bits = 0x0000000080000000 },
800
- REGUSERINFO_SENTINEL
801
};
802
modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo);
803
#endif
804
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
805
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 1,
806
.access = PL3_RW, .type = ARM_CP_CONST,
807
.resetvalue = 0 },
808
- REGINFO_SENTINEL
809
};
810
define_arm_cp_regs(cpu, auxcr_reginfo);
811
if (cpu_isar_feature(aa32_ac2, cpu)) {
812
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
813
.type = ARM_CP_CONST,
814
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 0,
815
.access = PL1_R, .resetvalue = cpu->reset_cbar },
816
- REGINFO_SENTINEL
817
};
818
/* We don't implement a r/w 64 bit CBAR currently */
819
assert(arm_feature(env, ARM_FEATURE_CBAR_RO));
820
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
821
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s),
822
offsetof(CPUARMState, cp15.vbar_ns) },
823
.resetvalue = 0 },
824
- REGINFO_SENTINEL
825
};
826
define_arm_cp_regs(cpu, vbar_cp_reginfo);
827
}
828
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
829
r->writefn);
830
}
831
}
832
- /* Bad type field probably means missing sentinel at end of reg list */
833
- assert(cptype_valid(r->type));
834
+
835
for (crm = crmmin; crm <= crmmax; crm++) {
836
for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
837
for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
838
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
34
}
839
}
35
}
840
}
36
841
37
+/* Return 56 if TBI is enabled, 64 otherwise. */
842
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
38
+static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
843
- const ARMCPRegInfo *regs, void *opaque)
39
+ uint64_t addr)
844
+/* Define a whole list of registers */
40
+{
845
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
41
+ uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
846
+ void *opaque, size_t len)
42
+ int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
43
+ int select = extract64(addr, 55, 1);
44
+
45
+ return (tbi >> select) & 1 ? 56 : 64;
46
+}
47
+
48
+static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
49
+{
50
+ ARMMMUIdx mmu_idx;
51
+
52
+ /* Only the regime of the mmu_idx below is significant. */
53
+ if (arm_is_secure_below_el3(env)) {
54
+ mmu_idx = ARMMMUIdx_SE10_0;
55
+ } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
56
+ == (HCR_E2H | HCR_TGE)) {
57
+ mmu_idx = ARMMMUIdx_E20_0;
58
+ } else {
59
+ mmu_idx = ARMMMUIdx_E10_0;
60
+ }
61
+ return tlbbits_for_regime(env, mmu_idx, addr);
62
+}
63
+
64
static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
65
uint64_t value)
66
{
847
{
67
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
848
- /* Define a whole list of registers */
68
CPUState *cs = env_cpu(env);
849
- const ARMCPRegInfo *r;
69
int mask = vae1_tlbmask(env);
850
- for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
70
uint64_t pageaddr = sextract64(value << 12, 0, 56);
851
- define_one_arm_cp_reg_with_opaque(cpu, r, opaque);
71
+ int bits = vae1_tlbbits(env, pageaddr);
852
+ size_t i;
72
853
+ for (i = 0; i < len; ++i) {
73
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
854
+ define_one_arm_cp_reg_with_opaque(cpu, regs + i, opaque);
74
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
75
}
76
77
static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
78
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
79
CPUState *cs = env_cpu(env);
80
int mask = vae1_tlbmask(env);
81
uint64_t pageaddr = sextract64(value << 12, 0, 56);
82
+ int bits = vae1_tlbbits(env, pageaddr);
83
84
if (tlb_force_broadcast(env)) {
85
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
86
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
87
} else {
88
- tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
89
+ tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
90
}
855
}
91
}
856
}
92
857
93
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
858
@@ -XXX,XX +XXX,XX @@ void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
859
* user-space cannot alter any values and dynamic values pertaining to
860
* execution state are hidden from user space view anyway.
861
*/
862
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods)
863
+void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
864
+ const ARMCPRegUserSpaceInfo *mods,
865
+ size_t mods_len)
94
{
866
{
95
CPUState *cs = env_cpu(env);
867
- const ARMCPRegUserSpaceInfo *m;
96
uint64_t pageaddr = sextract64(value << 12, 0, 56);
868
- ARMCPRegInfo *r;
97
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
869
-
98
870
- for (m = mods; m->name; m++) {
99
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
871
+ for (size_t mi = 0; mi < mods_len; ++mi) {
100
- ARMMMUIdxBit_E2);
872
+ const ARMCPRegUserSpaceInfo *m = mods + mi;
101
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
873
GPatternSpec *pat = NULL;
102
+ ARMMMUIdxBit_E2, bits);
874
+
103
}
875
if (m->is_glob) {
104
876
pat = g_pattern_spec_new(m->name);
105
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
877
}
106
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
878
- for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
107
{
879
+ for (size_t ri = 0; ri < regs_len; ++ri) {
108
CPUState *cs = env_cpu(env);
880
+ ARMCPRegInfo *r = regs + ri;
109
uint64_t pageaddr = sextract64(value << 12, 0, 56);
881
+
110
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr);
882
if (pat && g_pattern_match_string(pat, r->name)) {
111
883
r->type = ARM_CP_CONST;
112
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
884
r->access = PL0U_R;
113
- ARMMMUIdxBit_SE3);
114
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
115
+ ARMMMUIdxBit_SE3, bits);
116
}
117
118
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
119
--
885
--
120
2.20.1
886
2.25.1
121
887
122
888
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 reporting in AArch64.TagCheckFail only depends on PSTATE.EL,
3
These particular data structures are not modified at runtime.
4
and not the AccType of the operation. There are two guest
5
visible problems that affect LDTR and STTR because of this:
6
4
7
(1) Selecting TCF0 vs TCF1 to decide on reporting,
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
(2) Report "data abort same el" not "data abort lower el".
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
10
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
8
Message-id: 20220501055028.646596-5-richard.henderson@linaro.org
13
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Message-id: 20201008162155.161886-3-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
target/arm/mte_helper.c | 10 +++-------
11
target/arm/helper.c | 16 ++++++++--------
18
1 file changed, 3 insertions(+), 7 deletions(-)
12
1 file changed, 8 insertions(+), 8 deletions(-)
19
13
20
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/mte_helper.c
16
--- a/target/arm/helper.c
23
+++ b/target/arm/mte_helper.c
17
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
18
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
25
reg_el = regime_el(env, arm_mmu_idx);
19
.resetvalue = cpu->pmceid1 },
26
sctlr = env->cp15.sctlr_el[reg_el];
20
};
27
21
#ifdef CONFIG_USER_ONLY
28
- switch (arm_mmu_idx) {
22
- ARMCPRegUserSpaceInfo v8_user_idregs[] = {
29
- case ARMMMUIdx_E10_0:
23
+ static const ARMCPRegUserSpaceInfo v8_user_idregs[] = {
30
- case ARMMMUIdx_E20_0:
24
{ .name = "ID_AA64PFR0_EL1",
31
- el = 0;
25
.exported_bits = 0x000f000f00ff0000,
32
+ el = arm_current_el(env);
26
.fixed_bits = 0x0000000000000011 },
33
+ if (el == 0) {
27
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
34
tcf = extract64(sctlr, 38, 2);
28
*/
35
- break;
29
if (arm_feature(env, ARM_FEATURE_EL3)) {
36
- default:
30
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
37
- el = reg_el;
31
- ARMCPRegInfo nsacr = {
38
+ } else {
32
+ static const ARMCPRegInfo nsacr = {
39
tcf = extract64(sctlr, 40, 2);
33
.name = "NSACR", .type = ARM_CP_CONST,
34
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
35
.access = PL1_RW, .accessfn = nsacr_access,
36
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
37
};
38
define_one_arm_cp_reg(cpu, &nsacr);
39
} else {
40
- ARMCPRegInfo nsacr = {
41
+ static const ARMCPRegInfo nsacr = {
42
.name = "NSACR",
43
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
44
.access = PL3_RW | PL1_R,
45
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
46
}
47
} else {
48
if (arm_feature(env, ARM_FEATURE_V8)) {
49
- ARMCPRegInfo nsacr = {
50
+ static const ARMCPRegInfo nsacr = {
51
.name = "NSACR", .type = ARM_CP_CONST,
52
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
53
.access = PL1_R,
54
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
55
.access = PL1_R, .type = ARM_CP_CONST,
56
.resetvalue = cpu->pmsav7_dregion << 8
57
};
58
- ARMCPRegInfo crn0_wi_reginfo = {
59
+ static const ARMCPRegInfo crn0_wi_reginfo = {
60
.name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
61
.opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
62
.type = ARM_CP_NOP | ARM_CP_OVERRIDE
63
};
64
#ifdef CONFIG_USER_ONLY
65
- ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
66
+ static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
67
{ .name = "MIDR_EL1",
68
.exported_bits = 0x00000000ffffffff },
69
{ .name = "REVIDR_EL1" },
70
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
71
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
72
};
73
#ifdef CONFIG_USER_ONLY
74
- ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
75
+ static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
76
{ .name = "MPIDR_EL1",
77
.fixed_bits = 0x0000000080000000 },
78
};
79
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
40
}
80
}
41
81
82
if (arm_feature(env, ARM_FEATURE_VBAR)) {
83
- ARMCPRegInfo vbar_cp_reginfo[] = {
84
+ static const ARMCPRegInfo vbar_cp_reginfo[] = {
85
{ .name = "VBAR", .state = ARM_CP_STATE_BOTH,
86
.opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
87
.access = PL1_RW, .writefn = vbar_write,
42
--
88
--
43
2.20.1
89
2.25.1
44
90
45
91
diff view generated by jsdifflib
1
If the M-profile low-overhead-branch extension is implemented, FPSCR
1
From: Richard Henderson <richard.henderson@linaro.org>
2
bits [18:16] are a new field LTPSIZE. If MVE is not implemented
2
3
(currently always true for us) then this field always reads as 4 and
3
Instead of defining ARM_CP_FLAG_MASK to remove flags,
4
ignores writes.
4
define ARM_CP_SPECIAL_MASK to isolate special cases.
5
5
Sort the specials to the low bits. Use an enum.
6
These bits used to be the vector-length field for the old
6
7
short-vector extension, so we need to take care that they are not
7
Split the large comment block so as to document each
8
misinterpreted as setting vec_len. We do this with a rearrangement
8
value separately.
9
of the vfp_set_fpscr() code that deals with vec_len, vec_stride
9
10
and also the QC bit; this obviates the need for the M-profile
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
only masking step that we used to have at the start of the function.
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
12
Message-id: 20220501055028.646596-6-richard.henderson@linaro.org
13
We provide a new field in CPUState for LTPSIZE, even though this
14
will always be 4, in preparation for MVE, so we don't have to
15
come back later and split it out of the vfp.xregs[FPSCR] value.
16
(This state struct field will be saved and restored as part of
17
the FPSCR value via the vmstate_fpscr in machine.c.)
18
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20201019151301.2046-11-peter.maydell@linaro.org
22
---
14
---
23
target/arm/cpu.h | 1 +
15
target/arm/cpregs.h | 130 +++++++++++++++++++++++--------------
24
target/arm/cpu.c | 9 +++++++++
16
target/arm/cpu.c | 4 +-
25
target/arm/vfp_helper.c | 6 ++++++
17
target/arm/helper.c | 4 +-
26
3 files changed, 16 insertions(+)
18
target/arm/translate-a64.c | 6 +-
27
19
target/arm/translate.c | 6 +-
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
5 files changed, 92 insertions(+), 58 deletions(-)
29
index XXXXXXX..XXXXXXX 100644
21
30
--- a/target/arm/cpu.h
22
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
31
+++ b/target/arm/cpu.h
23
index XXXXXXX..XXXXXXX 100644
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
24
--- a/target/arm/cpregs.h
33
uint32_t fpdscr[M_REG_NUM_BANKS];
25
+++ b/target/arm/cpregs.h
34
uint32_t cpacr[M_REG_NUM_BANKS];
26
@@ -XXX,XX +XXX,XX @@
35
uint32_t nsacr;
27
#define TARGET_ARM_CPREGS_H
36
+ int ltpsize;
28
37
} v7m;
29
/*
38
30
- * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
39
/* Information associated with an exception about to be taken:
31
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
32
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
33
- * TCG can assume the value to be constant (ie load at translate time)
34
- * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
35
- * indicates that the TB should not be ended after a write to this register
36
- * (the default is that the TB ends after cp writes). OVERRIDE permits
37
- * a register definition to override a previous definition for the
38
- * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
39
- * old must have the OVERRIDE bit set.
40
- * ALIAS indicates that this register is an alias view of some underlying
41
- * state which is also visible via another register, and that the other
42
- * register is handling migration and reset; registers marked ALIAS will not be
43
- * migrated but may have their state set by syncing of register state from KVM.
44
- * NO_RAW indicates that this register has no underlying state and does not
45
- * support raw access for state saving/loading; it will not be used for either
46
- * migration or KVM state synchronization. (Typically this is for "registers"
47
- * which are actually used as instructions for cache maintenance and so on.)
48
- * IO indicates that this register does I/O and therefore its accesses
49
- * need to be marked with gen_io_start() and also end the TB. In particular,
50
- * registers which implement clocks or timers require this.
51
- * RAISES_EXC is for when the read or write hook might raise an exception;
52
- * the generated code will synchronize the CPU state before calling the hook
53
- * so that it is safe for the hook to call raise_exception().
54
- * NEWEL is for writes to registers that might change the exception
55
- * level - typically on older ARM chips. For those cases we need to
56
- * re-read the new el when recomputing the translation flags.
57
+ * ARMCPRegInfo type field bits:
58
*/
59
-#define ARM_CP_SPECIAL 0x0001
60
-#define ARM_CP_CONST 0x0002
61
-#define ARM_CP_64BIT 0x0004
62
-#define ARM_CP_SUPPRESS_TB_END 0x0008
63
-#define ARM_CP_OVERRIDE 0x0010
64
-#define ARM_CP_ALIAS 0x0020
65
-#define ARM_CP_IO 0x0040
66
-#define ARM_CP_NO_RAW 0x0080
67
-#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
68
-#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
69
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
70
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
71
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
72
-#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
73
-#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
74
-#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
75
-#define ARM_CP_FPU 0x1000
76
-#define ARM_CP_SVE 0x2000
77
-#define ARM_CP_NO_GDB 0x4000
78
-#define ARM_CP_RAISES_EXC 0x8000
79
-#define ARM_CP_NEWEL 0x10000
80
-/* Mask of only the flag bits in a type field */
81
-#define ARM_CP_FLAG_MASK 0x1f0ff
82
+enum {
83
+ /*
84
+ * Register must be handled specially during translation.
85
+ * The method is one of the values below:
86
+ */
87
+ ARM_CP_SPECIAL_MASK = 0x000f,
88
+ /* Special: no change to PE state: writes ignored, reads ignored. */
89
+ ARM_CP_NOP = 0x0001,
90
+ /* Special: sysreg is WFI, for v5 and v6. */
91
+ ARM_CP_WFI = 0x0002,
92
+ /* Special: sysreg is NZCV. */
93
+ ARM_CP_NZCV = 0x0003,
94
+ /* Special: sysreg is CURRENTEL. */
95
+ ARM_CP_CURRENTEL = 0x0004,
96
+ /* Special: sysreg is DC ZVA or similar. */
97
+ ARM_CP_DC_ZVA = 0x0005,
98
+ ARM_CP_DC_GVA = 0x0006,
99
+ ARM_CP_DC_GZVA = 0x0007,
100
+
101
+ /* Flag: reads produce resetvalue; writes ignored. */
102
+ ARM_CP_CONST = 1 << 4,
103
+ /* Flag: For ARM_CP_STATE_AA32, sysreg is 64-bit. */
104
+ ARM_CP_64BIT = 1 << 5,
105
+ /*
106
+ * Flag: TB should not be ended after a write to this register
107
+ * (the default is that the TB ends after cp writes).
108
+ */
109
+ ARM_CP_SUPPRESS_TB_END = 1 << 6,
110
+ /*
111
+ * Flag: Permit a register definition to override a previous definition
112
+ * for the same (cp, is64, crn, crm, opc1, opc2) tuple: either the new
113
+ * or the old must have the ARM_CP_OVERRIDE bit set.
114
+ */
115
+ ARM_CP_OVERRIDE = 1 << 7,
116
+ /*
117
+ * Flag: Register is an alias view of some underlying state which is also
118
+ * visible via another register, and that the other register is handling
119
+ * migration and reset; registers marked ARM_CP_ALIAS will not be migrated
120
+ * but may have their state set by syncing of register state from KVM.
121
+ */
122
+ ARM_CP_ALIAS = 1 << 8,
123
+ /*
124
+ * Flag: Register does I/O and therefore its accesses need to be marked
125
+ * with gen_io_start() and also end the TB. In particular, registers which
126
+ * implement clocks or timers require this.
127
+ */
128
+ ARM_CP_IO = 1 << 9,
129
+ /*
130
+ * Flag: Register has no underlying state and does not support raw access
131
+ * for state saving/loading; it will not be used for either migration or
132
+ * KVM state synchronization. Typically this is for "registers" which are
133
+ * actually used as instructions for cache maintenance and so on.
134
+ */
135
+ ARM_CP_NO_RAW = 1 << 10,
136
+ /*
137
+ * Flag: The read or write hook might raise an exception; the generated
138
+ * code will synchronize the CPU state before calling the hook so that it
139
+ * is safe for the hook to call raise_exception().
140
+ */
141
+ ARM_CP_RAISES_EXC = 1 << 11,
142
+ /*
143
+ * Flag: Writes to the sysreg might change the exception level - typically
144
+ * on older ARM chips. For those cases we need to re-read the new el when
145
+ * recomputing the translation flags.
146
+ */
147
+ ARM_CP_NEWEL = 1 << 12,
148
+ /*
149
+ * Flag: Access check for this sysreg is identical to accessing FPU state
150
+ * from an instruction: use translation fp_access_check().
151
+ */
152
+ ARM_CP_FPU = 1 << 13,
153
+ /*
154
+ * Flag: Access check for this sysreg is identical to accessing SVE state
155
+ * from an instruction: use translation sve_access_check().
156
+ */
157
+ ARM_CP_SVE = 1 << 14,
158
+ /* Flag: Do not expose in gdb sysreg xml. */
159
+ ARM_CP_NO_GDB = 1 << 15,
160
+};
161
162
/*
163
* Valid values for ARMCPRegInfo state field, indicating which of
40
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
164
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
41
index XXXXXXX..XXXXXXX 100644
165
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/cpu.c
166
--- a/target/arm/cpu.c
43
+++ b/target/arm/cpu.c
167
+++ b/target/arm/cpu.c
44
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
168
@@ -XXX,XX +XXX,XX @@ static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
45
uint8_t *rom;
169
ARMCPRegInfo *ri = value;
46
uint32_t vecbase;
170
ARMCPU *cpu = opaque;
47
171
48
+ if (cpu_isar_feature(aa32_lob, cpu)) {
172
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS)) {
49
+ /*
173
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS)) {
50
+ * LTPSIZE is constant 4 if MVE not implemented, and resets
174
return;
51
+ * to an UNKNOWN value if MVE is implemented. We choose to
175
}
52
+ * always reset to 4.
176
53
+ */
177
@@ -XXX,XX +XXX,XX @@ static void cp_reg_check_reset(gpointer key, gpointer value, gpointer opaque)
54
+ env->v7m.ltpsize = 4;
178
ARMCPU *cpu = opaque;
55
+ }
179
uint64_t oldvalue, newvalue;
56
+
180
57
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
181
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
58
env->v7m.secure = true;
182
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
59
} else {
183
return;
60
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
184
}
61
index XXXXXXX..XXXXXXX 100644
185
62
--- a/target/arm/vfp_helper.c
186
diff --git a/target/arm/helper.c b/target/arm/helper.c
63
+++ b/target/arm/vfp_helper.c
187
index XXXXXXX..XXXXXXX 100644
64
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
188
--- a/target/arm/helper.c
65
| (env->vfp.vec_len << 16)
189
+++ b/target/arm/helper.c
66
| (env->vfp.vec_stride << 20);
190
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
67
191
* multiple times. Special registers (ie NOP/WFI) are
68
+ /*
192
* never migratable and not even raw-accessible.
69
+ * M-profile LTPSIZE overlaps A-profile Stride; whichever of the
193
*/
70
+ * two is not applicable to this CPU will always be zero.
194
- if ((r->type & ARM_CP_SPECIAL)) {
71
+ */
195
+ if (r->type & ARM_CP_SPECIAL_MASK) {
72
+ fpscr |= env->v7m.ltpsize << 16;
196
r2->type |= ARM_CP_NO_RAW;
73
+
197
}
74
fpscr |= vfp_get_fpscr_from_host(env);
198
if (((r->crm == CP_ANY) && crm != 0) ||
75
199
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
76
i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
200
/* Check that the register definition has enough info to handle
201
* reads and writes if they are permitted.
202
*/
203
- if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
204
+ if (!(r->type & (ARM_CP_SPECIAL_MASK | ARM_CP_CONST))) {
205
if (r->access & PL3_R) {
206
assert((r->fieldoffset ||
207
(r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
208
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/target/arm/translate-a64.c
211
+++ b/target/arm/translate-a64.c
212
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
213
}
214
215
/* Handle special cases first */
216
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
217
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
218
+ case 0:
219
+ break;
220
case ARM_CP_NOP:
221
return;
222
case ARM_CP_NZCV:
223
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
224
}
225
return;
226
default:
227
- break;
228
+ g_assert_not_reached();
229
}
230
if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
231
return;
232
diff --git a/target/arm/translate.c b/target/arm/translate.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/target/arm/translate.c
235
+++ b/target/arm/translate.c
236
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
237
}
238
239
/* Handle special cases first */
240
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
241
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
242
+ case 0:
243
+ break;
244
case ARM_CP_NOP:
245
return;
246
case ARM_CP_WFI:
247
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
248
s->base.is_jmp = DISAS_WFI;
249
return;
250
default:
251
- break;
252
+ g_assert_not_reached();
253
}
254
255
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
77
--
256
--
78
2.20.1
257
2.25.1
79
80
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This is slightly clearer than just using strerror, though
3
Standardize on g_assert_not_reached() for "should not happen".
4
the different forms produced by error_setg_file_open and
4
Retain abort() when preceeded by fprintf or error_report.
5
error_setg_errno isn't entirely convenient.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20201016184207.786698-10-richard.henderson@linaro.org
8
Message-id: 20220501055028.646596-7-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
linux-user/elfload.c | 15 ++++++++-------
11
target/arm/helper.c | 7 +++----
13
1 file changed, 8 insertions(+), 7 deletions(-)
12
target/arm/hvf/hvf.c | 2 +-
13
target/arm/kvm-stub.c | 4 ++--
14
target/arm/kvm.c | 4 ++--
15
target/arm/machine.c | 4 ++--
16
target/arm/translate-a64.c | 4 ++--
17
target/arm/translate-neon.c | 2 +-
18
target/arm/translate.c | 4 ++--
19
8 files changed, 15 insertions(+), 16 deletions(-)
14
20
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
23
--- a/target/arm/helper.c
18
+++ b/linux-user/elfload.c
24
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
25
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
20
char bprm_buf[BPRM_BUF_SIZE])
26
break;
27
default:
28
/* broken reginfo with out-of-range opc1 */
29
- assert(false);
30
- break;
31
+ g_assert_not_reached();
32
}
33
/* assert our permissions are not too lax (stricter is fine) */
34
assert((r->access & ~mask) == 0);
35
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
36
break;
37
default:
38
/* Never happens, but compiler isn't smart enough to tell. */
39
- abort();
40
+ g_assert_not_reached();
41
}
42
}
43
*prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
44
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
45
break;
46
default:
47
/* Never happens, but compiler isn't smart enough to tell. */
48
- abort();
49
+ g_assert_not_reached();
50
}
51
}
52
if (domain_prot == 3) {
53
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/hvf/hvf.c
56
+++ b/target/arm/hvf/hvf.c
57
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
58
/* we got kicked, no exit to process */
59
return 0;
60
default:
61
- assert(0);
62
+ g_assert_not_reached();
63
}
64
65
hvf_sync_vtimer(cpu);
66
diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/kvm-stub.c
69
+++ b/target/arm/kvm-stub.c
70
@@ -XXX,XX +XXX,XX @@
71
72
bool write_kvmstate_to_list(ARMCPU *cpu)
21
{
73
{
22
int fd, retval;
74
- abort();
23
+ Error *err = NULL;
75
+ g_assert_not_reached();
24
76
}
25
fd = open(path(filename), O_RDONLY);
77
26
if (fd < 0) {
78
bool write_list_to_kvmstate(ARMCPU *cpu, int level)
27
- goto exit_perror;
79
{
28
+ error_setg_file_open(&err, errno, filename);
80
- abort();
29
+ error_report_err(err);
81
+ g_assert_not_reached();
30
+ exit(-1);
82
}
83
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/kvm.c
86
+++ b/target/arm/kvm.c
87
@@ -XXX,XX +XXX,XX @@ bool write_kvmstate_to_list(ARMCPU *cpu)
88
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
89
break;
90
default:
91
- abort();
92
+ g_assert_not_reached();
93
}
94
if (ret) {
95
ok = false;
96
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
97
r.addr = (uintptr_t)(cpu->cpreg_values + i);
98
break;
99
default:
100
- abort();
101
+ g_assert_not_reached();
102
}
103
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
104
if (ret) {
105
diff --git a/target/arm/machine.c b/target/arm/machine.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/machine.c
108
+++ b/target/arm/machine.c
109
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
110
if (kvm_enabled()) {
111
if (!write_kvmstate_to_list(cpu)) {
112
/* This should never fail */
113
- abort();
114
+ g_assert_not_reached();
115
}
116
117
/*
118
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
119
} else {
120
if (!write_cpustate_to_list(cpu, false)) {
121
/* This should never fail. */
122
- abort();
123
+ g_assert_not_reached();
124
}
31
}
125
}
32
126
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
127
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
34
if (retval < 0) {
128
index XXXXXXX..XXXXXXX 100644
35
- goto exit_perror;
129
--- a/target/arm/translate-a64.c
36
+ error_setg_errno(&err, errno, "Error reading file header");
130
+++ b/target/arm/translate-a64.c
37
+ error_reportf_err(err, "%s: ", filename);
131
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
38
+ exit(-1);
132
gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
133
break;
134
default:
135
- abort();
136
+ g_assert_not_reached();
39
}
137
}
40
+
138
41
if (retval < BPRM_BUF_SIZE) {
139
write_fp_sreg(s, rd, tcg_res);
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
140
@@ -XXX,XX +XXX,XX @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
141
break;
43
}
142
}
44
143
default:
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
144
- abort();
46
- return;
145
+ g_assert_not_reached();
47
-
146
}
48
- exit_perror:
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
50
- exit(-1);
51
}
147
}
52
148
53
static int symfind(const void *s0, const void *s1)
149
diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/target/arm/translate-neon.c
152
+++ b/target/arm/translate-neon.c
153
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
154
}
155
break;
156
default:
157
- abort();
158
+ g_assert_not_reached();
159
}
160
if ((vd + a->stride * (nregs - 1)) > 31) {
161
/*
162
diff --git a/target/arm/translate.c b/target/arm/translate.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/target/arm/translate.c
165
+++ b/target/arm/translate.c
166
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
167
offset = 4;
168
break;
169
default:
170
- abort();
171
+ g_assert_not_reached();
172
}
173
tcg_gen_addi_i32(addr, addr, offset);
174
tmp = load_reg(s, 14);
175
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
176
offset = 0;
177
break;
178
default:
179
- abort();
180
+ g_assert_not_reached();
181
}
182
tcg_gen_addi_i32(addr, addr, offset);
183
gen_helper_set_r13_banked(cpu_env, tcg_constant_i32(mode), addr);
54
--
184
--
55
2.20.1
185
2.25.1
56
57
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
These are all of the defines required to parse
3
Create a typedef as well, and use it in ARMCPRegInfo.
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
4
This won't be perfect for debugging, but it'll nicely
5
Other missing defines related to other GNU program headers
5
display the most common cases.
6
and notes are elided for now.
7
6
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201016184207.786698-4-richard.henderson@linaro.org
9
Message-id: 20220501055028.646596-8-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
include/elf.h | 22 ++++++++++++++++++++++
12
target/arm/cpregs.h | 44 +++++++++++++++++++++++---------------------
14
1 file changed, 22 insertions(+)
13
target/arm/helper.c | 2 +-
14
2 files changed, 24 insertions(+), 22 deletions(-)
15
15
16
diff --git a/include/elf.h b/include/elf.h
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/elf.h
18
--- a/target/arm/cpregs.h
19
+++ b/include/elf.h
19
+++ b/target/arm/cpregs.h
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
20
@@ -XXX,XX +XXX,XX @@ enum {
21
#define PT_NOTE 4
21
* described with these bits, then use a laxer set of restrictions, and
22
#define PT_SHLIB 5
22
* do the more restrictive/complex check inside a helper function.
23
#define PT_PHDR 6
23
*/
24
+#define PT_LOOS 0x60000000
24
-#define PL3_R 0x80
25
+#define PT_HIOS 0x6fffffff
25
-#define PL3_W 0x40
26
#define PT_LOPROC 0x70000000
26
-#define PL2_R (0x20 | PL3_R)
27
#define PT_HIPROC 0x7fffffff
27
-#define PL2_W (0x10 | PL3_W)
28
28
-#define PL1_R (0x08 | PL2_R)
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
29
-#define PL1_W (0x04 | PL2_W)
30
+
30
-#define PL0_R (0x02 | PL1_R)
31
#define PT_MIPS_REGINFO 0x70000000
31
-#define PL0_W (0x01 | PL1_W)
32
#define PT_MIPS_RTPROC 0x70000001
32
+typedef enum {
33
#define PT_MIPS_OPTIONS 0x70000002
33
+ PL3_R = 0x80,
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
34
+ PL3_W = 0x40,
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
35
+ PL2_R = 0x20 | PL3_R,
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
36
+ PL2_W = 0x10 | PL3_W,
37
37
+ PL1_R = 0x08 | PL2_R,
38
+/* Defined note types for GNU systems. */
38
+ PL1_W = 0x04 | PL2_W,
39
+
39
+ PL0_R = 0x02 | PL1_R,
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
40
+ PL0_W = 0x01 | PL1_W,
41
+
41
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
42
-/*
43
+
43
- * For user-mode some registers are accessible to EL0 via a kernel
44
+#define GNU_PROPERTY_STACK_SIZE 1
44
- * trap-and-emulate ABI. In this case we define the read permissions
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
45
- * as actually being PL0_R. However some bits of any given register
46
+
46
- * may still be masked.
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
47
- */
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
48
+ /*
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
49
+ * For user-mode some registers are accessible to EL0 via a kernel
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
50
+ * trap-and-emulate ABI. In this case we define the read permissions
51
+
51
+ * as actually being PL0_R. However some bits of any given register
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
52
+ * may still be masked.
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
53
+ */
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
54
#ifdef CONFIG_USER_ONLY
55
+
55
-#define PL0U_R PL0_R
56
/*
56
+ PL0U_R = PL0_R,
57
* Physical entry point into the kernel.
57
#else
58
*
58
-#define PL0U_R PL1_R
59
+ PL0U_R = PL1_R,
60
#endif
61
62
-#define PL3_RW (PL3_R | PL3_W)
63
-#define PL2_RW (PL2_R | PL2_W)
64
-#define PL1_RW (PL1_R | PL1_W)
65
-#define PL0_RW (PL0_R | PL0_W)
66
+ PL3_RW = PL3_R | PL3_W,
67
+ PL2_RW = PL2_R | PL2_W,
68
+ PL1_RW = PL1_R | PL1_W,
69
+ PL0_RW = PL0_R | PL0_W,
70
+} CPAccessRights;
71
72
typedef enum CPAccessResult {
73
/* Access is permitted */
74
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
75
/* Register type: ARM_CP_* bits/values */
76
int type;
77
/* Access rights: PL*_[RW] */
78
- int access;
79
+ CPAccessRights access;
80
/* Security state: ARM_CP_SECSTATE_* bits/values */
81
int secure;
82
/*
83
diff --git a/target/arm/helper.c b/target/arm/helper.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/helper.c
86
+++ b/target/arm/helper.c
87
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
88
* to encompass the generic architectural permission check.
89
*/
90
if (r->state != ARM_CP_STATE_AA32) {
91
- int mask = 0;
92
+ CPAccessRights mask;
93
switch (r->opc1) {
94
case 0:
95
/* min_EL EL1, but some accessible to EL0 via kernel ABI */
59
--
96
--
60
2.20.1
97
2.25.1
61
62
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Unlike many other bits in HCR_EL2, the description for this
3
Give this enum a name and use in ARMCPRegInfo,
4
bit does not contain the phrase "if ... this field behaves
4
add_cpreg_to_hashtable and define_one_arm_cp_reg_with_opaque.
5
as 0 for all purposes other than", so do not squash the bit
6
in arm_hcr_el2_eff.
7
5
8
Instead, replicate the E2H+TGE test in the two places that
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
require it.
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
11
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
9
Message-id: 20220501055028.646596-9-richard.henderson@linaro.org
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-4-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
11
---
18
target/arm/internals.h | 9 +++++----
12
target/arm/cpregs.h | 6 +++---
19
target/arm/helper.c | 9 +++++----
13
target/arm/helper.c | 6 ++++--
20
2 files changed, 10 insertions(+), 8 deletions(-)
14
2 files changed, 7 insertions(+), 5 deletions(-)
21
15
22
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/internals.h
18
--- a/target/arm/cpregs.h
25
+++ b/target/arm/internals.h
19
+++ b/target/arm/cpregs.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
20
@@ -XXX,XX +XXX,XX @@ enum {
27
&& !(env->cp15.scr_el3 & SCR_ATA)) {
21
* Note that we rely on the values of these enums as we iterate through
28
return false;
22
* the various states in some places.
29
}
23
*/
30
- if (el < 2
24
-enum {
31
- && arm_feature(env, ARM_FEATURE_EL2)
25
+typedef enum {
32
- && !(arm_hcr_el2_eff(env) & HCR_ATA)) {
26
ARM_CP_STATE_AA32 = 0,
33
- return false;
27
ARM_CP_STATE_AA64 = 1,
34
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
28
ARM_CP_STATE_BOTH = 2,
35
+ uint64_t hcr = arm_hcr_el2_eff(env);
29
-};
36
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
30
+} CPState;
37
+ return false;
31
38
+ }
32
/*
39
}
33
* ARM CP register secure state flags. These flags identify security state
40
sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA);
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
41
return sctlr != 0;
35
uint8_t opc1;
36
uint8_t opc2;
37
/* Execution state in which this register is visible: ARM_CP_STATE_* */
38
- int state;
39
+ CPState state;
40
/* Register type: ARM_CP_* bits/values */
41
int type;
42
/* Access rights: PL*_[RW] */
42
diff --git a/target/arm/helper.c b/target/arm/helper.c
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
43
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper.c
45
--- a/target/arm/helper.c
45
+++ b/target/arm/helper.c
46
+++ b/target/arm/helper.c
46
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
47
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
48
}
49
50
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
51
- void *opaque, int state, int secstate,
52
+ void *opaque, CPState state, int secstate,
53
int crm, int opc1, int opc2,
54
const char *name)
47
{
55
{
48
int el = arm_current_el(env);
56
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
49
57
* bits; the ARM_CP_64BIT* flag applies only to the AArch32 view of
50
- if (el < 2 &&
58
* the register, if any.
51
- arm_feature(env, ARM_FEATURE_EL2) &&
59
*/
52
- !(arm_hcr_el2_eff(env) & HCR_ATA)) {
60
- int crm, opc1, opc2, state;
53
- return CP_ACCESS_TRAP_EL2;
61
+ int crm, opc1, opc2;
54
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
62
int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
55
+ uint64_t hcr = arm_hcr_el2_eff(env);
63
int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
56
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
64
int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
57
+ return CP_ACCESS_TRAP_EL2;
65
int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
58
+ }
66
int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
59
}
67
int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
60
if (el < 3 &&
68
+ CPState state;
61
arm_feature(env, ARM_FEATURE_EL3) &&
69
+
70
/* 64 bit registers have only CRm and Opc1 fields */
71
assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
72
/* op0 only exists in the AArch64 encodings */
62
--
73
--
63
2.20.1
74
2.25.1
64
75
65
76
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 kernel sets btype for the signal handler as if for a call.
3
Give this enum a name and use in ARMCPRegInfo and add_cpreg_to_hashtable.
4
Add the enumerator ARM_CP_SECSTATE_BOTH to clarify how 0
5
is handled in define_one_arm_cp_reg_with_opaque.
4
6
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201016184207.786698-2-richard.henderson@linaro.org
9
Message-id: 20220501055028.646596-10-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
linux-user/aarch64/signal.c | 10 ++++++++--
12
target/arm/cpregs.h | 7 ++++---
11
1 file changed, 8 insertions(+), 2 deletions(-)
13
target/arm/helper.c | 7 +++++--
14
2 files changed, 9 insertions(+), 5 deletions(-)
12
15
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
18
--- a/target/arm/cpregs.h
16
+++ b/linux-user/aarch64/signal.c
19
+++ b/target/arm/cpregs.h
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
20
@@ -XXX,XX +XXX,XX @@ typedef enum {
18
+ offsetof(struct target_rt_frame_record, tramp);
21
* registered entry will only have one to identify whether the entry is secure
19
}
22
* or non-secure.
20
env->xregs[0] = usig;
23
*/
21
- env->xregs[31] = frame_addr;
24
-enum {
22
env->xregs[29] = frame_addr + fr_ofs;
25
+typedef enum {
23
- env->pc = ka->_sa_handler;
26
+ ARM_CP_SECSTATE_BOTH = 0, /* define one cpreg for each secstate */
24
env->xregs[30] = return_addr;
27
ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
25
+ env->xregs[31] = frame_addr;
28
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
26
+ env->pc = ka->_sa_handler;
29
-};
27
+
30
+} CPSecureState;
28
+ /* Invoke the signal handler as if by indirect call. */
31
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
32
/*
30
+ env->btype = 2;
33
* Access rights:
31
+ }
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
32
+
35
/* Access rights: PL*_[RW] */
33
if (info) {
36
CPAccessRights access;
34
tswap_siginfo(&frame->info, info);
37
/* Security state: ARM_CP_SECSTATE_* bits/values */
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
38
- int secure;
39
+ CPSecureState secure;
40
/*
41
* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
42
* this register was defined: can be used to hand data through to the
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
48
}
49
50
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
51
- void *opaque, CPState state, int secstate,
52
+ void *opaque, CPState state,
53
+ CPSecureState secstate,
54
int crm, int opc1, int opc2,
55
const char *name)
56
{
57
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
58
r->secure, crm, opc1, opc2,
59
r->name);
60
break;
61
- default:
62
+ case ARM_CP_SECSTATE_BOTH:
63
name = g_strdup_printf("%s_S", r->name);
64
add_cpreg_to_hashtable(cpu, r, opaque, state,
65
ARM_CP_SECSTATE_S,
66
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
67
ARM_CP_SECSTATE_NS,
68
crm, opc1, opc2, r->name);
69
break;
70
+ default:
71
+ g_assert_not_reached();
72
}
73
} else {
74
/* AArch64 registers get mapped to non-secure instance
36
--
75
--
37
2.20.1
76
2.25.1
38
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
3
The new_key field is always non-zero -- drop the if.
4
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201016184207.786698-12-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220501055028.646596-11-richard.henderson@linaro.org
8
[PMM: reinstated dropped PL3_RW mask]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
11
target/arm/helper.c | 23 +++++++++++------------
11
1 file changed, 46 insertions(+), 2 deletions(-)
12
1 file changed, 11 insertions(+), 12 deletions(-)
12
13
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
--- a/target/arm/helper.c
16
+++ b/linux-user/elfload.c
17
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
18
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
18
19
19
#include "elf.h"
20
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
20
21
const struct E2HAlias *a = &aliases[i];
21
+/* We must delay the following stanzas until after "elf.h". */
22
- ARMCPRegInfo *src_reg, *dst_reg;
22
+#if defined(TARGET_AARCH64)
23
+ ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
23
+
24
+ uint32_t *new_key;
24
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
25
+ bool ok;
25
+ const uint32_t *data,
26
26
+ struct image_info *info,
27
if (a->feature && !a->feature(&cpu->isar)) {
27
+ Error **errp)
28
continue;
28
+{
29
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
29
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
30
g_assert(src_reg->opaque == NULL);
30
+ if (pr_datasz != sizeof(uint32_t)) {
31
31
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
32
/* Create alias before redirection so we dup the right data. */
32
+ return false;
33
- if (a->new_key) {
33
+ }
34
- ARMCPRegInfo *new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
35
- uint32_t *new_key = g_memdup(&a->new_key, sizeof(uint32_t));
35
+ info->note_flags = *data;
36
- bool ok;
36
+ }
37
+ new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
37
+ return true;
38
+ new_key = g_memdup(&a->new_key, sizeof(uint32_t));
38
+}
39
39
+#define ARCH_USE_GNU_PROPERTY 1
40
- new_reg->name = a->new_name;
40
+
41
- new_reg->type |= ARM_CP_ALIAS;
41
+#else
42
- /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
42
+
43
- new_reg->access &= PL2_RW | PL3_RW;
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
44
+ new_reg->name = a->new_name;
44
const uint32_t *data,
45
+ new_reg->type |= ARM_CP_ALIAS;
45
struct image_info *info,
46
+ /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
47
+ new_reg->access &= PL2_RW | PL3_RW;
47
}
48
48
#define ARCH_USE_GNU_PROPERTY 0
49
- ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
49
50
- g_assert(ok);
50
+#endif
51
- }
51
+
52
+ ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
52
struct exec
53
+ g_assert(ok);
53
{
54
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
55
src_reg->opaque = dst_reg;
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
56
src_reg->orig_readfn = src_reg->readfn ?: raw_read;
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
57
struct elf_phdr *phdr;
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
59
- int i, retval;
60
+ int i, retval, prot_exec;
61
Error *err = NULL;
62
63
/* First of all, some simple consistency checks */
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
65
info->brk = 0;
66
info->elf_flags = ehdr->e_flags;
67
68
+ prot_exec = PROT_EXEC;
69
+#ifdef TARGET_AARCH64
70
+ /*
71
+ * If the BTI feature is present, this indicates that the executable
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
73
+ * branch targets are enforced.
74
+ *
75
+ * The startup binary is either the interpreter or the static executable.
76
+ * The interpreter is responsible for all pages of a dynamic executable.
77
+ *
78
+ * Elf notes are backward compatible to older cpus.
79
+ * Do not enable BTI unless it is supported.
80
+ */
81
+ if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
82
+ && (pinterp_name == NULL || *pinterp_name == 0)
83
+ && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
84
+ prot_exec |= TARGET_PROT_BTI;
85
+ }
86
+#endif
87
+
88
for (i = 0; i < ehdr->e_phnum; i++) {
89
struct elf_phdr *eppnt = phdr + i;
90
if (eppnt->p_type == PT_LOAD) {
91
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
92
elf_prot |= PROT_WRITE;
93
}
94
if (eppnt->p_flags & PF_X) {
95
- elf_prot |= PROT_EXEC;
96
+ elf_prot |= prot_exec;
97
}
98
99
vaddr = load_bias + eppnt->p_vaddr;
100
--
57
--
101
2.20.1
58
2.25.1
102
103
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
On ARM, the Top Byte Ignore feature means that only 56 bits of
3
Cast the uint32_t key into a gpointer directly, which
4
the address are significant in the virtual address. We are
4
allows us to avoid allocating storage for each key.
5
required to give the entire 64-bit address to FAR_ELx on fault,
6
which means that we do not "clean" the top byte early in TCG.
7
5
8
This new interface allows us to flush all 256 possible aliases
6
Use g_hash_table_lookup when we already have a gpointer
9
for a given page, currently missed by tlb_flush_page*.
7
(e.g. for callbacks like count_cpreg), or when using
8
get_arm_cp_reginfo would require casting away const.
10
9
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20201016210754.818257-2-richard.henderson@linaro.org
12
Message-id: 20220501055028.646596-12-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
14
---
17
include/exec/exec-all.h | 36 ++++++
15
target/arm/cpu.c | 4 ++--
18
accel/tcg/cputlb.c | 275 ++++++++++++++++++++++++++++++++++++++--
16
target/arm/gdbstub.c | 2 +-
19
2 files changed, 302 insertions(+), 9 deletions(-)
17
target/arm/helper.c | 41 ++++++++++++++++++-----------------------
18
3 files changed, 21 insertions(+), 26 deletions(-)
20
19
21
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
23
--- a/include/exec/exec-all.h
22
--- a/target/arm/cpu.c
24
+++ b/include/exec/exec-all.h
23
+++ b/target/arm/cpu.c
25
@@ -XXX,XX +XXX,XX @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
26
* depend on when the guests translation ends the TB.
25
ARMCPU *cpu = ARM_CPU(obj);
27
*/
26
28
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
27
cpu_set_cpustate_pointers(cpu);
29
+
28
- cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
30
+/**
29
- g_free, cpreg_hashtable_data_destroy);
31
+ * tlb_flush_page_bits_by_mmuidx
30
+ cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
32
+ * @cpu: CPU whose TLB should be flushed
31
+ NULL, cpreg_hashtable_data_destroy);
33
+ * @addr: virtual address of page to be flushed
32
34
+ * @idxmap: bitmap of mmu indexes to flush
33
QLIST_INIT(&cpu->pre_el_change_hooks);
35
+ * @bits: number of significant bits in address
34
QLIST_INIT(&cpu->el_change_hooks);
36
+ *
35
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
37
+ * Similar to tlb_flush_page_mask, but with a bitmap of indexes.
36
index XXXXXXX..XXXXXXX 100644
38
+ */
37
--- a/target/arm/gdbstub.c
39
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
38
+++ b/target/arm/gdbstub.c
40
+ uint16_t idxmap, unsigned bits);
39
@@ -XXX,XX +XXX,XX @@ static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
41
+
40
static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
42
+/* Similarly, with broadcast and syncing. */
41
gpointer p)
43
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
44
+ uint16_t idxmap, unsigned bits);
45
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced
46
+ (CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits);
47
+
48
/**
49
* tlb_set_page_with_attrs:
50
* @cpu: CPU to add this TLB entry for
51
@@ -XXX,XX +XXX,XX @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
52
uint16_t idxmap)
53
{
42
{
54
}
43
- uint32_t ri_key = *(uint32_t *)key;
55
+static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
44
+ uint32_t ri_key = (uintptr_t)key;
56
+ target_ulong addr,
45
ARMCPRegInfo *ri = value;
57
+ uint16_t idxmap,
46
RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
58
+ unsigned bits)
47
GString *s = param->s;
59
+{
48
diff --git a/target/arm/helper.c b/target/arm/helper.c
60
+}
61
+static inline void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu,
62
+ target_ulong addr,
63
+ uint16_t idxmap,
64
+ unsigned bits)
65
+{
66
+}
67
+static inline void
68
+tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, target_ulong addr,
69
+ uint16_t idxmap, unsigned bits)
70
+{
71
+}
72
#endif
73
/**
74
* probe_access:
75
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
76
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
77
--- a/accel/tcg/cputlb.c
50
--- a/target/arm/helper.c
78
+++ b/accel/tcg/cputlb.c
51
+++ b/target/arm/helper.c
79
@@ -XXX,XX +XXX,XX @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu)
52
@@ -XXX,XX +XXX,XX @@ bool write_list_to_cpustate(ARMCPU *cpu)
80
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
53
static void add_cpreg_to_list(gpointer key, gpointer opaque)
81
}
82
83
+static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry,
84
+ target_ulong page, target_ulong mask)
85
+{
86
+ page &= mask;
87
+ mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK;
88
+
89
+ return (page == (tlb_entry->addr_read & mask) ||
90
+ page == (tlb_addr_write(tlb_entry) & mask) ||
91
+ page == (tlb_entry->addr_code & mask));
92
+}
93
+
94
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
95
target_ulong page)
96
{
54
{
97
- return tlb_hit_page(tlb_entry->addr_read, page) ||
55
ARMCPU *cpu = opaque;
98
- tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
56
- uint64_t regidx;
99
- tlb_hit_page(tlb_entry->addr_code, page);
57
- const ARMCPRegInfo *ri;
100
+ return tlb_hit_page_mask_anyprot(tlb_entry, page, -1);
58
-
101
}
59
- regidx = *(uint32_t *)key;
102
60
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
103
/**
61
+ uint32_t regidx = (uintptr_t)key;
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te)
62
+ const ARMCPRegInfo *ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
105
}
63
106
64
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
107
/* Called with tlb_c.lock held */
65
cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
108
-static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
66
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_list(gpointer key, gpointer opaque)
109
- target_ulong page)
67
static void count_cpreg(gpointer key, gpointer opaque)
110
+static bool tlb_flush_entry_mask_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page,
112
+ target_ulong mask)
113
{
68
{
114
- if (tlb_hit_page_anyprot(tlb_entry, page)) {
69
ARMCPU *cpu = opaque;
115
+ if (tlb_hit_page_mask_anyprot(tlb_entry, page, mask)) {
70
- uint64_t regidx;
116
memset(tlb_entry, -1, sizeof(*tlb_entry));
71
const ARMCPRegInfo *ri;
117
return true;
72
73
- regidx = *(uint32_t *)key;
74
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
75
+ ri = g_hash_table_lookup(cpu->cp_regs, key);
76
77
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
78
cpu->cpreg_array_len++;
79
@@ -XXX,XX +XXX,XX @@ static void count_cpreg(gpointer key, gpointer opaque)
80
81
static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
82
{
83
- uint64_t aidx = cpreg_to_kvm_id(*(uint32_t *)a);
84
- uint64_t bidx = cpreg_to_kvm_id(*(uint32_t *)b);
85
+ uint64_t aidx = cpreg_to_kvm_id((uintptr_t)a);
86
+ uint64_t bidx = cpreg_to_kvm_id((uintptr_t)b);
87
88
if (aidx > bidx) {
89
return 1;
90
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
91
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
92
const struct E2HAlias *a = &aliases[i];
93
ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
94
- uint32_t *new_key;
95
bool ok;
96
97
if (a->feature && !a->feature(&cpu->isar)) {
98
continue;
99
}
100
101
- src_reg = g_hash_table_lookup(cpu->cp_regs, &a->src_key);
102
- dst_reg = g_hash_table_lookup(cpu->cp_regs, &a->dst_key);
103
+ src_reg = g_hash_table_lookup(cpu->cp_regs,
104
+ (gpointer)(uintptr_t)a->src_key);
105
+ dst_reg = g_hash_table_lookup(cpu->cp_regs,
106
+ (gpointer)(uintptr_t)a->dst_key);
107
g_assert(src_reg != NULL);
108
g_assert(dst_reg != NULL);
109
110
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
111
112
/* Create alias before redirection so we dup the right data. */
113
new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
114
- new_key = g_memdup(&a->new_key, sizeof(uint32_t));
115
116
new_reg->name = a->new_name;
117
new_reg->type |= ARM_CP_ALIAS;
118
/* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
119
new_reg->access &= PL2_RW | PL3_RW;
120
121
- ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
122
+ ok = g_hash_table_insert(cpu->cp_regs,
123
+ (gpointer)(uintptr_t)a->new_key, new_reg);
124
g_assert(ok);
125
126
src_reg->opaque = dst_reg;
127
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
128
/* Private utility function for define_one_arm_cp_reg_with_opaque():
129
* add a single reginfo struct to the hash table.
130
*/
131
- uint32_t *key = g_new(uint32_t, 1);
132
+ uint32_t key;
133
ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
134
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
135
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
136
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
137
if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) {
138
r2->cp = CP_REG_ARM64_SYSREG_CP;
139
}
140
- *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
141
- r2->opc0, opc1, opc2);
142
+ key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
143
+ r2->opc0, opc1, opc2);
144
} else {
145
- *key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
146
+ key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
118
}
147
}
119
return false;
148
if (opaque) {
120
}
149
r2->opaque = opaque;
121
150
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
122
+static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
151
* requested.
123
+ target_ulong page)
152
*/
124
+{
153
if (!(r->type & ARM_CP_OVERRIDE)) {
125
+ return tlb_flush_entry_mask_locked(tlb_entry, page, -1);
154
- ARMCPRegInfo *oldreg;
126
+}
155
- oldreg = g_hash_table_lookup(cpu->cp_regs, key);
127
+
156
+ const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
128
/* Called with tlb_c.lock held */
157
if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
129
-static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
158
fprintf(stderr, "Register redefined: cp=%d %d bit "
130
- target_ulong page)
159
"crn=%d crm=%d opc1=%d opc2=%d, "
131
+static void tlb_flush_vtlb_page_mask_locked(CPUArchState *env, int mmu_idx,
160
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
132
+ target_ulong page,
161
g_assert_not_reached();
133
+ target_ulong mask)
134
{
135
CPUTLBDesc *d = &env_tlb(env)->d[mmu_idx];
136
int k;
137
138
assert_cpu_is_self(env_cpu(env));
139
for (k = 0; k < CPU_VTLB_SIZE; k++) {
140
- if (tlb_flush_entry_locked(&d->vtable[k], page)) {
141
+ if (tlb_flush_entry_mask_locked(&d->vtable[k], page, mask)) {
142
tlb_n_used_entries_dec(env, mmu_idx);
143
}
162
}
144
}
163
}
164
- g_hash_table_insert(cpu->cp_regs, key, r2);
165
+ g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
145
}
166
}
146
167
147
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
168
148
+ target_ulong page)
169
@@ -XXX,XX +XXX,XX @@ void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
149
+{
170
150
+ tlb_flush_vtlb_page_mask_locked(env, mmu_idx, page, -1);
171
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
151
+}
152
+
153
static void tlb_flush_page_locked(CPUArchState *env, int midx,
154
target_ulong page)
155
{
172
{
156
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
173
- return g_hash_table_lookup(cpregs, &encoded_cp);
157
tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
174
+ return g_hash_table_lookup(cpregs, (gpointer)(uintptr_t)encoded_cp);
158
}
175
}
159
176
160
+static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
177
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
161
+ target_ulong page, unsigned bits)
162
+{
163
+ CPUTLBDesc *d = &env_tlb(env)->d[midx];
164
+ CPUTLBDescFast *f = &env_tlb(env)->f[midx];
165
+ target_ulong mask = MAKE_64BIT_MASK(0, bits);
166
+
167
+ /*
168
+ * If @bits is smaller than the tlb size, there may be multiple entries
169
+ * within the TLB; otherwise all addresses that match under @mask hit
170
+ * the same TLB entry.
171
+ *
172
+ * TODO: Perhaps allow bits to be a few bits less than the size.
173
+ * For now, just flush the entire TLB.
174
+ */
175
+ if (mask < f->mask) {
176
+ tlb_debug("forcing full flush midx %d ("
177
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
178
+ midx, page, mask);
179
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
180
+ return;
181
+ }
182
+
183
+ /* Check if we need to flush due to large pages. */
184
+ if ((page & d->large_page_mask) == d->large_page_addr) {
185
+ tlb_debug("forcing full flush midx %d ("
186
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
187
+ midx, d->large_page_addr, d->large_page_mask);
188
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
189
+ return;
190
+ }
191
+
192
+ if (tlb_flush_entry_mask_locked(tlb_entry(env, midx, page), page, mask)) {
193
+ tlb_n_used_entries_dec(env, midx);
194
+ }
195
+ tlb_flush_vtlb_page_mask_locked(env, midx, page, mask);
196
+}
197
+
198
+typedef struct {
199
+ target_ulong addr;
200
+ uint16_t idxmap;
201
+ uint16_t bits;
202
+} TLBFlushPageBitsByMMUIdxData;
203
+
204
+static void
205
+tlb_flush_page_bits_by_mmuidx_async_0(CPUState *cpu,
206
+ TLBFlushPageBitsByMMUIdxData d)
207
+{
208
+ CPUArchState *env = cpu->env_ptr;
209
+ int mmu_idx;
210
+
211
+ assert_cpu_is_self(cpu);
212
+
213
+ tlb_debug("page addr:" TARGET_FMT_lx "/%u mmu_map:0x%x\n",
214
+ d.addr, d.bits, d.idxmap);
215
+
216
+ qemu_spin_lock(&env_tlb(env)->c.lock);
217
+ for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
218
+ if ((d.idxmap >> mmu_idx) & 1) {
219
+ tlb_flush_page_bits_locked(env, mmu_idx, d.addr, d.bits);
220
+ }
221
+ }
222
+ qemu_spin_unlock(&env_tlb(env)->c.lock);
223
+
224
+ tb_flush_jmp_cache(cpu, d.addr);
225
+}
226
+
227
+static bool encode_pbm_to_runon(run_on_cpu_data *out,
228
+ TLBFlushPageBitsByMMUIdxData d)
229
+{
230
+ /* We need 6 bits to hold to hold @bits up to 63. */
231
+ if (d.idxmap <= MAKE_64BIT_MASK(0, TARGET_PAGE_BITS - 6)) {
232
+ *out = RUN_ON_CPU_TARGET_PTR(d.addr | (d.idxmap << 6) | d.bits);
233
+ return true;
234
+ }
235
+ return false;
236
+}
237
+
238
+static TLBFlushPageBitsByMMUIdxData
239
+decode_runon_to_pbm(run_on_cpu_data data)
240
+{
241
+ target_ulong addr_map_bits = (target_ulong) data.target_ptr;
242
+ return (TLBFlushPageBitsByMMUIdxData){
243
+ .addr = addr_map_bits & TARGET_PAGE_MASK,
244
+ .idxmap = (addr_map_bits & ~TARGET_PAGE_MASK) >> 6,
245
+ .bits = addr_map_bits & 0x3f
246
+ };
247
+}
248
+
249
+static void tlb_flush_page_bits_by_mmuidx_async_1(CPUState *cpu,
250
+ run_on_cpu_data runon)
251
+{
252
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, decode_runon_to_pbm(runon));
253
+}
254
+
255
+static void tlb_flush_page_bits_by_mmuidx_async_2(CPUState *cpu,
256
+ run_on_cpu_data data)
257
+{
258
+ TLBFlushPageBitsByMMUIdxData *d = data.host_ptr;
259
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, *d);
260
+ g_free(d);
261
+}
262
+
263
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
264
+ uint16_t idxmap, unsigned bits)
265
+{
266
+ TLBFlushPageBitsByMMUIdxData d;
267
+ run_on_cpu_data runon;
268
+
269
+ /* If all bits are significant, this devolves to tlb_flush_page. */
270
+ if (bits >= TARGET_LONG_BITS) {
271
+ tlb_flush_page_by_mmuidx(cpu, addr, idxmap);
272
+ return;
273
+ }
274
+ /* If no page bits are significant, this devolves to tlb_flush. */
275
+ if (bits < TARGET_PAGE_BITS) {
276
+ tlb_flush_by_mmuidx(cpu, idxmap);
277
+ return;
278
+ }
279
+
280
+ /* This should already be page aligned */
281
+ d.addr = addr & TARGET_PAGE_MASK;
282
+ d.idxmap = idxmap;
283
+ d.bits = bits;
284
+
285
+ if (qemu_cpu_is_self(cpu)) {
286
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, d);
287
+ } else if (encode_pbm_to_runon(&runon, d)) {
288
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
289
+ } else {
290
+ TLBFlushPageBitsByMMUIdxData *p
291
+ = g_new(TLBFlushPageBitsByMMUIdxData, 1);
292
+
293
+ /* Otherwise allocate a structure, freed by the worker. */
294
+ *p = d;
295
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_2,
296
+ RUN_ON_CPU_HOST_PTR(p));
297
+ }
298
+}
299
+
300
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
301
+ target_ulong addr,
302
+ uint16_t idxmap,
303
+ unsigned bits)
304
+{
305
+ TLBFlushPageBitsByMMUIdxData d;
306
+ run_on_cpu_data runon;
307
+
308
+ /* If all bits are significant, this devolves to tlb_flush_page. */
309
+ if (bits >= TARGET_LONG_BITS) {
310
+ tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap);
311
+ return;
312
+ }
313
+ /* If no page bits are significant, this devolves to tlb_flush. */
314
+ if (bits < TARGET_PAGE_BITS) {
315
+ tlb_flush_by_mmuidx_all_cpus(src_cpu, idxmap);
316
+ return;
317
+ }
318
+
319
+ /* This should already be page aligned */
320
+ d.addr = addr & TARGET_PAGE_MASK;
321
+ d.idxmap = idxmap;
322
+ d.bits = bits;
323
+
324
+ if (encode_pbm_to_runon(&runon, d)) {
325
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
326
+ } else {
327
+ CPUState *dst_cpu;
328
+ TLBFlushPageBitsByMMUIdxData *p;
329
+
330
+ /* Allocate a separate data block for each destination cpu. */
331
+ CPU_FOREACH(dst_cpu) {
332
+ if (dst_cpu != src_cpu) {
333
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
334
+ *p = d;
335
+ async_run_on_cpu(dst_cpu,
336
+ tlb_flush_page_bits_by_mmuidx_async_2,
337
+ RUN_ON_CPU_HOST_PTR(p));
338
+ }
339
+ }
340
+ }
341
+
342
+ tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d);
343
+}
344
+
345
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
346
+ target_ulong addr,
347
+ uint16_t idxmap,
348
+ unsigned bits)
349
+{
350
+ TLBFlushPageBitsByMMUIdxData d;
351
+ run_on_cpu_data runon;
352
+
353
+ /* If all bits are significant, this devolves to tlb_flush_page. */
354
+ if (bits >= TARGET_LONG_BITS) {
355
+ tlb_flush_page_by_mmuidx_all_cpus_synced(src_cpu, addr, idxmap);
356
+ return;
357
+ }
358
+ /* If no page bits are significant, this devolves to tlb_flush. */
359
+ if (bits < TARGET_PAGE_BITS) {
360
+ tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, idxmap);
361
+ return;
362
+ }
363
+
364
+ /* This should already be page aligned */
365
+ d.addr = addr & TARGET_PAGE_MASK;
366
+ d.idxmap = idxmap;
367
+ d.bits = bits;
368
+
369
+ if (encode_pbm_to_runon(&runon, d)) {
370
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
371
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1,
372
+ runon);
373
+ } else {
374
+ CPUState *dst_cpu;
375
+ TLBFlushPageBitsByMMUIdxData *p;
376
+
377
+ /* Allocate a separate data block for each destination cpu. */
378
+ CPU_FOREACH(dst_cpu) {
379
+ if (dst_cpu != src_cpu) {
380
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
381
+ *p = d;
382
+ async_run_on_cpu(dst_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
383
+ RUN_ON_CPU_HOST_PTR(p));
384
+ }
385
+ }
386
+
387
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
388
+ *p = d;
389
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
390
+ RUN_ON_CPU_HOST_PTR(p));
391
+ }
392
+}
393
+
394
/* update the TLBs so that writes to code in the virtual page 'addr'
395
can be detected */
396
void tlb_protect_code(ram_addr_t ram_addr)
397
--
178
--
398
2.20.1
179
2.25.1
399
400
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
2
1
3
Current documentation is not too clear on the GETPC usage.
4
In particular, when used outside the top level helper function
5
it causes unexpected behavior.
6
7
Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
8
Message-id: 20201015095147.1691-1-e.emanuelegiuseppe@gmail.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/devel/loads-stores.rst | 8 +++++++-
13
1 file changed, 7 insertions(+), 1 deletion(-)
14
15
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/devel/loads-stores.rst
18
+++ b/docs/devel/loads-stores.rst
19
@@ -XXX,XX +XXX,XX @@ guest CPU state in case of a guest CPU exception. This is passed
20
to ``cpu_restore_state()``. Therefore the value should either be 0,
21
to indicate that the guest CPU state is already synchronized, or
22
the result of ``GETPC()`` from the top level ``HELPER(foo)``
23
-function, which is a return address into the generated code.
24
+function, which is a return address into the generated code [#gpc]_.
25
+
26
+.. [#gpc] Note that ``GETPC()`` should be used with great care: calling
27
+ it in other functions that are *not* the top level
28
+ ``HELPER(foo)`` will cause unexpected behavior. Instead, the
29
+ value of ``GETPC()`` should be read from the helper and passed
30
+ if needed to the functions that the helper calls.
31
32
Function names follow the pattern:
33
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Add trace events for GPU and CPU IRQs.
4
5
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201017180731.1165871-2-f4bug@amsat.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/intc/bcm2835_ic.c | 4 +++-
11
hw/intc/trace-events | 4 ++++
12
2 files changed, 7 insertions(+), 1 deletion(-)
13
14
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2835_ic.c
17
+++ b/hw/intc/bcm2835_ic.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "migration/vmstate.h"
20
#include "qemu/log.h"
21
#include "qemu/module.h"
22
+#include "trace.h"
23
24
#define GPU_IRQS 64
25
#define ARM_IRQS 8
26
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_update(BCM2835ICState *s)
27
set = (s->gpu_irq_level & s->gpu_irq_enable)
28
|| (s->arm_irq_level & s->arm_irq_enable);
29
qemu_set_irq(s->irq, set);
30
-
31
}
32
33
static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
34
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
35
BCM2835ICState *s = opaque;
36
37
assert(irq >= 0 && irq < 64);
38
+ trace_bcm2835_ic_set_gpu_irq(irq, level);
39
s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
40
bcm2835_ic_update(s);
41
}
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
43
BCM2835ICState *s = opaque;
44
45
assert(irq >= 0 && irq < 8);
46
+ trace_bcm2835_ic_set_cpu_irq(irq, level);
47
s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
48
bcm2835_ic_update(s);
49
}
50
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/intc/trace-events
53
+++ b/hw/intc/trace-events
54
@@ -XXX,XX +XXX,XX @@ nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg wri
55
heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
56
heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
57
heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d"
58
+
59
+# bcm2835_ic.c
60
+bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d"
61
+bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d"
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The IRQ values are defined few lines earlier, use them instead of
4
the magic numbers.
5
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201017180731.1165871-3-f4bug@amsat.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/intc/bcm2836_control.c | 8 ++++----
12
1 file changed, 4 insertions(+), 4 deletions(-)
13
14
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2836_control.c
17
+++ b/hw/intc/bcm2836_control.c
18
@@ -XXX,XX +XXX,XX @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
19
20
static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
21
{
22
- bcm2836_control_set_local_irq(opaque, core, 0, level);
23
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level);
24
}
25
26
static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
27
{
28
- bcm2836_control_set_local_irq(opaque, core, 1, level);
29
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level);
30
}
31
32
static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
33
{
34
- bcm2836_control_set_local_irq(opaque, core, 2, level);
35
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTHPIRQ, level);
36
}
37
38
static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
39
{
40
- bcm2836_control_set_local_irq(opaque, core, 3, level);
41
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTVIRQ, level);
42
}
43
44
static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
1
In arm_cpu_realizefn(), if the CPU has VFP or Neon disabled then we
1
From: Richard Henderson <richard.henderson@linaro.org>
2
squash the ID register fields so that we don't advertise it to the
3
guest. This code was written for A-profile and needs some tweaks to
4
work correctly on M-profile:
5
2
6
* A-profile only fields should not be zeroed on M-profile:
3
Simplify freeing cp_regs hash table entries by using a single
7
- MVFR0.FPSHVEC,FPTRAP
4
allocation for the entire value.
8
- MVFR1.SIMDLS,SIMDINT,SIMDSP,SIMDHP
9
- MVFR2.SIMDMISC
10
* M-profile only fields should be zeroed on M-profile:
11
- MVFR1.FP16
12
5
13
In particular, because MVFR1.SIMDHP on A-profile is the same field as
6
This fixes a theoretical bug if we were to ever free the entire
14
MVFR1.FP16 on M-profile this code was incorrectly disabling FP16
7
hash table, because we've been installing string literal constants
15
support on an M-profile CPU (where has_neon is always false). This
8
into the cpreg structure in define_arm_vh_e2h_redirects_aliases.
16
isn't a visible bug yet because we don't have any M-profile CPUs with
9
However, at present we only free entries created for AArch32
17
FP16 support, but the change is necessary before we introduce any.
10
wildcard cpregs which get overwritten by more specific cpregs,
11
so this bug is never exposed.
18
12
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 20220501055028.646596-13-richard.henderson@linaro.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Message-id: 20201019151301.2046-9-peter.maydell@linaro.org
22
---
17
---
23
target/arm/cpu.c | 29 ++++++++++++++++++-----------
18
target/arm/cpu.c | 16 +---------------
24
1 file changed, 18 insertions(+), 11 deletions(-)
19
target/arm/helper.c | 10 ++++++++--
20
2 files changed, 9 insertions(+), 17 deletions(-)
25
21
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
27
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.c
24
--- a/target/arm/cpu.c
29
+++ b/target/arm/cpu.c
25
+++ b/target/arm/cpu.c
30
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
26
@@ -XXX,XX +XXX,XX @@ uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz)
31
u = cpu->isar.mvfr0;
27
return (Aff1 << ARM_AFF1_SHIFT) | Aff0;
32
u = FIELD_DP32(u, MVFR0, FPSP, 0);
28
}
33
u = FIELD_DP32(u, MVFR0, FPDP, 0);
29
34
- u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
30
-static void cpreg_hashtable_data_destroy(gpointer data)
35
u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
31
-{
36
u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
32
- /*
37
- u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
33
- * Destroy function for cpu->cp_regs hashtable data entries.
38
u = FIELD_DP32(u, MVFR0, FPROUND, 0);
34
- * We must free the name string because it was g_strdup()ed in
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
35
- * add_cpreg_to_hashtable(). It's OK to cast away the 'const'
40
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
36
- * from r->name because we know we definitely allocated it.
41
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
37
- */
42
+ }
38
- ARMCPRegInfo *r = data;
43
cpu->isar.mvfr0 = u;
39
-
44
40
- g_free((void *)r->name);
45
u = cpu->isar.mvfr1;
41
- g_free(r);
46
u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
42
-}
47
u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
43
-
48
u = FIELD_DP32(u, MVFR1, FPHP, 0);
44
static void arm_cpu_initfn(Object *obj)
49
+ if (arm_feature(env, ARM_FEATURE_M)) {
45
{
50
+ u = FIELD_DP32(u, MVFR1, FP16, 0);
46
ARMCPU *cpu = ARM_CPU(obj);
51
+ }
47
52
cpu->isar.mvfr1 = u;
48
cpu_set_cpustate_pointers(cpu);
53
49
cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
54
u = cpu->isar.mvfr2;
50
- NULL, cpreg_hashtable_data_destroy);
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
51
+ NULL, g_free);
56
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
52
57
cpu->isar.id_isar6 = u;
53
QLIST_INIT(&cpu->pre_el_change_hooks);
58
54
QLIST_INIT(&cpu->el_change_hooks);
59
- u = cpu->isar.mvfr1;
55
diff --git a/target/arm/helper.c b/target/arm/helper.c
60
- u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
56
index XXXXXXX..XXXXXXX 100644
61
- u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
57
--- a/target/arm/helper.c
62
- u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
58
+++ b/target/arm/helper.c
63
- u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
59
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
64
- cpu->isar.mvfr1 = u;
60
* add a single reginfo struct to the hash table.
65
+ if (!arm_feature(env, ARM_FEATURE_M)) {
61
*/
66
+ u = cpu->isar.mvfr1;
62
uint32_t key;
67
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
63
- ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
68
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
64
+ ARMCPRegInfo *r2;
69
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
65
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
70
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
66
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
71
+ cpu->isar.mvfr1 = u;
67
+ size_t name_len;
72
68
+
73
- u = cpu->isar.mvfr2;
69
+ /* Combine cpreg and name into one allocation. */
74
- u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
70
+ name_len = strlen(name) + 1;
75
- cpu->isar.mvfr2 = u;
71
+ r2 = g_malloc(sizeof(*r2) + name_len);
76
+ u = cpu->isar.mvfr2;
72
+ *r2 = *r;
77
+ u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
73
+ r2->name = memcpy(r2 + 1, name, name_len);
78
+ cpu->isar.mvfr2 = u;
74
79
+ }
75
- r2->name = g_strdup(name);
80
}
76
/* Reset the secure state to the specific incoming state. This is
81
77
* necessary as the register may have been defined with both states.
82
if (!cpu->has_neon && !cpu->has_vfp) {
78
*/
83
--
79
--
84
2.20.1
80
2.25.1
85
86
diff view generated by jsdifflib
1
v8.1M brings four new insns to M-profile:
1
From: Richard Henderson <richard.henderson@linaro.org>
2
* CSEL : Rd = cond ? Rn : Rm
3
* CSINC : Rd = cond ? Rn : Rm+1
4
* CSINV : Rd = cond ? Rn : ~Rm
5
* CSNEG : Rd = cond ? Rn : -Rm
6
2
7
Implement these.
3
Move the computation of key to the top of the function.
4
Hoist the resolution of cp as well, as an input to the
5
computation of key.
8
6
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
This will be required by a subsequent patch.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20220501055028.646596-14-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
12
---
13
---
13
target/arm/t32.decode | 3 +++
14
target/arm/helper.c | 49 +++++++++++++++++++++++++--------------------
14
target/arm/translate.c | 60 ++++++++++++++++++++++++++++++++++++++++++
15
1 file changed, 27 insertions(+), 22 deletions(-)
15
2 files changed, 63 insertions(+)
16
16
17
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/t32.decode
19
--- a/target/arm/helper.c
20
+++ b/target/arm/t32.decode
20
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
21
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
22
}
22
ARMCPRegInfo *r2;
23
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
23
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
24
24
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
25
+# v8.1M CSEL and friends
25
+ int cp = r->cp;
26
+CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
26
size_t name_len;
27
+
27
28
# Data-processing (register-shifted register)
28
+ switch (state) {
29
29
+ case ARM_CP_STATE_AA32:
30
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
30
+ /* We assume it is a cp15 register if the .cp field is left unset. */
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
31
+ if (cp == 0 && r->state == ARM_CP_STATE_BOTH) {
32
index XXXXXXX..XXXXXXX 100644
32
+ cp = 15;
33
--- a/target/arm/translate.c
33
+ }
34
+++ b/target/arm/translate.c
34
+ key = ENCODE_CP_REG(cp, is64, ns, r->crn, crm, opc1, opc2);
35
@@ -XXX,XX +XXX,XX @@ static bool trans_IT(DisasContext *s, arg_IT *a)
36
return true;
37
}
38
39
+/* v8.1M CSEL/CSINC/CSNEG/CSINV */
40
+static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
41
+{
42
+ TCGv_i32 rn, rm, zero;
43
+ DisasCompare c;
44
+
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
46
+ return false;
47
+ }
48
+
49
+ if (a->rm == 13) {
50
+ /* SEE "Related encodings" (MVE shifts) */
51
+ return false;
52
+ }
53
+
54
+ if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
55
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
56
+ return false;
57
+ }
58
+
59
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
60
+ if (a->rn == 15) {
61
+ rn = tcg_const_i32(0);
62
+ } else {
63
+ rn = load_reg(s, a->rn);
64
+ }
65
+ if (a->rm == 15) {
66
+ rm = tcg_const_i32(0);
67
+ } else {
68
+ rm = load_reg(s, a->rm);
69
+ }
70
+
71
+ switch (a->op) {
72
+ case 0: /* CSEL */
73
+ break;
35
+ break;
74
+ case 1: /* CSINC */
36
+ case ARM_CP_STATE_AA64:
75
+ tcg_gen_addi_i32(rm, rm, 1);
37
+ /*
76
+ break;
38
+ * To allow abbreviation of ARMCPRegInfo definitions, we treat
77
+ case 2: /* CSINV */
39
+ * cp == 0 as equivalent to the value for "standard guest-visible
78
+ tcg_gen_not_i32(rm, rm);
40
+ * sysreg". STATE_BOTH definitions are also always "standard sysreg"
79
+ break;
41
+ * in their AArch64 view (the .cp value may be non-zero for the
80
+ case 3: /* CSNEG */
42
+ * benefit of the AArch32 view).
81
+ tcg_gen_neg_i32(rm, rm);
43
+ */
44
+ if (cp == 0 || r->state == ARM_CP_STATE_BOTH) {
45
+ cp = CP_REG_ARM64_SYSREG_CP;
46
+ }
47
+ key = ENCODE_AA64_CP_REG(cp, r->crn, crm, r->opc0, opc1, opc2);
82
+ break;
48
+ break;
83
+ default:
49
+ default:
84
+ g_assert_not_reached();
50
+ g_assert_not_reached();
85
+ }
51
+ }
86
+
52
+
87
+ arm_test_cc(&c, a->fcond);
53
/* Combine cpreg and name into one allocation. */
88
+ zero = tcg_const_i32(0);
54
name_len = strlen(name) + 1;
89
+ tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
55
r2 = g_malloc(sizeof(*r2) + name_len);
90
+ arm_free_cc(&c);
56
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
91
+ tcg_temp_free_i32(zero);
57
}
92
+
58
93
+ store_reg(s, a->rd, rn);
59
if (r->state == ARM_CP_STATE_BOTH) {
94
+ tcg_temp_free_i32(rm);
60
- /* We assume it is a cp15 register if the .cp field is left unset.
95
+
61
- */
96
+ return true;
62
- if (r2->cp == 0) {
97
+}
63
- r2->cp = 15;
98
+
64
- }
99
/*
65
-
100
* Legacy decoder.
66
#if HOST_BIG_ENDIAN
101
*/
67
if (r2->fieldoffset) {
68
r2->fieldoffset += sizeof(uint32_t);
69
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
70
#endif
71
}
72
}
73
- if (state == ARM_CP_STATE_AA64) {
74
- /* To allow abbreviation of ARMCPRegInfo
75
- * definitions, we treat cp == 0 as equivalent to
76
- * the value for "standard guest-visible sysreg".
77
- * STATE_BOTH definitions are also always "standard
78
- * sysreg" in their AArch64 view (the .cp value may
79
- * be non-zero for the benefit of the AArch32 view).
80
- */
81
- if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) {
82
- r2->cp = CP_REG_ARM64_SYSREG_CP;
83
- }
84
- key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
85
- r2->opc0, opc1, opc2);
86
- } else {
87
- key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
88
- }
89
if (opaque) {
90
r2->opaque = opaque;
91
}
92
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
93
/* Make sure reginfo passed to helpers for wildcarded regs
94
* has the correct crm/opc1/opc2 for this reg, not CP_ANY:
95
*/
96
+ r2->cp = cp;
97
r2->crm = crm;
98
r2->opc1 = opc1;
99
r2->opc2 = opc2;
102
--
100
--
103
2.20.1
101
2.25.1
104
105
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Fixing this now will clarify following patches.
3
Put most of the value writeback to the same place,
4
and improve the comment that goes with them.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20201016184207.786698-6-richard.henderson@linaro.org
8
Message-id: 20220501055028.646596-15-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
linux-user/elfload.c | 12 +++++++++---
11
target/arm/helper.c | 28 ++++++++++++----------------
11
1 file changed, 9 insertions(+), 3 deletions(-)
12
1 file changed, 12 insertions(+), 16 deletions(-)
12
13
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
--- a/target/arm/helper.c
16
+++ b/linux-user/elfload.c
17
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
19
*r2 = *r;
19
int elf_prot = 0;
20
r2->name = memcpy(r2 + 1, name, name_len);
20
21
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
22
- /* Reset the secure state to the specific incoming state. This is
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
23
- * necessary as the register may have been defined with both states.
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
24
+ /*
24
+ if (eppnt->p_flags & PF_R) {
25
+ * Update fields to match the instantiation, overwiting wildcards
25
+ elf_prot |= PROT_READ;
26
+ * such as CP_ANY, ARM_CP_STATE_BOTH, or ARM_CP_SECSTATE_BOTH.
26
+ }
27
*/
27
+ if (eppnt->p_flags & PF_W) {
28
+ r2->cp = cp;
28
+ elf_prot |= PROT_WRITE;
29
+ r2->crm = crm;
29
+ }
30
+ r2->opc1 = opc1;
30
+ if (eppnt->p_flags & PF_X) {
31
+ r2->opc2 = opc2;
31
+ elf_prot |= PROT_EXEC;
32
+ r2->state = state;
32
+ }
33
r2->secure = secstate;
33
34
+ if (opaque) {
34
vaddr = load_bias + eppnt->p_vaddr;
35
+ r2->opaque = opaque;
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
36
+ }
37
38
if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
39
/* Register is banked (using both entries in array).
40
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
41
#endif
42
}
43
}
44
- if (opaque) {
45
- r2->opaque = opaque;
46
- }
47
- /* reginfo passed to helpers is correct for the actual access,
48
- * and is never ARM_CP_STATE_BOTH:
49
- */
50
- r2->state = state;
51
- /* Make sure reginfo passed to helpers for wildcarded regs
52
- * has the correct crm/opc1/opc2 for this reg, not CP_ANY:
53
- */
54
- r2->cp = cp;
55
- r2->crm = crm;
56
- r2->opc1 = opc1;
57
- r2->opc2 = opc2;
58
+
59
/* By convention, for wildcarded registers only the first
60
* entry is used for migration; the others are marked as
61
* ALIAS so we don't try to transfer the register
36
--
62
--
37
2.20.1
63
2.25.1
38
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We already have the full ARMMMUIdx as computed from the
3
Bool is a more appropriate type for these variables.
4
function parameter.
5
6
For the purpose of regime_has_2_ranges, we can ignore any
7
difference between AccType_Normal and AccType_Unpriv, which
8
would be the only difference between the passed mmu_idx
9
and arm_mmu_idx_el.
10
4
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
7
Message-id: 20220501055028.646596-16-richard.henderson@linaro.org
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-2-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
9
---
18
target/arm/mte_helper.c | 3 +--
10
target/arm/helper.c | 4 ++--
19
1 file changed, 1 insertion(+), 2 deletions(-)
11
1 file changed, 2 insertions(+), 2 deletions(-)
20
12
21
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/mte_helper.c
15
--- a/target/arm/helper.c
24
+++ b/target/arm/mte_helper.c
16
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
17
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
26
18
*/
27
case 2:
19
uint32_t key;
28
/* Tag check fail causes asynchronous flag set. */
20
ARMCPRegInfo *r2;
29
- mmu_idx = arm_mmu_idx_el(env, el);
21
- int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
30
- if (regime_has_2_ranges(mmu_idx)) {
22
- int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
31
+ if (regime_has_2_ranges(arm_mmu_idx)) {
23
+ bool is64 = r->type & ARM_CP_64BIT;
32
select = extract64(dirty_ptr, 55, 1);
24
+ bool ns = secstate & ARM_CP_SECSTATE_NS;
33
} else {
25
int cp = r->cp;
34
select = 0;
26
size_t name_len;
27
35
--
28
--
36
2.20.1
29
2.25.1
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Peng Liang <liangpeng10@huawei.com>
2
1
3
VMStateDescription.fields should be end with VMSTATE_END_OF_LIST().
4
However, microbit_i2c_vmstate doesn't follow it. Let's change it.
5
6
Fixes: 9d68bf564e ("arm: Stub out NRF51 TWI magnetometer/accelerometer detection")
7
Reported-by: Euler Robot <euler.robot@huawei.com>
8
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20201019093401.2993833-1-liangpeng10@huawei.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/i2c/microbit_i2c.c | 1 +
14
1 file changed, 1 insertion(+)
15
16
diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/i2c/microbit_i2c.c
19
+++ b/hw/i2c/microbit_i2c.c
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription microbit_i2c_vmstate = {
21
.fields = (VMStateField[]) {
22
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
23
VMSTATE_UINT32(read_idx, MicrobitI2CState),
24
+ VMSTATE_END_OF_LIST()
25
},
26
};
27
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Fix an unlikely memory leak in load_elf_image().
3
Computing isbanked only once makes the code
4
a bit easier to read.
4
5
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201016184207.786698-5-richard.henderson@linaro.org
9
Message-Id: <20201003174944.1972444-1-f4bug@amsat.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220501055028.646596-17-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
linux-user/elfload.c | 8 ++++----
11
target/arm/helper.c | 6 ++++--
15
1 file changed, 4 insertions(+), 4 deletions(-)
12
1 file changed, 4 insertions(+), 2 deletions(-)
16
13
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/linux-user/elfload.c
16
--- a/target/arm/helper.c
20
+++ b/linux-user/elfload.c
17
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
22
info->brk = vaddr_em;
19
bool is64 = r->type & ARM_CP_64BIT;
23
}
20
bool ns = secstate & ARM_CP_SECSTATE_NS;
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
21
int cp = r->cp;
25
- char *interp_name;
22
+ bool isbanked;
26
+ g_autofree char *interp_name = NULL;
23
size_t name_len;
27
24
28
if (*pinterp_name) {
25
switch (state) {
29
errmsg = "Multiple PT_INTERP entries";
26
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
30
goto exit_errmsg;
27
r2->opaque = opaque;
31
}
32
- interp_name = malloc(eppnt->p_filesz);
33
+ interp_name = g_malloc(eppnt->p_filesz);
34
if (!interp_name) {
35
goto exit_perror;
36
}
37
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
38
errmsg = "Invalid PT_INTERP entry";
39
goto exit_errmsg;
40
}
41
- *pinterp_name = interp_name;
42
+ *pinterp_name = g_steal_pointer(&interp_name);
43
#ifdef TARGET_MIPS
44
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
45
Mips_elf_abiflags_v0 abiflags;
46
@@ -XXX,XX +XXX,XX @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
47
if (elf_interpreter) {
48
info->load_bias = interp_info.load_bias;
49
info->entry = interp_info.entry;
50
- free(elf_interpreter);
51
+ g_free(elf_interpreter);
52
}
28
}
53
29
54
#ifdef USE_ELF_CORE_DUMP
30
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
31
+ isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
32
+ if (isbanked) {
33
/* Register is banked (using both entries in array).
34
* Overwriting fieldoffset as the array is only used to define
35
* banked registers but later only fieldoffset is used.
36
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
37
}
38
39
if (state == ARM_CP_STATE_AA32) {
40
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
41
+ if (isbanked) {
42
/* If the register is banked then we don't need to migrate or
43
* reset the 32-bit instance in certain cases:
44
*
55
--
45
--
56
2.20.1
46
2.25.1
57
58
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This is generic support, with the code disabled for all targets.
3
Perform the override check early, so that it is still done
4
even when we decide to discard an unreachable cpreg.
5
6
Use assert not printf+abort.
4
7
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201016184207.786698-11-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20220501055028.646596-18-richard.henderson@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
linux-user/qemu.h | 4 ++
13
target/arm/helper.c | 22 ++++++++--------------
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
14
1 file changed, 8 insertions(+), 14 deletions(-)
12
2 files changed, 161 insertions(+)
13
15
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/qemu.h
18
--- a/target/arm/helper.c
17
+++ b/linux-user/qemu.h
19
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
20
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
19
abi_ulong interpreter_loadmap_addr;
21
g_assert_not_reached();
20
abi_ulong interpreter_pt_dynamic_addr;
22
}
21
struct image_info *other_info;
23
22
+
24
+ /* Overriding of an existing definition must be explicitly requested. */
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
25
+ if (!(r->type & ARM_CP_OVERRIDE)) {
24
+ uint32_t note_flags;
26
+ const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
25
+
27
+ if (oldreg) {
26
#ifdef TARGET_MIPS
28
+ assert(oldreg->type & ARM_CP_OVERRIDE);
27
int fp_abi;
28
int interp_fp_abi;
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/linux-user/elfload.c
32
+++ b/linux-user/elfload.c
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
34
35
#include "elf.h"
36
37
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
38
+ const uint32_t *data,
39
+ struct image_info *info,
40
+ Error **errp)
41
+{
42
+ g_assert_not_reached();
43
+}
44
+#define ARCH_USE_GNU_PROPERTY 0
45
+
46
struct exec
47
{
48
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
49
@@ -XXX,XX +XXX,XX @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
50
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
51
}
52
53
+enum {
54
+ /* The string "GNU\0" as a magic number. */
55
+ GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
56
+ NOTE_DATA_SZ = 1 * KiB,
57
+ NOTE_NAME_SZ = 4,
58
+ ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
59
+};
60
+
61
+/*
62
+ * Process a single gnu_property entry.
63
+ * Return false for error.
64
+ */
65
+static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
66
+ struct image_info *info, bool have_prev_type,
67
+ uint32_t *prev_type, Error **errp)
68
+{
69
+ uint32_t pr_type, pr_datasz, step;
70
+
71
+ if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
72
+ goto error_data;
73
+ }
74
+ datasz -= *off;
75
+ data += *off / sizeof(uint32_t);
76
+
77
+ if (datasz < 2 * sizeof(uint32_t)) {
78
+ goto error_data;
79
+ }
80
+ pr_type = data[0];
81
+ pr_datasz = data[1];
82
+ data += 2;
83
+ datasz -= 2 * sizeof(uint32_t);
84
+ step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
85
+ if (step > datasz) {
86
+ goto error_data;
87
+ }
88
+
89
+ /* Properties are supposed to be unique and sorted on pr_type. */
90
+ if (have_prev_type && pr_type <= *prev_type) {
91
+ if (pr_type == *prev_type) {
92
+ error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
93
+ } else {
94
+ error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
95
+ }
96
+ return false;
97
+ }
98
+ *prev_type = pr_type;
99
+
100
+ if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
101
+ return false;
102
+ }
103
+
104
+ *off += 2 * sizeof(uint32_t) + step;
105
+ return true;
106
+
107
+ error_data:
108
+ error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
109
+ return false;
110
+}
111
+
112
+/* Process NT_GNU_PROPERTY_TYPE_0. */
113
+static bool parse_elf_properties(int image_fd,
114
+ struct image_info *info,
115
+ const struct elf_phdr *phdr,
116
+ char bprm_buf[BPRM_BUF_SIZE],
117
+ Error **errp)
118
+{
119
+ union {
120
+ struct elf_note nhdr;
121
+ uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
122
+ } note;
123
+
124
+ int n, off, datasz;
125
+ bool have_prev_type;
126
+ uint32_t prev_type;
127
+
128
+ /* Unless the arch requires properties, ignore them. */
129
+ if (!ARCH_USE_GNU_PROPERTY) {
130
+ return true;
131
+ }
132
+
133
+ /* If the properties are crazy large, that's too bad. */
134
+ n = phdr->p_filesz;
135
+ if (n > sizeof(note)) {
136
+ error_setg(errp, "PT_GNU_PROPERTY too large");
137
+ return false;
138
+ }
139
+ if (n < sizeof(note.nhdr)) {
140
+ error_setg(errp, "PT_GNU_PROPERTY too small");
141
+ return false;
142
+ }
143
+
144
+ if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
145
+ memcpy(&note, bprm_buf + phdr->p_offset, n);
146
+ } else {
147
+ ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
148
+ if (len != n) {
149
+ error_setg_errno(errp, errno, "Error reading file header");
150
+ return false;
151
+ }
29
+ }
152
+ }
30
+ }
153
+
31
+
154
+ /*
32
/* Combine cpreg and name into one allocation. */
155
+ * The contents of a valid PT_GNU_PROPERTY is a sequence
33
name_len = strlen(name) + 1;
156
+ * of uint32_t -- swap them all now.
34
r2 = g_malloc(sizeof(*r2) + name_len);
157
+ */
35
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
158
+#ifdef BSWAP_NEEDED
36
assert(!raw_accessors_invalid(r2));
159
+ for (int i = 0; i < n / 4; i++) {
160
+ bswap32s(note.data + i);
161
+ }
162
+#endif
163
+
164
+ /*
165
+ * Note that nhdr is 3 words, and that the "name" described by namesz
166
+ * immediately follows nhdr and is thus at the 4th word. Further, all
167
+ * of the inputs to the kernel's round_up are multiples of 4.
168
+ */
169
+ if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
170
+ note.nhdr.n_namesz != NOTE_NAME_SZ ||
171
+ note.data[3] != GNU0_MAGIC) {
172
+ error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
173
+ return false;
174
+ }
175
+ off = sizeof(note.nhdr) + NOTE_NAME_SZ;
176
+
177
+ datasz = note.nhdr.n_descsz + off;
178
+ if (datasz > n) {
179
+ error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
180
+ return false;
181
+ }
182
+
183
+ have_prev_type = false;
184
+ prev_type = 0;
185
+ while (1) {
186
+ if (off == datasz) {
187
+ return true; /* end, exit ok */
188
+ }
189
+ if (!parse_elf_property(note.data, &off, datasz, info,
190
+ have_prev_type, &prev_type, errp)) {
191
+ return false;
192
+ }
193
+ have_prev_type = true;
194
+ }
195
+}
196
+
197
/* Load an ELF image into the address space.
198
199
IMAGE_NAME is the filename of the image, to use in error messages.
200
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
201
goto exit_errmsg;
202
}
203
*pinterp_name = g_steal_pointer(&interp_name);
204
+ } else if (eppnt->p_type == PT_GNU_PROPERTY) {
205
+ if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
206
+ goto exit_errmsg;
207
+ }
208
}
209
}
37
}
210
38
39
- /* Overriding of an existing definition must be explicitly
40
- * requested.
41
- */
42
- if (!(r->type & ARM_CP_OVERRIDE)) {
43
- const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
44
- if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
45
- fprintf(stderr, "Register redefined: cp=%d %d bit "
46
- "crn=%d crm=%d opc1=%d opc2=%d, "
47
- "was %s, now %s\n", r2->cp, 32 + 32 * is64,
48
- r2->crn, r2->crm, r2->opc1, r2->opc2,
49
- oldreg->name, r2->name);
50
- g_assert_not_reached();
51
- }
52
- }
53
g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
54
}
55
211
--
56
--
212
2.20.1
57
2.25.1
213
214
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
For BTI, we need to know if the executable is static or dynamic,
3
Put the block comments into the current coding style.
4
which means looking for PT_INTERP earlier.
5
4
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201016184207.786698-8-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220501055028.646596-19-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
10
target/arm/helper.c | 24 +++++++++++++++---------
12
1 file changed, 31 insertions(+), 29 deletions(-)
11
1 file changed, 15 insertions(+), 9 deletions(-)
13
12
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
15
--- a/target/arm/helper.c
17
+++ b/linux-user/elfload.c
16
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
17
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
19
18
return cpu_list;
20
mmap_lock();
19
}
21
20
22
- /* Find the maximum size of the image and allocate an appropriate
21
+/*
23
- amount of memory to handle that. */
22
+ * Private utility function for define_one_arm_cp_reg_with_opaque():
24
+ /*
23
+ * add a single reginfo struct to the hash table.
25
+ * Find the maximum size of the image and allocate an appropriate
24
+ */
26
+ * amount of memory to handle that. Locate the interpreter, if any.
25
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
27
+ */
26
void *opaque, CPState state,
28
loaddr = -1, hiaddr = 0;
27
CPSecureState secstate,
29
info->alignment = 0;
28
int crm, int opc1, int opc2,
30
for (i = 0; i < ehdr->e_phnum; ++i) {
29
const char *name)
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
30
{
31
- /* Private utility function for define_one_arm_cp_reg_with_opaque():
32
- * add a single reginfo struct to the hash table.
33
- */
34
uint32_t key;
35
ARMCPRegInfo *r2;
36
bool is64 = r->type & ARM_CP_64BIT;
37
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
38
39
isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
40
if (isbanked) {
41
- /* Register is banked (using both entries in array).
42
+ /*
43
+ * Register is banked (using both entries in array).
44
* Overwriting fieldoffset as the array is only used to define
45
* banked registers but later only fieldoffset is used.
46
*/
47
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
48
49
if (state == ARM_CP_STATE_AA32) {
50
if (isbanked) {
51
- /* If the register is banked then we don't need to migrate or
52
+ /*
53
+ * If the register is banked then we don't need to migrate or
54
* reset the 32-bit instance in certain cases:
55
*
56
* 1) If the register has both 32-bit and 64-bit instances then we
57
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
58
r2->type |= ARM_CP_ALIAS;
32
}
59
}
33
++info->nsegs;
60
} else if ((secstate != r->secure) && !ns) {
34
info->alignment |= eppnt->p_align;
61
- /* The register is not banked so we only want to allow migration of
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
62
- * the non-secure instance.
36
+ g_autofree char *interp_name = NULL;
63
+ /*
37
+
64
+ * The register is not banked so we only want to allow migration
38
+ if (*pinterp_name) {
65
+ * of the non-secure instance.
39
+ errmsg = "Multiple PT_INTERP entries";
66
*/
40
+ goto exit_errmsg;
67
r2->type |= ARM_CP_ALIAS;
41
+ }
68
}
42
+ interp_name = g_malloc(eppnt->p_filesz);
69
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
43
+ if (!interp_name) {
44
+ goto exit_perror;
45
+ }
46
+
47
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
48
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
49
+ eppnt->p_filesz);
50
+ } else {
51
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
52
+ eppnt->p_offset);
53
+ if (retval != eppnt->p_filesz) {
54
+ goto exit_perror;
55
+ }
56
+ }
57
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
58
+ errmsg = "Invalid PT_INTERP entry";
59
+ goto exit_errmsg;
60
+ }
61
+ *pinterp_name = g_steal_pointer(&interp_name);
62
}
70
}
63
}
71
}
64
72
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
73
- /* By convention, for wildcarded registers only the first
66
if (vaddr_em > info->brk) {
74
+ /*
67
info->brk = vaddr_em;
75
+ * By convention, for wildcarded registers only the first
68
}
76
* entry is used for migration; the others are marked as
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
77
* ALIAS so we don't try to transfer the register
70
- g_autofree char *interp_name = NULL;
78
* multiple times. Special registers (ie NOP/WFI) are
71
-
79
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
72
- if (*pinterp_name) {
80
r2->type |= ARM_CP_ALIAS | ARM_CP_NO_GDB;
73
- errmsg = "Multiple PT_INTERP entries";
81
}
74
- goto exit_errmsg;
82
75
- }
83
- /* Check that raw accesses are either forbidden or handled. Note that
76
- interp_name = g_malloc(eppnt->p_filesz);
84
+ /*
77
- if (!interp_name) {
85
+ * Check that raw accesses are either forbidden or handled. Note that
78
- goto exit_perror;
86
* we can't assert this earlier because the setup of fieldoffset for
79
- }
87
* banked registers has to be done first.
80
-
88
*/
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
83
- eppnt->p_filesz);
84
- } else {
85
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
86
- eppnt->p_offset);
87
- if (retval != eppnt->p_filesz) {
88
- goto exit_perror;
89
- }
90
- }
91
- if (interp_name[eppnt->p_filesz - 1] != 0) {
92
- errmsg = "Invalid PT_INTERP entry";
93
- goto exit_errmsg;
94
- }
95
- *pinterp_name = g_steal_pointer(&interp_name);
96
#ifdef TARGET_MIPS
97
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
98
Mips_elf_abiflags_v0 abiflags;
99
--
89
--
100
2.20.1
90
2.25.1
101
102
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 second loop uses a loop induction variable, and the first
3
Since e03b56863d2bc, our host endian indicator is unconditionally
4
does not. Transform the first to match the second, to simplify
4
set, which means that we can use a normal C condition.
5
a following patch moving code between them.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20201016184207.786698-7-richard.henderson@linaro.org
8
Message-id: 20220501055028.646596-20-richard.henderson@linaro.org
9
[PMM: quote correct git hash in commit message]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
linux-user/elfload.c | 9 +++++----
12
target/arm/helper.c | 9 +++------
13
1 file changed, 5 insertions(+), 4 deletions(-)
13
1 file changed, 3 insertions(+), 6 deletions(-)
14
14
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
17
--- a/target/arm/helper.c
18
+++ b/linux-user/elfload.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
19
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
20
loaddr = -1, hiaddr = 0;
20
r2->type |= ARM_CP_ALIAS;
21
info->alignment = 0;
21
}
22
for (i = 0; i < ehdr->e_phnum; ++i) {
22
23
- if (phdr[i].p_type == PT_LOAD) {
23
- if (r->state == ARM_CP_STATE_BOTH) {
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
24
-#if HOST_BIG_ENDIAN
25
+ struct elf_phdr *eppnt = phdr + i;
25
- if (r2->fieldoffset) {
26
+ if (eppnt->p_type == PT_LOAD) {
26
- r2->fieldoffset += sizeof(uint32_t);
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
27
- }
28
if (a < loaddr) {
28
-#endif
29
loaddr = a;
29
+ if (HOST_BIG_ENDIAN &&
30
}
30
+ r->state == ARM_CP_STATE_BOTH && r2->fieldoffset) {
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
31
+ r2->fieldoffset += sizeof(uint32_t);
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
33
if (a > hiaddr) {
34
hiaddr = a;
35
}
36
++info->nsegs;
37
- info->alignment |= phdr[i].p_align;
38
+ info->alignment |= eppnt->p_align;
39
}
32
}
40
}
33
}
41
34
42
--
35
--
43
2.20.1
36
2.25.1
44
45
diff view generated by jsdifflib
1
v8.1M implements a new 'branch future' feature, which is a
1
From: Richard Henderson <richard.henderson@linaro.org>
2
set of instructions that request the CPU to perform a branch
3
"in the future", when it reaches a particular execution address.
4
In hardware, the expected implementation is that the information
5
about the branch location and destination is cached and then
6
acted upon when execution reaches the specified address.
7
However the architecture permits an implementation to discard
8
this cached information at any point, and so guest code must
9
always include a normal branch insn at the branch point as
10
a fallback. In particular, an implementation is specifically
11
permitted to treat all BF insns as NOPs (which is equivalent
12
to discarding the cached information immediately).
13
2
14
For QEMU, implementing this caching of branch information
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
would be complicated and would not improve the speed of
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
execution at all, so we make the IMPDEF choice to implement
5
Message-id: 20220501055028.646596-24-richard.henderson@linaro.org
17
all BF insns as NOPs.
18
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Message-id: 20201019151301.2046-7-peter.maydell@linaro.org
22
---
7
---
23
target/arm/cpu.h | 6 ++++++
8
target/arm/cpu.h | 15 +++++++++++++++
24
target/arm/t32.decode | 13 ++++++++++++-
9
1 file changed, 15 insertions(+)
25
target/arm/translate.c | 20 ++++++++++++++++++++
26
3 files changed, 38 insertions(+), 1 deletion(-)
27
10
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
13
--- a/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
14
+++ b/target/arm/cpu.h
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
15
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
33
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
16
return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
34
}
17
}
35
18
36
+static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
19
+static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
37
+{
20
+{
38
+ /* (M-profile) low-overhead loops and branch future */
21
+ return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8;
39
+ return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
40
+}
22
+}
41
+
23
+
42
static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
24
/*
43
{
25
* 64-bit feature tests via id registers.
44
return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
26
*/
45
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
27
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
46
index XXXXXXX..XXXXXXX 100644
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
47
--- a/target/arm/t32.decode
29
}
48
+++ b/target/arm/t32.decode
30
49
@@ -XXX,XX +XXX,XX @@ MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr
31
+static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id)
50
51
B 1111 0. .......... 10.1 ............ @branch24
52
BL 1111 0. .......... 11.1 ............ @branch24
53
-BLX_i 1111 0. .......... 11.0 ............ @branch24
54
+{
32
+{
55
+ # BLX_i is non-M-profile only
33
+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8;
56
+ BLX_i 1111 0. .......... 11.0 ............ @branch24
57
+ # M-profile only: loop and branch insns
58
+ [
59
+ # All these BF insns have boff != 0b0000; we NOP them all
60
+ BF 1111 0 boff:4 ------- 1100 - ---------- 1 # BFL
61
+ BF 1111 0 boff:4 0 ------ 1110 - ---------- 1 # BFCSEL
62
+ BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
63
+ BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
64
+ ]
65
+}
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate.c
69
+++ b/target/arm/translate.c
70
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
71
return true;
72
}
73
74
+static bool trans_BF(DisasContext *s, arg_BF *a)
75
+{
76
+ /*
77
+ * M-profile branch future insns. The architecture permits an
78
+ * implementation to implement these as NOPs (equivalent to
79
+ * discarding the LO_BRANCH_INFO cache immediately), and we
80
+ * take that IMPDEF option because for QEMU a "real" implementation
81
+ * would be complicated and wouldn't execute any faster.
82
+ */
83
+ if (!dc_isar_feature(aa32_lob, s)) {
84
+ return false;
85
+ }
86
+ if (a->boff == 0) {
87
+ /* SEE "Related encodings" (loop insns) */
88
+ return false;
89
+ }
90
+ /* Handle as NOP */
91
+ return true;
92
+}
34
+}
93
+
35
+
94
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
36
static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
95
{
37
{
96
TCGv_i32 addr, tmp;
38
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0;
39
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
40
return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
41
}
42
43
+static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
44
+{
45
+ return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
46
+}
47
+
48
/*
49
* Forward to the above feature tests given an ARMCPU pointer.
50
*/
97
--
51
--
98
2.20.1
52
2.25.1
99
100
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Transform the prot bit to a qemu internal page bit, and save
3
Add the aa64 predicate for detecting RAS support from id registers.
4
it in the page tables.
4
We already have the aa32 version from the M-profile work.
5
Add the 'any' predicate for testing both aa64 and aa32.
5
6
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201016184207.786698-3-richard.henderson@linaro.org
9
Message-id: 20220501055028.646596-34-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
include/exec/cpu-all.h | 2 ++
12
target/arm/cpu.h | 10 ++++++++++
12
linux-user/syscall_defs.h | 4 ++++
13
1 file changed, 10 insertions(+)
13
target/arm/cpu.h | 5 +++++
14
linux-user/mmap.c | 16 ++++++++++++++++
15
target/arm/translate-a64.c | 6 +++---
16
5 files changed, 30 insertions(+), 3 deletions(-)
17
14
18
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/cpu-all.h
21
+++ b/include/exec/cpu-all.h
22
@@ -XXX,XX +XXX,XX @@ extern intptr_t qemu_host_page_mask;
23
/* FIXME: Code that sets/uses this is broken and needs to go away. */
24
#define PAGE_RESERVED 0x0020
25
#endif
26
+/* Target-specific bits that will be used via page_get_flags(). */
27
+#define PAGE_TARGET_1 0x0080
28
29
#if defined(CONFIG_USER_ONLY)
30
void page_dump(FILE *f);
31
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/linux-user/syscall_defs.h
34
+++ b/linux-user/syscall_defs.h
35
@@ -XXX,XX +XXX,XX @@ struct target_winsize {
36
#define TARGET_PROT_SEM 0x08
37
#endif
38
39
+#ifdef TARGET_AARCH64
40
+#define TARGET_PROT_BTI 0x10
41
+#endif
42
+
43
/* Common */
44
#define TARGET_MAP_SHARED    0x01        /* Share changes */
45
#define TARGET_MAP_PRIVATE    0x02        /* Changes are private */
46
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
19
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
20
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
21
}
53
22
54
+/*
23
+static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
24
+{
56
+ */
25
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;
57
+#define PAGE_BTI PAGE_TARGET_1
26
+}
27
+
28
static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
29
{
30
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
32
return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
33
}
34
35
+static inline bool isar_feature_any_ras(const ARMISARegisters *id)
36
+{
37
+ return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id);
38
+}
58
+
39
+
59
/*
40
/*
60
* Naming convention for isar_feature functions:
41
* Forward to the above feature tests given an ARMCPU pointer.
61
* Functions which test 32-bit ID registers should have _aa32_ in
62
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/linux-user/mmap.c
65
+++ b/linux-user/mmap.c
66
@@ -XXX,XX +XXX,XX @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
67
*host_prot = (prot & (PROT_READ | PROT_WRITE))
68
| (prot & PROT_EXEC ? PROT_READ : 0);
69
70
+#ifdef TARGET_AARCH64
71
+ /*
72
+ * The PROT_BTI bit is only accepted if the cpu supports the feature.
73
+ * Since this is the unusual case, don't bother checking unless
74
+ * the bit has been requested. If set and valid, record the bit
75
+ * within QEMU's page_flags.
76
+ */
77
+ if (prot & TARGET_PROT_BTI) {
78
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
79
+ if (cpu_isar_feature(aa64_bti, cpu)) {
80
+ valid |= TARGET_PROT_BTI;
81
+ page_flags |= PAGE_BTI;
82
+ }
83
+ }
84
+#endif
85
+
86
return prot & ~valid ? 0 : page_flags;
87
}
88
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
94
*/
42
*/
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
96
{
97
-#ifdef CONFIG_USER_ONLY
98
- return false; /* FIXME */
99
-#else
100
uint64_t addr = s->base.pc_first;
101
+#ifdef CONFIG_USER_ONLY
102
+ return page_get_flags(addr) & PAGE_BTI;
103
+#else
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
105
unsigned int index = tlb_index(env, mmu_idx, addr);
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
107
--
43
--
108
2.20.1
44
2.25.1
109
110
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Alex Zuepke <alex.zuepke@tum.de>
2
2
3
Commit 7998beb9c2e removed the ram_size initialization in the
3
The ARMv8 manual defines that PMUSERENR_EL0.ER enables read-access
4
arm_boot_info structure, however it is used by arm_load_kernel().
4
to both PMXEVCNTR_EL0 and PMEVCNTR<n>_EL0 registers, however,
5
we only use it for PMXEVCNTR_EL0. Extend to PMEVCNTR<n>_EL0 as well.
5
6
6
Initialize the field to fix:
7
Signed-off-by: Alex Zuepke <alex.zuepke@tum.de>
7
8
$ qemu-system-arm -M n800 -append 'console=ttyS1' \
9
-kernel meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0
10
qemu-system-arm: kernel 'meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0' is too large to fit in RAM (kernel size 1964608, RAM size 0)
11
12
Noticed while running the test introduced in commit 050a82f0c5b
13
("tests/acceptance: Add a test for the N800 and N810 arm machines").
14
15
Fixes: 7998beb9c2e ("arm/nseries: use memdev for RAM")
16
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Tested-by: Thomas Huth <thuth@redhat.com>
9
Message-id: 20220428132717.84190-1-alex.zuepke@tum.de
19
Message-id: 20201019095148.1602119-1-f4bug@amsat.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
11
---
22
hw/arm/nseries.c | 1 +
12
target/arm/helper.c | 4 ++--
23
1 file changed, 1 insertion(+)
13
1 file changed, 2 insertions(+), 2 deletions(-)
24
14
25
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/nseries.c
17
--- a/target/arm/helper.c
28
+++ b/hw/arm/nseries.c
18
+++ b/target/arm/helper.c
29
@@ -XXX,XX +XXX,XX @@ static void n8x0_init(MachineState *machine,
19
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
30
g_free(sz);
20
.crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
31
exit(EXIT_FAILURE);
21
.access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
32
}
22
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
33
+ binfo->ram_size = machine->ram_size;
23
- .accessfn = pmreg_access },
34
24
+ .accessfn = pmreg_access_xevcntr },
35
memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
25
{ .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
36
machine->ram);
26
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
27
- .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
28
+ .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access_xevcntr,
29
.type = ARM_CP_IO,
30
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
31
.raw_readfn = pmevcntr_rawread,
37
--
32
--
38
2.20.1
33
2.25.1
39
40
diff view generated by jsdifflib
Deleted patch
1
For nested groups like:
2
1
3
{
4
[
5
pattern 1
6
pattern 2
7
]
8
pattern 3
9
}
10
11
the intended behaviour is that patterns 1 and 2 must not
12
overlap with each other; if the insn matches neither then
13
we fall through to pattern 3 as the next thing in the
14
outer overlapping group.
15
16
Currently we generate incorrect code for this situation,
17
because in the code path for a failed match inside the
18
inner non-overlapping group we generate a "return" statement,
19
which causes decode to stop entirely rather than continuing
20
to the next thing in the outer group.
21
22
Generate a "break" instead, so that decode flow behaves
23
as required for this nested group case.
24
25
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Message-id: 20201019151301.2046-2-peter.maydell@linaro.org
29
---
30
scripts/decodetree.py | 2 +-
31
1 file changed, 1 insertion(+), 1 deletion(-)
32
33
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
34
index XXXXXXX..XXXXXXX 100644
35
--- a/scripts/decodetree.py
36
+++ b/scripts/decodetree.py
37
@@ -XXX,XX +XXX,XX @@ class Tree:
38
output(ind, ' /* ',
39
str_match_bits(innerbits, innermask), ' */\n')
40
s.output_code(i + 4, extracted, innerbits, innermask)
41
- output(ind, ' return false;\n')
42
+ output(ind, ' break;\n')
43
output(ind, '}\n')
44
# end Tree
45
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
From v8.1M, disabled-coprocessor handling changes slightly:
2
* coprocessors 8, 9, 14 and 15 are also governed by the
3
cp10 enable bit, like cp11
4
* an extra range of instruction patterns is considered
5
to be inside the coprocessor space
6
1
7
We previously marked these up with TODO comments; implement the
8
correct behaviour.
9
10
Unfortunately there is no ID register field which indicates this
11
behaviour. We could in theory test an unrelated ID register which
12
indicates guaranteed-to-be-in-v8.1M behaviour like ID_ISAR0.CmpBranch
13
>= 3 (low-overhead-loops), but it seems better to simply define a new
14
ARM_FEATURE_V8_1M feature flag and use it for this and other
15
new-in-v8.1M behaviour that isn't identifiable from the ID registers.
16
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20201019151301.2046-3-peter.maydell@linaro.org
20
---
21
target/arm/cpu.h | 1 +
22
target/arm/m-nocp.decode | 10 ++++++----
23
target/arm/translate-vfp.c.inc | 17 +++++++++++++++--
24
3 files changed, 22 insertions(+), 6 deletions(-)
25
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.h
29
+++ b/target/arm/cpu.h
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
31
ARM_FEATURE_VBAR, /* has cp15 VBAR */
32
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
33
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
34
+ ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
35
};
36
37
static inline int arm_feature(CPUARMState *env, int feature)
38
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/m-nocp.decode
41
+++ b/target/arm/m-nocp.decode
42
@@ -XXX,XX +XXX,XX @@
43
# If the coprocessor is not present or disabled then we will generate
44
# the NOCP exception; otherwise we let the insn through to the main decode.
45
46
+&nocp cp
47
+
48
{
49
# Special cases which do not take an early NOCP: VLLDM and VLSTM
50
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
51
# TODO: VSCCLRM (new in v8.1M) is similar:
52
#VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
53
54
- NOCP 111- 1110 ---- ---- ---- cp:4 ---- ----
55
- NOCP 111- 110- ---- ---- ---- cp:4 ---- ----
56
- # TODO: From v8.1M onwards we will also want this range to NOCP
57
- #NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- cp=10
58
+ NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
59
+ NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
60
+ # From v8.1M onwards this range will also NOCP:
61
+ NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10
62
}
63
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-vfp.c.inc
66
+++ b/target/arm/translate-vfp.c.inc
67
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
68
return true;
69
}
70
71
-static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
72
+static bool trans_NOCP(DisasContext *s, arg_nocp *a)
73
{
74
/*
75
* Handle M-profile early check for disabled coprocessor:
76
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
77
if (a->cp == 11) {
78
a->cp = 10;
79
}
80
- /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
81
+ if (arm_dc_feature(s, ARM_FEATURE_V8_1M) &&
82
+ (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) {
83
+ /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
84
+ a->cp = 10;
85
+ }
86
87
if (a->cp != 10) {
88
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
89
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
90
return false;
91
}
92
93
+static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a)
94
+{
95
+ /* This range needs a coprocessor check for v8.1M and later only */
96
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
97
+ return false;
98
+ }
99
+ return trans_NOCP(s, a);
100
+}
101
+
102
static bool trans_VINS(DisasContext *s, arg_VINS *a)
103
{
104
TCGv_i32 rd, rm;
105
--
106
2.20.1
107
108
diff view generated by jsdifflib
Deleted patch
1
The t32 decode has a group which represents a set of insns
2
which overlap with B_cond_thumb because they have [25:23]=111
3
(which is an invalid condition code field for the branch insn).
4
This group is currently defined using the {} overlap-OK syntax,
5
but it is almost entirely non-overlapping patterns. Switch
6
it over to use a non-overlapping group.
7
1
8
For this to be valid syntactically, CPS must move into the same
9
overlapping-group as the hint insns (CPS vs hints was the
10
only actual use of the overlap facility for the group).
11
12
The non-overlapping subgroup for CLREX/DSB/DMB/ISB/SB is no longer
13
necessary and so we can remove it (promoting those insns to
14
be members of the parent group).
15
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20201019151301.2046-5-peter.maydell@linaro.org
19
---
20
target/arm/t32.decode | 26 ++++++++++++--------------
21
1 file changed, 12 insertions(+), 14 deletions(-)
22
23
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/t32.decode
26
+++ b/target/arm/t32.decode
27
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
28
{
29
# Group insn[25:23] = 111, which is cond=111x for the branch below,
30
# or unconditional, which would be illegal for the branch.
31
- {
32
- # Hints
33
+ [
34
+ # Hints, and CPS
35
{
36
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
37
WFE 1111 0011 1010 1111 1000 0000 0000 0010
38
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
39
# The canonical nop ends in 0000 0000, but the whole rest
40
# of the space is "reserved hint, behaves as nop".
41
NOP 1111 0011 1010 1111 1000 0000 ---- ----
42
+
43
+ # If imod == '00' && M == '0' then SEE "Hint instructions", above.
44
+ CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
45
+ &cps
46
}
47
48
- # If imod == '00' && M == '0' then SEE "Hint instructions", above.
49
- CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
50
- &cps
51
-
52
# Miscellaneous control
53
- [
54
- CLREX 1111 0011 1011 1111 1000 1111 0010 1111
55
- DSB 1111 0011 1011 1111 1000 1111 0100 ----
56
- DMB 1111 0011 1011 1111 1000 1111 0101 ----
57
- ISB 1111 0011 1011 1111 1000 1111 0110 ----
58
- SB 1111 0011 1011 1111 1000 1111 0111 0000
59
- ]
60
+ CLREX 1111 0011 1011 1111 1000 1111 0010 1111
61
+ DSB 1111 0011 1011 1111 1000 1111 0100 ----
62
+ DMB 1111 0011 1011 1111 1000 1111 0101 ----
63
+ ISB 1111 0011 1011 1111 1000 1111 0110 ----
64
+ SB 1111 0011 1011 1111 1000 1111 0111 0000
65
66
# Note that the v7m insn overlaps both the normal and banked insn.
67
{
68
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
69
HVC 1111 0111 1110 .... 1000 .... .... .... \
70
&i imm=%imm16_16_0
71
UDF 1111 0111 1111 ---- 1010 ---- ---- ----
72
- }
73
+ ]
74
B_cond_thumb 1111 0. cond:4 ...... 10.0 ............ &ci imm=%imm21
75
}
76
77
--
78
2.20.1
79
80
diff view generated by jsdifflib
Deleted patch
1
The BLX immediate insn in the Thumb encoding always performs
2
a switch from Thumb to Arm state. This would be totally useless
3
in M-profile which has no Arm decoder, and so the instruction
4
does not exist at all there. Make the encoding UNDEF for M-profile.
5
1
6
(This part of the encoding space is used for the branch-future
7
and low-overhead-loop insns in v8.1M.)
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-6-peter.maydell@linaro.org
12
---
13
target/arm/translate.c | 8 ++++++++
14
1 file changed, 8 insertions(+)
15
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
21
{
22
TCGv_i32 tmp;
23
24
+ /*
25
+ * BLX <imm> would be useless on M-profile; the encoding space
26
+ * is used for other insns from v8.1M onward, and UNDEFs before that.
27
+ */
28
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
29
+ return false;
30
+ }
31
+
32
/* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
33
if (s->thumb && (a->imm & 2)) {
34
return false;
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
v8.1M's "low-overhead-loop" extension has three instructions
2
for looping:
3
* DLS (start of a do-loop)
4
* WLS (start of a while-loop)
5
* LE (end of a loop)
6
1
7
The loop-start instructions are both simple operations to start a
8
loop whose iteration count (if any) is in LR. The loop-end
9
instruction handles "decrement iteration count and jump back to loop
10
start"; it also caches the information about the branch back to the
11
start of the loop to improve performance of the branch on subsequent
12
iterations.
13
14
As with the branch-future instructions, the architecture permits an
15
implementation to discard the LO_BRANCH_INFO cache at any time, and
16
QEMU takes the IMPDEF option to never set it in the first place
17
(equivalent to discarding it immediately), because for us a "real"
18
implementation would be unnecessary complexity.
19
20
(This implementation only provides the simple looping constructs; the
21
vector extension MVE (Helium) adds some extra variants to handle
22
looping across vectors. We'll add those later when we implement
23
MVE.)
24
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20201019151301.2046-8-peter.maydell@linaro.org
28
---
29
target/arm/t32.decode | 8 ++++
30
target/arm/translate.c | 93 +++++++++++++++++++++++++++++++++++++++++-
31
2 files changed, 99 insertions(+), 2 deletions(-)
32
33
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/t32.decode
36
+++ b/target/arm/t32.decode
37
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
38
BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
39
BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
40
]
41
+ [
42
+ # LE and WLS immediate
43
+ %lob_imm 1:10 11:1 !function=times_2
44
+
45
+ DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
46
+ WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm
47
+ LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
48
+ ]
49
}
50
diff --git a/target/arm/translate.c b/target/arm/translate.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate.c
53
+++ b/target/arm/translate.c
54
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
55
s->base.is_jmp = DISAS_NORETURN;
56
}
57
58
-static inline void gen_jmp (DisasContext *s, uint32_t dest)
59
+/* Jump, specifying which TB number to use if we gen_goto_tb() */
60
+static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
61
{
62
if (unlikely(is_singlestepping(s))) {
63
/* An indirect jump so that we still trigger the debug exception. */
64
gen_set_pc_im(s, dest);
65
s->base.is_jmp = DISAS_JUMP;
66
} else {
67
- gen_goto_tb(s, 0, dest);
68
+ gen_goto_tb(s, tbno, dest);
69
}
70
}
71
72
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
73
+{
74
+ gen_jmp_tb(s, dest, 0);
75
+}
76
+
77
static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
78
{
79
if (x)
80
@@ -XXX,XX +XXX,XX @@ static bool trans_BF(DisasContext *s, arg_BF *a)
81
return true;
82
}
83
84
+static bool trans_DLS(DisasContext *s, arg_DLS *a)
85
+{
86
+ /* M-profile low-overhead loop start */
87
+ TCGv_i32 tmp;
88
+
89
+ if (!dc_isar_feature(aa32_lob, s)) {
90
+ return false;
91
+ }
92
+ if (a->rn == 13 || a->rn == 15) {
93
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
94
+ return false;
95
+ }
96
+
97
+ /* Not a while loop, no tail predication: just set LR to the count */
98
+ tmp = load_reg(s, a->rn);
99
+ store_reg(s, 14, tmp);
100
+ return true;
101
+}
102
+
103
+static bool trans_WLS(DisasContext *s, arg_WLS *a)
104
+{
105
+ /* M-profile low-overhead while-loop start */
106
+ TCGv_i32 tmp;
107
+ TCGLabel *nextlabel;
108
+
109
+ if (!dc_isar_feature(aa32_lob, s)) {
110
+ return false;
111
+ }
112
+ if (a->rn == 13 || a->rn == 15) {
113
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
114
+ return false;
115
+ }
116
+ if (s->condexec_mask) {
117
+ /*
118
+ * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
119
+ * we choose to UNDEF, because otherwise our use of
120
+ * gen_goto_tb(1) would clash with the use of TB exit 1
121
+ * in the dc->condjmp condition-failed codepath in
122
+ * arm_tr_tb_stop() and we'd get an assertion.
123
+ */
124
+ return false;
125
+ }
126
+ nextlabel = gen_new_label();
127
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
128
+ tmp = load_reg(s, a->rn);
129
+ store_reg(s, 14, tmp);
130
+ gen_jmp_tb(s, s->base.pc_next, 1);
131
+
132
+ gen_set_label(nextlabel);
133
+ gen_jmp(s, read_pc(s) + a->imm);
134
+ return true;
135
+}
136
+
137
+static bool trans_LE(DisasContext *s, arg_LE *a)
138
+{
139
+ /*
140
+ * M-profile low-overhead loop end. The architecture permits an
141
+ * implementation to discard the LO_BRANCH_INFO cache at any time,
142
+ * and we take the IMPDEF option to never set it in the first place
143
+ * (equivalent to always discarding it immediately), because for QEMU
144
+ * a "real" implementation would be complicated and wouldn't execute
145
+ * any faster.
146
+ */
147
+ TCGv_i32 tmp;
148
+
149
+ if (!dc_isar_feature(aa32_lob, s)) {
150
+ return false;
151
+ }
152
+
153
+ if (!a->f) {
154
+ /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
155
+ arm_gen_condlabel(s);
156
+ tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel);
157
+ /* Decrement LR */
158
+ tmp = load_reg(s, 14);
159
+ tcg_gen_addi_i32(tmp, tmp, -1);
160
+ store_reg(s, 14, tmp);
161
+ }
162
+ /* Jump back to the loop start */
163
+ gen_jmp(s, read_pc(s) - a->imm);
164
+ return true;
165
+}
166
+
167
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
168
{
169
TCGv_i32 addr, tmp;
170
--
171
2.20.1
172
173
diff view generated by jsdifflib
Deleted patch
1
M-profile CPUs with half-precision floating point support should
2
be able to write to FPSCR.FZ16, but an M-profile specific masking
3
of the value at the top of vfp_set_fpscr() currently prevents that.
4
This is not yet an active bug because we have no M-profile
5
FP16 CPUs, but needs to be fixed before we can add any.
6
1
7
The bits that the masking is effectively preventing from being
8
set are the A-profile only short-vector Len and Stride fields,
9
plus the Neon QC bit. Rearrange the order of the function so
10
that those fields are handled earlier and only under a suitable
11
guard; this allows us to drop the M-profile specific masking,
12
making FZ16 writeable.
13
14
This change also makes the QC bit correctly RAZ/WI for older
15
no-Neon A-profile cores.
16
17
This refactoring also paves the way for the low-overhead-branch
18
LTPSIZE field, which uses some of the bits that are used for
19
A-profile Stride and Len.
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20201019151301.2046-10-peter.maydell@linaro.org
24
---
25
target/arm/vfp_helper.c | 47 ++++++++++++++++++++++++-----------------
26
1 file changed, 28 insertions(+), 19 deletions(-)
27
28
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/vfp_helper.c
31
+++ b/target/arm/vfp_helper.c
32
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
33
val &= ~FPCR_FZ16;
34
}
35
36
- if (arm_feature(env, ARM_FEATURE_M)) {
37
+ vfp_set_fpscr_to_host(env, val);
38
+
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
40
/*
41
- * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
42
- * and also for the trapped-exception-handling bits IxE.
43
+ * Short-vector length and stride; on M-profile these bits
44
+ * are used for different purposes.
45
+ * We can't make this conditional be "if MVFR0.FPShVec != 0",
46
+ * because in v7A no-short-vector-support cores still had to
47
+ * allow Stride/Len to be written with the only effect that
48
+ * some insns are required to UNDEF if the guest sets them.
49
+ *
50
+ * TODO: if M-profile MVE implemented, set LTPSIZE.
51
*/
52
- val &= 0xf7c0009f;
53
+ env->vfp.vec_len = extract32(val, 16, 3);
54
+ env->vfp.vec_stride = extract32(val, 20, 2);
55
}
56
57
- vfp_set_fpscr_to_host(env, val);
58
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
59
+ /*
60
+ * The bit we set within fpscr_q is arbitrary; the register as a
61
+ * whole being zero/non-zero is what counts.
62
+ * TODO: M-profile MVE also has a QC bit.
63
+ */
64
+ env->vfp.qc[0] = val & FPCR_QC;
65
+ env->vfp.qc[1] = 0;
66
+ env->vfp.qc[2] = 0;
67
+ env->vfp.qc[3] = 0;
68
+ }
69
70
/*
71
* We don't implement trapped exception handling, so the
72
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
73
*
74
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
75
- * (which are stored in fp_status), and the other RES0 bits
76
- * in between, then we clear all of the low 16 bits.
77
+ * The exception flags IOC|DZC|OFC|UFC|IXC|IDC are stored in
78
+ * fp_status; QC, Len and Stride are stored separately earlier.
79
+ * Clear out all of those and the RES0 bits: only NZCV, AHP, DN,
80
+ * FZ, RMode and FZ16 are kept in vfp.xregs[FPSCR].
81
*/
82
env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
83
- env->vfp.vec_len = (val >> 16) & 7;
84
- env->vfp.vec_stride = (val >> 20) & 3;
85
-
86
- /*
87
- * The bit we set within fpscr_q is arbitrary; the register as a
88
- * whole being zero/non-zero is what counts.
89
- */
90
- env->vfp.qc[0] = val & FPCR_QC;
91
- env->vfp.qc[1] = 0;
92
- env->vfp.qc[2] = 0;
93
- env->vfp.qc[3] = 0;
94
}
95
96
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
97
--
98
2.20.1
99
100
diff view generated by jsdifflib