1
Most of this is the Neon decodetree patches, followed by Edgar's versal cleanups.
1
The following changes since commit 4c41341af76cfc85b5a6c0f87de4838672ab9f89:
2
2
3
thanks
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into staging (2020-10-20 11:20:36 +0100)
4
-- PMM
5
6
7
The following changes since commit 2ef486e76d64436be90f7359a3071fb2a56ce835:
8
9
Merge remote-tracking branch 'remotes/marcel/tags/rdma-pull-request' into staging (2020-05-03 14:12:56 +0100)
10
4
11
are available in the Git repository at:
5
are available in the Git repository at:
12
6
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200504
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201020
14
8
15
for you to fetch changes up to 9aefc6cf9b73f66062d2f914a0136756e7a28211:
9
for you to fetch changes up to 6358890cb939192f6169fdf7664d903bf9b1d338:
16
10
17
target/arm: Move gen_ function typedefs to translate.h (2020-05-04 12:59:26 +0100)
11
tests/tcg/aarch64: Add bti smoke tests (2020-10-20 16:12:02 +0100)
18
12
19
----------------------------------------------------------------
13
----------------------------------------------------------------
20
target-arm queue:
14
target-arm queue:
21
* Start of conversion of Neon insns to decodetree
15
* Fix AArch32 SMLAD incorrect setting of Q bit
22
* versal board: support SD and RTC
16
* AArch32 VCVT fixed-point to float is always round-to-nearest
23
* Implement ARMv8.2-TTS2UXN
17
* strongarm: Fix 'time to transmit a char' unit comment
24
* Make VQDMULL undefined when U=1
18
* Restrict APEI tables generation to the 'virt' machine
25
* Some minor code cleanups
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
26
29
27
----------------------------------------------------------------
30
----------------------------------------------------------------
28
Edgar E. Iglesias (11):
31
Emanuele Giuseppe Esposito (1):
29
hw/arm: versal: Remove inclusion of arm_gicv3_common.h
32
loads-stores.rst: add footnote that clarifies GETPC usage
30
hw/arm: versal: Move misplaced comment
31
hw/arm: versal-virt: Fix typo xlnx-ve -> xlnx-versal
32
hw/arm: versal: Embed the UARTs into the SoC type
33
hw/arm: versal: Embed the GEMs into the SoC type
34
hw/arm: versal: Embed the ADMAs into the SoC type
35
hw/arm: versal: Embed the APUs into the SoC type
36
hw/arm: versal: Add support for SD
37
hw/arm: versal: Add support for the RTC
38
hw/arm: versal-virt: Add support for SD
39
hw/arm: versal-virt: Add support for the RTC
40
33
41
Fredrik Strupe (1):
34
Havard Skinnemoen (1):
42
target/arm: Make VQDMULL undefined when U=1
35
tests/qtest: Add npcm7xx timer test
43
36
44
Peter Maydell (25):
37
Peng Liang (1):
45
target/arm: Don't use a TLB for ARMMMUIdx_Stage2
38
microbit_i2c: Fix coredump when dump-vmstate
46
target/arm: Use enum constant in get_phys_addr_lpae() call
47
target/arm: Add new 's1_is_el0' argument to get_phys_addr_lpae()
48
target/arm: Implement ARMv8.2-TTS2UXN
49
target/arm: Use correct variable for setting 'max' cpu's ID_AA64DFR0
50
target/arm/translate-vfp.inc.c: Remove duplicate simd_r32 check
51
target/arm: Don't allow Thumb Neon insns without FEATURE_NEON
52
target/arm: Add stubs for AArch32 Neon decodetree
53
target/arm: Convert VCMLA (vector) to decodetree
54
target/arm: Convert VCADD (vector) to decodetree
55
target/arm: Convert V[US]DOT (vector) to decodetree
56
target/arm: Convert VFM[AS]L (vector) to decodetree
57
target/arm: Convert VCMLA (scalar) to decodetree
58
target/arm: Convert V[US]DOT (scalar) to decodetree
59
target/arm: Convert VFM[AS]L (scalar) to decodetree
60
target/arm: Convert Neon load/store multiple structures to decodetree
61
target/arm: Convert Neon 'load single structure to all lanes' to decodetree
62
target/arm: Convert Neon 'load/store single structure' to decodetree
63
target/arm: Convert Neon 3-reg-same VADD/VSUB to decodetree
64
target/arm: Convert Neon 3-reg-same logic ops to decodetree
65
target/arm: Convert Neon 3-reg-same VMAX/VMIN to decodetree
66
target/arm: Convert Neon 3-reg-same comparisons to decodetree
67
target/arm: Convert Neon 3-reg-same VQADD/VQSUB to decodetree
68
target/arm: Convert Neon 3-reg-same VMUL, VMLA, VMLS, VSHL to decodetree
69
target/arm: Move gen_ function typedefs to translate.h
70
39
71
Philippe Mathieu-Daudé (2):
40
Peter Maydell (12):
72
hw/arm/mps2-tz: Use TYPE_IOTKIT instead of hardcoded string
41
target/arm: Fix SMLAD incorrect setting of Q bit
73
target/arm: Use uint64_t for midr field in CPU state struct
42
target/arm: AArch32 VCVT fixed-point to float is always round-to-nearest
43
decodetree: Fix codegen for non-overlapping group inside overlapping group
44
target/arm: Implement v8.1M NOCP handling
45
target/arm: Implement v8.1M conditional-select insns
46
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
47
target/arm: Don't allow BLX imm for M-profile
48
target/arm: Implement v8.1M branch-future insns (as NOPs)
49
target/arm: Implement v8.1M low-overhead-loop instructions
50
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
51
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
52
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
74
53
75
include/hw/arm/xlnx-versal.h | 31 +-
54
Philippe Mathieu-Daudé (10):
76
target/arm/cpu-param.h | 2 +-
55
hw/arm/strongarm: Fix 'time to transmit a char' unit comment
77
target/arm/cpu.h | 38 ++-
56
hw/arm: Restrict APEI tables generation to the 'virt' machine
78
target/arm/translate-a64.h | 9 -
57
hw/timer/bcm2835: Introduce BCM2835_SYSTIMER_COUNT definition
79
target/arm/translate.h | 26 ++
58
hw/timer/bcm2835: Rename variable holding CTRL_STATUS register
80
target/arm/neon-dp.decode | 86 +++++
59
hw/timer/bcm2835: Support the timer COMPARE registers
81
target/arm/neon-ls.decode | 52 +++
60
hw/arm/bcm2835_peripherals: Correctly wire the SYS_timer IRQs
82
target/arm/neon-shared.decode | 66 ++++
61
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
83
hw/arm/mps2-tz.c | 2 +-
62
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
84
hw/arm/xlnx-versal-virt.c | 74 ++++-
63
hw/arm/nseries: Fix loading kernel image on n8x0 machines
85
hw/arm/xlnx-versal.c | 115 +++++--
64
linux-user/elfload: Avoid leaking interp_name using GLib memory API
86
target/arm/cpu.c | 3 +-
87
target/arm/cpu64.c | 8 +-
88
target/arm/helper.c | 183 ++++------
89
target/arm/translate-a64.c | 17 -
90
target/arm/translate-neon.inc.c | 714 +++++++++++++++++++++++++++++++++++++++
91
target/arm/translate-vfp.inc.c | 6 -
92
target/arm/translate.c | 716 +++-------------------------------------
93
target/arm/Makefile.objs | 18 +
94
19 files changed, 1302 insertions(+), 864 deletions(-)
95
create mode 100644 target/arm/neon-dp.decode
96
create mode 100644 target/arm/neon-ls.decode
97
create mode 100644 target/arm/neon-shared.decode
98
create mode 100644 target/arm/translate-neon.inc.c
99
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
1
Convert the Neon VMUL, VMLA, VMLS and VSHL insns in the
1
The SMLAD instruction is supposed to:
2
3-reg-same grouping to decodetree.
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
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.
3
28
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200430181003.21682-20-peter.maydell@linaro.org
31
Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
7
---
32
---
8
target/arm/neon-dp.decode | 9 +++++++
33
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++--------
9
target/arm/translate-neon.inc.c | 44 +++++++++++++++++++++++++++++++++
34
1 file changed, 48 insertions(+), 10 deletions(-)
10
target/arm/translate.c | 28 +++------------------
11
3 files changed, 56 insertions(+), 25 deletions(-)
12
35
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
16
+++ b/target/arm/neon-dp.decode
17
@@ -XXX,XX +XXX,XX @@ VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same
18
VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same
19
VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same
20
21
+VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same
22
+VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same
23
+
24
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
25
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
26
VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
27
@@ -XXX,XX +XXX,XX @@ VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
28
29
VTST_3s 1111 001 0 0 . .. .... .... 1000 . . . 1 .... @3same
30
VCEQ_3s 1111 001 1 0 . .. .... .... 1000 . . . 1 .... @3same
31
+
32
+VMLA_3s 1111 001 0 0 . .. .... .... 1001 . . . 0 .... @3same
33
+VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same
34
+
35
+VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
36
+VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
37
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-neon.inc.c
40
+++ b/target/arm/translate-neon.inc.c
41
@@ -XXX,XX +XXX,XX @@ DO_3SAME_NO_SZ_3(VMAX_S, tcg_gen_gvec_smax)
42
DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax)
43
DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin)
44
DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin)
45
+DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
46
47
#define DO_3SAME_CMP(INSN, COND) \
48
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
49
@@ -XXX,XX +XXX,XX @@ DO_3SAME_GVEC4(VQADD_S, sqadd_op)
50
DO_3SAME_GVEC4(VQADD_U, uqadd_op)
51
DO_3SAME_GVEC4(VQSUB_S, sqsub_op)
52
DO_3SAME_GVEC4(VQSUB_U, uqsub_op)
53
+
54
+static void gen_VMUL_p_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
55
+ uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
56
+{
57
+ tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz,
58
+ 0, gen_helper_gvec_pmul_b);
59
+}
60
+
61
+static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
62
+{
63
+ if (a->size != 0) {
64
+ return false;
65
+ }
66
+ return do_3same(s, a, gen_VMUL_p_3s);
67
+}
68
+
69
+#define DO_3SAME_GVEC3_NO_SZ_3(INSN, OPARRAY) \
70
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
71
+ uint32_t rn_ofs, uint32_t rm_ofs, \
72
+ uint32_t oprsz, uint32_t maxsz) \
73
+ { \
74
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
75
+ oprsz, maxsz, &OPARRAY[vece]); \
76
+ } \
77
+ DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s)
78
+
79
+
80
+DO_3SAME_GVEC3_NO_SZ_3(VMLA, mla_op)
81
+DO_3SAME_GVEC3_NO_SZ_3(VMLS, mls_op)
82
+
83
+#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \
84
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
85
+ uint32_t rn_ofs, uint32_t rm_ofs, \
86
+ uint32_t oprsz, uint32_t maxsz) \
87
+ { \
88
+ /* Note the operation is vshl vd,vm,vn */ \
89
+ tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, \
90
+ oprsz, maxsz, &OPARRAY[vece]); \
91
+ } \
92
+ DO_3SAME(INSN, gen_##INSN##_3s)
93
+
94
+DO_3SAME_GVEC3_SHIFT(VSHL_S, sshl_op)
95
+DO_3SAME_GVEC3_SHIFT(VSHL_U, ushl_op)
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
36
diff --git a/target/arm/translate.c b/target/arm/translate.c
97
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate.c
38
--- a/target/arm/translate.c
99
+++ b/target/arm/translate.c
39
+++ b/target/arm/translate.c
100
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
40
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
101
}
41
gen_smul_dual(t1, t2);
102
return 1;
42
103
43
if (sub) {
104
- case NEON_3R_VMUL: /* VMUL */
44
- /* This subtraction cannot overflow. */
105
- if (u) {
45
+ /*
106
- /* Polynomial case allows only P8. */
46
+ * This subtraction cannot overflow, so we can do a simple
107
- if (size != 0) {
47
+ * 32-bit subtraction and then a possible 32-bit saturating
108
- return 1;
48
+ * addition of Ra.
109
- }
49
+ */
110
- tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
50
tcg_gen_sub_i32(t1, t1, t2);
111
- 0, gen_helper_gvec_pmul_b);
51
+ tcg_temp_free_i32(t2);
112
- } else {
52
+
113
- tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
53
+ if (a->ra != 15) {
114
- vec_size, vec_size);
54
+ t2 = load_reg(s, a->ra);
115
- }
55
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
116
- return 0;
56
+ tcg_temp_free_i32(t2);
117
-
57
+ }
118
- case NEON_3R_VML: /* VMLA, VMLS */
58
+ } else if (a->ra == 15) {
119
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
59
+ /* Single saturation-checking addition */
120
- u ? &mls_op[size] : &mla_op[size]);
60
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
121
- return 0;
61
+ tcg_temp_free_i32(t2);
122
-
62
} else {
123
- case NEON_3R_VSHL:
63
/*
124
- /* Note the operation is vshl vd,vm,vn */
64
- * This addition cannot overflow 32 bits; however it may
125
- tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size,
65
- * overflow considered as a signed operation, in which case
126
- u ? &ushl_op[size] : &sshl_op[size]);
66
- * we must set the Q flag.
127
- return 0;
67
+ * We need to add the products and Ra together and then
128
-
68
+ * determine whether the final result overflowed. Doing
129
case NEON_3R_VADD_VSUB:
69
+ * this as two separate add-and-check-overflow steps incorrectly
130
case NEON_3R_LOGIC:
70
+ * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
131
case NEON_3R_VMAX:
71
+ * Do all the arithmetic at 64-bits and then check for overflow.
132
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
72
*/
133
case NEON_3R_VCGE:
73
- gen_helper_add_setq(t1, cpu_env, t1, t2);
134
case NEON_3R_VQADD:
74
- }
135
case NEON_3R_VQSUB:
75
- tcg_temp_free_i32(t2);
136
+ case NEON_3R_VMUL:
76
+ TCGv_i64 p64, q64;
137
+ case NEON_3R_VML:
77
+ TCGv_i32 t3, qf, one;
138
+ case NEON_3R_VSHL:
78
139
/* Already handled by decodetree */
79
- if (a->ra != 15) {
140
return 1;
80
- t2 = load_reg(s, a->ra);
141
}
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);
142
--
110
--
143
2.20.1
111
2.20.1
144
112
145
113
diff view generated by jsdifflib
1
Convert the Neon 3-reg-same VMAX and VMIN insns to decodetree.
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
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.
2
14
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200430181003.21682-17-peter.maydell@linaro.org
17
Message-id: 20201013103532.13391-1-peter.maydell@linaro.org
6
---
18
---
7
target/arm/neon-dp.decode | 5 +++++
19
target/arm/helper.h | 13 +++++++++++++
8
target/arm/translate-neon.inc.c | 14 ++++++++++++++
20
target/arm/vfp_helper.c | 23 ++++++++++++++++++++++-
9
target/arm/translate.c | 21 ++-------------------
21
target/arm/translate-vfp.c.inc | 24 ++++++++++++------------
10
3 files changed, 21 insertions(+), 19 deletions(-)
22
3 files changed, 47 insertions(+), 13 deletions(-)
11
23
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
26
--- a/target/arm/helper.h
15
+++ b/target/arm/neon-dp.decode
27
+++ b/target/arm/helper.h
16
@@ -XXX,XX +XXX,XX @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
17
VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic
29
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
18
VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic
30
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
19
31
20
+VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
32
+DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr)
21
+VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
33
+DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr)
22
+VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
34
+DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr)
23
+VMIN_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 1 .... @3same
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)
24
+
44
+
25
VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same
45
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
26
VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
46
27
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
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
28
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-neon.inc.c
50
--- a/target/arm/vfp_helper.c
30
+++ b/target/arm/translate-neon.inc.c
51
+++ b/target/arm/vfp_helper.c
31
@@ -XXX,XX +XXX,XX @@ DO_3SAME(VEOR, tcg_gen_gvec_xor)
52
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
32
DO_3SAME_BITSEL(VBSL, rd_ofs, rn_ofs, rm_ofs)
53
return float64_to_float32(x, &env->vfp.fp_status);
33
DO_3SAME_BITSEL(VBIT, rm_ofs, rn_ofs, rd_ofs)
54
}
34
DO_3SAME_BITSEL(VBIF, rm_ofs, rd_ofs, rn_ofs)
55
35
+
56
-/* VFP3 fixed point conversion. */
36
+#define DO_3SAME_NO_SZ_3(INSN, FUNC) \
57
+/*
37
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
58
+ * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
38
+ { \
59
+ * must always round-to-nearest; the AArch64 ones honour the FPSCR
39
+ if (a->size == 3) { \
60
+ * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
40
+ return false; \
61
+ * round-to-nearest so either helper will work.) AArch32 float-to-fix
41
+ } \
62
+ * must round-to-zero.
42
+ return do_3same(s, a, FUNC); \
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; \
43
+ }
81
+ }
44
+
82
+
45
+DO_3SAME_NO_SZ_3(VMAX_S, tcg_gen_gvec_smax)
83
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
46
+DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax)
84
uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
47
+DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin)
85
void *fpst) \
48
+DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin)
86
@@ -XXX,XX +XXX,XX @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
49
diff --git a/target/arm/translate.c b/target/arm/translate.c
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
50
index XXXXXXX..XXXXXXX 100644
95
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/translate.c
96
--- a/target/arm/translate-vfp.c.inc
52
+++ b/target/arm/translate.c
97
+++ b/target/arm/translate-vfp.c.inc
53
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
98
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
54
rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
99
/* Switch on op:U:sx bits */
55
return 0;
100
switch (a->opc) {
56
101
case 0:
57
- case NEON_3R_VMAX:
102
- gen_helper_vfp_shtoh(vd, vd, shift, fpst);
58
- if (u) {
103
+ gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst);
59
- tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
104
break;
60
- vec_size, vec_size);
105
case 1:
61
- } else {
106
- gen_helper_vfp_sltoh(vd, vd, shift, fpst);
62
- tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
107
+ gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst);
63
- vec_size, vec_size);
108
break;
64
- }
109
case 2:
65
- return 0;
110
- gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
66
- case NEON_3R_VMIN:
111
+ gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst);
67
- if (u) {
112
break;
68
- tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
113
case 3:
69
- vec_size, vec_size);
114
- gen_helper_vfp_ultoh(vd, vd, shift, fpst);
70
- } else {
115
+ gen_helper_vfp_ultoh_round_to_nearest(vd, vd, shift, fpst);
71
- tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
116
break;
72
- vec_size, vec_size);
117
case 4:
73
- }
118
gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
74
- return 0;
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
75
-
120
/* Switch on op:U:sx bits */
76
case NEON_3R_VSHL:
121
switch (a->opc) {
77
/* Note the operation is vshl vd,vm,vn */
122
case 0:
78
tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size,
123
- gen_helper_vfp_shtos(vd, vd, shift, fpst);
79
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
124
+ gen_helper_vfp_shtos_round_to_nearest(vd, vd, shift, fpst);
80
125
break;
81
case NEON_3R_VADD_VSUB:
126
case 1:
82
case NEON_3R_LOGIC:
127
- gen_helper_vfp_sltos(vd, vd, shift, fpst);
83
+ case NEON_3R_VMAX:
128
+ gen_helper_vfp_sltos_round_to_nearest(vd, vd, shift, fpst);
84
+ case NEON_3R_VMIN:
129
break;
85
/* Already handled by decodetree */
130
case 2:
86
return 1;
131
- gen_helper_vfp_uhtos(vd, vd, shift, fpst);
87
}
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);
88
--
161
--
89
2.20.1
162
2.20.1
90
163
91
164
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
By using the TYPE_* definitions for devices, we can:
3
The time to transmit a char is expressed in nanoseconds, not in ticks.
4
- quickly find where devices are used with 'git-grep'
5
- easily rename a device (one-line change).
6
4
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20200428154650.21991-1-f4bug@amsat.org
6
Message-id: 20201014213601.205222-1-f4bug@amsat.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
hw/arm/mps2-tz.c | 2 +-
10
hw/arm/strongarm.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
14
12
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
15
--- a/hw/arm/strongarm.c
18
+++ b/hw/arm/mps2-tz.c
16
+++ b/hw/arm/strongarm.c
19
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
17
@@ -XXX,XX +XXX,XX @@ struct StrongARMUARTState {
20
exit(EXIT_FAILURE);
18
uint8_t rx_start;
21
}
19
uint8_t rx_len;
22
20
23
- sysbus_init_child_obj(OBJECT(machine), "iotkit", &mms->iotkit,
21
- uint64_t char_transmit_time; /* time to transmit a char in ticks*/
24
+ sysbus_init_child_obj(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit,
22
+ uint64_t char_transmit_time; /* time to transmit a char in nanoseconds */
25
sizeof(mms->iotkit), mmc->armsse_type);
23
bool wait_break_end;
26
iotkitdev = DEVICE(&mms->iotkit);
24
QEMUTimer *rx_timeout_timer;
27
object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
25
QEMUTimer *tx_timer;
28
--
26
--
29
2.20.1
27
2.20.1
30
28
31
29
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
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
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
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
1
Convert the Neon VQADD/VQSUB insns in the 3-reg-same grouping
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
to decodetree.
3
2
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
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200430181003.21682-19-peter.maydell@linaro.org
7
---
12
---
8
target/arm/neon-dp.decode | 6 ++++++
13
include/hw/timer/bcm2835_systmr.h | 2 +-
9
target/arm/translate-neon.inc.c | 15 +++++++++++++++
14
hw/timer/bcm2835_systmr.c | 8 ++++----
10
target/arm/translate.c | 14 ++------------
15
2 files changed, 5 insertions(+), 5 deletions(-)
11
3 files changed, 23 insertions(+), 12 deletions(-)
12
16
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
17
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
19
--- a/include/hw/timer/bcm2835_systmr.h
16
+++ b/target/arm/neon-dp.decode
20
+++ b/include/hw/timer/bcm2835_systmr.h
17
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
18
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
22
qemu_irq irq;
19
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
23
20
24
struct {
21
+VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
25
- uint32_t status;
22
+VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same
26
+ uint32_t ctrl_status;
23
+
27
uint32_t compare[BCM2835_SYSTIMER_COUNT];
24
@3same_logic .... ... . . . .. .... .... .... . q:1 .. .... \
28
} reg;
25
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0
29
};
26
30
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
27
@@ -XXX,XX +XXX,XX @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic
28
VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic
29
VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic
30
31
+VQSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 1 .... @3same
32
+VQSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 1 .... @3same
33
+
34
VCGT_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 0 .... @3same
35
VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same
36
VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same
37
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
38
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-neon.inc.c
32
--- a/hw/timer/bcm2835_systmr.c
40
+++ b/target/arm/translate-neon.inc.c
33
+++ b/hw/timer/bcm2835_systmr.c
41
@@ -XXX,XX +XXX,XX @@ static void gen_VTST_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
34
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE3, 0x18)
42
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &cmtst_op[vece]);
35
43
}
36
static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
44
DO_3SAME_NO_SZ_3(VTST, gen_VTST_3s)
37
{
45
+
38
- bool enable = !!s->reg.status;
46
+#define DO_3SAME_GVEC4(INSN, OPARRAY) \
39
+ bool enable = !!s->reg.ctrl_status;
47
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
40
48
+ uint32_t rn_ofs, uint32_t rm_ofs, \
41
trace_bcm2835_systmr_irq(enable);
49
+ uint32_t oprsz, uint32_t maxsz) \
42
qemu_set_irq(s->irq, enable);
50
+ { \
43
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
51
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), \
44
52
+ rn_ofs, rm_ofs, oprsz, maxsz, &OPARRAY[vece]); \
45
switch (offset) {
53
+ } \
46
case A_CTRL_STATUS:
54
+ DO_3SAME(INSN, gen_##INSN##_3s)
47
- r = s->reg.status;
55
+
48
+ r = s->reg.ctrl_status;
56
+DO_3SAME_GVEC4(VQADD_S, sqadd_op)
49
break;
57
+DO_3SAME_GVEC4(VQADD_U, uqadd_op)
50
case A_COMPARE0 ... A_COMPARE3:
58
+DO_3SAME_GVEC4(VQSUB_S, sqsub_op)
51
r = s->reg.compare[(offset - A_COMPARE0) >> 2];
59
+DO_3SAME_GVEC4(VQSUB_U, uqsub_op)
52
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_write(void *opaque, hwaddr offset,
60
diff --git a/target/arm/translate.c b/target/arm/translate.c
53
trace_bcm2835_systmr_write(offset, value);
61
index XXXXXXX..XXXXXXX 100644
54
switch (offset) {
62
--- a/target/arm/translate.c
55
case A_CTRL_STATUS:
63
+++ b/target/arm/translate.c
56
- s->reg.status &= ~value; /* Ack */
64
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
57
+ s->reg.ctrl_status &= ~value; /* Ack */
65
}
58
bcm2835_systmr_update_irq(s);
66
return 1;
59
break;
67
60
case A_COMPARE0 ... A_COMPARE3:
68
- case NEON_3R_VQADD:
61
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
69
- tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
62
.version_id = 1,
70
- rn_ofs, rm_ofs, vec_size, vec_size,
63
.minimum_version_id = 1,
71
- (u ? uqadd_op : sqadd_op) + size);
64
.fields = (VMStateField[]) {
72
- return 0;
65
- VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
73
-
66
+ VMSTATE_UINT32(reg.ctrl_status, BCM2835SystemTimerState),
74
- case NEON_3R_VQSUB:
67
VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
75
- tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
68
BCM2835_SYSTIMER_COUNT),
76
- rn_ofs, rm_ofs, vec_size, vec_size,
69
VMSTATE_END_OF_LIST()
77
- (u ? uqsub_op : sqsub_op) + size);
78
- return 0;
79
-
80
case NEON_3R_VMUL: /* VMUL */
81
if (u) {
82
/* Polynomial case allows only P8. */
83
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
84
case NEON_3R_VTST_VCEQ:
85
case NEON_3R_VCGT:
86
case NEON_3R_VCGE:
87
+ case NEON_3R_VQADD:
88
+ case NEON_3R_VQSUB:
89
/* Already handled by decodetree */
90
return 1;
91
}
92
--
70
--
93
2.20.1
71
2.20.1
94
72
95
73
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Add support for SD.
3
This peripheral has 1 free-running timer and 4 compare registers.
4
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
Only the free-running timer is implemented. Add support the
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
COMPARE registers (each register is wired to an IRQ).
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reference: "BCM2835 ARM Peripherals" datasheet [*]
9
Message-id: 20200427181649.26851-9-edgar.iglesias@gmail.com
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
28
---
12
include/hw/arm/xlnx-versal.h | 12 ++++++++++++
29
include/hw/timer/bcm2835_systmr.h | 11 +++++--
13
hw/arm/xlnx-versal.c | 31 +++++++++++++++++++++++++++++++
30
hw/timer/bcm2835_systmr.c | 48 ++++++++++++++++++++-----------
14
2 files changed, 43 insertions(+)
31
hw/timer/trace-events | 6 ++--
32
3 files changed, 44 insertions(+), 21 deletions(-)
15
33
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
34
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
17
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-versal.h
36
--- a/include/hw/timer/bcm2835_systmr.h
19
+++ b/include/hw/arm/xlnx-versal.h
37
+++ b/include/hw/timer/bcm2835_systmr.h
20
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
21
39
22
#include "hw/sysbus.h"
40
#include "hw/sysbus.h"
23
#include "hw/arm/boot.h"
41
#include "hw/irq.h"
24
+#include "hw/sd/sdhci.h"
42
+#include "qemu/timer.h"
25
#include "hw/intc/arm_gicv3.h"
43
#include "qom/object.h"
26
#include "hw/char/pl011.h"
44
27
#include "hw/dma/xlnx-zdma.h"
45
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
28
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
29
#define XLNX_VERSAL_NR_UARTS 2
47
30
#define XLNX_VERSAL_NR_GEMS 2
48
#define BCM2835_SYSTIMER_COUNT 4
31
#define XLNX_VERSAL_NR_ADMAS 8
49
32
+#define XLNX_VERSAL_NR_SDS 2
50
+typedef struct {
33
#define XLNX_VERSAL_NR_IRQS 192
51
+ unsigned id;
34
52
+ QEMUTimer timer;
35
typedef struct Versal {
53
+ qemu_irq irq;
36
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
54
+ BCM2835SystemTimerState *state;
37
} iou;
55
+} BCM2835SystemTimerCompare;
38
} lpd;
39
40
+ /* The Platform Management Controller subsystem. */
41
+ struct {
42
+ struct {
43
+ SDHCIState sd[XLNX_VERSAL_NR_SDS];
44
+ } iou;
45
+ } pmc;
46
+
56
+
57
struct BCM2835SystemTimerState {
58
/*< private >*/
59
SysBusDevice parent_obj;
60
61
/*< public >*/
62
MemoryRegion iomem;
63
- qemu_irq irq;
64
-
47
struct {
65
struct {
48
MemoryRegion *mr_ddr;
66
uint32_t ctrl_status;
49
uint32_t psci_conduit;
67
uint32_t compare[BCM2835_SYSTIMER_COUNT];
50
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
68
} reg;
51
#define VERSAL_GEM1_IRQ_0 58
69
+ BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT];
52
#define VERSAL_GEM1_WAKE_IRQ_0 59
70
};
53
#define VERSAL_ADMA_IRQ_0 60
71
54
+#define VERSAL_SD0_IRQ_0 126
55
56
/* Architecturally reserved IRQs suitable for virtualization. */
57
#define VERSAL_RSVD_IRQ_FIRST 111
58
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
59
#define MM_FPD_CRF 0xfd1a0000U
60
#define MM_FPD_CRF_SIZE 0x140000
61
62
+#define MM_PMC_SD0 0xf1040000U
63
+#define MM_PMC_SD0_SIZE 0x10000
64
#define MM_PMC_CRP 0xf1260000U
65
#define MM_PMC_CRP_SIZE 0x10000
66
#endif
72
#endif
67
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
73
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
68
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/arm/xlnx-versal.c
75
--- a/hw/timer/bcm2835_systmr.c
70
+++ b/hw/arm/xlnx-versal.c
76
+++ b/hw/timer/bcm2835_systmr.c
71
@@ -XXX,XX +XXX,XX @@ static void versal_create_admas(Versal *s, qemu_irq *pic)
77
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE1, 0x10)
72
}
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);
73
}
100
}
74
101
75
+#define SDHCI_CAPABILITIES 0x280737ec6481 /* Same as on ZynqMP. */
102
static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
76
+static void versal_create_sds(Versal *s, qemu_irq *pic)
103
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
77
+{
104
}
78
+ int i;
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);
79
+
146
+
80
+ for (i = 0; i < ARRAY_SIZE(s->pmc.iou.sd); i++) {
147
+ for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) {
81
+ DeviceState *dev;
148
+ s->tmr[i].id = i;
82
+ MemoryRegion *mr;
149
+ s->tmr[i].state = s;
83
+
150
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq);
84
+ sysbus_init_child_obj(OBJECT(s), "sd[*]",
151
+ timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL,
85
+ &s->pmc.iou.sd[i], sizeof(s->pmc.iou.sd[i]),
152
+ bcm2835_systmr_timer_expire, &s->tmr[i]);
86
+ TYPE_SYSBUS_SDHCI);
87
+ dev = DEVICE(&s->pmc.iou.sd[i]);
88
+
89
+ object_property_set_uint(OBJECT(dev),
90
+ 3, "sd-spec-version", &error_fatal);
91
+ object_property_set_uint(OBJECT(dev), SDHCI_CAPABILITIES, "capareg",
92
+ &error_fatal);
93
+ object_property_set_uint(OBJECT(dev), UHS_I, "uhs", &error_fatal);
94
+ qdev_init_nofail(dev);
95
+
96
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
97
+ memory_region_add_subregion(&s->mr_ps,
98
+ MM_PMC_SD0 + i * MM_PMC_SD0_SIZE, mr);
99
+
100
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
101
+ pic[VERSAL_SD0_IRQ_0 + i * 2]);
102
+ }
153
+ }
103
+}
154
}
104
+
155
105
/* This takes the board allocated linear DDR memory and creates aliases
156
static const VMStateDescription bcm2835_systmr_vmstate = {
106
* for each split DDR range/aperture on the Versal address map.
157
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
107
*/
158
index XXXXXXX..XXXXXXX 100644
108
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
159
--- a/hw/timer/trace-events
109
versal_create_uarts(s, pic);
160
+++ b/hw/timer/trace-events
110
versal_create_gems(s, pic);
161
@@ -XXX,XX +XXX,XX @@ nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size
111
versal_create_admas(s, pic);
162
nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32
112
+ versal_create_sds(s, pic);
163
113
versal_map_ddr(s);
164
# bcm2835_systmr.c
114
versal_unimp(s);
165
-bcm2835_systmr_irq(bool enable) "timer irq state %u"
115
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"
116
--
175
--
117
2.20.1
176
2.20.1
118
177
119
178
diff view generated by jsdifflib
1
Convert the Neon comparison ops in the 3-reg-same grouping
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
to decodetree.
3
2
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
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200430181003.21682-18-peter.maydell@linaro.org
7
---
12
---
8
target/arm/neon-dp.decode | 8 ++++++++
13
hw/arm/bcm2835_peripherals.c | 13 +++++++++++--
9
target/arm/translate-neon.inc.c | 22 ++++++++++++++++++++++
14
1 file changed, 11 insertions(+), 2 deletions(-)
10
target/arm/translate.c | 23 +++--------------------
11
3 files changed, 33 insertions(+), 20 deletions(-)
12
15
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
16
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
18
--- a/hw/arm/bcm2835_peripherals.c
16
+++ b/target/arm/neon-dp.decode
19
+++ b/hw/arm/bcm2835_peripherals.c
17
@@ -XXX,XX +XXX,XX @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic
20
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
18
VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic
21
memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
19
VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic
22
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
20
23
sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
21
+VCGT_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 0 .... @3same
24
- qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
22
+VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same
25
- INTERRUPT_ARM_TIMER));
23
+VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same
26
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
24
+VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same
27
+ INTERRUPT_TIMER0));
25
+
28
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 1,
26
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
29
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
27
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
30
+ INTERRUPT_TIMER1));
28
VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
31
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 2,
29
@@ -XXX,XX +XXX,XX @@ VMIN_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 1 .... @3same
32
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
30
33
+ INTERRUPT_TIMER2));
31
VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same
34
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 3,
32
VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
35
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
33
+
36
+ INTERRUPT_TIMER3));
34
+VTST_3s 1111 001 0 0 . .. .... .... 1000 . . . 1 .... @3same
37
35
+VCEQ_3s 1111 001 1 0 . .. .... .... 1000 . . . 1 .... @3same
38
/* UART0 */
36
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
39
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-neon.inc.c
39
+++ b/target/arm/translate-neon.inc.c
40
@@ -XXX,XX +XXX,XX @@ DO_3SAME_NO_SZ_3(VMAX_S, tcg_gen_gvec_smax)
41
DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax)
42
DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin)
43
DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin)
44
+
45
+#define DO_3SAME_CMP(INSN, COND) \
46
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
47
+ uint32_t rn_ofs, uint32_t rm_ofs, \
48
+ uint32_t oprsz, uint32_t maxsz) \
49
+ { \
50
+ tcg_gen_gvec_cmp(COND, vece, rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz); \
51
+ } \
52
+ DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s)
53
+
54
+DO_3SAME_CMP(VCGT_S, TCG_COND_GT)
55
+DO_3SAME_CMP(VCGT_U, TCG_COND_GTU)
56
+DO_3SAME_CMP(VCGE_S, TCG_COND_GE)
57
+DO_3SAME_CMP(VCGE_U, TCG_COND_GEU)
58
+DO_3SAME_CMP(VCEQ, TCG_COND_EQ)
59
+
60
+static void gen_VTST_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
61
+ uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
62
+{
63
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &cmtst_op[vece]);
64
+}
65
+DO_3SAME_NO_SZ_3(VTST, gen_VTST_3s)
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 int disas_neon_data_insn(DisasContext *s, uint32_t insn)
71
u ? &mls_op[size] : &mla_op[size]);
72
return 0;
73
74
- case NEON_3R_VTST_VCEQ:
75
- if (u) { /* VCEQ */
76
- tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
77
- vec_size, vec_size);
78
- } else { /* VTST */
79
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
80
- vec_size, vec_size, &cmtst_op[size]);
81
- }
82
- return 0;
83
-
84
- case NEON_3R_VCGT:
85
- tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
86
- rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
87
- return 0;
88
-
89
- case NEON_3R_VCGE:
90
- tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
91
- rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
92
- return 0;
93
-
94
case NEON_3R_VSHL:
95
/* Note the operation is vshl vd,vm,vn */
96
tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size,
97
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
98
case NEON_3R_LOGIC:
99
case NEON_3R_VMAX:
100
case NEON_3R_VMIN:
101
+ case NEON_3R_VTST_VCEQ:
102
+ case NEON_3R_VCGT:
103
+ case NEON_3R_VCGE:
104
/* Already handled by decodetree */
105
return 1;
106
}
107
--
40
--
108
2.20.1
41
2.20.1
109
42
110
43
diff view generated by jsdifflib
1
Convert the V[US]DOT (scalar) insns in the 2reg-scalar-ext group
1
From: Richard Henderson <richard.henderson@linaro.org>
2
to decodetree.
2
3
3
On ARM, the Top Byte Ignore feature means that only 56 bits of
4
the address are significant in the virtual address. We are
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
8
This new interface allows us to flush all 256 possible aliases
9
for a given page, currently missed by tlb_flush_page*.
10
11
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>
14
Message-id: 20201016210754.818257-2-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200430181003.21682-10-peter.maydell@linaro.org
7
---
16
---
8
target/arm/neon-shared.decode | 3 +++
17
include/exec/exec-all.h | 36 ++++++
9
target/arm/translate-neon.inc.c | 35 +++++++++++++++++++++++++++++++++
18
accel/tcg/cputlb.c | 275 ++++++++++++++++++++++++++++++++++++++--
10
target/arm/translate.c | 13 +-----------
19
2 files changed, 302 insertions(+), 9 deletions(-)
11
3 files changed, 39 insertions(+), 12 deletions(-)
20
12
21
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
13
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-shared.decode
23
--- a/include/exec/exec-all.h
16
+++ b/target/arm/neon-shared.decode
24
+++ b/include/exec/exec-all.h
17
@@ -XXX,XX +XXX,XX @@ VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \
25
@@ -XXX,XX +XXX,XX @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
18
vn=%vn_dp vd=%vd_dp size=0
26
* depend on when the guests translation ends the TB.
19
VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \
27
*/
20
vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0
28
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
21
+
29
+
22
+VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \
30
+/**
23
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
31
+ * tlb_flush_page_bits_by_mmuidx
24
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
32
+ * @cpu: CPU whose TLB should be flushed
33
+ * @addr: virtual address of page to be flushed
34
+ * @idxmap: bitmap of mmu indexes to flush
35
+ * @bits: number of significant bits in address
36
+ *
37
+ * Similar to tlb_flush_page_mask, but with a bitmap of indexes.
38
+ */
39
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
40
+ uint16_t idxmap, unsigned bits);
41
+
42
+/* Similarly, with broadcast and syncing. */
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
{
54
}
55
+static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
56
+ target_ulong addr,
57
+ uint16_t idxmap,
58
+ unsigned bits)
59
+{
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
25
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/translate-neon.inc.c
77
--- a/accel/tcg/cputlb.c
27
+++ b/target/arm/translate-neon.inc.c
78
+++ b/accel/tcg/cputlb.c
28
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
79
@@ -XXX,XX +XXX,XX @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu)
29
tcg_temp_free_ptr(fpst);
80
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
30
return true;
81
}
31
}
82
32
+
83
+static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry,
33
+static bool trans_VDOT_scalar(DisasContext *s, arg_VDOT_scalar *a)
84
+ target_ulong page, target_ulong mask)
34
+{
85
+{
35
+ gen_helper_gvec_3 *fn_gvec;
86
+ page &= mask;
36
+ int opr_sz;
87
+ mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK;
37
+ TCGv_ptr fpst;
88
+
38
+
89
+ return (page == (tlb_entry->addr_read & mask) ||
39
+ if (!dc_isar_feature(aa32_dp, s)) {
90
+ page == (tlb_addr_write(tlb_entry) & mask) ||
40
+ return false;
91
+ page == (tlb_entry->addr_code & mask));
41
+ }
92
+}
42
+
93
+
43
+ /* UNDEF accesses to D16-D31 if they don't exist. */
94
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
44
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
95
target_ulong page)
45
+ ((a->vd | a->vn) & 0x10)) {
96
{
46
+ return false;
97
- return tlb_hit_page(tlb_entry->addr_read, page) ||
47
+ }
98
- tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
48
+
99
- tlb_hit_page(tlb_entry->addr_code, page);
49
+ if ((a->vd | a->vn) & a->q) {
100
+ return tlb_hit_page_mask_anyprot(tlb_entry, page, -1);
50
+ return false;
101
}
51
+ }
102
52
+
103
/**
53
+ if (!vfp_access_check(s)) {
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te)
105
}
106
107
/* Called with tlb_c.lock held */
108
-static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
109
- target_ulong page)
110
+static bool tlb_flush_entry_mask_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page,
112
+ target_ulong mask)
113
{
114
- if (tlb_hit_page_anyprot(tlb_entry, page)) {
115
+ if (tlb_hit_page_mask_anyprot(tlb_entry, page, mask)) {
116
memset(tlb_entry, -1, sizeof(*tlb_entry));
117
return true;
118
}
119
return false;
120
}
121
122
+static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
123
+ target_ulong page)
124
+{
125
+ return tlb_flush_entry_mask_locked(tlb_entry, page, -1);
126
+}
127
+
128
/* Called with tlb_c.lock held */
129
-static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
130
- target_ulong page)
131
+static void tlb_flush_vtlb_page_mask_locked(CPUArchState *env, int mmu_idx,
132
+ target_ulong page,
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
}
144
}
145
}
146
147
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
148
+ target_ulong page)
149
+{
150
+ tlb_flush_vtlb_page_mask_locked(env, mmu_idx, page, -1);
151
+}
152
+
153
static void tlb_flush_page_locked(CPUArchState *env, int midx,
154
target_ulong page)
155
{
156
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
157
tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
158
}
159
160
+static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
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);
54
+ return true;
233
+ return true;
55
+ }
234
+ }
56
+
235
+ return false;
57
+ fn_gvec = a->u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
236
+}
58
+ opr_sz = (1 + a->q) * 8;
237
+
59
+ fpst = get_fpstatus_ptr(1);
238
+static TLBFlushPageBitsByMMUIdxData
60
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, a->vd),
239
+decode_runon_to_pbm(run_on_cpu_data data)
61
+ vfp_reg_offset(1, a->vn),
240
+{
62
+ vfp_reg_offset(1, a->rm),
241
+ target_ulong addr_map_bits = (target_ulong) data.target_ptr;
63
+ opr_sz, opr_sz, a->index, fn_gvec);
242
+ return (TLBFlushPageBitsByMMUIdxData){
64
+ tcg_temp_free_ptr(fpst);
243
+ .addr = addr_map_bits & TARGET_PAGE_MASK,
65
+ return true;
244
+ .idxmap = (addr_map_bits & ~TARGET_PAGE_MASK) >> 6,
66
+}
245
+ .bits = addr_map_bits & 0x3f
67
diff --git a/target/arm/translate.c b/target/arm/translate.c
246
+ };
68
index XXXXXXX..XXXXXXX 100644
247
+}
69
--- a/target/arm/translate.c
248
+
70
+++ b/target/arm/translate.c
249
+static void tlb_flush_page_bits_by_mmuidx_async_1(CPUState *cpu,
71
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
250
+ run_on_cpu_data runon)
72
bool is_long = false, q = extract32(insn, 6, 1);
251
+{
73
bool ptr_is_env = false;
252
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, decode_runon_to_pbm(runon));
74
253
+}
75
- if ((insn & 0xffb00f00) == 0xfe200d00) {
254
+
76
- /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
255
+static void tlb_flush_page_bits_by_mmuidx_async_2(CPUState *cpu,
77
- int u = extract32(insn, 4, 1);
256
+ run_on_cpu_data data)
78
-
257
+{
79
- if (!dc_isar_feature(aa32_dp, s)) {
258
+ TLBFlushPageBitsByMMUIdxData *d = data.host_ptr;
80
- return 1;
259
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, *d);
81
- }
260
+ g_free(d);
82
- fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
261
+}
83
- /* rm is just Vm, and index is M. */
262
+
84
- data = extract32(insn, 5, 1); /* index */
263
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
85
- rm = extract32(insn, 0, 4);
264
+ uint16_t idxmap, unsigned bits)
86
- } else if ((insn & 0xffa00f10) == 0xfe000810) {
265
+{
87
+ if ((insn & 0xffa00f10) == 0xfe000810) {
266
+ TLBFlushPageBitsByMMUIdxData d;
88
/* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
267
+ run_on_cpu_data runon;
89
int is_s = extract32(insn, 20, 1);
268
+
90
int vm20 = extract32(insn, 0, 3);
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)
91
--
397
--
92
2.20.1
398
2.20.1
93
399
94
400
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add support for SD.
3
When TBI is enabled in a given regime, 56 bits of the address
4
are significant and we need to clear out any other matching
5
virtual addresses with differing tags.
4
6
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
The other uses of tlb_flush_page (without mmuidx) in this file
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
are only used by aarch32 mode.
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
8
Message-id: 20200427181649.26851-11-edgar.iglesias@gmail.com
10
Fixes: 38d931687fa1
11
Reported-by: Jordan Frank <jordanfrank@fb.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20201016210754.818257-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
17
---
11
hw/arm/xlnx-versal-virt.c | 46 +++++++++++++++++++++++++++++++++++++++
18
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++-------
12
1 file changed, 46 insertions(+)
19
1 file changed, 39 insertions(+), 7 deletions(-)
13
20
14
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/xlnx-versal-virt.c
23
--- a/target/arm/helper.c
17
+++ b/hw/arm/xlnx-versal-virt.c
24
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
19
#include "hw/arm/sysbus-fdt.h"
26
#endif
20
#include "hw/arm/fdt.h"
27
21
#include "cpu.h"
28
static void switch_mode(CPUARMState *env, int mode);
22
+#include "hw/qdev-properties.h"
29
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
23
#include "hw/arm/xlnx-versal.h"
30
24
31
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
25
#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
32
{
26
@@ -XXX,XX +XXX,XX @@ static void fdt_add_zdma_nodes(VersalVirt *s)
33
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
27
}
34
}
28
}
35
}
29
36
30
+static void fdt_add_sd_nodes(VersalVirt *s)
37
+/* Return 56 if TBI is enabled, 64 otherwise. */
38
+static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
39
+ uint64_t addr)
31
+{
40
+{
32
+ const char clocknames[] = "clk_xin\0clk_ahb";
41
+ uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
33
+ const char compat[] = "arasan,sdhci-8.9a";
42
+ int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
34
+ int i;
43
+ int select = extract64(addr, 55, 1);
35
+
44
+
36
+ for (i = ARRAY_SIZE(s->soc.pmc.iou.sd) - 1; i >= 0; i--) {
45
+ return (tbi >> select) & 1 ? 56 : 64;
37
+ uint64_t addr = MM_PMC_SD0 + MM_PMC_SD0_SIZE * i;
38
+ char *name = g_strdup_printf("/sdhci@%" PRIx64, addr);
39
+
40
+ qemu_fdt_add_subnode(s->fdt, name);
41
+
42
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
43
+ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
44
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
45
+ clocknames, sizeof(clocknames));
46
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
47
+ GIC_FDT_IRQ_TYPE_SPI, VERSAL_SD0_IRQ_0 + i * 2,
48
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
49
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
50
+ 2, addr, 2, MM_PMC_SD0_SIZE);
51
+ qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
52
+ g_free(name);
53
+ }
54
+}
46
+}
55
+
47
+
56
static void fdt_nop_memory_nodes(void *fdt, Error **errp)
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)
57
{
66
{
58
Error *err = NULL;
67
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
59
@@ -XXX,XX +XXX,XX @@ static void create_virtio_regions(VersalVirt *s)
68
CPUState *cs = env_cpu(env);
69
int mask = vae1_tlbmask(env);
70
uint64_t pageaddr = sextract64(value << 12, 0, 56);
71
+ int bits = vae1_tlbbits(env, pageaddr);
72
73
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
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);
60
}
90
}
61
}
91
}
62
92
63
+static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
93
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
64
+{
65
+ BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
66
+ DeviceState *card;
67
+
68
+ card = qdev_create(qdev_get_child_bus(DEVICE(sd), "sd-bus"), TYPE_SD_CARD);
69
+ object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card),
70
+ &error_fatal);
71
+ qdev_prop_set_drive(card, "drive", blk, &error_fatal);
72
+ object_property_set_bool(OBJECT(card), true, "realized", &error_fatal);
73
+}
74
+
75
static void versal_virt_init(MachineState *machine)
76
{
94
{
77
VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
95
CPUState *cs = env_cpu(env);
78
int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
96
uint64_t pageaddr = sextract64(value << 12, 0, 56);
79
+ int i;
97
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
80
98
81
/*
99
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
82
* If the user provides an Operating System to be loaded, we expect them
100
- ARMMMUIdxBit_E2);
83
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
101
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
84
fdt_add_gic_nodes(s);
102
+ ARMMMUIdxBit_E2, bits);
85
fdt_add_timer_nodes(s);
103
}
86
fdt_add_zdma_nodes(s);
104
87
+ fdt_add_sd_nodes(s);
105
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
88
fdt_add_cpu_nodes(s, psci_conduit);
106
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
89
fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
107
{
90
fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
108
CPUState *cs = env_cpu(env);
91
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
109
uint64_t pageaddr = sextract64(value << 12, 0, 56);
92
memory_region_add_subregion_overlap(get_system_memory(),
110
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr);
93
0, &s->soc.fpd.apu.mr, 0);
111
94
112
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
95
+ /* Plugin SD cards. */
113
- ARMMMUIdxBit_SE3);
96
+ for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
114
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
97
+ sd_plugin_card(&s->soc.pmc.iou.sd[i], drive_get_next(IF_SD));
115
+ ARMMMUIdxBit_SE3, bits);
98
+ }
116
}
99
+
117
100
s->binfo.ram_size = machine->ram_size;
118
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
101
s->binfo.loader_start = 0x0;
102
s->binfo.get_dtb = versal_virt_get_dtb;
103
--
119
--
104
2.20.1
120
2.20.1
105
121
106
122
diff view generated by jsdifflib
1
Convert the Neon "load/store multiple structures" insns to decodetree.
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
This test exercises the various modes of the npcm7xx timer. In
4
particular, it triggers the bug found by the fuzzer, as reported here:
5
6
https://lists.gnu.org/archive/html/qemu-devel/2020-09/msg02992.html
7
8
It also found several other bugs, especially related to interrupt
9
handling.
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
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200430181003.21682-12-peter.maydell@linaro.org
6
---
18
---
7
target/arm/neon-ls.decode | 7 ++
19
tests/qtest/npcm7xx_timer-test.c | 562 +++++++++++++++++++++++++++++++
8
target/arm/translate-neon.inc.c | 124 ++++++++++++++++++++++++++++++++
20
tests/qtest/meson.build | 1 +
9
target/arm/translate.c | 91 +----------------------
21
2 files changed, 563 insertions(+)
10
3 files changed, 133 insertions(+), 89 deletions(-)
22
create mode 100644 tests/qtest/npcm7xx_timer-test.c
11
23
12
diff --git a/target/arm/neon-ls.decode b/target/arm/neon-ls.decode
24
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
13
index XXXXXXX..XXXXXXX 100644
25
new file mode 100644
14
--- a/target/arm/neon-ls.decode
26
index XXXXXXX..XXXXXXX
15
+++ b/target/arm/neon-ls.decode
27
--- /dev/null
28
+++ b/tests/qtest/npcm7xx_timer-test.c
16
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@
17
# 0b1111_1001_xxx0_xxxx_xxxx_xxxx_xxxx_xxxx
30
+/*
18
# This file works on the A32 encoding only; calling code for T32 has to
31
+ * QTest testcase for the Nuvoton NPCM7xx Timer
19
# transform the insn into the A32 version first.
32
+ *
20
+
33
+ * Copyright 2020 Google LLC
21
+%vd_dp 22:1 12:4
34
+ *
22
+
35
+ * This program is free software; you can redistribute it and/or modify it
23
+# Neon load/store multiple structures
36
+ * under the terms of the GNU General Public License as published by the
24
+
37
+ * Free Software Foundation; either version 2 of the License, or
25
+VLDST_multiple 1111 0100 0 . l:1 0 rn:4 .... itype:4 size:2 align:2 rm:4 \
38
+ * (at your option) any later version.
26
+ vd=%vd_dp
39
+ *
27
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
40
+ * This program is distributed in the hope that it will be useful, but WITHOUT
28
index XXXXXXX..XXXXXXX 100644
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
29
--- a/target/arm/translate-neon.inc.c
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30
+++ b/target/arm/translate-neon.inc.c
43
+ * for more details.
31
@@ -XXX,XX +XXX,XX @@ static bool trans_VFML_scalar(DisasContext *s, arg_VFML_scalar *a)
44
+ */
32
gen_helper_gvec_fmlal_idx_a32);
45
+
33
return true;
46
+#include "qemu/osdep.h"
34
}
47
+#include "qemu/timer.h"
35
+
48
+#include "libqtest-single.h"
36
+static struct {
49
+
37
+ int nregs;
50
+#define TIM_REF_HZ (25000000)
38
+ int interleave;
51
+
39
+ int spacing;
52
+/* Bits in TCSRx */
40
+} const neon_ls_element_type[11] = {
53
+#define CEN BIT(30)
41
+ {1, 4, 1},
54
+#define IE BIT(29)
42
+ {1, 4, 2},
55
+#define MODE_ONESHOT (0 << 27)
43
+ {4, 1, 1},
56
+#define MODE_PERIODIC (1 << 27)
44
+ {2, 2, 2},
57
+#define CRST BIT(26)
45
+ {1, 3, 1},
58
+#define CACT BIT(25)
46
+ {1, 3, 2},
59
+#define PRESCALE(x) (x)
47
+ {3, 1, 1},
60
+
48
+ {1, 1, 1},
61
+/* Registers shared between all timers in a module. */
49
+ {1, 2, 1},
62
+#define TISR 0x18
50
+ {1, 2, 2},
63
+#define WTCR 0x1c
51
+ {2, 1, 1}
64
+# define WTCLK(x) ((x) << 10)
65
+
66
+/* Power-on default; used to re-initialize timers before each test. */
67
+#define TCSR_DEFAULT PRESCALE(5)
68
+
69
+/* Register offsets for a timer within a timer block. */
70
+typedef struct Timer {
71
+ unsigned int tcsr_offset;
72
+ unsigned int ticr_offset;
73
+ unsigned int tdr_offset;
74
+} Timer;
75
+
76
+/* A timer block containing 5 timers. */
77
+typedef struct TimerBlock {
78
+ int irq_base;
79
+ uint64_t base_addr;
80
+} TimerBlock;
81
+
82
+/* Testdata for testing a particular timer within a timer block. */
83
+typedef struct TestData {
84
+ const TimerBlock *tim;
85
+ const Timer *timer;
86
+} TestData;
87
+
88
+const TimerBlock timer_block[] = {
89
+ {
90
+ .irq_base = 32,
91
+ .base_addr = 0xf0008000,
92
+ },
93
+ {
94
+ .irq_base = 37,
95
+ .base_addr = 0xf0009000,
96
+ },
97
+ {
98
+ .irq_base = 42,
99
+ .base_addr = 0xf000a000,
100
+ },
52
+};
101
+};
53
+
102
+
54
+static void gen_neon_ldst_base_update(DisasContext *s, int rm, int rn,
103
+const Timer timer[] = {
55
+ int stride)
104
+ {
56
+{
105
+ .tcsr_offset = 0x00,
57
+ if (rm != 15) {
106
+ .ticr_offset = 0x08,
58
+ TCGv_i32 base;
107
+ .tdr_offset = 0x10,
59
+
108
+ }, {
60
+ base = load_reg(s, rn);
109
+ .tcsr_offset = 0x04,
61
+ if (rm == 13) {
110
+ .ticr_offset = 0x0c,
62
+ tcg_gen_addi_i32(base, base, stride);
111
+ .tdr_offset = 0x14,
63
+ } else {
112
+ }, {
64
+ TCGv_i32 index;
113
+ .tcsr_offset = 0x20,
65
+ index = load_reg(s, rm);
114
+ .ticr_offset = 0x28,
66
+ tcg_gen_add_i32(base, base, index);
115
+ .tdr_offset = 0x30,
67
+ tcg_temp_free_i32(index);
116
+ }, {
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
+};
126
+
127
+/* Returns the index of the timer block. */
128
+static int tim_index(const TimerBlock *tim)
129
+{
130
+ ptrdiff_t diff = tim - timer_block;
131
+
132
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
133
+
134
+ return diff;
135
+}
136
+
137
+/* Returns the index of a timer within a timer block. */
138
+static int timer_index(const Timer *t)
139
+{
140
+ ptrdiff_t diff = t - timer;
141
+
142
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
143
+
144
+ return diff;
145
+}
146
+
147
+/* Returns the irq line for a given timer. */
148
+static int tim_timer_irq(const TestData *td)
149
+{
150
+ return td->tim->irq_base + timer_index(td->timer);
151
+}
152
+
153
+/* Register read/write accessors. */
154
+
155
+static void tim_write(const TestData *td,
156
+ unsigned int offset, uint32_t value)
157
+{
158
+ writel(td->tim->base_addr + offset, value);
159
+}
160
+
161
+static uint32_t tim_read(const TestData *td, unsigned int offset)
162
+{
163
+ return readl(td->tim->base_addr + offset);
164
+}
165
+
166
+static void tim_write_tcsr(const TestData *td, uint32_t value)
167
+{
168
+ tim_write(td, td->timer->tcsr_offset, value);
169
+}
170
+
171
+static uint32_t tim_read_tcsr(const TestData *td)
172
+{
173
+ return tim_read(td, td->timer->tcsr_offset);
174
+}
175
+
176
+static void tim_write_ticr(const TestData *td, uint32_t value)
177
+{
178
+ tim_write(td, td->timer->ticr_offset, value);
179
+}
180
+
181
+static uint32_t tim_read_ticr(const TestData *td)
182
+{
183
+ return tim_read(td, td->timer->ticr_offset);
184
+}
185
+
186
+static uint32_t tim_read_tdr(const TestData *td)
187
+{
188
+ return tim_read(td, td->timer->tdr_offset);
189
+}
190
+
191
+/* Returns the number of nanoseconds to count the given number of cycles. */
192
+static int64_t tim_calculate_step(uint32_t count, uint32_t prescale)
193
+{
194
+ return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
195
+}
196
+
197
+/* Returns a bitmask corresponding to the timer under test. */
198
+static uint32_t tim_timer_bit(const TestData *td)
199
+{
200
+ return BIT(timer_index(td->timer));
201
+}
202
+
203
+/* Resets all timers to power-on defaults. */
204
+static void tim_reset(const TestData *td)
205
+{
206
+ int i, j;
207
+
208
+ /* Reset all the timers, in case a previous test left a timer running. */
209
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
210
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
211
+ writel(timer_block[i].base_addr + timer[j].tcsr_offset,
212
+ CRST | TCSR_DEFAULT);
68
+ }
213
+ }
69
+ store_reg(s, rn, base);
214
+ writel(timer_block[i].base_addr + TISR, -1);
70
+ }
215
+ }
71
+}
216
+}
72
+
217
+
73
+static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
218
+/* Verifies the reset state of a timer. */
74
+{
219
+static void test_reset(gconstpointer test_data)
75
+ /* Neon load/store multiple structures */
220
+{
76
+ int nregs, interleave, spacing, reg, n;
221
+ const TestData *td = test_data;
77
+ MemOp endian = s->be_data;
222
+
78
+ int mmu_idx = get_mem_index(s);
223
+ tim_reset(td);
79
+ int size = a->size;
224
+
80
+ TCGv_i64 tmp64;
225
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
81
+ TCGv_i32 addr, tmp;
226
+ g_assert_cmphex(tim_read_ticr(td), ==, 0);
82
+
227
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
83
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
228
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
84
+ return false;
229
+ g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
230
+}
231
+
232
+/* Verifies that CRST wins if both CEN and CRST are set. */
233
+static void test_reset_overrides_enable(gconstpointer test_data)
234
+{
235
+ const TestData *td = test_data;
236
+
237
+ tim_reset(td);
238
+
239
+ /* CRST should force CEN to 0 */
240
+ tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
241
+
242
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
243
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
244
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
245
+}
246
+
247
+/* Verifies the behavior when CEN is set and then cleared. */
248
+static void test_oneshot_enable_then_disable(gconstpointer test_data)
249
+{
250
+ const TestData *td = test_data;
251
+
252
+ tim_reset(td);
253
+
254
+ /* Enable the timer with zero initial count, then disable it again. */
255
+ tim_write_tcsr(td, CEN | TCSR_DEFAULT);
256
+ tim_write_tcsr(td, TCSR_DEFAULT);
257
+
258
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
259
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
260
+ /* Timer interrupt flag should be set, but interrupts are not enabled. */
261
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
262
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
263
+}
264
+
265
+/* Verifies that a one-shot timer fires when expected with prescaler 5. */
266
+static void test_oneshot_ps5(gconstpointer test_data)
267
+{
268
+ const TestData *td = test_data;
269
+ unsigned int count = 256;
270
+ unsigned int ps = 5;
271
+
272
+ tim_reset(td);
273
+
274
+ tim_write_ticr(td, count);
275
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
276
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
277
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
278
+
279
+ clock_step(tim_calculate_step(count, ps) - 1);
280
+
281
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
282
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
283
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
284
+
285
+ clock_step(1);
286
+
287
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
288
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
289
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
290
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
291
+
292
+ /* Clear the interrupt flag. */
293
+ tim_write(td, TISR, tim_timer_bit(td));
294
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
295
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
296
+
297
+ /* Verify that this isn't a periodic timer. */
298
+ clock_step(2 * tim_calculate_step(count, ps));
299
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
300
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
301
+}
302
+
303
+/* Verifies that a one-shot timer fires when expected with prescaler 0. */
304
+static void test_oneshot_ps0(gconstpointer test_data)
305
+{
306
+ const TestData *td = test_data;
307
+ unsigned int count = 1;
308
+ unsigned int ps = 0;
309
+
310
+ tim_reset(td);
311
+
312
+ tim_write_ticr(td, count);
313
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
314
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
315
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
316
+
317
+ clock_step(tim_calculate_step(count, ps) - 1);
318
+
319
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
320
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
321
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
322
+
323
+ clock_step(1);
324
+
325
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
326
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
327
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
328
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
329
+}
330
+
331
+/* Verifies that a one-shot timer fires when expected with highest prescaler. */
332
+static void test_oneshot_ps255(gconstpointer test_data)
333
+{
334
+ const TestData *td = test_data;
335
+ unsigned int count = (1U << 24) - 1;
336
+ unsigned int ps = 255;
337
+
338
+ tim_reset(td);
339
+
340
+ tim_write_ticr(td, count);
341
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
342
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
343
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
344
+
345
+ clock_step(tim_calculate_step(count, ps) - 1);
346
+
347
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
348
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
349
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
350
+
351
+ clock_step(1);
352
+
353
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
354
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
355
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
356
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
357
+}
358
+
359
+/* Verifies that a oneshot timer fires an interrupt when expected. */
360
+static void test_oneshot_interrupt(gconstpointer test_data)
361
+{
362
+ const TestData *td = test_data;
363
+ unsigned int count = 256;
364
+ unsigned int ps = 7;
365
+
366
+ tim_reset(td);
367
+
368
+ tim_write_ticr(td, count);
369
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
370
+
371
+ clock_step_next();
372
+
373
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
374
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
375
+}
376
+
377
+/*
378
+ * Verifies that the timer can be paused and later resumed, and it still fires
379
+ * at the right moment.
380
+ */
381
+static void test_pause_resume(gconstpointer test_data)
382
+{
383
+ const TestData *td = test_data;
384
+ unsigned int count = 256;
385
+ unsigned int ps = 1;
386
+
387
+ tim_reset(td);
388
+
389
+ tim_write_ticr(td, count);
390
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
391
+
392
+ /* Pause the timer halfway to expiration. */
393
+ clock_step(tim_calculate_step(count / 2, ps));
394
+ tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
395
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
396
+
397
+ /* Counter should not advance during the following step. */
398
+ clock_step(2 * tim_calculate_step(count, ps));
399
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
400
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
401
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
402
+
403
+ /* Resume the timer and run _almost_ to expiration. */
404
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
405
+ clock_step(tim_calculate_step(count / 2, ps) - 1);
406
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
407
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
408
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
409
+
410
+ /* Now, run the rest of the way and verify that the interrupt fires. */
411
+ clock_step(1);
412
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
413
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
414
+}
415
+
416
+/* Verifies that the prescaler can be changed while the timer is runnin. */
417
+static void test_prescaler_change(gconstpointer test_data)
418
+{
419
+ const TestData *td = test_data;
420
+ unsigned int count = 256;
421
+ unsigned int ps = 5;
422
+
423
+ tim_reset(td);
424
+
425
+ tim_write_ticr(td, count);
426
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
427
+
428
+ /* Run a quarter of the way, and change the prescaler. */
429
+ clock_step(tim_calculate_step(count / 4, ps));
430
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
431
+ ps = 2;
432
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
433
+ /* The counter must not change. */
434
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
435
+
436
+ /* Run another quarter of the way, and change the prescaler again. */
437
+ clock_step(tim_calculate_step(count / 4, ps));
438
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
439
+ ps = 8;
440
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
441
+ /* The counter must not change. */
442
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
443
+
444
+ /* Run another quarter of the way, and change the prescaler again. */
445
+ clock_step(tim_calculate_step(count / 4, ps));
446
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
447
+ ps = 0;
448
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
449
+ /* The counter must not change. */
450
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
451
+
452
+ /* Run almost to expiration, and verify the timer didn't fire yet. */
453
+ clock_step(tim_calculate_step(count / 4, ps) - 1);
454
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
455
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
456
+
457
+ /* Now, run the rest of the way and verify that the timer fires. */
458
+ clock_step(1);
459
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
460
+}
461
+
462
+/* Verifies that a periodic timer automatically restarts after expiration. */
463
+static void test_periodic_no_interrupt(gconstpointer test_data)
464
+{
465
+ const TestData *td = test_data;
466
+ unsigned int count = 2;
467
+ unsigned int ps = 3;
468
+ int i;
469
+
470
+ tim_reset(td);
471
+
472
+ tim_write_ticr(td, count);
473
+ tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
474
+
475
+ for (i = 0; i < 4; i++) {
476
+ clock_step_next();
477
+
478
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
479
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
480
+
481
+ tim_write(td, TISR, tim_timer_bit(td));
482
+
483
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
484
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
85
+ }
485
+ }
86
+
486
+}
87
+ /* UNDEF accesses to D16-D31 if they don't exist */
487
+
88
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
488
+/* Verifies that a periodict timer fires an interrupt every time it expires. */
89
+ return false;
489
+static void test_periodic_interrupt(gconstpointer test_data)
490
+{
491
+ const TestData *td = test_data;
492
+ unsigned int count = 65535;
493
+ unsigned int ps = 2;
494
+ int i;
495
+
496
+ tim_reset(td);
497
+
498
+ tim_write_ticr(td, count);
499
+ tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
500
+
501
+ for (i = 0; i < 4; i++) {
502
+ clock_step_next();
503
+
504
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
505
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
506
+
507
+ tim_write(td, TISR, tim_timer_bit(td));
508
+
509
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
510
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
90
+ }
511
+ }
91
+ if (a->itype > 10) {
512
+}
92
+ return false;
513
+
93
+ }
514
+/*
94
+ /* Catch UNDEF cases for bad values of align field */
515
+ * Verifies that the timer behaves correctly when disabled right before and
95
+ switch (a->itype & 0xc) {
516
+ * exactly when it's supposed to expire.
96
+ case 4:
517
+ */
97
+ if (a->align >= 2) {
518
+static void test_disable_on_expiration(gconstpointer test_data)
98
+ return false;
519
+{
99
+ }
520
+ const TestData *td = test_data;
100
+ break;
521
+ unsigned int count = 8;
101
+ case 8:
522
+ unsigned int ps = 255;
102
+ if (a->align == 3) {
523
+
103
+ return false;
524
+ tim_reset(td);
104
+ }
525
+
105
+ break;
526
+ tim_write_ticr(td, count);
106
+ default:
527
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
107
+ break;
528
+
108
+ }
529
+ clock_step(tim_calculate_step(count, ps) - 1);
109
+ nregs = neon_ls_element_type[a->itype].nregs;
530
+
110
+ interleave = neon_ls_element_type[a->itype].interleave;
531
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
111
+ spacing = neon_ls_element_type[a->itype].spacing;
532
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
112
+ if (size == 3 && (interleave | spacing) != 1) {
533
+ clock_step(1);
113
+ return false;
534
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
114
+ }
535
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
115
+
536
+}
116
+ if (!vfp_access_check(s)) {
537
+
117
+ return true;
538
+/*
118
+ }
539
+ * Constructs a name that includes the timer block, timer and testcase name,
119
+
540
+ * and adds the test to the test suite.
120
+ /* For our purposes, bytes are always little-endian. */
541
+ */
121
+ if (size == 0) {
542
+static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
122
+ endian = MO_LE;
543
+{
123
+ }
544
+ g_autofree char *full_name;
124
+ /*
545
+
125
+ * Consecutive little-endian elements from a single register
546
+ full_name = g_strdup_printf("npcm7xx_timer/tim[%d]/timer[%d]/%s",
126
+ * can be promoted to a larger little-endian operation.
547
+ tim_index(td->tim), timer_index(td->timer),
127
+ */
548
+ name);
128
+ if (interleave == 1 && endian == MO_LE) {
549
+ qtest_add_data_func(full_name, td, fn);
129
+ size = 3;
550
+}
130
+ }
551
+
131
+ tmp64 = tcg_temp_new_i64();
552
+/* Convenience macro for adding a test with a predictable function name. */
132
+ addr = tcg_temp_new_i32();
553
+#define add_test(name, td) tim_add_test(#name, td, test_##name)
133
+ tmp = tcg_const_i32(1 << size);
554
+
134
+ load_reg_var(s, addr, a->rn);
555
+int main(int argc, char **argv)
135
+ for (reg = 0; reg < nregs; reg++) {
556
+{
136
+ for (n = 0; n < 8 >> size; n++) {
557
+ TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
137
+ int xs;
558
+ int ret;
138
+ for (xs = 0; xs < interleave; xs++) {
559
+ int i, j;
139
+ int tt = a->vd + reg + spacing * xs;
560
+
140
+
561
+ g_test_init(&argc, &argv, NULL);
141
+ if (a->l) {
562
+ g_test_set_nonfatal_assertions();
142
+ gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
563
+
143
+ neon_store_element64(tt, n, size, tmp64);
564
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
144
+ } else {
565
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
145
+ neon_load_element64(tmp64, tt, n, size);
566
+ TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
146
+ gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
567
+ td->tim = &timer_block[i];
147
+ }
568
+ td->timer = &timer[j];
148
+ tcg_gen_add_i32(addr, addr, tmp);
569
+
149
+ }
570
+ add_test(reset, td);
571
+ add_test(reset_overrides_enable, td);
572
+ add_test(oneshot_enable_then_disable, td);
573
+ add_test(oneshot_ps5, td);
574
+ add_test(oneshot_ps0, td);
575
+ add_test(oneshot_ps255, td);
576
+ add_test(oneshot_interrupt, td);
577
+ add_test(pause_resume, td);
578
+ add_test(prescaler_change, td);
579
+ add_test(periodic_no_interrupt, td);
580
+ add_test(periodic_interrupt, td);
581
+ add_test(disable_on_expiration, td);
150
+ }
582
+ }
151
+ }
583
+ }
152
+ tcg_temp_free_i32(addr);
584
+
153
+ tcg_temp_free_i32(tmp);
585
+ qtest_start("-machine npcm750-evb");
154
+ tcg_temp_free_i64(tmp64);
586
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
155
+
587
+ ret = g_test_run();
156
+ gen_neon_ldst_base_update(s, a->rm, a->rn, nregs * interleave * 8);
588
+ qtest_end();
157
+ return true;
589
+
158
+}
590
+ return ret;
159
diff --git a/target/arm/translate.c b/target/arm/translate.c
591
+}
592
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
160
index XXXXXXX..XXXXXXX 100644
593
index XXXXXXX..XXXXXXX 100644
161
--- a/target/arm/translate.c
594
--- a/tests/qtest/meson.build
162
+++ b/target/arm/translate.c
595
+++ b/tests/qtest/meson.build
163
@@ -XXX,XX +XXX,XX @@ static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
596
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
164
}
597
['arm-cpu-features',
165
598
'microbit-test',
166
599
'm25p80-test',
167
-static struct {
600
+ 'npcm7xx_timer-test',
168
- int nregs;
601
'test-arm-mptimer',
169
- int interleave;
602
'boot-serial-test',
170
- int spacing;
603
'hexloader-test']
171
-} const neon_ls_element_type[11] = {
172
- {1, 4, 1},
173
- {1, 4, 2},
174
- {4, 1, 1},
175
- {2, 2, 2},
176
- {1, 3, 1},
177
- {1, 3, 2},
178
- {3, 1, 1},
179
- {1, 1, 1},
180
- {1, 2, 1},
181
- {1, 2, 2},
182
- {2, 1, 1}
183
-};
184
-
185
/* Translate a NEON load/store element instruction. Return nonzero if the
186
instruction is invalid. */
187
static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
188
{
189
int rd, rn, rm;
190
- int op;
191
int nregs;
192
- int interleave;
193
- int spacing;
194
int stride;
195
int size;
196
int reg;
197
int load;
198
- int n;
199
int vec_size;
200
- int mmu_idx;
201
- MemOp endian;
202
TCGv_i32 addr;
203
TCGv_i32 tmp;
204
- TCGv_i32 tmp2;
205
- TCGv_i64 tmp64;
206
207
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
208
return 1;
209
@@ -XXX,XX +XXX,XX @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
210
rn = (insn >> 16) & 0xf;
211
rm = insn & 0xf;
212
load = (insn & (1 << 21)) != 0;
213
- endian = s->be_data;
214
- mmu_idx = get_mem_index(s);
215
if ((insn & (1 << 23)) == 0) {
216
- /* Load store all elements. */
217
- op = (insn >> 8) & 0xf;
218
- size = (insn >> 6) & 3;
219
- if (op > 10)
220
- return 1;
221
- /* Catch UNDEF cases for bad values of align field */
222
- switch (op & 0xc) {
223
- case 4:
224
- if (((insn >> 5) & 1) == 1) {
225
- return 1;
226
- }
227
- break;
228
- case 8:
229
- if (((insn >> 4) & 3) == 3) {
230
- return 1;
231
- }
232
- break;
233
- default:
234
- break;
235
- }
236
- nregs = neon_ls_element_type[op].nregs;
237
- interleave = neon_ls_element_type[op].interleave;
238
- spacing = neon_ls_element_type[op].spacing;
239
- if (size == 3 && (interleave | spacing) != 1) {
240
- return 1;
241
- }
242
- /* For our purposes, bytes are always little-endian. */
243
- if (size == 0) {
244
- endian = MO_LE;
245
- }
246
- /* Consecutive little-endian elements from a single register
247
- * can be promoted to a larger little-endian operation.
248
- */
249
- if (interleave == 1 && endian == MO_LE) {
250
- size = 3;
251
- }
252
- tmp64 = tcg_temp_new_i64();
253
- addr = tcg_temp_new_i32();
254
- tmp2 = tcg_const_i32(1 << size);
255
- load_reg_var(s, addr, rn);
256
- for (reg = 0; reg < nregs; reg++) {
257
- for (n = 0; n < 8 >> size; n++) {
258
- int xs;
259
- for (xs = 0; xs < interleave; xs++) {
260
- int tt = rd + reg + spacing * xs;
261
-
262
- if (load) {
263
- gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
264
- neon_store_element64(tt, n, size, tmp64);
265
- } else {
266
- neon_load_element64(tmp64, tt, n, size);
267
- gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
268
- }
269
- tcg_gen_add_i32(addr, addr, tmp2);
270
- }
271
- }
272
- }
273
- tcg_temp_free_i32(addr);
274
- tcg_temp_free_i32(tmp2);
275
- tcg_temp_free_i64(tmp64);
276
- stride = nregs * interleave * 8;
277
+ /* Load store all elements -- handled already by decodetree */
278
+ return 1;
279
} else {
280
size = (insn >> 10) & 3;
281
if (size == 3) {
282
--
604
--
283
2.20.1
605
2.20.1
284
606
285
607
diff view generated by jsdifflib
1
From: Fredrik Strupe <fredrik@strupe.net>
1
From: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
2
2
3
According to Arm ARM, VQDMULL is only valid when U=0, while having
3
Current documentation is not too clear on the GETPC usage.
4
U=1 is unallocated.
4
In particular, when used outside the top level helper function
5
it causes unexpected behavior.
5
6
6
Signed-off-by: Fredrik Strupe <fredrik@strupe.net>
7
Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
7
Fixes: 695272dcb976 ("target-arm: Handle UNDEF cases for Neon 3-regs-different-widths")
8
Message-id: 20201015095147.1691-1-e.emanuelegiuseppe@gmail.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@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
target/arm/translate.c | 2 +-
12
docs/devel/loads-stores.rst | 8 +++++++-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 7 insertions(+), 1 deletion(-)
13
14
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
17
--- a/docs/devel/loads-stores.rst
17
+++ b/target/arm/translate.c
18
+++ b/docs/devel/loads-stores.rst
18
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ guest CPU state in case of a guest CPU exception. This is passed
19
{0, 0, 0, 0}, /* VMLSL */
20
to ``cpu_restore_state()``. Therefore the value should either be 0,
20
{0, 0, 0, 9}, /* VQDMLSL */
21
to indicate that the guest CPU state is already synchronized, or
21
{0, 0, 0, 0}, /* Integer VMULL */
22
the result of ``GETPC()`` from the top level ``HELPER(foo)``
22
- {0, 0, 0, 1}, /* VQDMULL */
23
-function, which is a return address into the generated code.
23
+ {0, 0, 0, 9}, /* VQDMULL */
24
+function, which is a return address into the generated code [#gpc]_.
24
{0, 0, 0, 0xa}, /* Polynomial VMULL */
25
+
25
{0, 0, 0, 7}, /* Reserved: always UNDEF */
26
+.. [#gpc] Note that ``GETPC()`` should be used with great care: calling
26
};
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
27
--
34
--
28
2.20.1
35
2.20.1
29
36
30
37
diff view generated by jsdifflib
1
Convert the Neon logic ops in the 3-reg-same grouping to decodetree.
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
Note that for the logic ops the 'size' field forms part of their
3
decode and the actual operations are always bitwise.
4
2
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
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200430181003.21682-16-peter.maydell@linaro.org
8
---
9
---
9
target/arm/neon-dp.decode | 12 +++++++++++
10
hw/intc/bcm2835_ic.c | 4 +++-
10
target/arm/translate-neon.inc.c | 19 +++++++++++++++++
11
hw/intc/trace-events | 4 ++++
11
target/arm/translate.c | 38 +--------------------------------
12
2 files changed, 7 insertions(+), 1 deletion(-)
12
3 files changed, 32 insertions(+), 37 deletions(-)
13
13
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
16
--- a/hw/intc/bcm2835_ic.c
17
+++ b/target/arm/neon-dp.decode
17
+++ b/hw/intc/bcm2835_ic.c
18
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
19
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
19
#include "migration/vmstate.h"
20
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
20
#include "qemu/log.h"
21
21
#include "qemu/module.h"
22
+@3same_logic .... ... . . . .. .... .... .... . q:1 .. .... \
22
+#include "trace.h"
23
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0
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"
24
+
58
+
25
+VAND_3s 1111 001 0 0 . 00 .... .... 0001 ... 1 .... @3same_logic
59
+# bcm2835_ic.c
26
+VBIC_3s 1111 001 0 0 . 01 .... .... 0001 ... 1 .... @3same_logic
60
+bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d"
27
+VORR_3s 1111 001 0 0 . 10 .... .... 0001 ... 1 .... @3same_logic
61
+bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d"
28
+VORN_3s 1111 001 0 0 . 11 .... .... 0001 ... 1 .... @3same_logic
29
+VEOR_3s 1111 001 1 0 . 00 .... .... 0001 ... 1 .... @3same_logic
30
+VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic
31
+VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic
32
+VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic
33
+
34
VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same
35
VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
36
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-neon.inc.c
39
+++ b/target/arm/translate-neon.inc.c
40
@@ -XXX,XX +XXX,XX @@ static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn)
41
42
DO_3SAME(VADD, tcg_gen_gvec_add)
43
DO_3SAME(VSUB, tcg_gen_gvec_sub)
44
+DO_3SAME(VAND, tcg_gen_gvec_and)
45
+DO_3SAME(VBIC, tcg_gen_gvec_andc)
46
+DO_3SAME(VORR, tcg_gen_gvec_or)
47
+DO_3SAME(VORN, tcg_gen_gvec_orc)
48
+DO_3SAME(VEOR, tcg_gen_gvec_xor)
49
+
50
+/* These insns are all gvec_bitsel but with the inputs in various orders. */
51
+#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \
52
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
53
+ uint32_t rn_ofs, uint32_t rm_ofs, \
54
+ uint32_t oprsz, uint32_t maxsz) \
55
+ { \
56
+ tcg_gen_gvec_bitsel(vece, rd_ofs, O1, O2, O3, oprsz, maxsz); \
57
+ } \
58
+ DO_3SAME(INSN, gen_##INSN##_3s)
59
+
60
+DO_3SAME_BITSEL(VBSL, rd_ofs, rn_ofs, rm_ofs)
61
+DO_3SAME_BITSEL(VBIT, rm_ofs, rn_ofs, rd_ofs)
62
+DO_3SAME_BITSEL(VBIF, rm_ofs, rd_ofs, rn_ofs)
63
diff --git a/target/arm/translate.c b/target/arm/translate.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate.c
66
+++ b/target/arm/translate.c
67
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
68
}
69
return 1;
70
71
- case NEON_3R_LOGIC: /* Logic ops. */
72
- switch ((u << 2) | size) {
73
- case 0: /* VAND */
74
- tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
75
- vec_size, vec_size);
76
- break;
77
- case 1: /* VBIC */
78
- tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
79
- vec_size, vec_size);
80
- break;
81
- case 2: /* VORR */
82
- tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
83
- vec_size, vec_size);
84
- break;
85
- case 3: /* VORN */
86
- tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
87
- vec_size, vec_size);
88
- break;
89
- case 4: /* VEOR */
90
- tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
91
- vec_size, vec_size);
92
- break;
93
- case 5: /* VBSL */
94
- tcg_gen_gvec_bitsel(MO_8, rd_ofs, rd_ofs, rn_ofs, rm_ofs,
95
- vec_size, vec_size);
96
- break;
97
- case 6: /* VBIT */
98
- tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rn_ofs, rd_ofs,
99
- vec_size, vec_size);
100
- break;
101
- case 7: /* VBIF */
102
- tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rd_ofs, rn_ofs,
103
- vec_size, vec_size);
104
- break;
105
- }
106
- return 0;
107
-
108
case NEON_3R_VQADD:
109
tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
110
rn_ofs, rm_ofs, vec_size, vec_size,
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
112
return 0;
113
114
case NEON_3R_VADD_VSUB:
115
+ case NEON_3R_LOGIC:
116
/* Already handled by decodetree */
117
return 1;
118
}
119
--
62
--
120
2.20.1
63
2.20.1
121
64
122
65
diff view generated by jsdifflib
1
We define ARMMMUIdx_Stage2 as being an MMU index which uses a QEMU
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
TLB. However we never actually use the TLB -- all stage 2 lookups
3
are done by direct calls to get_phys_addr_lpae() followed by a
4
physical address load via address_space_ld*().
5
2
6
Remove Stage2 from the list of ARM MMU indexes which correspond to
3
The IRQ values are defined few lines earlier, use them instead of
7
real core MMU indexes, and instead put it in the set of "NOTLB" ARM
4
the magic numbers.
8
MMU indexes.
9
5
10
This allows us to drop NB_MMU_MODES to 11. It also means we can
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
safely add support for the ARMv8.3-TTS2UXN extension, which adds
7
Message-id: 20201017180731.1165871-3-f4bug@amsat.org
12
permission bits to the stage 2 descriptors which define execute
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
permission separatel for EL0 and EL1; supporting that while keeping
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Stage2 in a QEMU TLB would require us to use separate TLBs for
10
---
15
"Stage2 for an EL0 access" and "Stage2 for an EL1 access", which is a
11
hw/intc/bcm2836_control.c | 8 ++++----
16
lot of extra complication given we aren't even using the QEMU TLB.
12
1 file changed, 4 insertions(+), 4 deletions(-)
17
13
18
In the process of updating the comment on our MMU index use,
14
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
19
fix a couple of other minor errors:
20
* NS EL2 EL2&0 was missing from the list in the comment
21
* some text hadn't been updated from when we bumped NB_MMU_MODES
22
above 8
23
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20200330210400.11724-2-peter.maydell@linaro.org
28
---
29
target/arm/cpu-param.h | 2 +-
30
target/arm/cpu.h | 21 +++++---
31
target/arm/helper.c | 112 ++++-------------------------------------
32
3 files changed, 27 insertions(+), 108 deletions(-)
33
34
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
35
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/cpu-param.h
16
--- a/hw/intc/bcm2836_control.c
37
+++ b/target/arm/cpu-param.h
17
+++ b/hw/intc/bcm2836_control.c
38
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
39
# define TARGET_PAGE_BITS_MIN 10
19
40
#endif
20
static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
41
21
{
42
-#define NB_MMU_MODES 12
22
- bcm2836_control_set_local_irq(opaque, core, 0, level);
43
+#define NB_MMU_MODES 11
23
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level);
44
45
#endif
46
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
51
* handling via the TLB. The only way to do a stage 1 translation without
52
* the immediate stage 2 translation is via the ATS or AT system insns,
53
* which can be slow-pathed and always do a page table walk.
54
+ * The only use of stage 2 translations is either as part of an s1+2
55
+ * lookup or when loading the descriptors during a stage 1 page table walk,
56
+ * and in both those cases we don't use the TLB.
57
* 4. we can also safely fold together the "32 bit EL3" and "64 bit EL3"
58
* translation regimes, because they map reasonably well to each other
59
* and they can't both be active at the same time.
60
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
61
* NS EL1 EL1&0 stage 1+2 (aka NS PL1)
62
* NS EL1 EL1&0 stage 1+2 +PAN
63
* NS EL0 EL2&0
64
+ * NS EL2 EL2&0
65
* NS EL2 EL2&0 +PAN
66
* NS EL2 (aka NS PL2)
67
* S EL0 EL1&0 (aka S PL0)
68
* S EL1 EL1&0 (not used if EL3 is 32 bit)
69
* S EL1 EL1&0 +PAN
70
* S EL3 (aka S PL1)
71
- * NS EL1&0 stage 2
72
*
73
- * for a total of 12 different mmu_idx.
74
+ * for a total of 11 different mmu_idx.
75
*
76
* R profile CPUs have an MPU, but can use the same set of MMU indexes
77
* as A profile. They only need to distinguish NS EL0 and NS EL1 (and
78
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
79
* are not quite the same -- different CPU types (most notably M profile
80
* vs A/R profile) would like to use MMU indexes with different semantics,
81
* but since we don't ever need to use all of those in a single CPU we
82
- * can avoid setting NB_MMU_MODES to more than 8. The lower bits of
83
+ * can avoid having to set NB_MMU_MODES to "total number of A profile MMU
84
+ * modes + total number of M profile MMU modes". The lower bits of
85
* ARMMMUIdx are the core TLB mmu index, and the higher bits are always
86
* the same for any particular CPU.
87
* Variables of type ARMMUIdx are always full values, and the core
88
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
89
ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A,
90
ARMMMUIdx_SE3 = 10 | ARM_MMU_IDX_A,
91
92
- ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A,
93
-
94
/*
95
* These are not allocated TLBs and are used only for AT system
96
* instructions or for the first stage of an S12 page table walk.
97
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
98
ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
99
ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
100
ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
101
+ /*
102
+ * Not allocated a TLB: used only for second stage of an S12 page
103
+ * table walk, or for descriptor loads during first stage of an S1
104
+ * page table walk. Note that if we ever want to have a TLB for this
105
+ * then various TLB flush insns which currently are no-ops or flush
106
+ * only stage 1 MMU indexes will need to change to flush stage 2.
107
+ */
108
+ ARMMMUIdx_Stage2 = 3 | ARM_MMU_IDX_NOTLB,
109
110
/*
111
* M-profile.
112
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdxBit {
113
TO_CORE_BIT(SE10_1),
114
TO_CORE_BIT(SE10_1_PAN),
115
TO_CORE_BIT(SE3),
116
- TO_CORE_BIT(Stage2),
117
118
TO_CORE_BIT(MUser),
119
TO_CORE_BIT(MPriv),
120
diff --git a/target/arm/helper.c b/target/arm/helper.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/target/arm/helper.c
123
+++ b/target/arm/helper.c
124
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
125
tlb_flush_by_mmuidx(cs,
126
ARMMMUIdxBit_E10_1 |
127
ARMMMUIdxBit_E10_1_PAN |
128
- ARMMMUIdxBit_E10_0 |
129
- ARMMMUIdxBit_Stage2);
130
+ ARMMMUIdxBit_E10_0);
131
}
24
}
132
25
133
static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
26
static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
134
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
27
{
135
tlb_flush_by_mmuidx_all_cpus_synced(cs,
28
- bcm2836_control_set_local_irq(opaque, core, 1, level);
136
ARMMMUIdxBit_E10_1 |
29
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level);
137
ARMMMUIdxBit_E10_1_PAN |
138
- ARMMMUIdxBit_E10_0 |
139
- ARMMMUIdxBit_Stage2);
140
+ ARMMMUIdxBit_E10_0);
141
}
30
}
142
31
143
-static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
32
static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
144
- uint64_t value)
33
{
145
-{
34
- bcm2836_control_set_local_irq(opaque, core, 2, level);
146
- /* Invalidate by IPA. This has to invalidate any structures that
35
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTHPIRQ, level);
147
- * contain only stage 2 translation information, but does not need
148
- * to apply to structures that contain combined stage 1 and stage 2
149
- * translation information.
150
- * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero.
151
- */
152
- CPUState *cs = env_cpu(env);
153
- uint64_t pageaddr;
154
-
155
- if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
156
- return;
157
- }
158
-
159
- pageaddr = sextract64(value << 12, 0, 40);
160
-
161
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
162
-}
163
-
164
-static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
165
- uint64_t value)
166
-{
167
- CPUState *cs = env_cpu(env);
168
- uint64_t pageaddr;
169
-
170
- if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
171
- return;
172
- }
173
-
174
- pageaddr = sextract64(value << 12, 0, 40);
175
-
176
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
177
- ARMMMUIdxBit_Stage2);
178
-}
179
180
static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
181
uint64_t value)
182
@@ -XXX,XX +XXX,XX @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
183
tlb_flush_by_mmuidx(cs,
184
ARMMMUIdxBit_E10_1 |
185
ARMMMUIdxBit_E10_1_PAN |
186
- ARMMMUIdxBit_E10_0 |
187
- ARMMMUIdxBit_Stage2);
188
+ ARMMMUIdxBit_E10_0);
189
raw_write(env, ri, value);
190
}
191
}
36
}
192
@@ -XXX,XX +XXX,XX @@ static int alle1_tlbmask(CPUARMState *env)
37
193
return ARMMMUIdxBit_SE10_1 |
38
static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
194
ARMMMUIdxBit_SE10_1_PAN |
39
{
195
ARMMMUIdxBit_SE10_0;
40
- bcm2836_control_set_local_irq(opaque, core, 3, level);
196
- } else if (arm_feature(env, ARM_FEATURE_EL2)) {
41
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTVIRQ, level);
197
- return ARMMMUIdxBit_E10_1 |
198
- ARMMMUIdxBit_E10_1_PAN |
199
- ARMMMUIdxBit_E10_0 |
200
- ARMMMUIdxBit_Stage2;
201
} else {
202
return ARMMMUIdxBit_E10_1 |
203
ARMMMUIdxBit_E10_1_PAN |
204
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
205
ARMMMUIdxBit_SE3);
206
}
42
}
207
43
208
-static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
44
static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
209
- uint64_t value)
210
-{
211
- /* Invalidate by IPA. This has to invalidate any structures that
212
- * contain only stage 2 translation information, but does not need
213
- * to apply to structures that contain combined stage 1 and stage 2
214
- * translation information.
215
- * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero.
216
- */
217
- ARMCPU *cpu = env_archcpu(env);
218
- CPUState *cs = CPU(cpu);
219
- uint64_t pageaddr;
220
-
221
- if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
222
- return;
223
- }
224
-
225
- pageaddr = sextract64(value << 12, 0, 48);
226
-
227
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
228
-}
229
-
230
-static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
231
- uint64_t value)
232
-{
233
- CPUState *cs = env_cpu(env);
234
- uint64_t pageaddr;
235
-
236
- if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
237
- return;
238
- }
239
-
240
- pageaddr = sextract64(value << 12, 0, 48);
241
-
242
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
243
- ARMMMUIdxBit_Stage2);
244
-}
245
-
246
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
247
bool isread)
248
{
249
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
250
.writefn = tlbi_aa64_vae1_write },
251
{ .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64,
252
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
253
- .access = PL2_W, .type = ARM_CP_NO_RAW,
254
- .writefn = tlbi_aa64_ipas2e1is_write },
255
+ .access = PL2_W, .type = ARM_CP_NOP },
256
{ .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64,
257
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
258
- .access = PL2_W, .type = ARM_CP_NO_RAW,
259
- .writefn = tlbi_aa64_ipas2e1is_write },
260
+ .access = PL2_W, .type = ARM_CP_NOP },
261
{ .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64,
262
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
263
.access = PL2_W, .type = ARM_CP_NO_RAW,
264
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
265
.writefn = tlbi_aa64_alle1is_write },
266
{ .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64,
267
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
268
- .access = PL2_W, .type = ARM_CP_NO_RAW,
269
- .writefn = tlbi_aa64_ipas2e1_write },
270
+ .access = PL2_W, .type = ARM_CP_NOP },
271
{ .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64,
272
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
273
- .access = PL2_W, .type = ARM_CP_NO_RAW,
274
- .writefn = tlbi_aa64_ipas2e1_write },
275
+ .access = PL2_W, .type = ARM_CP_NOP },
276
{ .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64,
277
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
278
.access = PL2_W, .type = ARM_CP_NO_RAW,
279
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
280
.writefn = tlbimva_hyp_is_write },
281
{ .name = "TLBIIPAS2",
282
.cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
283
- .type = ARM_CP_NO_RAW, .access = PL2_W,
284
- .writefn = tlbiipas2_write },
285
+ .type = ARM_CP_NOP, .access = PL2_W },
286
{ .name = "TLBIIPAS2IS",
287
.cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
288
- .type = ARM_CP_NO_RAW, .access = PL2_W,
289
- .writefn = tlbiipas2_is_write },
290
+ .type = ARM_CP_NOP, .access = PL2_W },
291
{ .name = "TLBIIPAS2L",
292
.cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
293
- .type = ARM_CP_NO_RAW, .access = PL2_W,
294
- .writefn = tlbiipas2_write },
295
+ .type = ARM_CP_NOP, .access = PL2_W },
296
{ .name = "TLBIIPAS2LIS",
297
.cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
298
- .type = ARM_CP_NO_RAW, .access = PL2_W,
299
- .writefn = tlbiipas2_is_write },
300
+ .type = ARM_CP_NOP, .access = PL2_W },
301
/* 32 bit cache operations */
302
{ .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
303
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access },
304
--
45
--
305
2.20.1
46
2.20.1
306
47
307
48
diff view generated by jsdifflib
1
Convert the V[US]DOT (vector) insns to decodetree.
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We already have the full ARMMMUIdx as computed from the
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
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-2-richard.henderson@linaro.org
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200430181003.21682-7-peter.maydell@linaro.org
6
---
17
---
7
target/arm/neon-shared.decode | 4 ++++
18
target/arm/mte_helper.c | 3 +--
8
target/arm/translate-neon.inc.c | 32 ++++++++++++++++++++++++++++++++
19
1 file changed, 1 insertion(+), 2 deletions(-)
9
target/arm/translate.c | 9 +--------
10
3 files changed, 37 insertions(+), 8 deletions(-)
11
20
12
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
21
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-shared.decode
23
--- a/target/arm/mte_helper.c
15
+++ b/target/arm/neon-shared.decode
24
+++ b/target/arm/mte_helper.c
16
@@ -XXX,XX +XXX,XX @@ VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \
25
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
17
26
18
VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \
27
case 2:
19
vm=%vm_dp vn=%vn_dp vd=%vd_dp
28
/* Tag check fail causes asynchronous flag set. */
20
+
29
- mmu_idx = arm_mmu_idx_el(env, el);
21
+# VUDOT and VSDOT
30
- if (regime_has_2_ranges(mmu_idx)) {
22
+VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \
31
+ if (regime_has_2_ranges(arm_mmu_idx)) {
23
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
32
select = extract64(dirty_ptr, 55, 1);
24
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
} else {
25
index XXXXXXX..XXXXXXX 100644
34
select = 0;
26
--- a/target/arm/translate-neon.inc.c
27
+++ b/target/arm/translate-neon.inc.c
28
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
29
tcg_temp_free_ptr(fpst);
30
return true;
31
}
32
+
33
+static bool trans_VDOT(DisasContext *s, arg_VDOT *a)
34
+{
35
+ int opr_sz;
36
+ gen_helper_gvec_3 *fn_gvec;
37
+
38
+ if (!dc_isar_feature(aa32_dp, s)) {
39
+ return false;
40
+ }
41
+
42
+ /* UNDEF accesses to D16-D31 if they don't exist. */
43
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
44
+ ((a->vd | a->vn | a->vm) & 0x10)) {
45
+ return false;
46
+ }
47
+
48
+ if ((a->vn | a->vm | a->vd) & a->q) {
49
+ return false;
50
+ }
51
+
52
+ if (!vfp_access_check(s)) {
53
+ return true;
54
+ }
55
+
56
+ opr_sz = (1 + a->q) * 8;
57
+ fn_gvec = a->u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
58
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, a->vd),
59
+ vfp_reg_offset(1, a->vn),
60
+ vfp_reg_offset(1, a->vm),
61
+ opr_sz, opr_sz, 0, fn_gvec);
62
+ return true;
63
+}
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate.c
67
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
69
bool is_long = false, q = extract32(insn, 6, 1);
70
bool ptr_is_env = false;
71
72
- if ((insn & 0xfeb00f00) == 0xfc200d00) {
73
- /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
74
- bool u = extract32(insn, 4, 1);
75
- if (!dc_isar_feature(aa32_dp, s)) {
76
- return 1;
77
- }
78
- fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
79
- } else if ((insn & 0xff300f10) == 0xfc200810) {
80
+ if ((insn & 0xff300f10) == 0xfc200810) {
81
/* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
82
int is_s = extract32(insn, 23, 1);
83
if (!dc_isar_feature(aa32_fhm, s)) {
84
--
35
--
85
2.20.1
36
2.20.1
86
37
87
38
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Move misplaced comment.
3
The reporting in AArch64.TagCheckFail only depends on PSTATE.EL,
4
and not the AccType of the operation. There are two guest
5
visible problems that affect LDTR and STTR because of this:
4
6
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
(1) Selecting TCF0 vs TCF1 to decide on reporting,
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
(2) Report "data abort same el" not "data abort lower el".
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
10
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
9
Message-id: 20200427181649.26851-3-edgar.iglesias@gmail.com
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
13
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Message-id: 20201008162155.161886-3-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
hw/arm/xlnx-versal.c | 2 +-
17
target/arm/mte_helper.c | 10 +++-------
13
1 file changed, 1 insertion(+), 1 deletion(-)
18
1 file changed, 3 insertions(+), 7 deletions(-)
14
19
15
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
20
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/xlnx-versal.c
22
--- a/target/arm/mte_helper.c
18
+++ b/hw/arm/xlnx-versal.c
23
+++ b/target/arm/mte_helper.c
19
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
24
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
20
25
reg_el = regime_el(env, arm_mmu_idx);
21
obj = object_new(XLNX_VERSAL_ACPU_TYPE);
26
sctlr = env->cp15.sctlr_el[reg_el];
22
if (!obj) {
27
23
- /* Secondary CPUs start in PSCI powered-down state */
28
- switch (arm_mmu_idx) {
24
error_report("Unable to create apu.cpu[%d] of type %s",
29
- case ARMMMUIdx_E10_0:
25
i, XLNX_VERSAL_ACPU_TYPE);
30
- case ARMMMUIdx_E20_0:
26
exit(EXIT_FAILURE);
31
- el = 0;
27
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
32
+ el = arm_current_el(env);
28
object_property_set_int(obj, s->cfg.psci_conduit,
33
+ if (el == 0) {
29
"psci-conduit", &error_abort);
34
tcf = extract64(sctlr, 38, 2);
30
if (i) {
35
- break;
31
+ /* Secondary CPUs start in PSCI powered-down state */
36
- default:
32
object_property_set_bool(obj, true,
37
- el = reg_el;
33
"start-powered-off", &error_abort);
38
+ } else {
34
}
39
tcf = extract64(sctlr, 40, 2);
40
}
41
35
--
42
--
36
2.20.1
43
2.20.1
37
44
38
45
diff view generated by jsdifflib
1
The access_type argument to get_phys_addr_lpae() is an MMUAccessType;
1
From: Richard Henderson <richard.henderson@linaro.org>
2
use the enum constant MMU_DATA_LOAD rather than a literal 0 when we
3
call it in S1_ptw_translate().
4
2
3
Unlike many other bits in HCR_EL2, the description for this
4
bit does not contain the phrase "if ... this field behaves
5
as 0 for all purposes other than", so do not squash the bit
6
in arm_hcr_el2_eff.
7
8
Instead, replicate the E2H+TGE test in the two places that
9
require it.
10
11
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-4-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200330210400.11724-3-peter.maydell@linaro.org
9
---
17
---
10
target/arm/helper.c | 5 +++--
18
target/arm/internals.h | 9 +++++----
11
1 file changed, 3 insertions(+), 2 deletions(-)
19
target/arm/helper.c | 9 +++++----
20
2 files changed, 10 insertions(+), 8 deletions(-)
12
21
22
diff --git a/target/arm/internals.h b/target/arm/internals.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/internals.h
25
+++ b/target/arm/internals.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
27
&& !(env->cp15.scr_el3 & SCR_ATA)) {
28
return false;
29
}
30
- if (el < 2
31
- && arm_feature(env, ARM_FEATURE_EL2)
32
- && !(arm_hcr_el2_eff(env) & HCR_ATA)) {
33
- return false;
34
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
35
+ uint64_t hcr = arm_hcr_el2_eff(env);
36
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
37
+ return false;
38
+ }
39
}
40
sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA);
41
return sctlr != 0;
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
42
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
44
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
45
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
46
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
18
pcacheattrs = &cacheattrs;
47
{
19
}
48
int el = arm_current_el(env);
20
49
21
- ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_Stage2, &s2pa,
50
- if (el < 2 &&
22
- &txattrs, &s2prot, &s2size, fi, pcacheattrs);
51
- arm_feature(env, ARM_FEATURE_EL2) &&
23
+ ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, ARMMMUIdx_Stage2,
52
- !(arm_hcr_el2_eff(env) & HCR_ATA)) {
24
+ &s2pa, &txattrs, &s2prot, &s2size, fi,
53
- return CP_ACCESS_TRAP_EL2;
25
+ pcacheattrs);
54
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
26
if (ret) {
55
+ uint64_t hcr = arm_hcr_el2_eff(env);
27
assert(fi->type != ARMFault_None);
56
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
28
fi->s2addr = addr;
57
+ return CP_ACCESS_TRAP_EL2;
58
+ }
59
}
60
if (el < 3 &&
61
arm_feature(env, ARM_FEATURE_EL3) &&
29
--
62
--
30
2.20.1
63
2.20.1
31
64
32
65
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Peng Liang <liangpeng10@huawei.com>
2
2
3
hw/arm: versal: Add support for the RTC.
3
VMStateDescription.fields should be end with VMSTATE_END_OF_LIST().
4
However, microbit_i2c_vmstate doesn't follow it. Let's change it.
4
5
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Fixes: 9d68bf564e ("arm: Stub out NRF51 TWI magnetometer/accelerometer detection")
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20200427181649.26851-10-edgar.iglesias@gmail.com
10
Message-id: 20201019093401.2993833-1-liangpeng10@huawei.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
include/hw/arm/xlnx-versal.h | 8 ++++++++
13
hw/i2c/microbit_i2c.c | 1 +
13
hw/arm/xlnx-versal.c | 21 +++++++++++++++++++++
14
1 file changed, 1 insertion(+)
14
2 files changed, 29 insertions(+)
15
15
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
16
diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-versal.h
18
--- a/hw/i2c/microbit_i2c.c
19
+++ b/include/hw/arm/xlnx-versal.h
19
+++ b/hw/i2c/microbit_i2c.c
20
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription microbit_i2c_vmstate = {
21
#include "hw/char/pl011.h"
21
.fields = (VMStateField[]) {
22
#include "hw/dma/xlnx-zdma.h"
22
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
23
#include "hw/net/cadence_gem.h"
23
VMSTATE_UINT32(read_idx, MicrobitI2CState),
24
+#include "hw/rtc/xlnx-zynqmp-rtc.h"
24
+ VMSTATE_END_OF_LIST()
25
25
},
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
26
};
27
#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL)
28
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
29
struct {
30
SDHCIState sd[XLNX_VERSAL_NR_SDS];
31
} iou;
32
+
33
+ XlnxZynqMPRTC rtc;
34
} pmc;
35
36
struct {
37
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
38
#define VERSAL_GEM1_IRQ_0 58
39
#define VERSAL_GEM1_WAKE_IRQ_0 59
40
#define VERSAL_ADMA_IRQ_0 60
41
+#define VERSAL_RTC_APB_ERR_IRQ 121
42
#define VERSAL_SD0_IRQ_0 126
43
+#define VERSAL_RTC_ALARM_IRQ 142
44
+#define VERSAL_RTC_SECONDS_IRQ 143
45
46
/* Architecturally reserved IRQs suitable for virtualization. */
47
#define VERSAL_RSVD_IRQ_FIRST 111
48
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
49
#define MM_PMC_SD0_SIZE 0x10000
50
#define MM_PMC_CRP 0xf1260000U
51
#define MM_PMC_CRP_SIZE 0x10000
52
+#define MM_PMC_RTC 0xf12a0000
53
+#define MM_PMC_RTC_SIZE 0x10000
54
#endif
55
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/xlnx-versal.c
58
+++ b/hw/arm/xlnx-versal.c
59
@@ -XXX,XX +XXX,XX @@ static void versal_create_sds(Versal *s, qemu_irq *pic)
60
}
61
}
62
63
+static void versal_create_rtc(Versal *s, qemu_irq *pic)
64
+{
65
+ SysBusDevice *sbd;
66
+ MemoryRegion *mr;
67
+
68
+ sysbus_init_child_obj(OBJECT(s), "rtc", &s->pmc.rtc, sizeof(s->pmc.rtc),
69
+ TYPE_XLNX_ZYNQMP_RTC);
70
+ sbd = SYS_BUS_DEVICE(&s->pmc.rtc);
71
+ qdev_init_nofail(DEVICE(sbd));
72
+
73
+ mr = sysbus_mmio_get_region(sbd, 0);
74
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr);
75
+
76
+ /*
77
+ * TODO: Connect the ALARM and SECONDS interrupts once our RTC model
78
+ * supports them.
79
+ */
80
+ sysbus_connect_irq(sbd, 1, pic[VERSAL_RTC_APB_ERR_IRQ]);
81
+}
82
+
83
/* This takes the board allocated linear DDR memory and creates aliases
84
* for each split DDR range/aperture on the Versal address map.
85
*/
86
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
87
versal_create_gems(s, pic);
88
versal_create_admas(s, pic);
89
versal_create_sds(s, pic);
90
+ versal_create_rtc(s, pic);
91
versal_map_ddr(s);
92
versal_unimp(s);
93
27
94
--
28
--
95
2.20.1
29
2.20.1
96
30
97
31
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Embed the ADMAs into the SoC type.
3
Commit 7998beb9c2e removed the ram_size initialization in the
4
arm_boot_info structure, however it is used by arm_load_kernel().
4
5
5
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
6
Initialize the field to fix:
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
$ qemu-system-arm -M n800 -append 'console=ttyS1' \
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
-kernel meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
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)
10
Message-id: 20200427181649.26851-7-edgar.iglesias@gmail.com
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>
18
Tested-by: Thomas Huth <thuth@redhat.com>
19
Message-id: 20201019095148.1602119-1-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
21
---
13
include/hw/arm/xlnx-versal.h | 3 ++-
22
hw/arm/nseries.c | 1 +
14
hw/arm/xlnx-versal.c | 14 +++++++-------
23
1 file changed, 1 insertion(+)
15
2 files changed, 9 insertions(+), 8 deletions(-)
16
24
17
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
25
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
18
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/xlnx-versal.h
27
--- a/hw/arm/nseries.c
20
+++ b/include/hw/arm/xlnx-versal.h
28
+++ b/hw/arm/nseries.c
21
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ static void n8x0_init(MachineState *machine,
22
#include "hw/arm/boot.h"
30
g_free(sz);
23
#include "hw/intc/arm_gicv3.h"
31
exit(EXIT_FAILURE);
24
#include "hw/char/pl011.h"
25
+#include "hw/dma/xlnx-zdma.h"
26
#include "hw/net/cadence_gem.h"
27
28
#define TYPE_XLNX_VERSAL "xlnx-versal"
29
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
30
struct {
31
PL011State uart[XLNX_VERSAL_NR_UARTS];
32
CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
33
- SysBusDevice *adma[XLNX_VERSAL_NR_ADMAS];
34
+ XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
35
} iou;
36
} lpd;
37
38
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/arm/xlnx-versal.c
41
+++ b/hw/arm/xlnx-versal.c
42
@@ -XXX,XX +XXX,XX @@ static void versal_create_admas(Versal *s, qemu_irq *pic)
43
DeviceState *dev;
44
MemoryRegion *mr;
45
46
- dev = qdev_create(NULL, "xlnx.zdma");
47
- s->lpd.iou.adma[i] = SYS_BUS_DEVICE(dev);
48
- object_property_set_int(OBJECT(s->lpd.iou.adma[i]), 128, "bus-width",
49
- &error_abort);
50
- object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
51
+ sysbus_init_child_obj(OBJECT(s), name,
52
+ &s->lpd.iou.adma[i], sizeof(s->lpd.iou.adma[i]),
53
+ TYPE_XLNX_ZDMA);
54
+ dev = DEVICE(&s->lpd.iou.adma[i]);
55
+ object_property_set_int(OBJECT(dev), 128, "bus-width", &error_abort);
56
qdev_init_nofail(dev);
57
58
- mr = sysbus_mmio_get_region(s->lpd.iou.adma[i], 0);
59
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
60
memory_region_add_subregion(&s->mr_ps,
61
MM_ADMA_CH0 + i * MM_ADMA_CH0_SIZE, mr);
62
63
- sysbus_connect_irq(s->lpd.iou.adma[i], 0, pic[VERSAL_ADMA_IRQ_0 + i]);
64
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[VERSAL_ADMA_IRQ_0 + i]);
65
g_free(name);
66
}
32
}
67
}
33
+ binfo->ram_size = machine->ram_size;
34
35
memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
36
machine->ram);
68
--
37
--
69
2.20.1
38
2.20.1
70
39
71
40
diff view generated by jsdifflib
1
Convert VCMLA (scalar) in the 2reg-scalar-ext group to decodetree.
1
For nested groups like:
2
2
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>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Message-id: 20201019151301.2046-2-peter.maydell@linaro.org
5
Message-id: 20200430181003.21682-9-peter.maydell@linaro.org
6
---
29
---
7
target/arm/neon-shared.decode | 5 +++++
30
scripts/decodetree.py | 2 +-
8
target/arm/translate-neon.inc.c | 40 +++++++++++++++++++++++++++++++++
31
1 file changed, 1 insertion(+), 1 deletion(-)
9
target/arm/translate.c | 26 +--------------------
10
3 files changed, 46 insertions(+), 25 deletions(-)
11
32
12
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
33
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
13
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-shared.decode
35
--- a/scripts/decodetree.py
15
+++ b/target/arm/neon-shared.decode
36
+++ b/scripts/decodetree.py
16
@@ -XXX,XX +XXX,XX @@ VFML 1111 110 0 s:1 . 10 .... .... 1000 . 0 . 1 .... \
37
@@ -XXX,XX +XXX,XX @@ class Tree:
17
vm=%vm_sp vn=%vn_sp vd=%vd_dp q=0
38
output(ind, ' /* ',
18
VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \
39
str_match_bits(innerbits, innermask), ' */\n')
19
vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1
40
s.output_code(i + 4, extracted, innerbits, innermask)
20
+
41
- output(ind, ' return false;\n')
21
+VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \
42
+ output(ind, ' break;\n')
22
+ vn=%vn_dp vd=%vd_dp size=0
43
output(ind, '}\n')
23
+VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \
44
# end Tree
24
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0
25
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-neon.inc.c
28
+++ b/target/arm/translate-neon.inc.c
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VFML(DisasContext *s, arg_VFML *a)
30
gen_helper_gvec_fmlal_a32);
31
return true;
32
}
33
+
34
+static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
35
+{
36
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
37
+ int opr_sz;
38
+ TCGv_ptr fpst;
39
+
40
+ if (!dc_isar_feature(aa32_vcma, s)) {
41
+ return false;
42
+ }
43
+ if (a->size == 0 && !dc_isar_feature(aa32_fp16_arith, s)) {
44
+ return false;
45
+ }
46
+
47
+ /* UNDEF accesses to D16-D31 if they don't exist. */
48
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
49
+ ((a->vd | a->vn | a->vm) & 0x10)) {
50
+ return false;
51
+ }
52
+
53
+ if ((a->vd | a->vn) & a->q) {
54
+ return false;
55
+ }
56
+
57
+ if (!vfp_access_check(s)) {
58
+ return true;
59
+ }
60
+
61
+ fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx
62
+ : gen_helper_gvec_fcmlah_idx);
63
+ opr_sz = (1 + a->q) * 8;
64
+ fpst = get_fpstatus_ptr(1);
65
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
66
+ vfp_reg_offset(1, a->vn),
67
+ vfp_reg_offset(1, a->vm),
68
+ fpst, opr_sz, opr_sz,
69
+ (a->index << 2) | a->rot, fn_gvec_ptr);
70
+ tcg_temp_free_ptr(fpst);
71
+ return true;
72
+}
73
diff --git a/target/arm/translate.c b/target/arm/translate.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/target/arm/translate.c
76
+++ b/target/arm/translate.c
77
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
78
bool is_long = false, q = extract32(insn, 6, 1);
79
bool ptr_is_env = false;
80
81
- if ((insn & 0xff000f10) == 0xfe000800) {
82
- /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
83
- int rot = extract32(insn, 20, 2);
84
- int size = extract32(insn, 23, 1);
85
- int index;
86
-
87
- if (!dc_isar_feature(aa32_vcma, s)) {
88
- return 1;
89
- }
90
- if (size == 0) {
91
- if (!dc_isar_feature(aa32_fp16_arith, s)) {
92
- return 1;
93
- }
94
- /* For fp16, rm is just Vm, and index is M. */
95
- rm = extract32(insn, 0, 4);
96
- index = extract32(insn, 5, 1);
97
- } else {
98
- /* For fp32, rm is the usual M:Vm, and index is 0. */
99
- VFP_DREG_M(rm, insn);
100
- index = 0;
101
- }
102
- data = (index << 2) | rot;
103
- fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
104
- : gen_helper_gvec_fcmlah_idx);
105
- } else if ((insn & 0xffb00f00) == 0xfe200d00) {
106
+ if ((insn & 0xffb00f00) == 0xfe200d00) {
107
/* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
108
int u = extract32(insn, 4, 1);
109
45
110
--
46
--
111
2.20.1
47
2.20.1
112
48
113
49
diff view generated by jsdifflib
1
Convert the Neon 3-reg-same VADD and VSUB insns to decodetree.
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
2
6
3
Note that we don't need the neon_3r_sizes[op] check here because all
7
We previously marked these up with TODO comments; implement the
4
size values are OK for VADD and VSUB; we'll add this when we convert
8
correct behaviour.
5
the first insn that has size restrictions.
6
9
7
For this we need one of the GVecGen*Fn typedefs currently in
10
Unfortunately there is no ID register field which indicates this
8
translate-a64.h; move them all to translate.h as a block so they
11
behaviour. We could in theory test an unrelated ID register which
9
are visible to the 32-bit decoder.
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.
10
16
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20200430181003.21682-15-peter.maydell@linaro.org
19
Message-id: 20201019151301.2046-3-peter.maydell@linaro.org
14
---
20
---
15
target/arm/translate-a64.h | 9 --------
21
target/arm/cpu.h | 1 +
16
target/arm/translate.h | 9 ++++++++
22
target/arm/m-nocp.decode | 10 ++++++----
17
target/arm/neon-dp.decode | 17 +++++++++++++++
23
target/arm/translate-vfp.c.inc | 17 +++++++++++++++--
18
target/arm/translate-neon.inc.c | 38 +++++++++++++++++++++++++++++++++
24
3 files changed, 22 insertions(+), 6 deletions(-)
19
target/arm/translate.c | 14 ++++--------
20
5 files changed, 68 insertions(+), 19 deletions(-)
21
25
22
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/translate-a64.h
28
--- a/target/arm/cpu.h
25
+++ b/target/arm/translate-a64.h
29
+++ b/target/arm/cpu.h
26
@@ -XXX,XX +XXX,XX @@ static inline int vec_full_reg_size(DisasContext *s)
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
27
31
ARM_FEATURE_VBAR, /* has cp15 VBAR */
28
bool disas_sve(DisasContext *, uint32_t);
32
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
29
33
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
30
-/* Note that the gvec expanders operate on offsets + sizes. */
34
+ ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
31
-typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t);
35
};
32
-typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
36
33
- uint32_t, uint32_t);
37
static inline int arm_feature(CPUARMState *env, int feature)
34
-typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
38
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
35
- uint32_t, uint32_t, uint32_t);
36
-typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t,
37
- uint32_t, uint32_t, uint32_t);
38
-
39
#endif /* TARGET_ARM_TRANSLATE_A64_H */
40
diff --git a/target/arm/translate.h b/target/arm/translate.h
41
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/translate.h
40
--- a/target/arm/m-nocp.decode
43
+++ b/target/arm/translate.h
41
+++ b/target/arm/m-nocp.decode
44
@@ -XXX,XX +XXX,XX @@ void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
42
@@ -XXX,XX +XXX,XX @@
45
#define dc_isar_feature(name, ctx) \
43
# If the coprocessor is not present or disabled then we will generate
46
({ DisasContext *ctx_ = (ctx); isar_feature_##name(ctx_->isar); })
44
# the NOCP exception; otherwise we let the insn through to the main decode.
47
45
48
+/* Note that the gvec expanders operate on offsets + sizes. */
46
+&nocp cp
49
+typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t);
50
+typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
51
+ uint32_t, uint32_t);
52
+typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
53
+ uint32_t, uint32_t, uint32_t);
54
+typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t,
55
+ uint32_t, uint32_t, uint32_t);
56
+
47
+
57
#endif /* TARGET_ARM_TRANSLATE_H */
48
{
58
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
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
59
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/neon-dp.decode
65
--- a/target/arm/translate-vfp.c.inc
61
+++ b/target/arm/neon-dp.decode
66
+++ b/target/arm/translate-vfp.c.inc
62
@@ -XXX,XX +XXX,XX @@
67
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
63
#
64
# This file is processed by scripts/decodetree.py
65
#
66
+# VFP/Neon register fields; same as vfp.decode
67
+%vm_dp 5:1 0:4
68
+%vn_dp 7:1 16:4
69
+%vd_dp 22:1 12:4
70
71
# Encodings for Neon data processing instructions where the T32 encoding
72
# is a simple transformation of the A32 encoding.
73
@@ -XXX,XX +XXX,XX @@
74
# 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
75
# This file works on the A32 encoding only; calling code for T32 has to
76
# transform the insn into the A32 version first.
77
+
78
+######################################################################
79
+# 3-reg-same grouping:
80
+# 1111 001 U 0 D sz:2 Vn:4 Vd:4 opc:4 N Q M op Vm:4
81
+######################################################################
82
+
83
+&3same vm vn vd q size
84
+
85
+@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
86
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
87
+
88
+VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same
89
+VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
90
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/translate-neon.inc.c
93
+++ b/target/arm/translate-neon.inc.c
94
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
95
96
return true;
68
return true;
97
}
69
}
98
+
70
99
+static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn)
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)
100
+{
94
+{
101
+ int vec_size = a->q ? 16 : 8;
95
+ /* This range needs a coprocessor check for v8.1M and later only */
102
+ int rd_ofs = neon_reg_offset(a->vd, 0);
96
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
103
+ int rn_ofs = neon_reg_offset(a->vn, 0);
104
+ int rm_ofs = neon_reg_offset(a->vm, 0);
105
+
106
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
107
+ return false;
97
+ return false;
108
+ }
98
+ }
109
+
99
+ return trans_NOCP(s, a);
110
+ /* UNDEF accesses to D16-D31 if they don't exist. */
111
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
112
+ ((a->vd | a->vn | a->vm) & 0x10)) {
113
+ return false;
114
+ }
115
+
116
+ if ((a->vn | a->vm | a->vd) & a->q) {
117
+ return false;
118
+ }
119
+
120
+ if (!vfp_access_check(s)) {
121
+ return true;
122
+ }
123
+
124
+ fn(a->size, rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
125
+ return true;
126
+}
100
+}
127
+
101
+
128
+#define DO_3SAME(INSN, FUNC) \
102
static bool trans_VINS(DisasContext *s, arg_VINS *a)
129
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
103
{
130
+ { \
104
TCGv_i32 rd, rm;
131
+ return do_3same(s, a, FUNC); \
132
+ }
133
+
134
+DO_3SAME(VADD, tcg_gen_gvec_add)
135
+DO_3SAME(VSUB, tcg_gen_gvec_sub)
136
diff --git a/target/arm/translate.c b/target/arm/translate.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/target/arm/translate.c
139
+++ b/target/arm/translate.c
140
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
141
}
142
return 0;
143
144
- case NEON_3R_VADD_VSUB:
145
- if (u) {
146
- tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
147
- vec_size, vec_size);
148
- } else {
149
- tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
150
- vec_size, vec_size);
151
- }
152
- return 0;
153
-
154
case NEON_3R_VQADD:
155
tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
156
rn_ofs, rm_ofs, vec_size, vec_size,
157
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
158
tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size,
159
u ? &ushl_op[size] : &sshl_op[size]);
160
return 0;
161
+
162
+ case NEON_3R_VADD_VSUB:
163
+ /* Already handled by decodetree */
164
+ return 1;
165
}
166
167
if (size == 3) {
168
--
105
--
169
2.20.1
106
2.20.1
170
107
171
108
diff view generated by jsdifflib
1
Convert the VFM[AS]L (vector) insns to decodetree. This is the last
1
v8.1M brings four new insns to M-profile:
2
insn in the legacy decoder for the 3same_ext group, so we can
2
* CSEL : Rd = cond ? Rn : Rm
3
delete the legacy decoder function for the group entirely.
3
* CSINC : Rd = cond ? Rn : Rm+1
4
* CSINV : Rd = cond ? Rn : ~Rm
5
* CSNEG : Rd = cond ? Rn : -Rm
4
6
5
Note that in disas_thumb2_insn() the parts of this encoding space
7
Implement these.
6
where the decodetree decoder returns false will correctly be directed
7
to illegal_op by the "(insn & (1 << 28))" check so they won't fall
8
into disas_coproc_insn() by mistake.
9
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
12
Message-id: 20200430181003.21682-8-peter.maydell@linaro.org
13
---
12
---
14
target/arm/neon-shared.decode | 6 +++
13
target/arm/t32.decode | 3 +++
15
target/arm/translate-neon.inc.c | 31 +++++++++++
14
target/arm/translate.c | 60 ++++++++++++++++++++++++++++++++++++++++++
16
target/arm/translate.c | 92 +--------------------------------
15
2 files changed, 63 insertions(+)
17
3 files changed, 38 insertions(+), 91 deletions(-)
18
16
19
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
17
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/neon-shared.decode
19
--- a/target/arm/t32.decode
22
+++ b/target/arm/neon-shared.decode
20
+++ b/target/arm/t32.decode
23
@@ -XXX,XX +XXX,XX @@ VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \
21
@@ -XXX,XX +XXX,XX @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
24
# VUDOT and VSDOT
22
}
25
VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \
23
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
26
vm=%vm_dp vn=%vn_dp vd=%vd_dp
24
25
+# v8.1M CSEL and friends
26
+CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
27
+
27
+
28
+# VFM[AS]L
28
# Data-processing (register-shifted register)
29
+VFML 1111 110 0 s:1 . 10 .... .... 1000 . 0 . 1 .... \
29
30
+ vm=%vm_sp vn=%vn_sp vd=%vd_dp q=0
30
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
31
+VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \
32
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1
33
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-neon.inc.c
36
+++ b/target/arm/translate-neon.inc.c
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VDOT(DisasContext *s, arg_VDOT *a)
38
opr_sz, opr_sz, 0, fn_gvec);
39
return true;
40
}
41
+
42
+static bool trans_VFML(DisasContext *s, arg_VFML *a)
43
+{
44
+ int opr_sz;
45
+
46
+ if (!dc_isar_feature(aa32_fhm, s)) {
47
+ return false;
48
+ }
49
+
50
+ /* UNDEF accesses to D16-D31 if they don't exist. */
51
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
52
+ (a->vd & 0x10)) {
53
+ return false;
54
+ }
55
+
56
+ if (a->vd & a->q) {
57
+ return false;
58
+ }
59
+
60
+ if (!vfp_access_check(s)) {
61
+ return true;
62
+ }
63
+
64
+ opr_sz = (1 + a->q) * 8;
65
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
66
+ vfp_reg_offset(a->q, a->vn),
67
+ vfp_reg_offset(a->q, a->vm),
68
+ cpu_env, opr_sz, opr_sz, a->s, /* is_2 == 0 */
69
+ gen_helper_gvec_fmlal_a32);
70
+ return true;
71
+}
72
diff --git a/target/arm/translate.c b/target/arm/translate.c
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
73
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/translate.c
33
--- a/target/arm/translate.c
75
+++ b/target/arm/translate.c
34
+++ b/target/arm/translate.c
76
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
35
@@ -XXX,XX +XXX,XX @@ static bool trans_IT(DisasContext *s, arg_IT *a)
77
return 0;
36
return true;
78
}
37
}
79
38
80
-/* Advanced SIMD three registers of the same length extension.
39
+/* v8.1M CSEL/CSINC/CSNEG/CSINV */
81
- * 31 25 23 22 20 16 12 11 10 9 8 3 0
40
+static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
82
- * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
41
+{
83
- * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
42
+ TCGv_i32 rn, rm, zero;
84
- * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
43
+ DisasCompare c;
85
- */
44
+
86
-static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
87
-{
46
+ return false;
88
- gen_helper_gvec_3 *fn_gvec = NULL;
47
+ }
89
- gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
48
+
90
- int rd, rn, rm, opr_sz;
49
+ if (a->rm == 13) {
91
- int data = 0;
50
+ /* SEE "Related encodings" (MVE shifts) */
92
- int off_rn, off_rm;
51
+ return false;
93
- bool is_long = false, q = extract32(insn, 6, 1);
52
+ }
94
- bool ptr_is_env = false;
53
+
95
-
54
+ if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
96
- if ((insn & 0xff300f10) == 0xfc200810) {
55
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
97
- /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
56
+ return false;
98
- int is_s = extract32(insn, 23, 1);
57
+ }
99
- if (!dc_isar_feature(aa32_fhm, s)) {
58
+
100
- return 1;
59
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
101
- }
60
+ if (a->rn == 15) {
102
- is_long = true;
61
+ rn = tcg_const_i32(0);
103
- data = is_s; /* is_2 == 0 */
62
+ } else {
104
- fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
63
+ rn = load_reg(s, a->rn);
105
- ptr_is_env = true;
64
+ }
106
- } else {
65
+ if (a->rm == 15) {
107
- return 1;
66
+ rm = tcg_const_i32(0);
108
- }
67
+ } else {
109
-
68
+ rm = load_reg(s, a->rm);
110
- VFP_DREG_D(rd, insn);
69
+ }
111
- if (rd & q) {
70
+
112
- return 1;
71
+ switch (a->op) {
113
- }
72
+ case 0: /* CSEL */
114
- if (q || !is_long) {
73
+ break;
115
- VFP_DREG_N(rn, insn);
74
+ case 1: /* CSINC */
116
- VFP_DREG_M(rm, insn);
75
+ tcg_gen_addi_i32(rm, rm, 1);
117
- if ((rn | rm) & q & !is_long) {
76
+ break;
118
- return 1;
77
+ case 2: /* CSINV */
119
- }
78
+ tcg_gen_not_i32(rm, rm);
120
- off_rn = vfp_reg_offset(1, rn);
79
+ break;
121
- off_rm = vfp_reg_offset(1, rm);
80
+ case 3: /* CSNEG */
122
- } else {
81
+ tcg_gen_neg_i32(rm, rm);
123
- rn = VFP_SREG_N(insn);
82
+ break;
124
- rm = VFP_SREG_M(insn);
83
+ default:
125
- off_rn = vfp_reg_offset(0, rn);
84
+ g_assert_not_reached();
126
- off_rm = vfp_reg_offset(0, rm);
85
+ }
127
- }
86
+
128
-
87
+ arm_test_cc(&c, a->fcond);
129
- if (s->fp_excp_el) {
88
+ zero = tcg_const_i32(0);
130
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
89
+ tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
131
- syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
90
+ arm_free_cc(&c);
132
- return 0;
91
+ tcg_temp_free_i32(zero);
133
- }
92
+
134
- if (!s->vfp_enabled) {
93
+ store_reg(s, a->rd, rn);
135
- return 1;
94
+ tcg_temp_free_i32(rm);
136
- }
95
+
137
-
96
+ return true;
138
- opr_sz = (1 + q) * 8;
97
+}
139
- if (fn_gvec_ptr) {
98
+
140
- TCGv_ptr ptr;
99
/*
141
- if (ptr_is_env) {
100
* Legacy decoder.
142
- ptr = cpu_env;
101
*/
143
- } else {
144
- ptr = get_fpstatus_ptr(1);
145
- }
146
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
147
- opr_sz, opr_sz, data, fn_gvec_ptr);
148
- if (!ptr_is_env) {
149
- tcg_temp_free_ptr(ptr);
150
- }
151
- } else {
152
- tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
153
- opr_sz, opr_sz, data, fn_gvec);
154
- }
155
- return 0;
156
-}
157
-
158
/* Advanced SIMD two registers and a scalar extension.
159
* 31 24 23 22 20 16 12 11 10 9 8 3 0
160
* +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
161
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
162
}
163
}
164
}
165
- } else if ((insn & 0x0e000a00) == 0x0c000800
166
- && arm_dc_feature(s, ARM_FEATURE_V8)) {
167
- if (disas_neon_insn_3same_ext(s, insn)) {
168
- goto illegal_op;
169
- }
170
- return;
171
} else if ((insn & 0x0f000a00) == 0x0e000800
172
&& arm_dc_feature(s, ARM_FEATURE_V8)) {
173
if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
174
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
175
}
176
break;
177
}
178
- if ((insn & 0xfe000a00) == 0xfc000800
179
+ if ((insn & 0xff000a00) == 0xfe000800
180
&& arm_dc_feature(s, ARM_FEATURE_V8)) {
181
/* The Thumb2 and ARM encodings are identical. */
182
- if (disas_neon_insn_3same_ext(s, insn)) {
183
- goto illegal_op;
184
- }
185
- } else if ((insn & 0xff000a00) == 0xfe000800
186
- && arm_dc_feature(s, ARM_FEATURE_V8)) {
187
- /* The Thumb2 and ARM encodings are identical. */
188
if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
189
goto illegal_op;
190
}
191
--
102
--
192
2.20.1
103
2.20.1
193
104
194
105
diff view generated by jsdifflib
1
In aarch64_max_initfn() we update both 32-bit and 64-bit ID
1
The t32 decode has a group which represents a set of insns
2
registers. The intended pattern is that for 64-bit ID registers we
2
which overlap with B_cond_thumb because they have [25:23]=111
3
use FIELD_DP64 and the uint64_t 't' register, while 32-bit ID
3
(which is an invalid condition code field for the branch insn).
4
registers use FIELD_DP32 and the uint32_t 'u' register. For
4
This group is currently defined using the {} overlap-OK syntax,
5
ID_AA64DFR0 we accidentally used 'u', meaning that the top 32 bits of
5
but it is almost entirely non-overlapping patterns. Switch
6
this 64-bit ID register would end up always zero. Luckily at the
6
it over to use a non-overlapping group.
7
moment that's what they should be anyway, so this bug has no visible
8
effects.
9
7
10
Use the right-sized variable.
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
11
12
Fixes: 3bec78447a958d481991
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>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
18
Message-id: 20201019151301.2046-5-peter.maydell@linaro.org
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20200423110915.10527-1-peter.maydell@linaro.org
17
---
19
---
18
target/arm/cpu64.c | 6 +++---
20
target/arm/t32.decode | 26 ++++++++++++--------------
19
1 file changed, 3 insertions(+), 3 deletions(-)
21
1 file changed, 12 insertions(+), 14 deletions(-)
20
22
21
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
23
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
22
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu64.c
25
--- a/target/arm/t32.decode
24
+++ b/target/arm/cpu64.c
26
+++ b/target/arm/t32.decode
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
27
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
26
u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */
28
{
27
cpu->isar.id_mmfr4 = u;
29
# Group insn[25:23] = 111, which is cond=111x for the branch below,
28
30
# or unconditional, which would be illegal for the branch.
29
- u = cpu->isar.id_aa64dfr0;
31
- {
30
- u = FIELD_DP64(u, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */
32
- # Hints
31
- cpu->isar.id_aa64dfr0 = u;
33
+ [
32
+ t = cpu->isar.id_aa64dfr0;
34
+ # Hints, and CPS
33
+ t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */
35
{
34
+ cpu->isar.id_aa64dfr0 = t;
36
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
35
37
WFE 1111 0011 1010 1111 1000 0000 0000 0010
36
u = cpu->isar.id_dfr0;
38
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
37
u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
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
38
--
77
--
39
2.20.1
78
2.20.1
40
79
41
80
diff view generated by jsdifflib
1
We were accidentally permitting decode of Thumb Neon insns even if
1
The BLX immediate insn in the Thumb encoding always performs
2
the CPU didn't have the FEATURE_NEON bit set, because the feature
2
a switch from Thumb to Arm state. This would be totally useless
3
check was being done before the call to disas_neon_data_insn() and
3
in M-profile which has no Arm decoder, and so the instruction
4
disas_neon_ls_insn() in the Arm decoder but was omitted from the
4
does not exist at all there. Make the encoding UNDEF for M-profile.
5
Thumb decoder. Push the feature bit check down into the called
6
functions so it is done for both Arm and Thumb encodings.
7
5
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>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20201019151301.2046-6-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20200430181003.21682-3-peter.maydell@linaro.org
12
---
12
---
13
target/arm/translate.c | 16 ++++++++--------
13
target/arm/translate.c | 8 ++++++++
14
1 file changed, 8 insertions(+), 8 deletions(-)
14
1 file changed, 8 insertions(+)
15
15
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
18
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
19
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
20
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
21
TCGv_i32 tmp2;
21
{
22
TCGv_i64 tmp64;
22
TCGv_i32 tmp;
23
23
24
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
24
+ /*
25
+ return 1;
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;
26
+ }
30
+ }
27
+
31
+
28
/* FIXME: this access check should not take precedence over UNDEF
32
/* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
29
* for invalid encodings; we will generate incorrect syndrome information
33
if (s->thumb && (a->imm & 2)) {
30
* for attempts to execute invalid vfp/neon encodings with FP disabled.
34
return false;
31
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
32
TCGv_ptr ptr1, ptr2, ptr3;
33
TCGv_i64 tmp64;
34
35
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
36
+ return 1;
37
+ }
38
+
39
/* FIXME: this access check should not take precedence over UNDEF
40
* for invalid encodings; we will generate incorrect syndrome information
41
* for attempts to execute invalid vfp/neon encodings with FP disabled.
42
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
43
44
if (((insn >> 25) & 7) == 1) {
45
/* NEON Data processing. */
46
- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
47
- goto illegal_op;
48
- }
49
-
50
if (disas_neon_data_insn(s, insn)) {
51
goto illegal_op;
52
}
53
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
54
}
55
if ((insn & 0x0f100000) == 0x04000000) {
56
/* NEON load/store. */
57
- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
58
- goto illegal_op;
59
- }
60
-
61
if (disas_neon_ls_insn(s, insn)) {
62
goto illegal_op;
63
}
64
--
35
--
65
2.20.1
36
2.20.1
66
37
67
38
diff view generated by jsdifflib
1
Convert the Neon "load/store single structure to one lane" insns to
1
v8.1M implements a new 'branch future' feature, which is a
2
decodetree.
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).
3
13
4
As this is the last set of insns in the neon load/store group,
14
For QEMU, implementing this caching of branch information
5
we can remove the whole disas_neon_ls_insn() function.
15
would be complicated and would not improve the speed of
16
execution at all, so we make the IMPDEF choice to implement
17
all BF insns as NOPs.
6
18
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20201019151301.2046-7-peter.maydell@linaro.org
9
Message-id: 20200430181003.21682-14-peter.maydell@linaro.org
10
---
22
---
11
target/arm/neon-ls.decode | 11 +++
23
target/arm/cpu.h | 6 ++++++
12
target/arm/translate-neon.inc.c | 89 +++++++++++++++++++
24
target/arm/t32.decode | 13 ++++++++++++-
13
target/arm/translate.c | 147 --------------------------------
25
target/arm/translate.c | 20 ++++++++++++++++++++
14
3 files changed, 100 insertions(+), 147 deletions(-)
26
3 files changed, 38 insertions(+), 1 deletion(-)
15
27
16
diff --git a/target/arm/neon-ls.decode b/target/arm/neon-ls.decode
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/neon-ls.decode
30
--- a/target/arm/cpu.h
19
+++ b/target/arm/neon-ls.decode
31
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ VLDST_multiple 1111 0100 0 . l:1 0 rn:4 .... itype:4 size:2 align:2 rm:4 \
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
21
33
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
22
VLD_all_lanes 1111 0100 1 . 1 0 rn:4 .... 11 n:2 size:2 t:1 a:1 rm:4 \
34
}
23
vd=%vd_dp
35
24
+
36
+static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
25
+# Neon load/store single structure to one lane
26
+%imm1_5_p1 5:1 !function=plus1
27
+%imm1_6_p1 6:1 !function=plus1
28
+
29
+VLDST_single 1111 0100 1 . l:1 0 rn:4 .... 00 n:2 reg_idx:3 align:1 rm:4 \
30
+ vd=%vd_dp size=0 stride=1
31
+VLDST_single 1111 0100 1 . l:1 0 rn:4 .... 01 n:2 reg_idx:2 align:2 rm:4 \
32
+ vd=%vd_dp size=1 stride=%imm1_5_p1
33
+VLDST_single 1111 0100 1 . l:1 0 rn:4 .... 10 n:2 reg_idx:1 align:3 rm:4 \
34
+ vd=%vd_dp size=2 stride=%imm1_6_p1
35
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate-neon.inc.c
38
+++ b/target/arm/translate-neon.inc.c
39
@@ -XXX,XX +XXX,XX @@
40
* It might be possible to convert it to a standalone .c file eventually.
41
*/
42
43
+static inline int plus1(DisasContext *s, int x)
44
+{
37
+{
45
+ return x + 1;
38
+ /* (M-profile) low-overhead loops and branch future */
39
+ return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
46
+}
40
+}
47
+
41
+
48
/* Include the generated Neon decoder */
42
static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
49
#include "decode-neon-dp.inc.c"
43
{
50
#include "decode-neon-ls.inc.c"
44
return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
51
@@ -XXX,XX +XXX,XX @@ static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a)
45
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
52
46
index XXXXXXX..XXXXXXX 100644
53
return true;
47
--- a/target/arm/t32.decode
54
}
48
+++ b/target/arm/t32.decode
55
+
49
@@ -XXX,XX +XXX,XX @@ MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr
56
+static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
50
51
B 1111 0. .......... 10.1 ............ @branch24
52
BL 1111 0. .......... 11.1 ............ @branch24
53
-BLX_i 1111 0. .......... 11.0 ............ @branch24
57
+{
54
+{
58
+ /* Neon load/store single structure to one lane */
55
+ # BLX_i is non-M-profile only
59
+ int reg;
56
+ BLX_i 1111 0. .......... 11.0 ............ @branch24
60
+ int nregs = a->n + 1;
57
+ # M-profile only: loop and branch insns
61
+ int vd = a->vd;
58
+ [
62
+ TCGv_i32 addr, tmp;
59
+ # All these BF insns have boff != 0b0000; we NOP them all
63
+
60
+ BF 1111 0 boff:4 ------- 1100 - ---------- 1 # BFL
64
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
61
+ BF 1111 0 boff:4 0 ------ 1110 - ---------- 1 # BFCSEL
65
+ return false;
62
+ BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
66
+ }
63
+ BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
67
+
64
+ ]
68
+ /* UNDEF accesses to D16-D31 if they don't exist */
69
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
70
+ return false;
71
+ }
72
+
73
+ /* Catch the UNDEF cases. This is unavoidably a bit messy. */
74
+ switch (nregs) {
75
+ case 1:
76
+ if (((a->align & (1 << a->size)) != 0) ||
77
+ (a->size == 2 && ((a->align & 3) == 1 || (a->align & 3) == 2))) {
78
+ return false;
79
+ }
80
+ break;
81
+ case 3:
82
+ if ((a->align & 1) != 0) {
83
+ return false;
84
+ }
85
+ /* fall through */
86
+ case 2:
87
+ if (a->size == 2 && (a->align & 2) != 0) {
88
+ return false;
89
+ }
90
+ break;
91
+ case 4:
92
+ if ((a->size == 2) && ((a->align & 3) == 3)) {
93
+ return false;
94
+ }
95
+ break;
96
+ default:
97
+ abort();
98
+ }
99
+ if ((vd + a->stride * (nregs - 1)) > 31) {
100
+ /*
101
+ * Attempts to write off the end of the register file are
102
+ * UNPREDICTABLE; we choose to UNDEF because otherwise we would
103
+ * access off the end of the array that holds the register data.
104
+ */
105
+ return false;
106
+ }
107
+
108
+ if (!vfp_access_check(s)) {
109
+ return true;
110
+ }
111
+
112
+ tmp = tcg_temp_new_i32();
113
+ addr = tcg_temp_new_i32();
114
+ load_reg_var(s, addr, a->rn);
115
+ /*
116
+ * TODO: if we implemented alignment exceptions, we should check
117
+ * addr against the alignment encoded in a->align here.
118
+ */
119
+ for (reg = 0; reg < nregs; reg++) {
120
+ if (a->l) {
121
+ gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
122
+ s->be_data | a->size);
123
+ neon_store_element(vd, a->reg_idx, a->size, tmp);
124
+ } else { /* Store */
125
+ neon_load_element(tmp, vd, a->reg_idx, a->size);
126
+ gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
127
+ s->be_data | a->size);
128
+ }
129
+ vd += a->stride;
130
+ tcg_gen_addi_i32(addr, addr, 1 << a->size);
131
+ }
132
+ tcg_temp_free_i32(addr);
133
+ tcg_temp_free_i32(tmp);
134
+
135
+ gen_neon_ldst_base_update(s, a->rm, a->rn, (1 << a->size) * nregs);
136
+
137
+ return true;
138
+}
65
+}
139
diff --git a/target/arm/translate.c b/target/arm/translate.c
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
140
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
141
--- a/target/arm/translate.c
68
--- a/target/arm/translate.c
142
+++ b/target/arm/translate.c
69
+++ b/target/arm/translate.c
143
@@ -XXX,XX +XXX,XX @@ static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
70
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
144
tcg_temp_free_i32(rd);
71
return true;
145
}
72
}
146
73
147
-
74
+static bool trans_BF(DisasContext *s, arg_BF *a)
148
-/* Translate a NEON load/store element instruction. Return nonzero if the
75
+{
149
- instruction is invalid. */
76
+ /*
150
-static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
77
+ * M-profile branch future insns. The architecture permits an
151
-{
78
+ * implementation to implement these as NOPs (equivalent to
152
- int rd, rn, rm;
79
+ * discarding the LO_BRANCH_INFO cache immediately), and we
153
- int nregs;
80
+ * take that IMPDEF option because for QEMU a "real" implementation
154
- int stride;
81
+ * would be complicated and wouldn't execute any faster.
155
- int size;
82
+ */
156
- int reg;
83
+ if (!dc_isar_feature(aa32_lob, s)) {
157
- int load;
84
+ return false;
158
- TCGv_i32 addr;
85
+ }
159
- TCGv_i32 tmp;
86
+ if (a->boff == 0) {
160
-
87
+ /* SEE "Related encodings" (loop insns) */
161
- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
88
+ return false;
162
- return 1;
89
+ }
163
- }
90
+ /* Handle as NOP */
164
-
91
+ return true;
165
- /* FIXME: this access check should not take precedence over UNDEF
92
+}
166
- * for invalid encodings; we will generate incorrect syndrome information
93
+
167
- * for attempts to execute invalid vfp/neon encodings with FP disabled.
94
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
168
- */
169
- if (s->fp_excp_el) {
170
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
171
- syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
172
- return 0;
173
- }
174
-
175
- if (!s->vfp_enabled)
176
- return 1;
177
- VFP_DREG_D(rd, insn);
178
- rn = (insn >> 16) & 0xf;
179
- rm = insn & 0xf;
180
- load = (insn & (1 << 21)) != 0;
181
- if ((insn & (1 << 23)) == 0) {
182
- /* Load store all elements -- handled already by decodetree */
183
- return 1;
184
- } else {
185
- size = (insn >> 10) & 3;
186
- if (size == 3) {
187
- /* Load single element to all lanes -- handled by decodetree */
188
- return 1;
189
- } else {
190
- /* Single element. */
191
- int idx = (insn >> 4) & 0xf;
192
- int reg_idx;
193
- switch (size) {
194
- case 0:
195
- reg_idx = (insn >> 5) & 7;
196
- stride = 1;
197
- break;
198
- case 1:
199
- reg_idx = (insn >> 6) & 3;
200
- stride = (insn & (1 << 5)) ? 2 : 1;
201
- break;
202
- case 2:
203
- reg_idx = (insn >> 7) & 1;
204
- stride = (insn & (1 << 6)) ? 2 : 1;
205
- break;
206
- default:
207
- abort();
208
- }
209
- nregs = ((insn >> 8) & 3) + 1;
210
- /* Catch the UNDEF cases. This is unavoidably a bit messy. */
211
- switch (nregs) {
212
- case 1:
213
- if (((idx & (1 << size)) != 0) ||
214
- (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
215
- return 1;
216
- }
217
- break;
218
- case 3:
219
- if ((idx & 1) != 0) {
220
- return 1;
221
- }
222
- /* fall through */
223
- case 2:
224
- if (size == 2 && (idx & 2) != 0) {
225
- return 1;
226
- }
227
- break;
228
- case 4:
229
- if ((size == 2) && ((idx & 3) == 3)) {
230
- return 1;
231
- }
232
- break;
233
- default:
234
- abort();
235
- }
236
- if ((rd + stride * (nregs - 1)) > 31) {
237
- /* Attempts to write off the end of the register file
238
- * are UNPREDICTABLE; we choose to UNDEF because otherwise
239
- * the neon_load_reg() would write off the end of the array.
240
- */
241
- return 1;
242
- }
243
- tmp = tcg_temp_new_i32();
244
- addr = tcg_temp_new_i32();
245
- load_reg_var(s, addr, rn);
246
- for (reg = 0; reg < nregs; reg++) {
247
- if (load) {
248
- gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
249
- s->be_data | size);
250
- neon_store_element(rd, reg_idx, size, tmp);
251
- } else { /* Store */
252
- neon_load_element(tmp, rd, reg_idx, size);
253
- gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
254
- s->be_data | size);
255
- }
256
- rd += stride;
257
- tcg_gen_addi_i32(addr, addr, 1 << size);
258
- }
259
- tcg_temp_free_i32(addr);
260
- tcg_temp_free_i32(tmp);
261
- stride = nregs * (1 << size);
262
- }
263
- }
264
- if (rm != 15) {
265
- TCGv_i32 base;
266
-
267
- base = load_reg(s, rn);
268
- if (rm == 13) {
269
- tcg_gen_addi_i32(base, base, stride);
270
- } else {
271
- TCGv_i32 index;
272
- index = load_reg(s, rm);
273
- tcg_gen_add_i32(base, base, index);
274
- tcg_temp_free_i32(index);
275
- }
276
- store_reg(s, rn, base);
277
- }
278
- return 0;
279
-}
280
-
281
static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
282
{
95
{
283
switch (size) {
96
TCGv_i32 addr, tmp;
284
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
285
}
286
return;
287
}
288
- if ((insn & 0x0f100000) == 0x04000000) {
289
- /* NEON load/store. */
290
- if (disas_neon_ls_insn(s, insn)) {
291
- goto illegal_op;
292
- }
293
- return;
294
- }
295
if ((insn & 0x0e000f00) == 0x0c000100) {
296
if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
297
/* iWMMXt register transfer. */
298
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
299
}
300
break;
301
case 12:
302
- if ((insn & 0x01100000) == 0x01000000) {
303
- if (disas_neon_ls_insn(s, insn)) {
304
- goto illegal_op;
305
- }
306
- break;
307
- }
308
goto illegal_op;
309
default:
310
illegal_op:
311
--
97
--
312
2.20.1
98
2.20.1
313
99
314
100
diff view generated by jsdifflib
1
Convert the VFM[AS]L (scalar) insns in the 2reg-scalar-ext group
1
v8.1M's "low-overhead-loop" extension has three instructions
2
to decodetree. These are the last ones in the group so we can remove
2
for looping:
3
all the legacy decode for the group.
3
* DLS (start of a do-loop)
4
* WLS (start of a while-loop)
5
* LE (end of a loop)
4
6
5
Note that in disas_thumb2_insn() the parts of this encoding space
7
The loop-start instructions are both simple operations to start a
6
where the decodetree decoder returns false will correctly be directed
8
loop whose iteration count (if any) is in LR. The loop-end
7
to illegal_op by the "(insn & (1 << 28))" check so they won't fall
9
instruction handles "decrement iteration count and jump back to loop
8
into disas_coproc_insn() by mistake.
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.)
9
24
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200430181003.21682-11-peter.maydell@linaro.org
27
Message-id: 20201019151301.2046-8-peter.maydell@linaro.org
13
---
28
---
14
target/arm/neon-shared.decode | 7 +++
29
target/arm/t32.decode | 8 ++++
15
target/arm/translate-neon.inc.c | 32 ++++++++++
30
target/arm/translate.c | 93 +++++++++++++++++++++++++++++++++++++++++-
16
target/arm/translate.c | 107 +-------------------------------
31
2 files changed, 99 insertions(+), 2 deletions(-)
17
3 files changed, 40 insertions(+), 106 deletions(-)
18
32
19
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
33
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
20
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/neon-shared.decode
35
--- a/target/arm/t32.decode
22
+++ b/target/arm/neon-shared.decode
36
+++ b/target/arm/t32.decode
23
@@ -XXX,XX +XXX,XX @@ VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \
37
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
24
38
BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
25
VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \
39
BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
26
vm=%vm_dp vn=%vn_dp vd=%vd_dp
40
]
41
+ [
42
+ # LE and WLS immediate
43
+ %lob_imm 1:10 11:1 !function=times_2
27
+
44
+
28
+%vfml_scalar_q0_rm 0:3 5:1
45
+ DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
29
+%vfml_scalar_q1_index 5:1 3:1
46
+ WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm
30
+VFML_scalar 1111 1110 0 . 0 s:1 .... .... 1000 . 0 . 1 index:1 ... \
47
+ LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
31
+ rm=%vfml_scalar_q0_rm vn=%vn_sp vd=%vd_dp q=0
48
+ ]
32
+VFML_scalar 1111 1110 0 . 0 s:1 .... .... 1000 . 1 . 1 . rm:3 \
33
+ index=%vfml_scalar_q1_index vn=%vn_dp vd=%vd_dp q=1
34
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/translate-neon.inc.c
37
+++ b/target/arm/translate-neon.inc.c
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VDOT_scalar(DisasContext *s, arg_VDOT_scalar *a)
39
tcg_temp_free_ptr(fpst);
40
return true;
41
}
49
}
42
+
43
+static bool trans_VFML_scalar(DisasContext *s, arg_VFML_scalar *a)
44
+{
45
+ int opr_sz;
46
+
47
+ if (!dc_isar_feature(aa32_fhm, s)) {
48
+ return false;
49
+ }
50
+
51
+ /* UNDEF accesses to D16-D31 if they don't exist. */
52
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
53
+ ((a->vd & 0x10) || (a->q && (a->vn & 0x10)))) {
54
+ return false;
55
+ }
56
+
57
+ if (a->vd & a->q) {
58
+ return false;
59
+ }
60
+
61
+ if (!vfp_access_check(s)) {
62
+ return true;
63
+ }
64
+
65
+ opr_sz = (1 + a->q) * 8;
66
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
67
+ vfp_reg_offset(a->q, a->vn),
68
+ vfp_reg_offset(a->q, a->rm),
69
+ cpu_env, opr_sz, opr_sz,
70
+ (a->index << 2) | a->s, /* is_2 == 0 */
71
+ gen_helper_gvec_fmlal_idx_a32);
72
+ return true;
73
+}
74
diff --git a/target/arm/translate.c b/target/arm/translate.c
50
diff --git a/target/arm/translate.c b/target/arm/translate.c
75
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/translate.c
52
--- a/target/arm/translate.c
77
+++ b/target/arm/translate.c
53
+++ b/target/arm/translate.c
78
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
54
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
55
s->base.is_jmp = DISAS_NORETURN;
79
}
56
}
80
57
81
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
58
-static inline void gen_jmp (DisasContext *s, uint32_t dest)
82
-#define VFP_SREG(insn, bigbit, smallbit) \
59
+/* Jump, specifying which TB number to use if we gen_goto_tb() */
83
- ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
60
+static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
84
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
61
{
85
if (dc_isar_feature(aa32_simd_r32, s)) { \
62
if (unlikely(is_singlestepping(s))) {
86
reg = (((insn) >> (bigbit)) & 0x0f) \
63
/* An indirect jump so that we still trigger the debug exception. */
87
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
64
gen_set_pc_im(s, dest);
88
reg = ((insn) >> (bigbit)) & 0x0f; \
65
s->base.is_jmp = DISAS_JUMP;
89
}} while (0)
66
} else {
90
67
- gen_goto_tb(s, 0, dest);
91
-#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
68
+ gen_goto_tb(s, tbno, dest);
92
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
69
}
93
-#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
94
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
95
-#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
96
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
97
98
static void gen_neon_dup_low16(TCGv_i32 var)
99
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
100
return 0;
101
}
70
}
102
71
103
-/* Advanced SIMD two registers and a scalar extension.
72
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
104
- * 31 24 23 22 20 16 12 11 10 9 8 3 0
73
+{
105
- * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
74
+ gen_jmp_tb(s, dest, 0);
106
- * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
75
+}
107
- * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
76
+
108
- *
77
static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
109
- */
110
-
111
-static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
112
-{
113
- gen_helper_gvec_3 *fn_gvec = NULL;
114
- gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
115
- int rd, rn, rm, opr_sz, data;
116
- int off_rn, off_rm;
117
- bool is_long = false, q = extract32(insn, 6, 1);
118
- bool ptr_is_env = false;
119
-
120
- if ((insn & 0xffa00f10) == 0xfe000810) {
121
- /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
122
- int is_s = extract32(insn, 20, 1);
123
- int vm20 = extract32(insn, 0, 3);
124
- int vm3 = extract32(insn, 3, 1);
125
- int m = extract32(insn, 5, 1);
126
- int index;
127
-
128
- if (!dc_isar_feature(aa32_fhm, s)) {
129
- return 1;
130
- }
131
- if (q) {
132
- rm = vm20;
133
- index = m * 2 + vm3;
134
- } else {
135
- rm = vm20 * 2 + m;
136
- index = vm3;
137
- }
138
- is_long = true;
139
- data = (index << 2) | is_s; /* is_2 == 0 */
140
- fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
141
- ptr_is_env = true;
142
- } else {
143
- return 1;
144
- }
145
-
146
- VFP_DREG_D(rd, insn);
147
- if (rd & q) {
148
- return 1;
149
- }
150
- if (q || !is_long) {
151
- VFP_DREG_N(rn, insn);
152
- if (rn & q & !is_long) {
153
- return 1;
154
- }
155
- off_rn = vfp_reg_offset(1, rn);
156
- off_rm = vfp_reg_offset(1, rm);
157
- } else {
158
- rn = VFP_SREG_N(insn);
159
- off_rn = vfp_reg_offset(0, rn);
160
- off_rm = vfp_reg_offset(0, rm);
161
- }
162
- if (s->fp_excp_el) {
163
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
164
- syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
165
- return 0;
166
- }
167
- if (!s->vfp_enabled) {
168
- return 1;
169
- }
170
-
171
- opr_sz = (1 + q) * 8;
172
- if (fn_gvec_ptr) {
173
- TCGv_ptr ptr;
174
- if (ptr_is_env) {
175
- ptr = cpu_env;
176
- } else {
177
- ptr = get_fpstatus_ptr(1);
178
- }
179
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
180
- opr_sz, opr_sz, data, fn_gvec_ptr);
181
- if (!ptr_is_env) {
182
- tcg_temp_free_ptr(ptr);
183
- }
184
- } else {
185
- tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
186
- opr_sz, opr_sz, data, fn_gvec);
187
- }
188
- return 0;
189
-}
190
-
191
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
192
{
78
{
193
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
79
if (x)
194
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
80
@@ -XXX,XX +XXX,XX @@ static bool trans_BF(DisasContext *s, arg_BF *a)
195
}
81
return true;
196
}
82
}
197
}
83
198
- } else if ((insn & 0x0f000a00) == 0x0e000800
84
+static bool trans_DLS(DisasContext *s, arg_DLS *a)
199
- && arm_dc_feature(s, ARM_FEATURE_V8)) {
85
+{
200
- if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
86
+ /* M-profile low-overhead loop start */
201
- goto illegal_op;
87
+ TCGv_i32 tmp;
202
- }
88
+
203
- return;
89
+ if (!dc_isar_feature(aa32_lob, s)) {
204
}
90
+ return false;
205
goto illegal_op;
91
+ }
206
}
92
+ if (a->rn == 13 || a->rn == 15) {
207
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
93
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
208
}
94
+ return false;
209
break;
95
+ }
210
}
96
+
211
- if ((insn & 0xff000a00) == 0xfe000800
97
+ /* Not a while loop, no tail predication: just set LR to the count */
212
- && arm_dc_feature(s, ARM_FEATURE_V8)) {
98
+ tmp = load_reg(s, a->rn);
213
- /* The Thumb2 and ARM encodings are identical. */
99
+ store_reg(s, 14, tmp);
214
- if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
100
+ return true;
215
- goto illegal_op;
101
+}
216
- }
102
+
217
- } else if (((insn >> 24) & 3) == 3) {
103
+static bool trans_WLS(DisasContext *s, arg_WLS *a)
218
+ if (((insn >> 24) & 3) == 3) {
104
+{
219
/* Translate into the equivalent ARM encoding. */
105
+ /* M-profile low-overhead while-loop start */
220
insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
106
+ TCGv_i32 tmp;
221
if (disas_neon_data_insn(s, insn)) {
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;
222
--
170
--
223
2.20.1
171
2.20.1
224
172
225
173
diff view generated by jsdifflib
1
For ARMv8.2-TTS2UXN, the stage 2 page table walk wants to know
1
In arm_cpu_realizefn(), if the CPU has VFP or Neon disabled then we
2
whether the stage 1 access is for EL0 or not, because whether
2
squash the ID register fields so that we don't advertise it to the
3
exec permission is given can depend on whether this is an EL0
3
guest. This code was written for A-profile and needs some tweaks to
4
or EL1 access. Add a new argument to get_phys_addr_lpae() so
4
work correctly on M-profile:
5
the call sites can pass this information in.
6
5
7
Since get_phys_addr_lpae() doesn't already have a doc comment,
6
* A-profile only fields should not be zeroed on M-profile:
8
add one so we have a place to put the documentation of the
7
- MVFR0.FPSHVEC,FPTRAP
9
semantics of the new s1_is_el0 argument.
8
- MVFR1.SIMDLS,SIMDINT,SIMDSP,SIMDHP
9
- MVFR2.SIMDMISC
10
* M-profile only fields should be zeroed on M-profile:
11
- MVFR1.FP16
10
12
13
In particular, because MVFR1.SIMDHP on A-profile is the same field as
14
MVFR1.FP16 on M-profile this code was incorrectly disabling FP16
15
support on an M-profile CPU (where has_neon is always false). This
16
isn't a visible bug yet because we don't have any M-profile CPUs with
17
FP16 support, but the change is necessary before we introduce any.
18
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
21
Message-id: 20201019151301.2046-9-peter.maydell@linaro.org
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200330210400.11724-4-peter.maydell@linaro.org
15
---
22
---
16
target/arm/helper.c | 29 ++++++++++++++++++++++++++++-
23
target/arm/cpu.c | 29 ++++++++++++++++++-----------
17
1 file changed, 28 insertions(+), 1 deletion(-)
24
1 file changed, 18 insertions(+), 11 deletions(-)
18
25
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
28
--- a/target/arm/cpu.c
22
+++ b/target/arm/helper.c
29
+++ b/target/arm/cpu.c
23
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
24
31
u = cpu->isar.mvfr0;
25
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
32
u = FIELD_DP32(u, MVFR0, FPSP, 0);
26
MMUAccessType access_type, ARMMMUIdx mmu_idx,
33
u = FIELD_DP32(u, MVFR0, FPDP, 0);
27
+ bool s1_is_el0,
34
- u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
28
hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
35
u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
29
target_ulong *page_size_ptr,
36
u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
30
ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs);
37
- u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
31
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
38
u = FIELD_DP32(u, MVFR0, FPROUND, 0);
32
}
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
33
40
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
34
ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, ARMMMUIdx_Stage2,
41
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
35
+ false,
42
+ }
36
&s2pa, &txattrs, &s2prot, &s2size, fi,
43
cpu->isar.mvfr0 = u;
37
pcacheattrs);
44
38
if (ret) {
45
u = cpu->isar.mvfr1;
39
@@ -XXX,XX +XXX,XX @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
46
u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
40
};
47
u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
41
}
48
u = FIELD_DP32(u, MVFR1, FPHP, 0);
42
49
+ if (arm_feature(env, ARM_FEATURE_M)) {
43
+/**
50
+ u = FIELD_DP32(u, MVFR1, FP16, 0);
44
+ * get_phys_addr_lpae: perform one stage of page table walk, LPAE format
51
+ }
45
+ *
52
cpu->isar.mvfr1 = u;
46
+ * Returns false if the translation was successful. Otherwise, phys_ptr, attrs,
53
47
+ * prot and page_size may not be filled in, and the populated fsr value provides
54
u = cpu->isar.mvfr2;
48
+ * information on why the translation aborted, in the format of a long-format
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
49
+ * DFSR/IFSR fault register, with the following caveats:
56
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
50
+ * * the WnR bit is never set (the caller must do this).
57
cpu->isar.id_isar6 = u;
51
+ *
58
52
+ * @env: CPUARMState
59
- u = cpu->isar.mvfr1;
53
+ * @address: virtual address to get physical address for
60
- u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
54
+ * @access_type: MMU_DATA_LOAD, MMU_DATA_STORE or MMU_INST_FETCH
61
- u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
55
+ * @mmu_idx: MMU index indicating required translation regime
62
- u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
56
+ * @s1_is_el0: if @mmu_idx is ARMMMUIdx_Stage2 (so this is a stage 2 page table
63
- u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
57
+ * walk), must be true if this is stage 2 of a stage 1+2 walk for an
64
- cpu->isar.mvfr1 = u;
58
+ * EL0 access). If @mmu_idx is anything else, @s1_is_el0 is ignored.
65
+ if (!arm_feature(env, ARM_FEATURE_M)) {
59
+ * @phys_ptr: set to the physical address corresponding to the virtual address
66
+ u = cpu->isar.mvfr1;
60
+ * @attrs: set to the memory transaction attributes to use
67
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
61
+ * @prot: set to the permissions for the page containing phys_ptr
68
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
62
+ * @page_size_ptr: set to the size of the page containing phys_ptr
69
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
63
+ * @fi: set to fault info if the translation fails
70
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
64
+ * @cacheattrs: (if non-NULL) set to the cacheability/shareability attributes
71
+ cpu->isar.mvfr1 = u;
65
+ */
72
66
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
73
- u = cpu->isar.mvfr2;
67
MMUAccessType access_type, ARMMMUIdx mmu_idx,
74
- u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
68
+ bool s1_is_el0,
75
- cpu->isar.mvfr2 = u;
69
hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
76
+ u = cpu->isar.mvfr2;
70
target_ulong *page_size_ptr,
77
+ u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
71
ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
78
+ cpu->isar.mvfr2 = u;
72
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
79
+ }
73
74
/* S1 is done. Now do S2 translation. */
75
ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_Stage2,
76
+ mmu_idx == ARMMMUIdx_E10_0,
77
phys_ptr, attrs, &s2_prot,
78
page_size, fi,
79
cacheattrs != NULL ? &cacheattrs2 : NULL);
80
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
81
}
80
}
82
81
83
if (regime_using_lpae_format(env, mmu_idx)) {
82
if (!cpu->has_neon && !cpu->has_vfp) {
84
- return get_phys_addr_lpae(env, address, access_type, mmu_idx,
85
+ return get_phys_addr_lpae(env, address, access_type, mmu_idx, false,
86
phys_ptr, attrs, prot, page_size,
87
fi, cacheattrs);
88
} else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
89
--
83
--
90
2.20.1
84
2.20.1
91
85
92
86
diff view generated by jsdifflib
1
Somewhere along theline we accidentally added a duplicate
1
M-profile CPUs with half-precision floating point support should
2
"using D16-D31 when they don't exist" check to do_vfm_dp()
2
be able to write to FPSCR.FZ16, but an M-profile specific masking
3
(probably an artifact of a patchseries rebase). Remove it.
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
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.
4
20
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Message-id: 20201019151301.2046-10-peter.maydell@linaro.org
8
Message-id: 20200430181003.21682-2-peter.maydell@linaro.org
9
---
24
---
10
target/arm/translate-vfp.inc.c | 6 ------
25
target/arm/vfp_helper.c | 47 ++++++++++++++++++++++++-----------------
11
1 file changed, 6 deletions(-)
26
1 file changed, 28 insertions(+), 19 deletions(-)
12
27
13
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
28
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
14
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.inc.c
30
--- a/target/arm/vfp_helper.c
16
+++ b/target/arm/translate-vfp.inc.c
31
+++ b/target/arm/vfp_helper.c
17
@@ -XXX,XX +XXX,XX @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
32
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
18
return false;
33
val &= ~FPCR_FZ16;
19
}
34
}
20
35
21
- /* UNDEF accesses to D16-D31 if they don't exist. */
36
- if (arm_feature(env, ARM_FEATURE_M)) {
22
- if (!dc_isar_feature(aa32_simd_r32, s) &&
37
+ vfp_set_fpscr_to_host(env, val);
23
- ((a->vd | a->vn | a->vm) & 0x10)) {
38
+
24
- return false;
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
25
- }
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;
26
-
85
-
27
if (!vfp_access_check(s)) {
86
- /*
28
return true;
87
- * The bit we set within fpscr_q is arbitrary; the register as a
29
}
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)
30
--
97
--
31
2.20.1
98
2.20.1
32
99
33
100
diff view generated by jsdifflib
1
The ARMv8.2-TTS2UXN feature extends the XN field in stage 2
1
If the M-profile low-overhead-branch extension is implemented, FPSCR
2
translation table descriptors from just bit [54] to bits [54:53],
2
bits [18:16] are a new field LTPSIZE. If MVE is not implemented
3
allowing stage 2 to control execution permissions separately for EL0
3
(currently always true for us) then this field always reads as 4 and
4
and EL1. Implement the new semantics of the XN field and enable
4
ignores writes.
5
the feature for our 'max' CPU.
5
6
These bits used to be the vector-length field for the old
7
short-vector extension, so we need to take care that they are not
8
misinterpreted as setting vec_len. We do this with a rearrangement
9
of the vfp_set_fpscr() code that deals with vec_len, vec_stride
10
and also the QC bit; this obviates the need for the M-profile
11
only masking step that we used to have at the start of the function.
12
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.)
6
18
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200330210400.11724-5-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-11-peter.maydell@linaro.org
11
---
22
---
12
target/arm/cpu.h | 15 +++++++++++++++
23
target/arm/cpu.h | 1 +
13
target/arm/cpu.c | 1 +
24
target/arm/cpu.c | 9 +++++++++
14
target/arm/cpu64.c | 2 ++
25
target/arm/vfp_helper.c | 6 ++++++
15
target/arm/helper.c | 37 +++++++++++++++++++++++++++++++------
26
3 files changed, 16 insertions(+)
16
4 files changed, 49 insertions(+), 6 deletions(-)
17
27
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
30
--- a/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id)
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
23
return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0;
33
uint32_t fpdscr[M_REG_NUM_BANKS];
24
}
34
uint32_t cpacr[M_REG_NUM_BANKS];
25
35
uint32_t nsacr;
26
+static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id)
36
+ int ltpsize;
27
+{
37
} v7m;
28
+ return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0;
38
29
+}
39
/* Information associated with an exception about to be taken:
30
+
31
/*
32
* 64-bit feature tests via id registers.
33
*/
34
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
35
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
36
}
37
38
+static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
39
+{
40
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
41
+}
42
+
43
/*
44
* Feature tests for "does this exist in either 32-bit or 64-bit?"
45
*/
46
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_ccidx(const ARMISARegisters *id)
47
return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id);
48
}
49
50
+static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
51
+{
52
+ return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
53
+}
54
+
55
/*
56
* Forward to the above feature tests given an ARMCPU pointer.
57
*/
58
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
40
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/cpu.c
42
--- a/target/arm/cpu.c
61
+++ b/target/arm/cpu.c
43
+++ b/target/arm/cpu.c
62
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
44
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
63
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
45
uint8_t *rom;
64
t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
46
uint32_t vecbase;
65
t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
47
66
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
48
+ if (cpu_isar_feature(aa32_lob, cpu)) {
67
cpu->isar.id_mmfr4 = t;
49
+ /*
68
}
50
+ * LTPSIZE is constant 4 if MVE not implemented, and resets
69
#endif
51
+ * to an UNKNOWN value if MVE is implemented. We choose to
70
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
52
+ * always reset to 4.
53
+ */
54
+ env->v7m.ltpsize = 4;
55
+ }
56
+
57
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
58
env->v7m.secure = true;
59
} else {
60
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
71
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/cpu64.c
62
--- a/target/arm/vfp_helper.c
73
+++ b/target/arm/cpu64.c
63
+++ b/target/arm/vfp_helper.c
74
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
64
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
75
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
65
| (env->vfp.vec_len << 16)
76
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
66
| (env->vfp.vec_stride << 20);
77
t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */
67
78
+ t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* TTS2UXN */
68
+ /*
79
cpu->isar.id_aa64mmfr1 = t;
69
+ * M-profile LTPSIZE overlaps A-profile Stride; whichever of the
80
70
+ * two is not applicable to this CPU will always be zero.
81
t = cpu->isar.id_aa64mmfr2;
71
+ */
82
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
72
+ fpscr |= env->v7m.ltpsize << 16;
83
u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */
84
u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
85
u = FIELD_DP32(u, ID_MMFR4, CNP, 1); /* TTCNP */
86
+ u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */
87
cpu->isar.id_mmfr4 = u;
88
89
u = cpu->isar.id_aa64dfr0;
90
diff --git a/target/arm/helper.c b/target/arm/helper.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/helper.c
93
+++ b/target/arm/helper.c
94
@@ -XXX,XX +XXX,XX @@ simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap)
95
*
96
* @env: CPUARMState
97
* @s2ap: The 2-bit stage2 access permissions (S2AP)
98
- * @xn: XN (execute-never) bit
99
+ * @xn: XN (execute-never) bits
100
+ * @s1_is_el0: true if this is S2 of an S1+2 walk for EL0
101
*/
102
-static int get_S2prot(CPUARMState *env, int s2ap, int xn)
103
+static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
104
{
105
int prot = 0;
106
107
@@ -XXX,XX +XXX,XX @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn)
108
if (s2ap & 2) {
109
prot |= PAGE_WRITE;
110
}
111
- if (!xn) {
112
- if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) {
113
+
73
+
114
+ if (cpu_isar_feature(any_tts2uxn, env_archcpu(env))) {
74
fpscr |= vfp_get_fpscr_from_host(env);
115
+ switch (xn) {
75
116
+ case 0:
76
i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
117
prot |= PAGE_EXEC;
118
+ break;
119
+ case 1:
120
+ if (s1_is_el0) {
121
+ prot |= PAGE_EXEC;
122
+ }
123
+ break;
124
+ case 2:
125
+ break;
126
+ case 3:
127
+ if (!s1_is_el0) {
128
+ prot |= PAGE_EXEC;
129
+ }
130
+ break;
131
+ default:
132
+ g_assert_not_reached();
133
+ }
134
+ } else {
135
+ if (!extract32(xn, 1, 1)) {
136
+ if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) {
137
+ prot |= PAGE_EXEC;
138
+ }
139
}
140
}
141
return prot;
142
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
143
}
144
145
ap = extract32(attrs, 4, 2);
146
- xn = extract32(attrs, 12, 1);
147
148
if (mmu_idx == ARMMMUIdx_Stage2) {
149
ns = true;
150
- *prot = get_S2prot(env, ap, xn);
151
+ xn = extract32(attrs, 11, 2);
152
+ *prot = get_S2prot(env, ap, xn, s1_is_el0);
153
} else {
154
ns = extract32(attrs, 3, 1);
155
+ xn = extract32(attrs, 12, 1);
156
pxn = extract32(attrs, 11, 1);
157
*prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
158
}
159
--
77
--
160
2.20.1
78
2.20.1
161
79
162
80
diff view generated by jsdifflib
1
Convert the VCADD (vector) insns to decodetree.
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The kernel sets btype for the signal handler as if for a call.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201016184207.786698-2-richard.henderson@linaro.org
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200430181003.21682-6-peter.maydell@linaro.org
6
---
9
---
7
target/arm/neon-shared.decode | 3 +++
10
linux-user/aarch64/signal.c | 10 ++++++++--
8
target/arm/translate-neon.inc.c | 37 +++++++++++++++++++++++++++++++++
11
1 file changed, 8 insertions(+), 2 deletions(-)
9
target/arm/translate.c | 11 +---------
10
3 files changed, 41 insertions(+), 10 deletions(-)
11
12
12
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-shared.decode
15
--- a/linux-user/aarch64/signal.c
15
+++ b/target/arm/neon-shared.decode
16
+++ b/linux-user/aarch64/signal.c
16
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
17
18
+ offsetof(struct target_rt_frame_record, tramp);
18
VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \
19
}
19
vm=%vm_dp vn=%vn_dp vd=%vd_dp
20
env->xregs[0] = usig;
21
- env->xregs[31] = frame_addr;
22
env->xregs[29] = frame_addr + fr_ofs;
23
- env->pc = ka->_sa_handler;
24
env->xregs[30] = return_addr;
25
+ env->xregs[31] = frame_addr;
26
+ env->pc = ka->_sa_handler;
20
+
27
+
21
+VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \
28
+ /* Invoke the signal handler as if by indirect call. */
22
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
23
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
30
+ env->btype = 2;
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/translate-neon.inc.c
26
+++ b/target/arm/translate-neon.inc.c
27
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
28
tcg_temp_free_ptr(fpst);
29
return true;
30
}
31
+
32
+static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
33
+{
34
+ int opr_sz;
35
+ TCGv_ptr fpst;
36
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
37
+
38
+ if (!dc_isar_feature(aa32_vcma, s)
39
+ || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
40
+ return false;
41
+ }
31
+ }
42
+
32
+
43
+ /* UNDEF accesses to D16-D31 if they don't exist. */
33
if (info) {
44
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
34
tswap_siginfo(&frame->info, info);
45
+ ((a->vd | a->vn | a->vm) & 0x10)) {
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
46
+ return false;
47
+ }
48
+
49
+ if ((a->vn | a->vm | a->vd) & a->q) {
50
+ return false;
51
+ }
52
+
53
+ if (!vfp_access_check(s)) {
54
+ return true;
55
+ }
56
+
57
+ opr_sz = (1 + a->q) * 8;
58
+ fpst = get_fpstatus_ptr(1);
59
+ fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
60
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
61
+ vfp_reg_offset(1, a->vn),
62
+ vfp_reg_offset(1, a->vm),
63
+ fpst, opr_sz, opr_sz, a->rot,
64
+ fn_gvec_ptr);
65
+ tcg_temp_free_ptr(fpst);
66
+ return true;
67
+}
68
diff --git a/target/arm/translate.c b/target/arm/translate.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/translate.c
71
+++ b/target/arm/translate.c
72
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
73
bool is_long = false, q = extract32(insn, 6, 1);
74
bool ptr_is_env = false;
75
76
- if ((insn & 0xfea00f10) == 0xfc800800) {
77
- /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
78
- int size = extract32(insn, 20, 1);
79
- data = extract32(insn, 24, 1); /* rot */
80
- if (!dc_isar_feature(aa32_vcma, s)
81
- || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
82
- return 1;
83
- }
84
- fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
85
- } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
86
+ if ((insn & 0xfeb00f00) == 0xfc200d00) {
87
/* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
88
bool u = extract32(insn, 4, 1);
89
if (!dc_isar_feature(aa32_dp, s)) {
90
--
36
--
91
2.20.1
37
2.20.1
92
38
93
39
diff view generated by jsdifflib
1
We're going to want at least some of the NeonGen* typedefs
1
From: Richard Henderson <richard.henderson@linaro.org>
2
for the refactored 32-bit Neon decoder, so move them all
3
to translate.h since it makes more sense to keep them in
4
one group.
5
2
3
Transform the prot bit to a qemu internal page bit, and save
4
it in the page tables.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201016184207.786698-3-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200430181003.21682-23-peter.maydell@linaro.org
9
---
10
---
10
target/arm/translate.h | 17 +++++++++++++++++
11
include/exec/cpu-all.h | 2 ++
11
target/arm/translate-a64.c | 17 -----------------
12
linux-user/syscall_defs.h | 4 ++++
12
2 files changed, 17 insertions(+), 17 deletions(-)
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(-)
13
17
14
diff --git a/target/arm/translate.h b/target/arm/translate.h
18
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.h
20
--- a/include/exec/cpu-all.h
17
+++ b/target/arm/translate.h
21
+++ b/include/exec/cpu-all.h
18
@@ -XXX,XX +XXX,XX @@ typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
22
@@ -XXX,XX +XXX,XX @@ extern intptr_t qemu_host_page_mask;
19
typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t,
23
/* FIXME: Code that sets/uses this is broken and needs to go away. */
20
uint32_t, uint32_t, uint32_t);
24
#define PAGE_RESERVED 0x0020
21
25
#endif
22
+/* Function prototype for gen_ functions for calling Neon helpers */
26
+/* Target-specific bits that will be used via page_get_flags(). */
23
+typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
27
+#define PAGE_TARGET_1 0x0080
24
+typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
28
25
+typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
29
#if defined(CONFIG_USER_ONLY)
26
+typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
30
void page_dump(FILE *f);
27
+typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
31
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
28
+typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
32
index XXXXXXX..XXXXXXX 100644
29
+typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
33
--- a/linux-user/syscall_defs.h
30
+typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
34
+++ b/linux-user/syscall_defs.h
31
+typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
35
@@ -XXX,XX +XXX,XX @@ struct target_winsize {
32
+typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
36
#define TARGET_PROT_SEM 0x08
33
+typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
37
#endif
34
+typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
38
35
+typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
39
+#ifdef TARGET_AARCH64
36
+typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
40
+#define TARGET_PROT_BTI 0x10
37
+typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp);
41
+#endif
38
+
42
+
39
#endif /* TARGET_ARM_TRANSLATE_H */
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
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
53
54
+/*
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
56
+ */
57
+#define PAGE_BTI PAGE_TARGET_1
58
+
59
/*
60
* Naming convention for isar_feature functions:
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
40
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
41
index XXXXXXX..XXXXXXX 100644
90
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/translate-a64.c
91
--- a/target/arm/translate-a64.c
43
+++ b/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
44
@@ -XXX,XX +XXX,XX @@ typedef struct AArch64DecodeTable {
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
45
AArch64DecodeFn *disas_fn;
94
*/
46
} AArch64DecodeTable;
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
47
48
-/* Function prototype for gen_ functions for calling Neon helpers */
49
-typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
50
-typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
51
-typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
52
-typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
53
-typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
54
-typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
55
-typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
56
-typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
57
-typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
58
-typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
59
-typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
60
-typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
61
-typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
62
-typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
63
-typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp);
64
-
65
/* initialize TCG globals. */
66
void a64_translate_init(void)
67
{
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);
68
--
107
--
69
2.20.1
108
2.20.1
70
109
71
110
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add support for the RTC.
3
These are all of the defines required to parse
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
5
Other missing defines related to other GNU program headers
6
and notes are elided for now.
4
7
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
10
Message-id: 20201016184207.786698-4-richard.henderson@linaro.org
8
Message-id: 20200427181649.26851-12-edgar.iglesias@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
hw/arm/xlnx-versal-virt.c | 22 ++++++++++++++++++++++
13
include/elf.h | 22 ++++++++++++++++++++++
12
1 file changed, 22 insertions(+)
14
1 file changed, 22 insertions(+)
13
15
14
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
16
diff --git a/include/elf.h b/include/elf.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/xlnx-versal-virt.c
18
--- a/include/elf.h
17
+++ b/hw/arm/xlnx-versal-virt.c
19
+++ b/include/elf.h
18
@@ -XXX,XX +XXX,XX @@ static void fdt_add_sd_nodes(VersalVirt *s)
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
19
}
21
#define PT_NOTE 4
20
}
22
#define PT_SHLIB 5
21
23
#define PT_PHDR 6
22
+static void fdt_add_rtc_node(VersalVirt *s)
24
+#define PT_LOOS 0x60000000
23
+{
25
+#define PT_HIOS 0x6fffffff
24
+ const char compat[] = "xlnx,zynqmp-rtc";
26
#define PT_LOPROC 0x70000000
25
+ const char interrupt_names[] = "alarm\0sec";
27
#define PT_HIPROC 0x7fffffff
26
+ char *name = g_strdup_printf("/rtc@%x", MM_PMC_RTC);
28
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
27
+
30
+
28
+ qemu_fdt_add_subnode(s->fdt, name);
31
#define PT_MIPS_REGINFO 0x70000000
32
#define PT_MIPS_RTPROC 0x70000001
33
#define PT_MIPS_OPTIONS 0x70000002
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
37
38
+/* Defined note types for GNU systems. */
29
+
39
+
30
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
31
+ GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_ALARM_IRQ,
32
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI,
33
+ GIC_FDT_IRQ_TYPE_SPI, VERSAL_RTC_SECONDS_IRQ,
34
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
35
+ qemu_fdt_setprop(s->fdt, name, "interrupt-names",
36
+ interrupt_names, sizeof(interrupt_names));
37
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
38
+ 2, MM_PMC_RTC, 2, MM_PMC_RTC_SIZE);
39
+ qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
40
+ g_free(name);
41
+}
42
+
41
+
43
static void fdt_nop_memory_nodes(void *fdt, Error **errp)
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
44
{
43
+
45
Error *err = NULL;
44
+#define GNU_PROPERTY_STACK_SIZE 1
46
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
47
fdt_add_timer_nodes(s);
46
+
48
fdt_add_zdma_nodes(s);
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
49
fdt_add_sd_nodes(s);
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
50
+ fdt_add_rtc_node(s);
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
51
fdt_add_cpu_nodes(s, psci_conduit);
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
52
fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
51
+
53
fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
55
+
56
/*
57
* Physical entry point into the kernel.
58
*
54
--
59
--
55
2.20.1
60
2.20.1
56
61
57
62
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
MIDR_EL1 is a 64-bit system register with the top 32-bit being RES0.
3
Fix an unlikely memory leak in load_elf_image().
4
Represent it in QEMU's ARMCPU struct with a uint64_t, not a
5
uint32_t.
6
4
7
This fixes an error when compiling with -Werror=conversion
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
8
because we were manipulating the register value using a
9
local uint64_t variable:
10
11
target/arm/cpu64.c: In function ‘aarch64_max_initfn’:
12
target/arm/cpu64.c:628:21: error: conversion from ‘uint64_t’ {aka ‘long unsigned int’} to ‘uint32_t’ {aka ‘unsigned int’} may change value [-Werror=conversion]
13
628 | cpu->midr = t;
14
| ^
15
16
and future-proofs us against a possible future architecture
17
change using some of the top 32 bits.
18
19
Suggested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
20
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20200428172634.29707-1-f4bug@amsat.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>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
13
---
27
target/arm/cpu.h | 2 +-
14
linux-user/elfload.c | 8 ++++----
28
target/arm/cpu.c | 2 +-
15
1 file changed, 4 insertions(+), 4 deletions(-)
29
2 files changed, 2 insertions(+), 2 deletions(-)
30
16
31
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
32
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/cpu.h
19
--- a/linux-user/elfload.c
34
+++ b/target/arm/cpu.h
20
+++ b/linux-user/elfload.c
35
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
36
uint64_t id_aa64dfr0;
22
info->brk = vaddr_em;
37
uint64_t id_aa64dfr1;
23
}
38
} isar;
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
39
- uint32_t midr;
25
- char *interp_name;
40
+ uint64_t midr;
26
+ g_autofree char *interp_name = NULL;
41
uint32_t revidr;
27
42
uint32_t reset_fpsid;
28
if (*pinterp_name) {
43
uint32_t ctr;
29
errmsg = "Multiple PT_INTERP entries";
44
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
30
goto exit_errmsg;
45
index XXXXXXX..XXXXXXX 100644
31
}
46
--- a/target/arm/cpu.c
32
- interp_name = malloc(eppnt->p_filesz);
47
+++ b/target/arm/cpu.c
33
+ interp_name = g_malloc(eppnt->p_filesz);
48
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
34
if (!interp_name) {
49
static Property arm_cpu_properties[] = {
35
goto exit_perror;
50
DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false),
36
}
51
DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0),
37
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
52
- DEFINE_PROP_UINT32("midr", ARMCPU, midr, 0),
38
errmsg = "Invalid PT_INTERP entry";
53
+ DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0),
39
goto exit_errmsg;
54
DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
40
}
55
mp_affinity, ARM64_AFFINITY_INVALID),
41
- *pinterp_name = interp_name;
56
DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
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
}
53
54
#ifdef USE_ELF_CORE_DUMP
57
--
55
--
58
2.20.1
56
2.20.1
59
57
60
58
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Embed the GEMs into the SoC type.
3
Fixing this now will clarify following patches.
4
4
5
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Message-id: 20201016184207.786698-6-richard.henderson@linaro.org
10
Message-id: 20200427181649.26851-6-edgar.iglesias@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
9
---
13
include/hw/arm/xlnx-versal.h | 3 ++-
10
linux-user/elfload.c | 12 +++++++++---
14
hw/arm/xlnx-versal.c | 15 ++++++++-------
11
1 file changed, 9 insertions(+), 3 deletions(-)
15
2 files changed, 10 insertions(+), 8 deletions(-)
16
12
17
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/xlnx-versal.h
15
--- a/linux-user/elfload.c
20
+++ b/include/hw/arm/xlnx-versal.h
16
+++ b/linux-user/elfload.c
21
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
22
#include "hw/arm/boot.h"
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
23
#include "hw/intc/arm_gicv3.h"
19
int elf_prot = 0;
24
#include "hw/char/pl011.h"
20
25
+#include "hw/net/cadence_gem.h"
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
26
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
27
#define TYPE_XLNX_VERSAL "xlnx-versal"
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
28
#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL)
24
+ if (eppnt->p_flags & PF_R) {
29
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
25
+ elf_prot |= PROT_READ;
30
26
+ }
31
struct {
27
+ if (eppnt->p_flags & PF_W) {
32
PL011State uart[XLNX_VERSAL_NR_UARTS];
28
+ elf_prot |= PROT_WRITE;
33
- SysBusDevice *gem[XLNX_VERSAL_NR_GEMS];
29
+ }
34
+ CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
30
+ if (eppnt->p_flags & PF_X) {
35
SysBusDevice *adma[XLNX_VERSAL_NR_ADMAS];
31
+ elf_prot |= PROT_EXEC;
36
} iou;
32
+ }
37
} lpd;
33
38
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
34
vaddr = load_bias + eppnt->p_vaddr;
39
index XXXXXXX..XXXXXXX 100644
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
40
--- a/hw/arm/xlnx-versal.c
41
+++ b/hw/arm/xlnx-versal.c
42
@@ -XXX,XX +XXX,XX @@ static void versal_create_gems(Versal *s, qemu_irq *pic)
43
DeviceState *dev;
44
MemoryRegion *mr;
45
46
- dev = qdev_create(NULL, "cadence_gem");
47
- s->lpd.iou.gem[i] = SYS_BUS_DEVICE(dev);
48
- object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
49
+ sysbus_init_child_obj(OBJECT(s), name,
50
+ &s->lpd.iou.gem[i], sizeof(s->lpd.iou.gem[i]),
51
+ TYPE_CADENCE_GEM);
52
+ dev = DEVICE(&s->lpd.iou.gem[i]);
53
if (nd->used) {
54
qemu_check_nic_model(nd, "cadence_gem");
55
qdev_set_nic_properties(dev, nd);
56
}
57
- object_property_set_int(OBJECT(s->lpd.iou.gem[i]),
58
+ object_property_set_int(OBJECT(dev),
59
2, "num-priority-queues",
60
&error_abort);
61
- object_property_set_link(OBJECT(s->lpd.iou.gem[i]),
62
+ object_property_set_link(OBJECT(dev),
63
OBJECT(&s->mr_ps), "dma",
64
&error_abort);
65
qdev_init_nofail(dev);
66
67
- mr = sysbus_mmio_get_region(s->lpd.iou.gem[i], 0);
68
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
69
memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
70
71
- sysbus_connect_irq(s->lpd.iou.gem[i], 0, pic[irqs[i]]);
72
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
73
g_free(name);
74
}
75
}
76
--
36
--
77
2.20.1
37
2.20.1
78
38
79
39
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Embed the UARTs into the SoC type.
3
The second loop uses a loop induction variable, and the first
4
does not. Transform the first to match the second, to simplify
5
a following patch moving code between them.
4
6
5
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Message-id: 20201016184207.786698-7-richard.henderson@linaro.org
10
Message-id: 20200427181649.26851-5-edgar.iglesias@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
include/hw/arm/xlnx-versal.h | 3 ++-
12
linux-user/elfload.c | 9 +++++----
14
hw/arm/xlnx-versal.c | 12 ++++++------
13
1 file changed, 5 insertions(+), 4 deletions(-)
15
2 files changed, 8 insertions(+), 7 deletions(-)
16
14
17
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/xlnx-versal.h
17
--- a/linux-user/elfload.c
20
+++ b/include/hw/arm/xlnx-versal.h
18
+++ b/linux-user/elfload.c
21
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
22
#include "hw/sysbus.h"
20
loaddr = -1, hiaddr = 0;
23
#include "hw/arm/boot.h"
21
info->alignment = 0;
24
#include "hw/intc/arm_gicv3.h"
22
for (i = 0; i < ehdr->e_phnum; ++i) {
25
+#include "hw/char/pl011.h"
23
- if (phdr[i].p_type == PT_LOAD) {
26
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
27
#define TYPE_XLNX_VERSAL "xlnx-versal"
25
+ struct elf_phdr *eppnt = phdr + i;
28
#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL)
26
+ if (eppnt->p_type == PT_LOAD) {
29
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
30
MemoryRegion mr_ocm;
28
if (a < loaddr) {
31
29
loaddr = a;
32
struct {
30
}
33
- SysBusDevice *uart[XLNX_VERSAL_NR_UARTS];
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
34
+ PL011State uart[XLNX_VERSAL_NR_UARTS];
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
35
SysBusDevice *gem[XLNX_VERSAL_NR_GEMS];
33
if (a > hiaddr) {
36
SysBusDevice *adma[XLNX_VERSAL_NR_ADMAS];
34
hiaddr = a;
37
} iou;
35
}
38
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
36
++info->nsegs;
39
index XXXXXXX..XXXXXXX 100644
37
- info->alignment |= phdr[i].p_align;
40
--- a/hw/arm/xlnx-versal.c
38
+ info->alignment |= eppnt->p_align;
41
+++ b/hw/arm/xlnx-versal.c
39
}
42
@@ -XXX,XX +XXX,XX @@
43
#include "kvm_arm.h"
44
#include "hw/misc/unimp.h"
45
#include "hw/arm/xlnx-versal.h"
46
-#include "hw/char/pl011.h"
47
48
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
49
#define GEM_REVISION 0x40070106
50
@@ -XXX,XX +XXX,XX @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
51
DeviceState *dev;
52
MemoryRegion *mr;
53
54
- dev = qdev_create(NULL, TYPE_PL011);
55
- s->lpd.iou.uart[i] = SYS_BUS_DEVICE(dev);
56
+ sysbus_init_child_obj(OBJECT(s), name,
57
+ &s->lpd.iou.uart[i], sizeof(s->lpd.iou.uart[i]),
58
+ TYPE_PL011);
59
+ dev = DEVICE(&s->lpd.iou.uart[i]);
60
qdev_prop_set_chr(dev, "chardev", serial_hd(i));
61
- object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
62
qdev_init_nofail(dev);
63
64
- mr = sysbus_mmio_get_region(s->lpd.iou.uart[i], 0);
65
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
66
memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
67
68
- sysbus_connect_irq(s->lpd.iou.uart[i], 0, pic[irqs[i]]);
69
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
70
g_free(name);
71
}
40
}
72
}
41
73
--
42
--
74
2.20.1
43
2.20.1
75
44
76
45
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Fix typo xlnx-ve -> xlnx-versal.
3
For BTI, we need to know if the executable is static or dynamic,
4
which means looking for PT_INTERP earlier.
4
5
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Message-id: 20201016184207.786698-8-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Message-id: 20200427181649.26851-4-edgar.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/arm/xlnx-versal-virt.c | 2 +-
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
13
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 31 insertions(+), 29 deletions(-)
14
13
15
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/xlnx-versal-virt.c
16
--- a/linux-user/elfload.c
18
+++ b/hw/arm/xlnx-versal-virt.c
17
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
20
psci_conduit = QEMU_PSCI_CONDUIT_SMC;
19
20
mmap_lock();
21
22
- /* Find the maximum size of the image and allocate an appropriate
23
- amount of memory to handle that. */
24
+ /*
25
+ * Find the maximum size of the image and allocate an appropriate
26
+ * amount of memory to handle that. Locate the interpreter, if any.
27
+ */
28
loaddr = -1, hiaddr = 0;
29
info->alignment = 0;
30
for (i = 0; i < ehdr->e_phnum; ++i) {
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
32
}
33
++info->nsegs;
34
info->alignment |= eppnt->p_align;
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
36
+ g_autofree char *interp_name = NULL;
37
+
38
+ if (*pinterp_name) {
39
+ errmsg = "Multiple PT_INTERP entries";
40
+ goto exit_errmsg;
41
+ }
42
+ interp_name = g_malloc(eppnt->p_filesz);
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
}
21
}
63
}
22
64
23
- sysbus_init_child_obj(OBJECT(machine), "xlnx-ve", &s->soc,
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
24
+ sysbus_init_child_obj(OBJECT(machine), "xlnx-versal", &s->soc,
66
if (vaddr_em > info->brk) {
25
sizeof(s->soc), TYPE_XLNX_VERSAL);
67
info->brk = vaddr_em;
26
object_property_set_link(OBJECT(&s->soc), OBJECT(machine->ram),
68
}
27
"ddr", &error_abort);
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
70
- g_autofree char *interp_name = NULL;
71
-
72
- if (*pinterp_name) {
73
- errmsg = "Multiple PT_INTERP entries";
74
- goto exit_errmsg;
75
- }
76
- interp_name = g_malloc(eppnt->p_filesz);
77
- if (!interp_name) {
78
- goto exit_perror;
79
- }
80
-
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;
28
--
99
--
29
2.20.1
100
2.20.1
30
101
31
102
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Remove inclusion of arm_gicv3_common.h, this already gets
3
This is a bit clearer than open-coding some of this
4
included via xlnx-versal.h.
4
with a bare c string.
5
5
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20201016184207.786698-9-richard.henderson@linaro.org
9
Message-id: 20200427181649.26851-2-edgar.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/arm/xlnx-versal.c | 1 -
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
13
1 file changed, 1 deletion(-)
12
1 file changed, 20 insertions(+), 17 deletions(-)
14
13
15
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/xlnx-versal.c
16
--- a/linux-user/elfload.c
18
+++ b/hw/arm/xlnx-versal.c
17
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
20
#include "hw/arm/boot.h"
19
#include "qemu/guest-random.h"
21
#include "kvm_arm.h"
20
#include "qemu/units.h"
22
#include "hw/misc/unimp.h"
21
#include "qemu/selfmap.h"
23
-#include "hw/intc/arm_gicv3_common.h"
22
+#include "qapi/error.h"
24
#include "hw/arm/xlnx-versal.h"
23
25
#include "hw/char/pl011.h"
24
#ifdef _ARCH_PPC64
25
#undef ARCH_DLINFO
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
27
struct elf_phdr *phdr;
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
29
int i, retval;
30
- const char *errmsg;
31
+ Error *err = NULL;
32
33
/* First of all, some simple consistency checks */
34
- errmsg = "Invalid ELF image for this architecture";
35
if (!elf_check_ident(ehdr)) {
36
+ error_setg(&err, "Invalid ELF image for this architecture");
37
goto exit_errmsg;
38
}
39
bswap_ehdr(ehdr);
40
if (!elf_check_ehdr(ehdr)) {
41
+ error_setg(&err, "Invalid ELF image for this architecture");
42
goto exit_errmsg;
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
46
g_autofree char *interp_name = NULL;
47
48
if (*pinterp_name) {
49
- errmsg = "Multiple PT_INTERP entries";
50
+ error_setg(&err, "Multiple PT_INTERP entries");
51
goto exit_errmsg;
52
}
53
+
54
interp_name = g_malloc(eppnt->p_filesz);
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
}
26
132
27
--
133
--
28
2.20.1
134
2.20.1
29
135
30
136
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Embed the APUs into the SoC type.
3
This is slightly clearer than just using strerror, though
4
the different forms produced by error_setg_file_open and
5
error_setg_errno isn't entirely convenient.
4
6
5
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Message-id: 20201016184207.786698-10-richard.henderson@linaro.org
10
Message-id: 20200427181649.26851-8-edgar.iglesias@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
include/hw/arm/xlnx-versal.h | 2 +-
12
linux-user/elfload.c | 15 ++++++++-------
14
hw/arm/xlnx-versal-virt.c | 4 ++--
13
1 file changed, 8 insertions(+), 7 deletions(-)
15
hw/arm/xlnx-versal.c | 19 +++++--------------
16
3 files changed, 8 insertions(+), 17 deletions(-)
17
14
18
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/xlnx-versal.h
17
--- a/linux-user/elfload.c
21
+++ b/include/hw/arm/xlnx-versal.h
18
+++ b/linux-user/elfload.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct Versal {
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
23
struct {
20
char bprm_buf[BPRM_BUF_SIZE])
24
struct {
21
{
25
MemoryRegion mr;
22
int fd, retval;
26
- ARMCPU *cpu[XLNX_VERSAL_NR_ACPUS];
23
+ Error *err = NULL;
27
+ ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
24
28
GICv3State gic;
25
fd = open(path(filename), O_RDONLY);
29
} apu;
26
if (fd < 0) {
30
} fpd;
27
- goto exit_perror;
31
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
28
+ error_setg_file_open(&err, errno, filename);
32
index XXXXXXX..XXXXXXX 100644
29
+ error_report_err(err);
33
--- a/hw/arm/xlnx-versal-virt.c
30
+ exit(-1);
34
+++ b/hw/arm/xlnx-versal-virt.c
31
}
35
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
32
36
s->binfo.get_dtb = versal_virt_get_dtb;
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
37
s->binfo.modify_dtb = versal_virt_modify_dtb;
34
if (retval < 0) {
38
if (machine->kernel_filename) {
35
- goto exit_perror;
39
- arm_load_kernel(s->soc.fpd.apu.cpu[0], machine, &s->binfo);
36
+ error_setg_errno(&err, errno, "Error reading file header");
40
+ arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
37
+ error_reportf_err(err, "%s: ", filename);
41
} else {
38
+ exit(-1);
42
- AddressSpace *as = arm_boot_address_space(s->soc.fpd.apu.cpu[0],
39
}
43
+ AddressSpace *as = arm_boot_address_space(&s->soc.fpd.apu.cpu[0],
40
+
44
&s->binfo);
41
if (retval < BPRM_BUF_SIZE) {
45
/* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
46
* Offset things by 4K. */
43
}
47
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
44
48
index XXXXXXX..XXXXXXX 100644
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
49
--- a/hw/arm/xlnx-versal.c
46
- return;
50
+++ b/hw/arm/xlnx-versal.c
51
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
52
53
for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
54
Object *obj;
55
- char *name;
56
-
47
-
57
- obj = object_new(XLNX_VERSAL_ACPU_TYPE);
48
- exit_perror:
58
- if (!obj) {
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
59
- error_report("Unable to create apu.cpu[%d] of type %s",
50
- exit(-1);
60
- i, XLNX_VERSAL_ACPU_TYPE);
61
- exit(EXIT_FAILURE);
62
- }
63
-
64
- name = g_strdup_printf("apu-cpu[%d]", i);
65
- object_property_add_child(OBJECT(s), name, obj, &error_fatal);
66
- g_free(name);
67
68
+ object_initialize_child(OBJECT(s), "apu-cpu[*]",
69
+ &s->fpd.apu.cpu[i], sizeof(s->fpd.apu.cpu[i]),
70
+ XLNX_VERSAL_ACPU_TYPE, &error_abort, NULL);
71
+ obj = OBJECT(&s->fpd.apu.cpu[i]);
72
object_property_set_int(obj, s->cfg.psci_conduit,
73
"psci-conduit", &error_abort);
74
if (i) {
75
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
76
object_property_set_link(obj, OBJECT(&s->fpd.apu.mr), "memory",
77
&error_abort);
78
object_property_set_bool(obj, true, "realized", &error_fatal);
79
- s->fpd.apu.cpu[i] = ARM_CPU(obj);
80
}
81
}
51
}
82
52
83
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
53
static int symfind(const void *s0, const void *s1)
84
}
85
86
for (i = 0; i < nr_apu_cpus; i++) {
87
- DeviceState *cpudev = DEVICE(s->fpd.apu.cpu[i]);
88
+ DeviceState *cpudev = DEVICE(&s->fpd.apu.cpu[i]);
89
int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
90
qemu_irq maint_irq;
91
int ti;
92
--
54
--
93
2.20.1
55
2.20.1
94
56
95
57
diff view generated by jsdifflib
1
Convert the VCMLA (vector) insns in the 3same extension group to
1
From: Richard Henderson <richard.henderson@linaro.org>
2
decodetree.
2
3
3
This is generic support, with the code disabled for all targets.
4
5
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>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200430181003.21682-5-peter.maydell@linaro.org
7
---
9
---
8
target/arm/neon-shared.decode | 11 ++++++++++
10
linux-user/qemu.h | 4 ++
9
target/arm/translate-neon.inc.c | 37 +++++++++++++++++++++++++++++++++
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
10
target/arm/translate.c | 11 +---------
12
2 files changed, 161 insertions(+)
11
3 files changed, 49 insertions(+), 10 deletions(-)
13
12
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
13
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-shared.decode
16
--- a/linux-user/qemu.h
16
+++ b/target/arm/neon-shared.decode
17
+++ b/linux-user/qemu.h
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
18
# More specifically, this covers:
19
abi_ulong interpreter_loadmap_addr;
19
# 2reg scalar ext: 0b1111_1110_xxxx_xxxx_xxxx_1x0x_xxxx_xxxx
20
abi_ulong interpreter_pt_dynamic_addr;
20
# 3same ext: 0b1111_110x_xxxx_xxxx_xxxx_1x0x_xxxx_xxxx
21
struct image_info *other_info;
21
+
22
+
22
+# VFP/Neon register fields; same as vfp.decode
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
23
+%vm_dp 5:1 0:4
24
+ uint32_t note_flags;
24
+%vm_sp 0:4 5:1
25
+
25
+%vn_dp 7:1 16:4
26
#ifdef TARGET_MIPS
26
+%vn_sp 16:4 7:1
27
int fp_abi;
27
+%vd_dp 22:1 12:4
28
int interp_fp_abi;
28
+%vd_sp 12:4 22:1
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
29
+
30
+VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \
31
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
32
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate-neon.inc.c
31
--- a/linux-user/elfload.c
35
+++ b/target/arm/translate-neon.inc.c
32
+++ b/linux-user/elfload.c
36
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
37
#include "decode-neon-dp.inc.c"
34
38
#include "decode-neon-ls.inc.c"
35
#include "elf.h"
39
#include "decode-neon-shared.inc.c"
36
40
+
37
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
41
+static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
38
+ const uint32_t *data,
39
+ struct image_info *info,
40
+ Error **errp)
42
+{
41
+{
43
+ int opr_sz;
42
+ g_assert_not_reached();
44
+ TCGv_ptr fpst;
43
+}
45
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
44
+#define ARCH_USE_GNU_PROPERTY 0
46
+
45
+
47
+ if (!dc_isar_feature(aa32_vcma, s)
46
struct exec
48
+ || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
47
{
49
+ return false;
48
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
50
+ }
49
@@ -XXX,XX +XXX,XX @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
51
+
50
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
52
+ /* UNDEF accesses to D16-D31 if they don't exist. */
51
}
53
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
52
54
+ ((a->vd | a->vn | a->vm) & 0x10)) {
53
+enum {
55
+ return false;
54
+ /* The string "GNU\0" as a magic number. */
56
+ }
55
+ GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
57
+
56
+ NOTE_DATA_SZ = 1 * KiB,
58
+ if ((a->vn | a->vm | a->vd) & a->q) {
57
+ NOTE_NAME_SZ = 4,
59
+ return false;
58
+ ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
60
+ }
59
+};
61
+
60
+
62
+ if (!vfp_access_check(s)) {
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) {
63
+ return true;
130
+ return true;
64
+ }
131
+ }
65
+
132
+
66
+ opr_sz = (1 + a->q) * 8;
133
+ /* If the properties are crazy large, that's too bad. */
67
+ fpst = get_fpstatus_ptr(1);
134
+ n = phdr->p_filesz;
68
+ fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
135
+ if (n > sizeof(note)) {
69
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
136
+ error_setg(errp, "PT_GNU_PROPERTY too large");
70
+ vfp_reg_offset(1, a->vn),
137
+ return false;
71
+ vfp_reg_offset(1, a->vm),
138
+ }
72
+ fpst, opr_sz, opr_sz, a->rot,
139
+ if (n < sizeof(note.nhdr)) {
73
+ fn_gvec_ptr);
140
+ error_setg(errp, "PT_GNU_PROPERTY too small");
74
+ tcg_temp_free_ptr(fpst);
141
+ return false;
75
+ return true;
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
+ }
152
+ }
153
+
154
+ /*
155
+ * The contents of a valid PT_GNU_PROPERTY is a sequence
156
+ * of uint32_t -- swap them all now.
157
+ */
158
+#ifdef BSWAP_NEEDED
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
+ }
76
+}
195
+}
77
diff --git a/target/arm/translate.c b/target/arm/translate.c
196
+
78
index XXXXXXX..XXXXXXX 100644
197
/* Load an ELF image into the address space.
79
--- a/target/arm/translate.c
198
80
+++ b/target/arm/translate.c
199
IMAGE_NAME is the filename of the image, to use in error messages.
81
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
200
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
82
bool is_long = false, q = extract32(insn, 6, 1);
201
goto exit_errmsg;
83
bool ptr_is_env = false;
202
}
84
203
*pinterp_name = g_steal_pointer(&interp_name);
85
- if ((insn & 0xfe200f10) == 0xfc200800) {
204
+ } else if (eppnt->p_type == PT_GNU_PROPERTY) {
86
- /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
205
+ if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
87
- int size = extract32(insn, 20, 1);
206
+ goto exit_errmsg;
88
- data = extract32(insn, 23, 2); /* rot */
207
+ }
89
- if (!dc_isar_feature(aa32_vcma, s)
208
}
90
- || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
209
}
91
- return 1;
210
92
- }
93
- fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
94
- } else if ((insn & 0xfea00f10) == 0xfc800800) {
95
+ if ((insn & 0xfea00f10) == 0xfc800800) {
96
/* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
97
int size = extract32(insn, 20, 1);
98
data = extract32(insn, 24, 1); /* rot */
99
--
211
--
100
2.20.1
212
2.20.1
101
213
102
214
diff view generated by jsdifflib
1
Convert the Neon "load single structure to all lanes" insns to
1
From: Richard Henderson <richard.henderson@linaro.org>
2
decodetree.
3
2
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
4
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>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200430181003.21682-13-peter.maydell@linaro.org
7
---
9
---
8
target/arm/neon-ls.decode | 5 +++
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
9
target/arm/translate-neon.inc.c | 73 +++++++++++++++++++++++++++++++++
11
1 file changed, 46 insertions(+), 2 deletions(-)
10
target/arm/translate.c | 55 +------------------------
11
3 files changed, 80 insertions(+), 53 deletions(-)
12
12
13
diff --git a/target/arm/neon-ls.decode b/target/arm/neon-ls.decode
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-ls.decode
15
--- a/linux-user/elfload.c
16
+++ b/target/arm/neon-ls.decode
16
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
18
18
19
VLDST_multiple 1111 0100 0 . l:1 0 rn:4 .... itype:4 size:2 align:2 rm:4 \
19
#include "elf.h"
20
vd=%vd_dp
20
21
+/* We must delay the following stanzas until after "elf.h". */
22
+#if defined(TARGET_AARCH64)
21
+
23
+
22
+# Neon load single element to all lanes
24
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
23
+
25
+ const uint32_t *data,
24
+VLD_all_lanes 1111 0100 1 . 1 0 rn:4 .... 11 n:2 size:2 t:1 a:1 rm:4 \
26
+ struct image_info *info,
25
+ vd=%vd_dp
27
+ Error **errp)
26
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/translate-neon.inc.c
29
+++ b/target/arm/translate-neon.inc.c
30
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
31
gen_neon_ldst_base_update(s, a->rm, a->rn, nregs * interleave * 8);
32
return true;
33
}
34
+
35
+static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a)
36
+{
28
+{
37
+ /* Neon load single structure to all lanes */
29
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
38
+ int reg, stride, vec_size;
30
+ if (pr_datasz != sizeof(uint32_t)) {
39
+ int vd = a->vd;
31
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
40
+ int size = a->size;
41
+ int nregs = a->n + 1;
42
+ TCGv_i32 addr, tmp;
43
+
44
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
45
+ return false;
46
+ }
47
+
48
+ /* UNDEF accesses to D16-D31 if they don't exist */
49
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
50
+ return false;
51
+ }
52
+
53
+ if (size == 3) {
54
+ if (nregs != 4 || a->a == 0) {
55
+ return false;
32
+ return false;
56
+ }
33
+ }
57
+ /* For VLD4 size == 3 a == 1 means 32 bits at 16 byte alignment */
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
58
+ size = 2;
35
+ info->note_flags = *data;
59
+ }
36
+ }
60
+ if (nregs == 1 && a->a == 1 && size == 0) {
61
+ return false;
62
+ }
63
+ if (nregs == 3 && a->a == 1) {
64
+ return false;
65
+ }
66
+
67
+ if (!vfp_access_check(s)) {
68
+ return true;
69
+ }
70
+
71
+ /*
72
+ * VLD1 to all lanes: T bit indicates how many Dregs to write.
73
+ * VLD2/3/4 to all lanes: T bit indicates register stride.
74
+ */
75
+ stride = a->t ? 2 : 1;
76
+ vec_size = nregs == 1 ? stride * 8 : 8;
77
+
78
+ tmp = tcg_temp_new_i32();
79
+ addr = tcg_temp_new_i32();
80
+ load_reg_var(s, addr, a->rn);
81
+ for (reg = 0; reg < nregs; reg++) {
82
+ gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
83
+ s->be_data | size);
84
+ if ((vd & 1) && vec_size == 16) {
85
+ /*
86
+ * We cannot write 16 bytes at once because the
87
+ * destination is unaligned.
88
+ */
89
+ tcg_gen_gvec_dup_i32(size, neon_reg_offset(vd, 0),
90
+ 8, 8, tmp);
91
+ tcg_gen_gvec_mov(0, neon_reg_offset(vd + 1, 0),
92
+ neon_reg_offset(vd, 0), 8, 8);
93
+ } else {
94
+ tcg_gen_gvec_dup_i32(size, neon_reg_offset(vd, 0),
95
+ vec_size, vec_size, tmp);
96
+ }
97
+ tcg_gen_addi_i32(addr, addr, 1 << size);
98
+ vd += stride;
99
+ }
100
+ tcg_temp_free_i32(tmp);
101
+ tcg_temp_free_i32(addr);
102
+
103
+ gen_neon_ldst_base_update(s, a->rm, a->rn, (1 << size) * nregs);
104
+
105
+ return true;
37
+ return true;
106
+}
38
+}
107
diff --git a/target/arm/translate.c b/target/arm/translate.c
39
+#define ARCH_USE_GNU_PROPERTY 1
108
index XXXXXXX..XXXXXXX 100644
40
+
109
--- a/target/arm/translate.c
41
+#else
110
+++ b/target/arm/translate.c
42
+
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
112
int size;
44
const uint32_t *data,
113
int reg;
45
struct image_info *info,
114
int load;
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
115
- int vec_size;
47
}
116
TCGv_i32 addr;
48
#define ARCH_USE_GNU_PROPERTY 0
117
TCGv_i32 tmp;
49
118
50
+#endif
119
@@ -XXX,XX +XXX,XX @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
51
+
120
} else {
52
struct exec
121
size = (insn >> 10) & 3;
53
{
122
if (size == 3) {
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
123
- /* Load single element to all lanes. */
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
124
- int a = (insn >> 4) & 1;
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
125
- if (!load) {
57
struct elf_phdr *phdr;
126
- return 1;
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
127
- }
59
- int i, retval;
128
- size = (insn >> 6) & 3;
60
+ int i, retval, prot_exec;
129
- nregs = ((insn >> 8) & 3) + 1;
61
Error *err = NULL;
130
-
62
131
- if (size == 3) {
63
/* First of all, some simple consistency checks */
132
- if (nregs != 4 || a == 0) {
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
133
- return 1;
65
info->brk = 0;
134
- }
66
info->elf_flags = ehdr->e_flags;
135
- /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
67
136
- size = 2;
68
+ prot_exec = PROT_EXEC;
137
- }
69
+#ifdef TARGET_AARCH64
138
- if (nregs == 1 && a == 1 && size == 0) {
70
+ /*
139
- return 1;
71
+ * If the BTI feature is present, this indicates that the executable
140
- }
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
141
- if (nregs == 3 && a == 1) {
73
+ * branch targets are enforced.
142
- return 1;
74
+ *
143
- }
75
+ * The startup binary is either the interpreter or the static executable.
144
- addr = tcg_temp_new_i32();
76
+ * The interpreter is responsible for all pages of a dynamic executable.
145
- load_reg_var(s, addr, rn);
77
+ *
146
-
78
+ * Elf notes are backward compatible to older cpus.
147
- /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
79
+ * Do not enable BTI unless it is supported.
148
- * VLD2/3/4 to all lanes: bit 5 indicates register stride.
80
+ */
149
- */
81
+ if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
150
- stride = (insn & (1 << 5)) ? 2 : 1;
82
+ && (pinterp_name == NULL || *pinterp_name == 0)
151
- vec_size = nregs == 1 ? stride * 8 : 8;
83
+ && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
152
-
84
+ prot_exec |= TARGET_PROT_BTI;
153
- tmp = tcg_temp_new_i32();
85
+ }
154
- for (reg = 0; reg < nregs; reg++) {
86
+#endif
155
- gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
87
+
156
- s->be_data | size);
88
for (i = 0; i < ehdr->e_phnum; i++) {
157
- if ((rd & 1) && vec_size == 16) {
89
struct elf_phdr *eppnt = phdr + i;
158
- /* We cannot write 16 bytes at once because the
90
if (eppnt->p_type == PT_LOAD) {
159
- * destination is unaligned.
91
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
160
- */
92
elf_prot |= PROT_WRITE;
161
- tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
93
}
162
- 8, 8, tmp);
94
if (eppnt->p_flags & PF_X) {
163
- tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
95
- elf_prot |= PROT_EXEC;
164
- neon_reg_offset(rd, 0), 8, 8);
96
+ elf_prot |= prot_exec;
165
- } else {
97
}
166
- tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
98
167
- vec_size, vec_size, tmp);
99
vaddr = load_bias + eppnt->p_vaddr;
168
- }
169
- tcg_gen_addi_i32(addr, addr, 1 << size);
170
- rd += stride;
171
- }
172
- tcg_temp_free_i32(tmp);
173
- tcg_temp_free_i32(addr);
174
- stride = (1 << size) * nregs;
175
+ /* Load single element to all lanes -- handled by decodetree */
176
+ return 1;
177
} else {
178
/* Single element. */
179
int idx = (insn >> 4) & 0xf;
180
--
100
--
181
2.20.1
101
2.20.1
182
102
183
103
diff view generated by jsdifflib
1
Add the infrastructure for building and invoking a decodetree decoder
1
From: Richard Henderson <richard.henderson@linaro.org>
2
for the AArch32 Neon encodings. At the moment the new decoder covers
2
3
nothing, so we always fall back to the existing hand-written decode.
3
The note test requires gcc 10 for -mbranch-protection=standard.
4
4
The mmap test uses PROT_BTI and does not require special compiler support.
5
We follow the same pattern we did for the VFP decodetree conversion
5
6
(commit 78e138bc1f672c145ef6ace74617d and following): code that deals
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
7
with Neon will be moving gradually out to translate-neon.vfp.inc,
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
which we #include into translate.c.
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
9
Message-id: 20201016184207.786698-13-richard.henderson@linaro.org
10
In order to share the decode files between A32 and T32, we
11
split Neon into 3 parts:
12
* data-processing
13
* load-store
14
* 'shared' encodings
15
16
The first two groups of instructions have similar but not identical
17
A32 and T32 encodings, so we need to manually transform the T32
18
encoding into the A32 one before calling the decoder; the third group
19
covers the Neon instructions which are identical in A32 and T32.
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20200430181003.21682-4-peter.maydell@linaro.org
24
---
11
---
25
target/arm/neon-dp.decode | 29 ++++++++++++++++++++++++++
12
tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++
26
target/arm/neon-ls.decode | 29 ++++++++++++++++++++++++++
13
tests/tcg/aarch64/bti-2.c | 108 ++++++++++++++++++++++++++++++
27
target/arm/neon-shared.decode | 27 +++++++++++++++++++++++++
14
tests/tcg/aarch64/bti-crt.inc.c | 51 ++++++++++++++
28
target/arm/translate-neon.inc.c | 32 +++++++++++++++++++++++++++++
15
tests/tcg/aarch64/Makefile.target | 10 +++
29
target/arm/translate.c | 36 +++++++++++++++++++++++++++++++--
16
tests/tcg/configure.sh | 4 ++
30
target/arm/Makefile.objs | 18 +++++++++++++++++
17
5 files changed, 235 insertions(+)
31
6 files changed, 169 insertions(+), 2 deletions(-)
18
create mode 100644 tests/tcg/aarch64/bti-1.c
32
create mode 100644 target/arm/neon-dp.decode
19
create mode 100644 tests/tcg/aarch64/bti-2.c
33
create mode 100644 target/arm/neon-ls.decode
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
34
create mode 100644 target/arm/neon-shared.decode
21
35
create mode 100644 target/arm/translate-neon.inc.c
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
36
37
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
38
new file mode 100644
23
new file mode 100644
39
index XXXXXXX..XXXXXXX
24
index XXXXXXX..XXXXXXX
40
--- /dev/null
25
--- /dev/null
41
+++ b/target/arm/neon-dp.decode
26
+++ b/tests/tcg/aarch64/bti-1.c
42
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
43
+# AArch32 Neon data-processing instruction descriptions
28
+/*
44
+#
29
+ * Branch target identification, basic notskip cases.
45
+# Copyright (c) 2020 Linaro, Ltd
30
+ */
46
+#
31
+
47
+# This library is free software; you can redistribute it and/or
32
+#include "bti-crt.inc.c"
48
+# modify it under the terms of the GNU Lesser General Public
33
+
49
+# License as published by the Free Software Foundation; either
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
50
+# version 2 of the License, or (at your option) any later version.
35
+{
51
+#
36
+ uc->uc_mcontext.pc += 8;
52
+# This library is distributed in the hope that it will be useful,
37
+ uc->uc_mcontext.pstate = 1;
53
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
38
+}
54
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39
+
55
+# Lesser General Public License for more details.
40
+#define NOP "nop"
56
+#
41
+#define BTI_N "hint #32"
57
+# You should have received a copy of the GNU Lesser General Public
42
+#define BTI_C "hint #34"
58
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
43
+#define BTI_J "hint #36"
59
+
44
+#define BTI_JC "hint #38"
60
+#
45
+
61
+# This file is processed by scripts/decodetree.py
46
+#define BTYPE_1(DEST) \
62
+#
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
63
+
48
+ : "=r"(skipped) : : "x16")
64
+# Encodings for Neon data processing instructions where the T32 encoding
49
+
65
+# is a simple transformation of the A32 encoding.
50
+#define BTYPE_2(DEST) \
66
+# More specifically, this file covers instructions where the A32 encoding is
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
67
+# 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
52
+ : "=r"(skipped) : : "x16", "x30")
68
+# and the T32 encoding is
53
+
69
+# 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
54
+#define BTYPE_3(DEST) \
70
+# This file works on the A32 encoding only; calling code for T32 has to
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
71
+# transform the insn into the A32 version first.
56
+ : "=r"(skipped) : : "x15")
72
diff --git a/target/arm/neon-ls.decode b/target/arm/neon-ls.decode
57
+
58
+#define TEST(WHICH, DEST, EXPECT) \
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
60
+
61
+
62
+int main()
63
+{
64
+ int fail = 0;
65
+ int skipped;
66
+
67
+ /* Signal-like with SA_SIGINFO. */
68
+ signal_info(SIGILL, skip2_sigill);
69
+
70
+ TEST(BTYPE_1, NOP, 1);
71
+ TEST(BTYPE_1, BTI_N, 1);
72
+ TEST(BTYPE_1, BTI_C, 0);
73
+ TEST(BTYPE_1, BTI_J, 0);
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
+
88
+ return fail;
89
+}
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
73
new file mode 100644
91
new file mode 100644
74
index XXXXXXX..XXXXXXX
92
index XXXXXXX..XXXXXXX
75
--- /dev/null
93
--- /dev/null
76
+++ b/target/arm/neon-ls.decode
94
+++ b/tests/tcg/aarch64/bti-2.c
77
@@ -XXX,XX +XXX,XX @@
95
@@ -XXX,XX +XXX,XX @@
78
+# AArch32 Neon load/store instruction descriptions
96
+/*
79
+#
97
+ * Branch target identification, basic notskip cases.
80
+# Copyright (c) 2020 Linaro, Ltd
98
+ */
81
+#
99
+
82
+# This library is free software; you can redistribute it and/or
100
+#include <stdio.h>
83
+# modify it under the terms of the GNU Lesser General Public
101
+#include <signal.h>
84
+# License as published by the Free Software Foundation; either
102
+#include <string.h>
85
+# version 2 of the License, or (at your option) any later version.
103
+#include <unistd.h>
86
+#
104
+#include <sys/mman.h>
87
+# This library is distributed in the hope that it will be useful,
105
+
88
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
106
+#ifndef PROT_BTI
89
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
107
+#define PROT_BTI 0x10
90
+# Lesser General Public License for more details.
108
+#endif
91
+#
109
+
92
+# You should have received a copy of the GNU Lesser General Public
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
93
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
111
+{
94
+
112
+ ucontext_t *uc = vuc;
95
+#
113
+ uc->uc_mcontext.pc += 8;
96
+# This file is processed by scripts/decodetree.py
114
+ uc->uc_mcontext.pstate = 1;
97
+#
115
+}
98
+
116
+
99
+# Encodings for Neon load/store instructions where the T32 encoding
117
+#define NOP "nop"
100
+# is a simple transformation of the A32 encoding.
118
+#define BTI_N "hint #32"
101
+# More specifically, this file covers instructions where the A32 encoding is
119
+#define BTI_C "hint #34"
102
+# 0b1111_0100_xxx0_xxxx_xxxx_xxxx_xxxx_xxxx
120
+#define BTI_J "hint #36"
103
+# and the T32 encoding is
121
+#define BTI_JC "hint #38"
104
+# 0b1111_1001_xxx0_xxxx_xxxx_xxxx_xxxx_xxxx
122
+
105
+# This file works on the A32 encoding only; calling code for T32 has to
123
+#define BTYPE_1(DEST) \
106
+# transform the insn into the A32 version first.
124
+ "mov x1, #1\n\t" \
107
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
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
108
new file mode 100644
205
new file mode 100644
109
index XXXXXXX..XXXXXXX
206
index XXXXXXX..XXXXXXX
110
--- /dev/null
207
--- /dev/null
111
+++ b/target/arm/neon-shared.decode
208
+++ b/tests/tcg/aarch64/bti-crt.inc.c
112
@@ -XXX,XX +XXX,XX @@
113
+# AArch32 Neon instruction descriptions
114
+#
115
+# Copyright (c) 2020 Linaro, Ltd
116
+#
117
+# This library is free software; you can redistribute it and/or
118
+# modify it under the terms of the GNU Lesser General Public
119
+# License as published by the Free Software Foundation; either
120
+# version 2 of the License, or (at your option) any later version.
121
+#
122
+# This library is distributed in the hope that it will be useful,
123
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
124
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
125
+# Lesser General Public License for more details.
126
+#
127
+# You should have received a copy of the GNU Lesser General Public
128
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
129
+
130
+#
131
+# This file is processed by scripts/decodetree.py
132
+#
133
+
134
+# Encodings for Neon instructions whose encoding is the same for
135
+# both A32 and T32.
136
+
137
+# More specifically, this covers:
138
+# 2reg scalar ext: 0b1111_1110_xxxx_xxxx_xxxx_1x0x_xxxx_xxxx
139
+# 3same ext: 0b1111_110x_xxxx_xxxx_xxxx_1x0x_xxxx_xxxx
140
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
141
new file mode 100644
142
index XXXXXXX..XXXXXXX
143
--- /dev/null
144
+++ b/target/arm/translate-neon.inc.c
145
@@ -XXX,XX +XXX,XX @@
209
@@ -XXX,XX +XXX,XX @@
146
+/*
210
+/*
147
+ * ARM translation: AArch32 Neon instructions
211
+ * Minimal user-environment for testing BTI.
148
+ *
212
+ *
149
+ * Copyright (c) 2003 Fabrice Bellard
213
+ * Normal libc is not (yet) built with BTI support enabled,
150
+ * Copyright (c) 2005-2007 CodeSourcery
214
+ * and so could generate a BTI TRAP before ever reaching main.
151
+ * Copyright (c) 2007 OpenedHand, Ltd.
152
+ * Copyright (c) 2020 Linaro, Ltd.
153
+ *
154
+ * This library is free software; you can redistribute it and/or
155
+ * modify it under the terms of the GNU Lesser General Public
156
+ * License as published by the Free Software Foundation; either
157
+ * version 2 of the License, or (at your option) any later version.
158
+ *
159
+ * This library is distributed in the hope that it will be useful,
160
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
161
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
162
+ * Lesser General Public License for more details.
163
+ *
164
+ * You should have received a copy of the GNU Lesser General Public
165
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
166
+ */
215
+ */
167
+
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
+
168
+/*
238
+/*
169
+ * This file is intended to be included from translate.c; it uses
239
+ * Irritatingly, the user API struct sigaction does not match the
170
+ * some macros and definitions provided by that file.
240
+ * kernel API struct sigaction. So for simplicity, isolate the
171
+ * It might be possible to convert it to a standalone .c file eventually.
241
+ * kernel ABI here, and make this act like signal.
172
+ */
242
+ */
173
+
243
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
174
+/* Include the generated Neon decoder */
244
+{
175
+#include "decode-neon-dp.inc.c"
245
+ struct kernel_sigaction {
176
+#include "decode-neon-ls.inc.c"
246
+ void (*handler)(int, siginfo_t *, ucontext_t *);
177
+#include "decode-neon-shared.inc.c"
247
+ unsigned long flags;
178
diff --git a/target/arm/translate.c b/target/arm/translate.c
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
+}
261
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
179
index XXXXXXX..XXXXXXX 100644
262
index XXXXXXX..XXXXXXX 100644
180
--- a/target/arm/translate.c
263
--- a/tests/tcg/aarch64/Makefile.target
181
+++ b/target/arm/translate.c
264
+++ b/tests/tcg/aarch64/Makefile.target
182
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
265
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
183
266
run-plugin-pauth-%: QEMU_OPTS += -cpu max
184
#define ARM_CP_RW_BIT (1 << 20)
267
endif
185
268
186
-/* Include the VFP decoder */
269
+# BTI Tests
187
+/* Include the VFP and Neon decoders */
270
+# bti-1 tests the elf notes, so we require special compiler support.
188
#include "translate-vfp.inc.c"
271
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
189
+#include "translate-neon.inc.c"
272
+AARCH64_TESTS += bti-1
190
273
+bti-1: CFLAGS += -mbranch-protection=standard
191
static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
274
+bti-1: LDFLAGS += -nostdlib
192
{
275
+endif
193
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
276
+# bti-2 tests PROT_BTI, so no special compiler support required.
194
/* Unconditional instructions. */
277
+AARCH64_TESTS += bti-2
195
/* TODO: Perhaps merge these into one decodetree output file. */
278
+
196
if (disas_a32_uncond(s, insn) ||
279
# Semihosting smoke test for linux-user
197
- disas_vfp_uncond(s, insn)) {
280
AARCH64_TESTS += semihosting
198
+ disas_vfp_uncond(s, insn) ||
281
run-semihosting: semihosting
199
+ disas_neon_dp(s, insn) ||
282
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
200
+ disas_neon_ls(s, insn) ||
283
index XXXXXXX..XXXXXXX 100755
201
+ disas_neon_shared(s, insn)) {
284
--- a/tests/tcg/configure.sh
202
return;
285
+++ b/tests/tcg/configure.sh
203
}
286
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
204
/* fall back to legacy decoder */
287
-march=armv8.3-a -o $TMPE $TMPC; then
205
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
288
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
206
ARCH(6T2);
289
fi
207
}
290
+ if do_compiler "$target_compiler" $target_compiler_cflags \
208
291
+ -mbranch-protection=standard -o $TMPE $TMPC; then
209
+ if ((insn & 0xef000000) == 0xef000000) {
292
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
210
+ /*
293
+ fi
211
+ * T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
294
;;
212
+ * transform into
295
esac
213
+ * A32 encodings 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
296
214
+ */
215
+ uint32_t a32_insn = (insn & 0xe2ffffff) |
216
+ ((insn & (1 << 28)) >> 4) | (1 << 28);
217
+
218
+ if (disas_neon_dp(s, a32_insn)) {
219
+ return;
220
+ }
221
+ }
222
+
223
+ if ((insn & 0xff100000) == 0xf9000000) {
224
+ /*
225
+ * T32 encodings 0b1111_1001_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
226
+ * transform into
227
+ * A32 encodings 0b1111_0100_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
228
+ */
229
+ uint32_t a32_insn = (insn & 0x00ffffff) | 0xf4000000;
230
+
231
+ if (disas_neon_ls(s, a32_insn)) {
232
+ return;
233
+ }
234
+ }
235
+
236
/*
237
* TODO: Perhaps merge these into one decodetree output file.
238
* Note disas_vfp is written for a32 with cond field in the
239
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
240
*/
241
if (disas_t32(s, insn) ||
242
disas_vfp_uncond(s, insn) ||
243
+ disas_neon_shared(s, insn) ||
244
((insn >> 28) == 0xe && disas_vfp(s, insn))) {
245
return;
246
}
247
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
248
index XXXXXXX..XXXXXXX 100644
249
--- a/target/arm/Makefile.objs
250
+++ b/target/arm/Makefile.objs
251
@@ -XXX,XX +XXX,XX @@ target/arm/decode-sve.inc.c: $(SRC_PATH)/target/arm/sve.decode $(DECODETREE)
252
     $(PYTHON) $(DECODETREE) --decode disas_sve -o $@ $<,\
253
     "GEN", $(TARGET_DIR)$@)
254
255
+target/arm/decode-neon-shared.inc.c: $(SRC_PATH)/target/arm/neon-shared.decode $(DECODETREE)
256
+    $(call quiet-command,\
257
+     $(PYTHON) $(DECODETREE) --static-decode disas_neon_shared -o $@ $<,\
258
+     "GEN", $(TARGET_DIR)$@)
259
+
260
+target/arm/decode-neon-dp.inc.c: $(SRC_PATH)/target/arm/neon-dp.decode $(DECODETREE)
261
+    $(call quiet-command,\
262
+     $(PYTHON) $(DECODETREE) --static-decode disas_neon_dp -o $@ $<,\
263
+     "GEN", $(TARGET_DIR)$@)
264
+
265
+target/arm/decode-neon-ls.inc.c: $(SRC_PATH)/target/arm/neon-ls.decode $(DECODETREE)
266
+    $(call quiet-command,\
267
+     $(PYTHON) $(DECODETREE) --static-decode disas_neon_ls -o $@ $<,\
268
+     "GEN", $(TARGET_DIR)$@)
269
+
270
target/arm/decode-vfp.inc.c: $(SRC_PATH)/target/arm/vfp.decode $(DECODETREE)
271
    $(call quiet-command,\
272
     $(PYTHON) $(DECODETREE) --static-decode disas_vfp -o $@ $<,\
273
@@ -XXX,XX +XXX,XX @@ target/arm/decode-t16.inc.c: $(SRC_PATH)/target/arm/t16.decode $(DECODETREE)
274
     "GEN", $(TARGET_DIR)$@)
275
276
target/arm/translate-sve.o: target/arm/decode-sve.inc.c
277
+target/arm/translate.o: target/arm/decode-neon-shared.inc.c
278
+target/arm/translate.o: target/arm/decode-neon-dp.inc.c
279
+target/arm/translate.o: target/arm/decode-neon-ls.inc.c
280
target/arm/translate.o: target/arm/decode-vfp.inc.c
281
target/arm/translate.o: target/arm/decode-vfp-uncond.inc.c
282
target/arm/translate.o: target/arm/decode-a32.inc.c
283
--
297
--
284
2.20.1
298
2.20.1
285
299
286
300
diff view generated by jsdifflib