1
Second pull request of the week; mostly RTH's support for some
1
I don't have anything else queued up at the moment, so this is just
2
new-in-v8.1/v8.3 instructions, and my v8M board model.
2
Richard's SME patches.
3
3
4
thanks
5
-- PMM
4
-- PMM
6
5
7
The following changes since commit 427cbc7e4136a061628cb4315cc8182ea36d772f:
6
The following changes since commit 63b38f6c85acd312c2cab68554abf33adf4ee2b3:
8
7
9
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2018-03-01 18:46:41 +0000)
8
Merge tag 'pull-target-arm-20220707' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2022-07-08 06:17:11 +0530)
10
9
11
are available in the Git repository at:
10
are available in the Git repository at:
12
11
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180302
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220711
14
13
15
for you to fetch changes up to e66a67bf28e1b4fce2e3d72a2610dbd48d9d3078:
14
for you to fetch changes up to f9982ceaf26df27d15547a3a7990a95019e9e3a8:
16
15
17
target/arm: Enable ARM_FEATURE_V8_FCMA (2018-03-02 11:03:45 +0000)
16
linux-user/aarch64: Add SME related hwcap entries (2022-07-11 13:43:52 +0100)
18
17
19
----------------------------------------------------------------
18
----------------------------------------------------------------
20
target-arm queue:
19
target-arm:
21
* implement FCMA and RDM v8.1 and v8.3 instructions
20
* Implement SME emulation, for both system and linux-user
22
* enable Cortex-M33 v8M core, and provide new mps2-an505 board model
23
that uses it
24
* decodetree: Propagate return value from translate subroutines
25
* xlnx-zynqmp: Implement the RTC device
26
21
27
----------------------------------------------------------------
22
----------------------------------------------------------------
28
Alistair Francis (3):
23
Richard Henderson (45):
29
xlnx-zynqmp-rtc: Initial commit
24
target/arm: Handle SME in aarch64_cpu_dump_state
30
xlnx-zynqmp-rtc: Add basic time support
25
target/arm: Add infrastructure for disas_sme
31
xlnx-zynqmp: Connect the RTC device
26
target/arm: Trap non-streaming usage when Streaming SVE is active
27
target/arm: Mark ADR as non-streaming
28
target/arm: Mark RDFFR, WRFFR, SETFFR as non-streaming
29
target/arm: Mark BDEP, BEXT, BGRP, COMPACT, FEXPA, FTSSEL as non-streaming
30
target/arm: Mark PMULL, FMMLA as non-streaming
31
target/arm: Mark FTSMUL, FTMAD, FADDA as non-streaming
32
target/arm: Mark SMMLA, UMMLA, USMMLA as non-streaming
33
target/arm: Mark string/histo/crypto as non-streaming
34
target/arm: Mark gather/scatter load/store as non-streaming
35
target/arm: Mark gather prefetch as non-streaming
36
target/arm: Mark LDFF1 and LDNF1 as non-streaming
37
target/arm: Mark LD1RO as non-streaming
38
target/arm: Add SME enablement checks
39
target/arm: Handle SME in sve_access_check
40
target/arm: Implement SME RDSVL, ADDSVL, ADDSPL
41
target/arm: Implement SME ZERO
42
target/arm: Implement SME MOVA
43
target/arm: Implement SME LD1, ST1
44
target/arm: Export unpredicated ld/st from translate-sve.c
45
target/arm: Implement SME LDR, STR
46
target/arm: Implement SME ADDHA, ADDVA
47
target/arm: Implement FMOPA, FMOPS (non-widening)
48
target/arm: Implement BFMOPA, BFMOPS
49
target/arm: Implement FMOPA, FMOPS (widening)
50
target/arm: Implement SME integer outer product
51
target/arm: Implement PSEL
52
target/arm: Implement REVD
53
target/arm: Implement SCLAMP, UCLAMP
54
target/arm: Reset streaming sve state on exception boundaries
55
target/arm: Enable SME for -cpu max
56
linux-user/aarch64: Clear tpidr2_el0 if CLONE_SETTLS
57
linux-user/aarch64: Reset PSTATE.SM on syscalls
58
linux-user/aarch64: Add SM bit to SVE signal context
59
linux-user/aarch64: Tidy target_restore_sigframe error return
60
linux-user/aarch64: Do not allow duplicate or short sve records
61
linux-user/aarch64: Verify extra record lock succeeded
62
linux-user/aarch64: Move sve record checks into restore
63
linux-user/aarch64: Implement SME signal handling
64
linux-user: Rename sve prctls
65
linux-user/aarch64: Implement PR_SME_GET_VL, PR_SME_SET_VL
66
target/arm: Only set ZEN in reset if SVE present
67
target/arm: Enable SME for user-only
68
linux-user/aarch64: Add SME related hwcap entries
32
69
33
Peter Maydell (19):
70
docs/system/arm/emulation.rst | 4 +
34
loader: Add new load_ramdisk_as()
71
linux-user/aarch64/target_cpu.h | 5 +-
35
hw/arm/boot: Honour CPU's address space for image loads
72
linux-user/aarch64/target_prctl.h | 62 +-
36
hw/arm/armv7m: Honour CPU's address space for image loads
73
target/arm/cpu.h | 7 +
37
target/arm: Define an IDAU interface
74
target/arm/helper-sme.h | 126 ++++
38
armv7m: Forward idau property to CPU object
75
target/arm/helper-sve.h | 4 +
39
target/arm: Define init-svtor property for the reset secure VTOR value
76
target/arm/helper.h | 18 +
40
armv7m: Forward init-svtor property to CPU object
77
target/arm/translate-a64.h | 45 ++
41
target/arm: Add Cortex-M33
78
target/arm/translate.h | 16 +
42
hw/misc/unimp: Move struct to header file
79
target/arm/sme-fa64.decode | 60 ++
43
include/hw/or-irq.h: Add missing include guard
80
target/arm/sme.decode | 88 +++
44
qdev: Add new qdev_init_gpio_in_named_with_opaque()
81
target/arm/sve.decode | 41 +-
45
hw/core/split-irq: Device that splits IRQ lines
82
linux-user/aarch64/cpu_loop.c | 9 +
46
hw/misc/mps2-fpgaio: FPGA control block for MPS2 AN505
83
linux-user/aarch64/signal.c | 243 ++++++--
47
hw/misc/tz-ppc: Model TrustZone peripheral protection controller
84
linux-user/elfload.c | 20 +
48
hw/misc/iotkit-secctl: Arm IoT Kit security controller initial skeleton
85
linux-user/syscall.c | 28 +-
49
hw/misc/iotkit-secctl: Add handling for PPCs
86
target/arm/cpu.c | 35 +-
50
hw/misc/iotkit-secctl: Add remaining simple registers
87
target/arm/cpu64.c | 11 +
51
hw/arm/iotkit: Model Arm IOT Kit
88
target/arm/helper.c | 56 +-
52
mps2-an505: New board model: MPS2 with AN505 Cortex-M33 FPGA image
89
target/arm/sme_helper.c | 1140 +++++++++++++++++++++++++++++++++++++
53
90
target/arm/sve_helper.c | 28 +
54
Richard Henderson (17):
91
target/arm/translate-a64.c | 103 +++-
55
decodetree: Propagate return value from translate subroutines
92
target/arm/translate-sme.c | 373 ++++++++++++
56
target/arm: Add ARM_FEATURE_V8_RDM
93
target/arm/translate-sve.c | 393 ++++++++++---
57
target/arm: Refactor disas_simd_indexed decode
94
target/arm/translate-vfp.c | 12 +
58
target/arm: Refactor disas_simd_indexed size checks
95
target/arm/translate.c | 2 +
59
target/arm: Decode aa64 armv8.1 scalar three same extra
96
target/arm/vec_helper.c | 24 +
60
target/arm: Decode aa64 armv8.1 three same extra
97
target/arm/meson.build | 3 +
61
target/arm: Decode aa64 armv8.1 scalar/vector x indexed element
98
28 files changed, 2821 insertions(+), 135 deletions(-)
62
target/arm: Decode aa32 armv8.1 three same
99
create mode 100644 target/arm/sme-fa64.decode
63
target/arm: Decode aa32 armv8.1 two reg and a scalar
100
create mode 100644 target/arm/sme.decode
64
target/arm: Enable ARM_FEATURE_V8_RDM
101
create mode 100644 target/arm/translate-sme.c
65
target/arm: Add ARM_FEATURE_V8_FCMA
66
target/arm: Decode aa64 armv8.3 fcadd
67
target/arm: Decode aa64 armv8.3 fcmla
68
target/arm: Decode aa32 armv8.3 3-same
69
target/arm: Decode aa32 armv8.3 2-reg-index
70
target/arm: Decode t32 simd 3reg and 2reg_scalar extension
71
target/arm: Enable ARM_FEATURE_V8_FCMA
72
73
hw/arm/Makefile.objs | 2 +
74
hw/core/Makefile.objs | 1 +
75
hw/misc/Makefile.objs | 4 +
76
hw/timer/Makefile.objs | 1 +
77
target/arm/Makefile.objs | 2 +-
78
include/hw/arm/armv7m.h | 5 +
79
include/hw/arm/iotkit.h | 109 ++++++
80
include/hw/arm/xlnx-zynqmp.h | 2 +
81
include/hw/core/split-irq.h | 57 +++
82
include/hw/irq.h | 4 +-
83
include/hw/loader.h | 12 +-
84
include/hw/misc/iotkit-secctl.h | 103 ++++++
85
include/hw/misc/mps2-fpgaio.h | 43 +++
86
include/hw/misc/tz-ppc.h | 101 ++++++
87
include/hw/misc/unimp.h | 10 +
88
include/hw/or-irq.h | 5 +
89
include/hw/qdev-core.h | 30 +-
90
include/hw/timer/xlnx-zynqmp-rtc.h | 86 +++++
91
target/arm/cpu.h | 8 +
92
target/arm/helper.h | 31 ++
93
target/arm/idau.h | 61 ++++
94
hw/arm/armv7m.c | 35 +-
95
hw/arm/boot.c | 119 ++++---
96
hw/arm/iotkit.c | 598 +++++++++++++++++++++++++++++++
97
hw/arm/mps2-tz.c | 503 ++++++++++++++++++++++++++
98
hw/arm/xlnx-zynqmp.c | 14 +
99
hw/core/loader.c | 8 +-
100
hw/core/qdev.c | 8 +-
101
hw/core/split-irq.c | 89 +++++
102
hw/misc/iotkit-secctl.c | 704 +++++++++++++++++++++++++++++++++++++
103
hw/misc/mps2-fpgaio.c | 176 ++++++++++
104
hw/misc/tz-ppc.c | 302 ++++++++++++++++
105
hw/misc/unimp.c | 10 -
106
hw/timer/xlnx-zynqmp-rtc.c | 272 ++++++++++++++
107
linux-user/elfload.c | 2 +
108
target/arm/cpu.c | 66 +++-
109
target/arm/cpu64.c | 2 +
110
target/arm/helper.c | 28 +-
111
target/arm/translate-a64.c | 514 +++++++++++++++++++++------
112
target/arm/translate.c | 275 +++++++++++++--
113
target/arm/vec_helper.c | 429 ++++++++++++++++++++++
114
default-configs/arm-softmmu.mak | 5 +
115
hw/misc/trace-events | 24 ++
116
hw/timer/trace-events | 3 +
117
scripts/decodetree.py | 5 +-
118
45 files changed, 4668 insertions(+), 200 deletions(-)
119
create mode 100644 include/hw/arm/iotkit.h
120
create mode 100644 include/hw/core/split-irq.h
121
create mode 100644 include/hw/misc/iotkit-secctl.h
122
create mode 100644 include/hw/misc/mps2-fpgaio.h
123
create mode 100644 include/hw/misc/tz-ppc.h
124
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
125
create mode 100644 target/arm/idau.h
126
create mode 100644 hw/arm/iotkit.c
127
create mode 100644 hw/arm/mps2-tz.c
128
create mode 100644 hw/core/split-irq.c
129
create mode 100644 hw/misc/iotkit-secctl.c
130
create mode 100644 hw/misc/mps2-fpgaio.c
131
create mode 100644 hw/misc/tz-ppc.c
132
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
133
create mode 100644 target/arm/vec_helper.c
134
diff view generated by jsdifflib
1
The Cortex-M33 allows the system to specify the reset value of the
1
From: Richard Henderson <richard.henderson@linaro.org>
2
secure Vector Table Offset Register (VTOR) by asserting config
3
signals. In particular, guest images for the MPS2 AN505 board rely
4
on the MPS2's initial VTOR being correct for that board.
5
Implement a QEMU property so board and SoC code can set the reset
6
value to the correct value.
7
2
3
Dump SVCR, plus use the correct access check for Streaming Mode.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220708151540.18136-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-7-peter.maydell@linaro.org
11
---
9
---
12
target/arm/cpu.h | 3 +++
10
target/arm/cpu.c | 17 ++++++++++++++++-
13
target/arm/cpu.c | 18 ++++++++++++++----
11
1 file changed, 16 insertions(+), 1 deletion(-)
14
2 files changed, 17 insertions(+), 4 deletions(-)
15
12
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
*/
22
uint32_t psci_conduit;
23
24
+ /* For v8M, initial value of the Secure VTOR */
25
+ uint32_t init_svtor;
26
+
27
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
28
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
29
*/
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
15
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
16
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
17
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
35
uint32_t initial_msp; /* Loaded from 0x0 */
18
int i;
36
uint32_t initial_pc; /* Loaded from 0x4 */
19
int el = arm_current_el(env);
37
uint8_t *rom;
20
const char *ns_status;
38
+ uint32_t vecbase;
21
+ bool sve;
39
22
40
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
23
qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
41
env->v7m.secure = true;
24
for (i = 0; i < 32; i++) {
42
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
43
/* Unlike A/R profile, M profile defines the reset LR value */
26
el,
44
env->regs[14] = 0xffffffff;
27
psr & PSTATE_SP ? 'h' : 't');
45
28
46
- /* Load the initial SP and PC from the vector table at address 0 */
29
+ if (cpu_isar_feature(aa64_sme, cpu)) {
47
- rom = rom_ptr(0);
30
+ qemu_fprintf(f, " SVCR=%08" PRIx64 " %c%c",
48
+ env->v7m.vecbase[M_REG_S] = cpu->init_svtor & 0xffffff80;
31
+ env->svcr,
32
+ (FIELD_EX64(env->svcr, SVCR, ZA) ? 'Z' : '-'),
33
+ (FIELD_EX64(env->svcr, SVCR, SM) ? 'S' : '-'));
34
+ }
35
if (cpu_isar_feature(aa64_bti, cpu)) {
36
qemu_fprintf(f, " BTYPE=%d", (psr & PSTATE_BTYPE) >> 10);
37
}
38
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
39
qemu_fprintf(f, " FPCR=%08x FPSR=%08x\n",
40
vfp_get_fpcr(env), vfp_get_fpsr(env));
41
42
- if (cpu_isar_feature(aa64_sve, cpu) && sve_exception_el(env, el) == 0) {
43
+ if (cpu_isar_feature(aa64_sme, cpu) && FIELD_EX64(env->svcr, SVCR, SM)) {
44
+ sve = sme_exception_el(env, el) == 0;
45
+ } else if (cpu_isar_feature(aa64_sve, cpu)) {
46
+ sve = sve_exception_el(env, el) == 0;
47
+ } else {
48
+ sve = false;
49
+ }
49
+
50
+
50
+ /* Load the initial SP and PC from offset 0 and 4 in the vector table */
51
+ if (sve) {
51
+ vecbase = env->v7m.vecbase[env->v7m.secure];
52
int j, zcr_len = sve_vqm1_for_el(env, el);
52
+ rom = rom_ptr(vecbase);
53
53
if (rom) {
54
for (i = 0; i <= FFR_PRED_NUM; i++) {
54
/* Address zero is covered by ROM which hasn't yet been
55
* copied into physical memory.
56
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
57
* it got copied into memory. In the latter case, rom_ptr
58
* will return a NULL pointer and we should use ldl_phys instead.
59
*/
60
- initial_msp = ldl_phys(s->as, 0);
61
- initial_pc = ldl_phys(s->as, 4);
62
+ initial_msp = ldl_phys(s->as, vecbase);
63
+ initial_pc = ldl_phys(s->as, vecbase + 4);
64
}
65
66
env->regs[13] = initial_msp & 0xFFFFFFFC;
67
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_pmsav7_dregion_property =
68
pmsav7_dregion,
69
qdev_prop_uint32, uint32_t);
70
71
+/* M profile: initial value of the Secure VTOR */
72
+static Property arm_cpu_initsvtor_property =
73
+ DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
74
+
75
static void arm_cpu_post_init(Object *obj)
76
{
77
ARMCPU *cpu = ARM_CPU(obj);
78
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
79
qdev_prop_allow_set_link_before_realize,
80
OBJ_PROP_LINK_UNREF_ON_RELEASE,
81
&error_abort);
82
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
83
+ &error_abort);
84
}
85
86
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
87
--
55
--
88
2.16.2
56
2.25.1
89
90
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
This includes the build rules for the decoder, and the
4
new file for translation, but excludes any instructions.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-5-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-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
---
10
---
8
target/arm/Makefile.objs | 2 +-
11
target/arm/translate-a64.h | 1 +
9
target/arm/helper.h | 4 ++
12
target/arm/sme.decode | 20 ++++++++++++++++++++
10
target/arm/translate-a64.c | 84 ++++++++++++++++++++++++++++++++++
13
target/arm/translate-a64.c | 7 ++++++-
11
target/arm/vec_helper.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
14
target/arm/translate-sme.c | 35 +++++++++++++++++++++++++++++++++++
12
4 files changed, 198 insertions(+), 1 deletion(-)
15
target/arm/meson.build | 2 ++
13
create mode 100644 target/arm/vec_helper.c
16
5 files changed, 64 insertions(+), 1 deletion(-)
17
create mode 100644 target/arm/sme.decode
18
create mode 100644 target/arm/translate-sme.c
14
19
15
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
20
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/Makefile.objs
22
--- a/target/arm/translate-a64.h
18
+++ b/target/arm/Makefile.objs
23
+++ b/target/arm/translate-a64.h
19
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
24
@@ -XXX,XX +XXX,XX @@ static inline int pred_gvec_reg_size(DisasContext *s)
20
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
25
}
21
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
26
22
obj-y += translate.o op_helper.o helper.o cpu.o
27
bool disas_sve(DisasContext *, uint32_t);
23
-obj-y += neon_helper.o iwmmxt_helper.o
28
+bool disas_sme(DisasContext *, uint32_t);
24
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
29
25
obj-y += gdbstub.o
30
void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
26
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
31
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
27
obj-y += crypto_helper.o
32
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
28
diff --git a/target/arm/helper.h b/target/arm/helper.h
33
new file mode 100644
29
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX
30
--- a/target/arm/helper.h
35
--- /dev/null
31
+++ b/target/arm/helper.h
36
+++ b/target/arm/sme.decode
32
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_1(neon_rbit_u8, TCG_CALL_NO_RWG_SE, i32, i32)
37
@@ -XXX,XX +XXX,XX @@
33
38
+# AArch64 SME instruction descriptions
34
DEF_HELPER_3(neon_qdmulh_s16, i32, env, i32, i32)
39
+#
35
DEF_HELPER_3(neon_qrdmulh_s16, i32, env, i32, i32)
40
+# Copyright (c) 2022 Linaro, Ltd
36
+DEF_HELPER_4(neon_qrdmlah_s16, i32, env, i32, i32, i32)
41
+#
37
+DEF_HELPER_4(neon_qrdmlsh_s16, i32, env, i32, i32, i32)
42
+# This library is free software; you can redistribute it and/or
38
DEF_HELPER_3(neon_qdmulh_s32, i32, env, i32, i32)
43
+# modify it under the terms of the GNU Lesser General Public
39
DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
44
+# License as published by the Free Software Foundation; either
40
+DEF_HELPER_4(neon_qrdmlah_s32, i32, env, s32, s32, s32)
45
+# version 2.1 of the License, or (at your option) any later version.
41
+DEF_HELPER_4(neon_qrdmlsh_s32, i32, env, s32, s32, s32)
46
+#
42
47
+# This library is distributed in the hope that it will be useful,
43
DEF_HELPER_1(neon_narrow_u8, i32, i64)
48
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
44
DEF_HELPER_1(neon_narrow_u16, i32, i64)
49
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
50
+# Lesser General Public License for more details.
51
+#
52
+# You should have received a copy of the GNU Lesser General Public
53
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
54
+
55
+#
56
+# This file is processed by scripts/decodetree.py
57
+#
45
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
58
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
46
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate-a64.c
60
--- a/target/arm/translate-a64.c
48
+++ b/target/arm/translate-a64.c
61
+++ b/target/arm/translate-a64.c
49
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
62
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
50
tcg_temp_free_ptr(fpst);
63
}
51
}
64
52
65
switch (extract32(insn, 25, 4)) {
53
+/* AdvSIMD scalar three same extra
66
- case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
54
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
67
+ case 0x0:
55
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
68
+ if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
56
+ * | 0 1 | U | 1 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
57
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
58
+ */
59
+static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
60
+ uint32_t insn)
61
+{
62
+ int rd = extract32(insn, 0, 5);
63
+ int rn = extract32(insn, 5, 5);
64
+ int opcode = extract32(insn, 11, 4);
65
+ int rm = extract32(insn, 16, 5);
66
+ int size = extract32(insn, 22, 2);
67
+ bool u = extract32(insn, 29, 1);
68
+ TCGv_i32 ele1, ele2, ele3;
69
+ TCGv_i64 res;
70
+ int feature;
71
+
72
+ switch (u * 16 + opcode) {
73
+ case 0x10: /* SQRDMLAH (vector) */
74
+ case 0x11: /* SQRDMLSH (vector) */
75
+ if (size != 1 && size != 2) {
76
+ unallocated_encoding(s);
69
+ unallocated_encoding(s);
77
+ return;
78
+ }
79
+ feature = ARM_FEATURE_V8_RDM;
80
+ break;
81
+ default:
82
+ unallocated_encoding(s);
83
+ return;
84
+ }
85
+ if (!arm_dc_feature(s, feature)) {
86
+ unallocated_encoding(s);
87
+ return;
88
+ }
89
+ if (!fp_access_check(s)) {
90
+ return;
91
+ }
92
+
93
+ /* Do a single operation on the lowest element in the vector.
94
+ * We use the standard Neon helpers and rely on 0 OP 0 == 0
95
+ * with no side effects for all these operations.
96
+ * OPTME: special-purpose helpers would avoid doing some
97
+ * unnecessary work in the helper for the 16 bit cases.
98
+ */
99
+ ele1 = tcg_temp_new_i32();
100
+ ele2 = tcg_temp_new_i32();
101
+ ele3 = tcg_temp_new_i32();
102
+
103
+ read_vec_element_i32(s, ele1, rn, 0, size);
104
+ read_vec_element_i32(s, ele2, rm, 0, size);
105
+ read_vec_element_i32(s, ele3, rd, 0, size);
106
+
107
+ switch (opcode) {
108
+ case 0x0: /* SQRDMLAH */
109
+ if (size == 1) {
110
+ gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
111
+ } else {
112
+ gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
113
+ }
70
+ }
114
+ break;
71
+ break;
115
+ case 0x1: /* SQRDMLSH */
72
+ case 0x1: case 0x3: /* UNALLOCATED */
116
+ if (size == 1) {
73
unallocated_encoding(s);
117
+ gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
74
break;
118
+ } else {
75
case 0x2:
119
+ gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
76
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
120
+ }
121
+ break;
122
+ default:
123
+ g_assert_not_reached();
124
+ }
125
+ tcg_temp_free_i32(ele1);
126
+ tcg_temp_free_i32(ele2);
127
+
128
+ res = tcg_temp_new_i64();
129
+ tcg_gen_extu_i32_i64(res, ele3);
130
+ tcg_temp_free_i32(ele3);
131
+
132
+ write_fp_dreg(s, rd, res);
133
+ tcg_temp_free_i64(res);
134
+}
135
+
136
static void handle_2misc_64(DisasContext *s, int opcode, bool u,
137
TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
138
TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
139
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
140
{ 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
141
{ 0x2e000000, 0xbf208400, disas_simd_ext },
142
{ 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
143
+ { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
144
{ 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
145
{ 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
146
{ 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
147
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
148
new file mode 100644
77
new file mode 100644
149
index XXXXXXX..XXXXXXX
78
index XXXXXXX..XXXXXXX
150
--- /dev/null
79
--- /dev/null
151
+++ b/target/arm/vec_helper.c
80
+++ b/target/arm/translate-sme.c
152
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
153
+/*
82
+/*
154
+ * ARM AdvSIMD / SVE Vector Operations
83
+ * AArch64 SME translation
155
+ *
84
+ *
156
+ * Copyright (c) 2018 Linaro
85
+ * Copyright (c) 2022 Linaro, Ltd
157
+ *
86
+ *
158
+ * This library is free software; you can redistribute it and/or
87
+ * This library is free software; you can redistribute it and/or
159
+ * modify it under the terms of the GNU Lesser General Public
88
+ * modify it under the terms of the GNU Lesser General Public
160
+ * License as published by the Free Software Foundation; either
89
+ * License as published by the Free Software Foundation; either
161
+ * version 2 of the License, or (at your option) any later version.
90
+ * version 2.1 of the License, or (at your option) any later version.
162
+ *
91
+ *
163
+ * This library is distributed in the hope that it will be useful,
92
+ * This library is distributed in the hope that it will be useful,
164
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
93
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
165
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
94
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
166
+ * Lesser General Public License for more details.
95
+ * Lesser General Public License for more details.
...
...
169
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
98
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
170
+ */
99
+ */
171
+
100
+
172
+#include "qemu/osdep.h"
101
+#include "qemu/osdep.h"
173
+#include "cpu.h"
102
+#include "cpu.h"
174
+#include "exec/exec-all.h"
103
+#include "tcg/tcg-op.h"
175
+#include "exec/helper-proto.h"
104
+#include "tcg/tcg-op-gvec.h"
176
+#include "tcg/tcg-gvec-desc.h"
105
+#include "tcg/tcg-gvec-desc.h"
106
+#include "translate.h"
107
+#include "exec/helper-gen.h"
108
+#include "translate-a64.h"
109
+#include "fpu/softfloat.h"
177
+
110
+
178
+
111
+
179
+#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
112
+/*
113
+ * Include the generated decoder.
114
+ */
180
+
115
+
181
+/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
116
+#include "decode-sme.c.inc"
182
+static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
117
diff --git a/target/arm/meson.build b/target/arm/meson.build
183
+ int16_t src2, int16_t src3)
118
index XXXXXXX..XXXXXXX 100644
184
+{
119
--- a/target/arm/meson.build
185
+ /* Simplify:
120
+++ b/target/arm/meson.build
186
+ * = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
121
@@ -XXX,XX +XXX,XX @@
187
+ * = ((a3 << 15) + (e1 * e2) + (1 << 14)) >> 15
122
gen = [
188
+ */
123
decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
189
+ int32_t ret = (int32_t)src1 * src2;
124
+ decodetree.process('sme.decode', extra_args: '--decode=disas_sme'),
190
+ ret = ((int32_t)src3 << 15) + ret + (1 << 14);
125
decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
191
+ ret >>= 15;
126
decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
192
+ if (ret != (int16_t)ret) {
127
decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
193
+ SET_QC();
128
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
194
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
129
'sme_helper.c',
195
+ }
130
'translate-a64.c',
196
+ return ret;
131
'translate-sve.c',
197
+}
132
+ 'translate-sme.c',
198
+
133
))
199
+uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
134
200
+ uint32_t src2, uint32_t src3)
135
arm_softmmu_ss = ss.source_set()
201
+{
202
+ uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
203
+ uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
204
+ return deposit32(e1, 16, 16, e2);
205
+}
206
+
207
+/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
208
+static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
209
+ int16_t src2, int16_t src3)
210
+{
211
+ /* Similarly, using subtraction:
212
+ * = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
213
+ * = ((a3 << 15) - (e1 * e2) + (1 << 14)) >> 15
214
+ */
215
+ int32_t ret = (int32_t)src1 * src2;
216
+ ret = ((int32_t)src3 << 15) - ret + (1 << 14);
217
+ ret >>= 15;
218
+ if (ret != (int16_t)ret) {
219
+ SET_QC();
220
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
221
+ }
222
+ return ret;
223
+}
224
+
225
+uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
226
+ uint32_t src2, uint32_t src3)
227
+{
228
+ uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
229
+ uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
230
+ return deposit32(e1, 16, 16, e2);
231
+}
232
+
233
+/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
234
+uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
235
+ int32_t src2, int32_t src3)
236
+{
237
+ /* Simplify similarly to int_qrdmlah_s16 above. */
238
+ int64_t ret = (int64_t)src1 * src2;
239
+ ret = ((int64_t)src3 << 31) + ret + (1 << 30);
240
+ ret >>= 31;
241
+ if (ret != (int32_t)ret) {
242
+ SET_QC();
243
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
244
+ }
245
+ return ret;
246
+}
247
+
248
+/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
249
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
250
+ int32_t src2, int32_t src3)
251
+{
252
+ /* Simplify similarly to int_qrdmlsh_s16 above. */
253
+ int64_t ret = (int64_t)src1 * src2;
254
+ ret = ((int64_t)src3 << 31) - ret + (1 << 30);
255
+ ret >>= 31;
256
+ if (ret != (int32_t)ret) {
257
+ SET_QC();
258
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
259
+ }
260
+ return ret;
261
+}
262
--
136
--
263
2.16.2
137
2.25.1
264
265
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not enabled anywhere yet.
3
This new behaviour is in the ARM pseudocode function
4
4
AArch64.CheckFPAdvSIMDEnabled, which applies to AArch32
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
via AArch32.CheckAdvSIMDOrFPEnabled when the EL to which
6
the trap would be delivered is in AArch64 mode.
7
8
Given that ARMv9 drops support for AArch32 outside EL0, the trap EL
9
detection ought to be trivially true, but the pseudocode still contains
10
a number of conditions, and QEMU has not yet committed to dropping A32
11
support for EL[12] when v9 features are present.
12
13
Since the computation of SME_TRAP_NONSTREAMING is necessarily different
14
for the two modes, we might as well preserve bits within TBFLAG_ANY and
15
allocate separate bits within TBFLAG_A32 and TBFLAG_A64 instead.
16
17
Note that DDI0616A.a has typos for bits [22:21] of LD1RO in the table
18
of instructions illegal in streaming mode.
19
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
21
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180228193125.20577-11-richard.henderson@linaro.org
22
Message-id: 20220708151540.18136-4-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
24
---
10
target/arm/cpu.h | 1 +
25
target/arm/cpu.h | 7 +++
11
linux-user/elfload.c | 1 +
26
target/arm/translate.h | 4 ++
12
2 files changed, 2 insertions(+)
27
target/arm/sme-fa64.decode | 90 ++++++++++++++++++++++++++++++++++++++
28
target/arm/helper.c | 41 +++++++++++++++++
29
target/arm/translate-a64.c | 40 ++++++++++++++++-
30
target/arm/translate-vfp.c | 12 +++++
31
target/arm/translate.c | 2 +
32
target/arm/meson.build | 1 +
33
8 files changed, 195 insertions(+), 2 deletions(-)
34
create mode 100644 target/arm/sme-fa64.decode
13
35
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
38
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
39
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ enum arm_features {
40
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, HSTR_ACTIVE, 9, 1)
19
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
41
* the same thing as the current security state of the processor!
20
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
42
*/
21
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
43
FIELD(TBFLAG_A32, NS, 10, 1)
22
+ ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
44
+/*
23
};
45
+ * Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not.
24
46
+ * This requires an SME trap from AArch32 mode when using NEON.
25
static inline int arm_feature(CPUARMState *env, int feature)
47
+ */
26
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
48
+FIELD(TBFLAG_A32, SME_TRAP_NONSTREAMING, 11, 1)
27
index XXXXXXX..XXXXXXX 100644
49
28
--- a/linux-user/elfload.c
50
/*
29
+++ b/linux-user/elfload.c
51
* Bit usage when in AArch32 state, for M-profile only.
30
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
52
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, SMEEXC_EL, 20, 2)
31
GET_FEATURE(ARM_FEATURE_V8_FP16,
53
FIELD(TBFLAG_A64, PSTATE_SM, 22, 1)
32
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
54
FIELD(TBFLAG_A64, PSTATE_ZA, 23, 1)
33
GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
55
FIELD(TBFLAG_A64, SVL, 24, 4)
34
+ GET_FEATURE(ARM_FEATURE_V8_FCMA, ARM_HWCAP_A64_FCMA);
56
+/* Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not. */
35
#undef GET_FEATURE
57
+FIELD(TBFLAG_A64, SME_TRAP_NONSTREAMING, 28, 1)
36
58
37
return hwcaps;
59
/*
60
* Helpers for using the above.
61
diff --git a/target/arm/translate.h b/target/arm/translate.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/translate.h
64
+++ b/target/arm/translate.h
65
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
66
bool pstate_sm;
67
/* True if PSTATE.ZA is set. */
68
bool pstate_za;
69
+ /* True if non-streaming insns should raise an SME Streaming exception. */
70
+ bool sme_trap_nonstreaming;
71
+ /* True if the current instruction is non-streaming. */
72
+ bool is_nonstreaming;
73
/* True if MVE insns are definitely not predicated by VPR or LTPSIZE */
74
bool mve_no_pred;
75
/*
76
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
77
new file mode 100644
78
index XXXXXXX..XXXXXXX
79
--- /dev/null
80
+++ b/target/arm/sme-fa64.decode
81
@@ -XXX,XX +XXX,XX @@
82
+# AArch64 SME allowed instruction decoding
83
+#
84
+# Copyright (c) 2022 Linaro, Ltd
85
+#
86
+# This library is free software; you can redistribute it and/or
87
+# modify it under the terms of the GNU Lesser General Public
88
+# License as published by the Free Software Foundation; either
89
+# version 2.1 of the License, or (at your option) any later version.
90
+#
91
+# This library is distributed in the hope that it will be useful,
92
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
93
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
94
+# Lesser General Public License for more details.
95
+#
96
+# You should have received a copy of the GNU Lesser General Public
97
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
98
+
99
+#
100
+# This file is processed by scripts/decodetree.py
101
+#
102
+
103
+# These patterns are taken from Appendix E1.1 of DDI0616 A.a,
104
+# Arm Architecture Reference Manual Supplement,
105
+# The Scalable Matrix Extension (SME), for Armv9-A
106
+
107
+{
108
+ [
109
+ OK 0-00 1110 0000 0001 0010 11-- ---- ---- # SMOV W|Xd,Vn.B[0]
110
+ OK 0-00 1110 0000 0010 0010 11-- ---- ---- # SMOV W|Xd,Vn.H[0]
111
+ OK 0100 1110 0000 0100 0010 11-- ---- ---- # SMOV Xd,Vn.S[0]
112
+ OK 0000 1110 0000 0001 0011 11-- ---- ---- # UMOV Wd,Vn.B[0]
113
+ OK 0000 1110 0000 0010 0011 11-- ---- ---- # UMOV Wd,Vn.H[0]
114
+ OK 0000 1110 0000 0100 0011 11-- ---- ---- # UMOV Wd,Vn.S[0]
115
+ OK 0100 1110 0000 1000 0011 11-- ---- ---- # UMOV Xd,Vn.D[0]
116
+ ]
117
+ FAIL 0--0 111- ---- ---- ---- ---- ---- ---- # Advanced SIMD vector operations
118
+}
119
+
120
+{
121
+ [
122
+ OK 0101 1110 --1- ---- 11-1 11-- ---- ---- # FMULX/FRECPS/FRSQRTS (scalar)
123
+ OK 0101 1110 -10- ---- 00-1 11-- ---- ---- # FMULX/FRECPS/FRSQRTS (scalar, FP16)
124
+ OK 01-1 1110 1-10 0001 11-1 10-- ---- ---- # FRECPE/FRSQRTE/FRECPX (scalar)
125
+ OK 01-1 1110 1111 1001 11-1 10-- ---- ---- # FRECPE/FRSQRTE/FRECPX (scalar, FP16)
126
+ ]
127
+ FAIL 01-1 111- ---- ---- ---- ---- ---- ---- # Advanced SIMD single-element operations
128
+}
129
+
130
+FAIL 0-00 110- ---- ---- ---- ---- ---- ---- # Advanced SIMD structure load/store
131
+FAIL 1100 1110 ---- ---- ---- ---- ---- ---- # Advanced SIMD cryptography extensions
132
+FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
133
+
134
+# These are the "avoidance of doubt" final table of Illegal Advanced SIMD instructions
135
+# We don't actually need to include these, as the default is OK.
136
+# -001 111- ---- ---- ---- ---- ---- ---- # Scalar floating-point operations
137
+# --10 110- ---- ---- ---- ---- ---- ---- # Load/store pair of FP registers
138
+# --01 1100 ---- ---- ---- ---- ---- ---- # Load FP register (PC-relative literal)
139
+# --11 1100 --0- ---- ---- ---- ---- ---- # Load/store FP register (unscaled imm)
140
+# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
141
+# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
142
+
143
+FAIL 0000 0100 --1- ---- 1010 ---- ---- ---- # ADR
144
+FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
145
+FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
146
+FAIL 0010 0101 --01 100- 1111 000- ---0 ---- # RDFFR, RDFFRS
147
+FAIL 0010 0101 --10 1--- 1001 ---- ---- ---- # WRFFR, SETFFR
148
+FAIL 0100 0101 --0- ---- 1011 ---- ---- ---- # BDEP, BEXT, BGRP
149
+FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
150
+FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
151
+FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
152
+FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
153
+FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
154
+FAIL 0100 0101 --0- ---- 1001 10-- ---- ---- # SMMLA, UMMLA, USMMLA
155
+FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
156
+FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
157
+FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
158
+FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
159
+FAIL 1000 010- -01- ---- 1--- ---- ---- ---- # SVE 32-bit gather load (vector+imm)
160
+FAIL 1000 0100 0-0- ---- 0--- ---- ---- ---- # SVE 32-bit gather load byte (scalar+vector)
161
+FAIL 1000 0100 1--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load half (scalar+vector)
162
+FAIL 1000 0101 0--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load word (scalar+vector)
163
+FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
164
+FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
165
+FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
166
+FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
167
+FAIL 1100 010- ---- ---- ---- ---- ---- ---- # SVE 64-bit gather load/prefetch
168
+FAIL 1110 010- -00- ---- 001- ---- ---- ---- # SVE2 64-bit scatter NT store (vector+scalar)
169
+FAIL 1110 010- -10- ---- 001- ---- ---- ---- # SVE2 32-bit scatter NT store (vector+scalar)
170
+FAIL 1110 010- ---- ---- 1-0- ---- ---- ---- # SVE scatter store (scalar+32-bit vector)
171
+FAIL 1110 010- ---- ---- 101- ---- ---- ---- # SVE scatter store (misc)
172
diff --git a/target/arm/helper.c b/target/arm/helper.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/target/arm/helper.c
175
+++ b/target/arm/helper.c
176
@@ -XXX,XX +XXX,XX @@ int sme_exception_el(CPUARMState *env, int el)
177
return 0;
178
}
179
180
+/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */
181
+static bool sme_fa64(CPUARMState *env, int el)
182
+{
183
+ if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) {
184
+ return false;
185
+ }
186
+
187
+ if (el <= 1 && !el_is_in_host(env, el)) {
188
+ if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) {
189
+ return false;
190
+ }
191
+ }
192
+ if (el <= 2 && arm_is_el2_enabled(env)) {
193
+ if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) {
194
+ return false;
195
+ }
196
+ }
197
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
198
+ if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) {
199
+ return false;
200
+ }
201
+ }
202
+
203
+ return true;
204
+}
205
+
206
/*
207
* Given that SVE is enabled, return the vector length for EL.
208
*/
209
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
210
DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
211
}
212
213
+ /*
214
+ * The SME exception we are testing for is raised via
215
+ * AArch64.CheckFPAdvSIMDEnabled(), as called from
216
+ * AArch32.CheckAdvSIMDOrFPEnabled().
217
+ */
218
+ if (el == 0
219
+ && FIELD_EX64(env->svcr, SVCR, SM)
220
+ && (!arm_is_el2_enabled(env)
221
+ || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE)))
222
+ && arm_el_is_aa64(env, 1)
223
+ && !sme_fa64(env, el)) {
224
+ DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1);
225
+ }
226
+
227
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
228
}
229
230
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
231
}
232
if (FIELD_EX64(env->svcr, SVCR, SM)) {
233
DP_TBFLAG_A64(flags, PSTATE_SM, 1);
234
+ DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el));
235
}
236
DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA));
237
}
238
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
239
index XXXXXXX..XXXXXXX 100644
240
--- a/target/arm/translate-a64.c
241
+++ b/target/arm/translate-a64.c
242
@@ -XXX,XX +XXX,XX @@ static void do_vec_ld(DisasContext *s, int destidx, int element,
243
* unallocated-encoding checks (otherwise the syndrome information
244
* for the resulting exception will be incorrect).
245
*/
246
-static bool fp_access_check(DisasContext *s)
247
+static bool fp_access_check_only(DisasContext *s)
248
{
249
if (s->fp_excp_el) {
250
assert(!s->fp_access_checked);
251
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
252
return true;
253
}
254
255
+static bool fp_access_check(DisasContext *s)
256
+{
257
+ if (!fp_access_check_only(s)) {
258
+ return false;
259
+ }
260
+ if (s->sme_trap_nonstreaming && s->is_nonstreaming) {
261
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
262
+ syn_smetrap(SME_ET_Streaming, false));
263
+ return false;
264
+ }
265
+ return true;
266
+}
267
+
268
/* Check that SVE access is enabled. If it is, return true.
269
* If not, emit code to generate an appropriate exception and return false.
270
*/
271
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
272
default:
273
g_assert_not_reached();
274
}
275
- if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
276
+ if ((ri->type & ARM_CP_FPU) && !fp_access_check_only(s)) {
277
return;
278
} else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
279
return;
280
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
281
}
282
}
283
284
+/*
285
+ * Include the generated SME FA64 decoder.
286
+ */
287
+
288
+#include "decode-sme-fa64.c.inc"
289
+
290
+static bool trans_OK(DisasContext *s, arg_OK *a)
291
+{
292
+ return true;
293
+}
294
+
295
+static bool trans_FAIL(DisasContext *s, arg_OK *a)
296
+{
297
+ s->is_nonstreaming = true;
298
+ return true;
299
+}
300
+
301
/**
302
* is_guarded_page:
303
* @env: The cpu environment
304
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
305
dc->mte_active[1] = EX_TBFLAG_A64(tb_flags, MTE0_ACTIVE);
306
dc->pstate_sm = EX_TBFLAG_A64(tb_flags, PSTATE_SM);
307
dc->pstate_za = EX_TBFLAG_A64(tb_flags, PSTATE_ZA);
308
+ dc->sme_trap_nonstreaming = EX_TBFLAG_A64(tb_flags, SME_TRAP_NONSTREAMING);
309
dc->vec_len = 0;
310
dc->vec_stride = 0;
311
dc->cp_regs = arm_cpu->cp_regs;
312
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
313
}
314
}
315
316
+ s->is_nonstreaming = false;
317
+ if (s->sme_trap_nonstreaming) {
318
+ disas_sme_fa64(s, insn);
319
+ }
320
+
321
switch (extract32(insn, 25, 4)) {
322
case 0x0:
323
if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
324
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
325
index XXXXXXX..XXXXXXX 100644
326
--- a/target/arm/translate-vfp.c
327
+++ b/target/arm/translate-vfp.c
328
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
329
return false;
330
}
331
332
+ /*
333
+ * Note that rebuild_hflags_a32 has already accounted for being in EL0
334
+ * and the higher EL in A64 mode, etc. Unlike A64 mode, there do not
335
+ * appear to be any insns which touch VFP which are allowed.
336
+ */
337
+ if (s->sme_trap_nonstreaming) {
338
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
339
+ syn_smetrap(SME_ET_Streaming,
340
+ s->base.pc_next - s->pc_curr == 2));
341
+ return false;
342
+ }
343
+
344
if (!s->vfp_enabled && !ignore_vfp_enabled) {
345
assert(!arm_dc_feature(s, ARM_FEATURE_M));
346
unallocated_encoding(s);
347
diff --git a/target/arm/translate.c b/target/arm/translate.c
348
index XXXXXXX..XXXXXXX 100644
349
--- a/target/arm/translate.c
350
+++ b/target/arm/translate.c
351
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
352
dc->vec_len = EX_TBFLAG_A32(tb_flags, VECLEN);
353
dc->vec_stride = EX_TBFLAG_A32(tb_flags, VECSTRIDE);
354
}
355
+ dc->sme_trap_nonstreaming =
356
+ EX_TBFLAG_A32(tb_flags, SME_TRAP_NONSTREAMING);
357
}
358
dc->cp_regs = cpu->cp_regs;
359
dc->features = env->features;
360
diff --git a/target/arm/meson.build b/target/arm/meson.build
361
index XXXXXXX..XXXXXXX 100644
362
--- a/target/arm/meson.build
363
+++ b/target/arm/meson.build
364
@@ -XXX,XX +XXX,XX @@
365
gen = [
366
decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
367
decodetree.process('sme.decode', extra_args: '--decode=disas_sme'),
368
+ decodetree.process('sme-fa64.decode', extra_args: '--static-decode=disas_sme_fa64'),
369
decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
370
decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
371
decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
38
--
372
--
39
2.16.2
373
2.25.1
40
41
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The integer size check was already outside of the opcode switch;
3
Mark ADR as a non-streaming instruction, which should trap
4
move the floating-point size check outside as well. Unify the
4
if full a64 support is not enabled in streaming mode.
5
size vs index adjustment between fp and integer paths.
6
5
6
Removing entries from sme-fa64.decode is an easy way to see
7
what remains to be done.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20220708151540.18136-5-richard.henderson@linaro.org
9
Message-id: 20180228193125.20577-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
target/arm/translate-a64.c | 65 +++++++++++++++++++++++-----------------------
14
target/arm/translate.h | 7 +++++++
13
1 file changed, 32 insertions(+), 33 deletions(-)
15
target/arm/sme-fa64.decode | 1 -
16
target/arm/translate-sve.c | 8 ++++----
17
3 files changed, 11 insertions(+), 5 deletions(-)
14
18
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
19
diff --git a/target/arm/translate.h b/target/arm/translate.h
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
21
--- a/target/arm/translate.h
18
+++ b/target/arm/translate-a64.c
22
+++ b/target/arm/translate.h
19
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
23
@@ -XXX,XX +XXX,XX @@ uint64_t asimd_imm_const(uint32_t imm, int cmode, int op);
20
case 0x05: /* FMLS */
24
static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
21
case 0x09: /* FMUL */
25
{ return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); }
22
case 0x19: /* FMULX */
26
23
- if (size == 1) {
27
+#define TRANS_FEAT_NONSTREAMING(NAME, FEAT, FUNC, ...) \
24
- unallocated_encoding(s);
28
+ static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
25
- return;
29
+ { \
26
- }
30
+ s->is_nonstreaming = true; \
27
is_fp = true;
31
+ return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); \
28
break;
29
default:
30
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
31
if (is_fp) {
32
/* convert insn encoded size to TCGMemOp size */
33
switch (size) {
34
- case 2: /* single precision */
35
- size = MO_32;
36
- index = h << 1 | l;
37
- rm |= (m << 4);
38
- break;
39
- case 3: /* double precision */
40
- size = MO_64;
41
- if (l || !is_q) {
42
+ case 0: /* half-precision */
43
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
44
unallocated_encoding(s);
45
return;
46
}
47
- index = h;
48
- rm |= (m << 4);
49
- break;
50
- case 0: /* half precision */
51
size = MO_16;
52
- index = h << 2 | l << 1 | m;
53
- is_fp16 = true;
54
- if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
55
- break;
56
- }
57
- /* fallthru */
58
- default: /* unallocated */
59
- unallocated_encoding(s);
60
- return;
61
- }
62
- } else {
63
- switch (size) {
64
- case 1:
65
- index = h << 2 | l << 1 | m;
66
break;
67
- case 2:
68
- index = h << 1 | l;
69
- rm |= (m << 4);
70
+ case MO_32: /* single precision */
71
+ case MO_64: /* double precision */
72
break;
73
default:
74
unallocated_encoding(s);
75
return;
76
}
77
+ } else {
78
+ switch (size) {
79
+ case MO_8:
80
+ case MO_64:
81
+ unallocated_encoding(s);
82
+ return;
83
+ }
84
+ }
32
+ }
85
+
33
+
86
+ /* Given TCGMemOp size, adjust register and indexing. */
34
#endif /* TARGET_ARM_TRANSLATE_H */
87
+ switch (size) {
35
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
88
+ case MO_16:
36
index XXXXXXX..XXXXXXX 100644
89
+ index = h << 2 | l << 1 | m;
37
--- a/target/arm/sme-fa64.decode
90
+ break;
38
+++ b/target/arm/sme-fa64.decode
91
+ case MO_32:
39
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
92
+ index = h << 1 | l;
40
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
93
+ rm |= m << 4;
41
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
94
+ break;
42
95
+ case MO_64:
43
-FAIL 0000 0100 --1- ---- 1010 ---- ---- ---- # ADR
96
+ if (l || !is_q) {
44
FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
97
+ unallocated_encoding(s);
45
FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
98
+ return;
46
FAIL 0010 0101 --01 100- 1111 000- ---0 ---- # RDFFR, RDFFRS
99
+ }
47
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
100
+ index = h;
48
index XXXXXXX..XXXXXXX 100644
101
+ rm |= m << 4;
49
--- a/target/arm/translate-sve.c
102
+ break;
50
+++ b/target/arm/translate-sve.c
103
+ default:
51
@@ -XXX,XX +XXX,XX @@ static bool do_adr(DisasContext *s, arg_rrri *a, gen_helper_gvec_3 *fn)
104
+ g_assert_not_reached();
52
return gen_gvec_ool_zzz(s, fn, a->rd, a->rn, a->rm, a->imm);
105
}
53
}
106
54
107
if (!fp_access_check(s)) {
55
-TRANS_FEAT(ADR_p32, aa64_sve, do_adr, a, gen_helper_sve_adr_p32)
56
-TRANS_FEAT(ADR_p64, aa64_sve, do_adr, a, gen_helper_sve_adr_p64)
57
-TRANS_FEAT(ADR_s32, aa64_sve, do_adr, a, gen_helper_sve_adr_s32)
58
-TRANS_FEAT(ADR_u32, aa64_sve, do_adr, a, gen_helper_sve_adr_u32)
59
+TRANS_FEAT_NONSTREAMING(ADR_p32, aa64_sve, do_adr, a, gen_helper_sve_adr_p32)
60
+TRANS_FEAT_NONSTREAMING(ADR_p64, aa64_sve, do_adr, a, gen_helper_sve_adr_p64)
61
+TRANS_FEAT_NONSTREAMING(ADR_s32, aa64_sve, do_adr, a, gen_helper_sve_adr_s32)
62
+TRANS_FEAT_NONSTREAMING(ADR_u32, aa64_sve, do_adr, a, gen_helper_sve_adr_u32)
63
64
/*
65
*** SVE Integer Misc - Unpredicated Group
108
--
66
--
109
2.16.2
67
2.25.1
110
111
diff view generated by jsdifflib
1
Add a function load_ramdisk_as() which behaves like the existing
1
From: Richard Henderson <richard.henderson@linaro.org>
2
load_ramdisk() but allows the caller to specify the AddressSpace
3
to use. This matches the pattern we have already for various
4
other loader functions.
5
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-6-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: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-2-peter.maydell@linaro.org
10
---
10
---
11
include/hw/loader.h | 12 +++++++++++-
11
target/arm/sme-fa64.decode | 2 --
12
hw/core/loader.c | 8 +++++++-
12
target/arm/translate-sve.c | 9 ++++++---
13
2 files changed, 18 insertions(+), 2 deletions(-)
13
2 files changed, 6 insertions(+), 5 deletions(-)
14
14
15
diff --git a/include/hw/loader.h b/include/hw/loader.h
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/loader.h
17
--- a/target/arm/sme-fa64.decode
18
+++ b/include/hw/loader.h
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ int load_uimage(const char *filename, hwaddr *ep,
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
void *translate_opaque);
20
21
21
FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
22
/**
22
FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
23
- * load_ramdisk:
23
-FAIL 0010 0101 --01 100- 1111 000- ---0 ---- # RDFFR, RDFFRS
24
+ * load_ramdisk_as:
24
-FAIL 0010 0101 --10 1--- 1001 ---- ---- ---- # WRFFR, SETFFR
25
* @filename: Path to the ramdisk image
25
FAIL 0100 0101 --0- ---- 1011 ---- ---- ---- # BDEP, BEXT, BGRP
26
* @addr: Memory address to load the ramdisk to
26
FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
27
* @max_sz: Maximum allowed ramdisk size (for non-u-boot ramdisks)
27
FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
28
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
28
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
29
+ * is used if nothing is supplied here.
29
index XXXXXXX..XXXXXXX 100644
30
*
30
--- a/target/arm/translate-sve.c
31
* Load a ramdisk image with U-Boot header to the specified memory
31
+++ b/target/arm/translate-sve.c
32
* address.
32
@@ -XXX,XX +XXX,XX @@ static bool do_predset(DisasContext *s, int esz, int rd, int pat, bool setflag)
33
*
33
TRANS_FEAT(PTRUE, aa64_sve, do_predset, a->esz, a->rd, a->pat, a->s)
34
* Returns the size of the loaded image on success, -1 otherwise.
34
35
*/
35
/* Note pat == 31 is #all, to set all elements. */
36
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
36
-TRANS_FEAT(SETFFR, aa64_sve, do_predset, 0, FFR_PRED_NUM, 31, false)
37
+ AddressSpace *as);
37
+TRANS_FEAT_NONSTREAMING(SETFFR, aa64_sve,
38
+ do_predset, 0, FFR_PRED_NUM, 31, false)
39
40
/* Note pat == 32 is #unimp, to set no elements. */
41
TRANS_FEAT(PFALSE, aa64_sve, do_predset, 0, a->rd, 32, false)
42
@@ -XXX,XX +XXX,XX @@ static bool trans_RDFFR_p(DisasContext *s, arg_RDFFR_p *a)
43
.rd = a->rd, .pg = a->pg, .s = a->s,
44
.rn = FFR_PRED_NUM, .rm = FFR_PRED_NUM,
45
};
38
+
46
+
39
+/**
47
+ s->is_nonstreaming = true;
40
+ * load_ramdisk:
48
return trans_AND_pppp(s, &alt_a);
41
+ * Same as load_ramdisk_as(), but doesn't allow the caller to specify
42
+ * an AddressSpace.
43
+ */
44
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
45
46
ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen);
47
diff --git a/hw/core/loader.c b/hw/core/loader.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/core/loader.c
50
+++ b/hw/core/loader.c
51
@@ -XXX,XX +XXX,XX @@ int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
52
53
/* Load a ramdisk. */
54
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
55
+{
56
+ return load_ramdisk_as(filename, addr, max_sz, NULL);
57
+}
58
+
59
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
60
+ AddressSpace *as)
61
{
62
return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
63
- NULL, NULL, NULL);
64
+ NULL, NULL, as);
65
}
49
}
66
50
67
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
51
-TRANS_FEAT(RDFFR, aa64_sve, do_mov_p, a->rd, FFR_PRED_NUM)
52
-TRANS_FEAT(WRFFR, aa64_sve, do_mov_p, FFR_PRED_NUM, a->rn)
53
+TRANS_FEAT_NONSTREAMING(RDFFR, aa64_sve, do_mov_p, a->rd, FFR_PRED_NUM)
54
+TRANS_FEAT_NONSTREAMING(WRFFR, aa64_sve, do_mov_p, FFR_PRED_NUM, a->rn)
55
56
static bool do_pfirst_pnext(DisasContext *s, arg_rr_esz *a,
57
void (*gen_fn)(TCGv_i32, TCGv_ptr,
68
--
58
--
69
2.16.2
59
2.25.1
70
71
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-7-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 3 ---
12
target/arm/translate-sve.c | 22 ++++++++++++----------
13
2 files changed, 12 insertions(+), 13 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
24
-FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
25
-FAIL 0100 0101 --0- ---- 1011 ---- ---- ---- # BDEP, BEXT, BGRP
26
FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
27
FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
28
FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
29
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate-sve.c
32
+++ b/target/arm/translate-sve.c
33
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_2 * const fexpa_fns[4] = {
34
NULL, gen_helper_sve_fexpa_h,
35
gen_helper_sve_fexpa_s, gen_helper_sve_fexpa_d,
36
};
37
-TRANS_FEAT(FEXPA, aa64_sve, gen_gvec_ool_zz,
38
- fexpa_fns[a->esz], a->rd, a->rn, 0)
39
+TRANS_FEAT_NONSTREAMING(FEXPA, aa64_sve, gen_gvec_ool_zz,
40
+ fexpa_fns[a->esz], a->rd, a->rn, 0)
41
42
static gen_helper_gvec_3 * const ftssel_fns[4] = {
43
NULL, gen_helper_sve_ftssel_h,
44
gen_helper_sve_ftssel_s, gen_helper_sve_ftssel_d,
45
};
46
-TRANS_FEAT(FTSSEL, aa64_sve, gen_gvec_ool_arg_zzz, ftssel_fns[a->esz], a, 0)
47
+TRANS_FEAT_NONSTREAMING(FTSSEL, aa64_sve, gen_gvec_ool_arg_zzz,
48
+ ftssel_fns[a->esz], a, 0)
49
50
/*
51
*** SVE Predicate Logical Operations Group
52
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(TRN2_q, aa64_sve_f64mm, gen_gvec_ool_arg_zzz,
53
static gen_helper_gvec_3 * const compact_fns[4] = {
54
NULL, NULL, gen_helper_sve_compact_s, gen_helper_sve_compact_d
55
};
56
-TRANS_FEAT(COMPACT, aa64_sve, gen_gvec_ool_arg_zpz, compact_fns[a->esz], a, 0)
57
+TRANS_FEAT_NONSTREAMING(COMPACT, aa64_sve, gen_gvec_ool_arg_zpz,
58
+ compact_fns[a->esz], a, 0)
59
60
/* Call the helper that computes the ARM LastActiveElement pseudocode
61
* function, scaled by the element size. This includes the not found
62
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const bext_fns[4] = {
63
gen_helper_sve2_bext_b, gen_helper_sve2_bext_h,
64
gen_helper_sve2_bext_s, gen_helper_sve2_bext_d,
65
};
66
-TRANS_FEAT(BEXT, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
67
- bext_fns[a->esz], a, 0)
68
+TRANS_FEAT_NONSTREAMING(BEXT, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
69
+ bext_fns[a->esz], a, 0)
70
71
static gen_helper_gvec_3 * const bdep_fns[4] = {
72
gen_helper_sve2_bdep_b, gen_helper_sve2_bdep_h,
73
gen_helper_sve2_bdep_s, gen_helper_sve2_bdep_d,
74
};
75
-TRANS_FEAT(BDEP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
76
- bdep_fns[a->esz], a, 0)
77
+TRANS_FEAT_NONSTREAMING(BDEP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
78
+ bdep_fns[a->esz], a, 0)
79
80
static gen_helper_gvec_3 * const bgrp_fns[4] = {
81
gen_helper_sve2_bgrp_b, gen_helper_sve2_bgrp_h,
82
gen_helper_sve2_bgrp_s, gen_helper_sve2_bgrp_d,
83
};
84
-TRANS_FEAT(BGRP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
85
- bgrp_fns[a->esz], a, 0)
86
+TRANS_FEAT_NONSTREAMING(BGRP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
87
+ bgrp_fns[a->esz], a, 0)
88
89
static gen_helper_gvec_3 * const cadd_fns[4] = {
90
gen_helper_sve2_cadd_b, gen_helper_sve2_cadd_h,
91
--
92
2.25.1
diff view generated by jsdifflib
1
The or-irq.h header file is missing the customary guard against
1
From: Richard Henderson <richard.henderson@linaro.org>
2
multiple inclusion, which means compilation fails if it gets
3
included twice. Fix the omission.
4
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-8-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-11-peter.maydell@linaro.org
9
---
10
---
10
include/hw/or-irq.h | 5 +++++
11
target/arm/sme-fa64.decode | 2 --
11
1 file changed, 5 insertions(+)
12
target/arm/translate-sve.c | 24 +++++++++++++++---------
13
2 files changed, 15 insertions(+), 11 deletions(-)
12
14
13
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/or-irq.h
17
--- a/target/arm/sme-fa64.decode
16
+++ b/include/hw/or-irq.h
18
+++ b/target/arm/sme-fa64.decode
17
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
18
* THE SOFTWARE.
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
24
-FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
25
FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
26
FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
27
FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
28
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-sve.c
31
+++ b/target/arm/translate-sve.c
32
@@ -XXX,XX +XXX,XX @@ static bool do_trans_pmull(DisasContext *s, arg_rrr_esz *a, bool sel)
33
gen_helper_gvec_pmull_q, gen_helper_sve2_pmull_h,
34
NULL, gen_helper_sve2_pmull_d,
35
};
36
- if (a->esz == 0
37
- ? !dc_isar_feature(aa64_sve2_pmull128, s)
38
- : !dc_isar_feature(aa64_sve, s)) {
39
+
40
+ if (a->esz == 0) {
41
+ if (!dc_isar_feature(aa64_sve2_pmull128, s)) {
42
+ return false;
43
+ }
44
+ s->is_nonstreaming = true;
45
+ } else if (!dc_isar_feature(aa64_sve, s)) {
46
return false;
47
}
48
return gen_gvec_ool_arg_zzz(s, fns[a->esz], a, sel);
49
@@ -XXX,XX +XXX,XX @@ DO_ZPZZ_FP(FMINP, aa64_sve2, sve2_fminp_zpzz)
50
* SVE Integer Multiply-Add (unpredicated)
19
*/
51
*/
20
52
21
+#ifndef HW_OR_IRQ_H
53
-TRANS_FEAT(FMMLA_s, aa64_sve_f32mm, gen_gvec_fpst_zzzz, gen_helper_fmmla_s,
22
+#define HW_OR_IRQ_H
54
- a->rd, a->rn, a->rm, a->ra, 0, FPST_FPCR)
23
+
55
-TRANS_FEAT(FMMLA_d, aa64_sve_f64mm, gen_gvec_fpst_zzzz, gen_helper_fmmla_d,
24
#include "hw/irq.h"
56
- a->rd, a->rn, a->rm, a->ra, 0, FPST_FPCR)
25
#include "hw/sysbus.h"
57
+TRANS_FEAT_NONSTREAMING(FMMLA_s, aa64_sve_f32mm, gen_gvec_fpst_zzzz,
26
#include "qom/object.h"
58
+ gen_helper_fmmla_s, a->rd, a->rn, a->rm, a->ra,
27
@@ -XXX,XX +XXX,XX @@ struct OrIRQState {
59
+ 0, FPST_FPCR)
28
bool levels[MAX_OR_LINES];
60
+TRANS_FEAT_NONSTREAMING(FMMLA_d, aa64_sve_f64mm, gen_gvec_fpst_zzzz,
29
uint16_t num_lines;
61
+ gen_helper_fmmla_d, a->rd, a->rn, a->rm, a->ra,
30
};
62
+ 0, FPST_FPCR)
31
+
63
32
+#endif
64
static gen_helper_gvec_4 * const sqdmlal_zzzw_fns[] = {
65
NULL, gen_helper_sve2_sqdmlal_zzzw_h,
66
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(BFDOT_zzzz, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
67
TRANS_FEAT(BFDOT_zzxz, aa64_sve_bf16, gen_gvec_ool_arg_zzxz,
68
gen_helper_gvec_bfdot_idx, a)
69
70
-TRANS_FEAT(BFMMLA, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
71
- gen_helper_gvec_bfmmla, a, 0)
72
+TRANS_FEAT_NONSTREAMING(BFMMLA, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
73
+ gen_helper_gvec_bfmmla, a, 0)
74
75
static bool do_BFMLAL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sel)
76
{
33
--
77
--
34
2.16.2
78
2.25.1
35
36
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-9-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 3 ---
12
target/arm/translate-sve.c | 15 +++++++++++----
13
2 files changed, 11 insertions(+), 7 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
24
-FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
25
-FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
26
FAIL 0100 0101 --0- ---- 1001 10-- ---- ---- # SMMLA, UMMLA, USMMLA
27
FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
28
FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
29
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate-sve.c
32
+++ b/target/arm/translate-sve.c
33
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const ftmad_fns[4] = {
34
NULL, gen_helper_sve_ftmad_h,
35
gen_helper_sve_ftmad_s, gen_helper_sve_ftmad_d,
36
};
37
-TRANS_FEAT(FTMAD, aa64_sve, gen_gvec_fpst_zzz,
38
- ftmad_fns[a->esz], a->rd, a->rn, a->rm, a->imm,
39
- a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR)
40
+TRANS_FEAT_NONSTREAMING(FTMAD, aa64_sve, gen_gvec_fpst_zzz,
41
+ ftmad_fns[a->esz], a->rd, a->rn, a->rm, a->imm,
42
+ a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR)
43
44
/*
45
*** SVE Floating Point Accumulating Reduction Group
46
@@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a)
47
if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) {
48
return false;
49
}
50
+ s->is_nonstreaming = true;
51
if (!sve_access_check(s)) {
52
return true;
53
}
54
@@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a)
55
DO_FP3(FADD_zzz, fadd)
56
DO_FP3(FSUB_zzz, fsub)
57
DO_FP3(FMUL_zzz, fmul)
58
-DO_FP3(FTSMUL, ftsmul)
59
DO_FP3(FRECPS, recps)
60
DO_FP3(FRSQRTS, rsqrts)
61
62
#undef DO_FP3
63
64
+static gen_helper_gvec_3_ptr * const ftsmul_fns[4] = {
65
+ NULL, gen_helper_gvec_ftsmul_h,
66
+ gen_helper_gvec_ftsmul_s, gen_helper_gvec_ftsmul_d
67
+};
68
+TRANS_FEAT_NONSTREAMING(FTSMUL, aa64_sve, gen_gvec_fpst_arg_zzz,
69
+ ftsmul_fns[a->esz], a, 0)
70
+
71
/*
72
*** SVE Floating Point Arithmetic - Predicated Group
73
*/
74
--
75
2.25.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-10-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 1 -
12
target/arm/translate-sve.c | 12 ++++++------
13
2 files changed, 6 insertions(+), 7 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0100 0101 --0- ---- 1001 10-- ---- ---- # SMMLA, UMMLA, USMMLA
24
FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
25
FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
26
FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
31
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FMLALT_zzxw, aa64_sve2, do_FMLAL_zzxw, a, false, true)
32
TRANS_FEAT(FMLSLB_zzxw, aa64_sve2, do_FMLAL_zzxw, a, true, false)
33
TRANS_FEAT(FMLSLT_zzxw, aa64_sve2, do_FMLAL_zzxw, a, true, true)
34
35
-TRANS_FEAT(SMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
36
- gen_helper_gvec_smmla_b, a, 0)
37
-TRANS_FEAT(USMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
38
- gen_helper_gvec_usmmla_b, a, 0)
39
-TRANS_FEAT(UMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
40
- gen_helper_gvec_ummla_b, a, 0)
41
+TRANS_FEAT_NONSTREAMING(SMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
42
+ gen_helper_gvec_smmla_b, a, 0)
43
+TRANS_FEAT_NONSTREAMING(USMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
44
+ gen_helper_gvec_usmmla_b, a, 0)
45
+TRANS_FEAT_NONSTREAMING(UMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
46
+ gen_helper_gvec_ummla_b, a, 0)
47
48
TRANS_FEAT(BFDOT_zzzz, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
49
gen_helper_gvec_bfdot, a, 0)
50
--
51
2.25.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Mark these as non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-11-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 1 -
12
target/arm/translate-sve.c | 35 ++++++++++++++++++-----------------
13
2 files changed, 18 insertions(+), 18 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
24
FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
25
FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
26
FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
31
@@ -XXX,XX +XXX,XX @@ DO_SVE2_ZZZ_NARROW(RSUBHNT, rsubhnt)
32
static gen_helper_gvec_flags_4 * const match_fns[4] = {
33
gen_helper_sve2_match_ppzz_b, gen_helper_sve2_match_ppzz_h, NULL, NULL
34
};
35
-TRANS_FEAT(MATCH, aa64_sve2, do_ppzz_flags, a, match_fns[a->esz])
36
+TRANS_FEAT_NONSTREAMING(MATCH, aa64_sve2, do_ppzz_flags, a, match_fns[a->esz])
37
38
static gen_helper_gvec_flags_4 * const nmatch_fns[4] = {
39
gen_helper_sve2_nmatch_ppzz_b, gen_helper_sve2_nmatch_ppzz_h, NULL, NULL
40
};
41
-TRANS_FEAT(NMATCH, aa64_sve2, do_ppzz_flags, a, nmatch_fns[a->esz])
42
+TRANS_FEAT_NONSTREAMING(NMATCH, aa64_sve2, do_ppzz_flags, a, nmatch_fns[a->esz])
43
44
static gen_helper_gvec_4 * const histcnt_fns[4] = {
45
NULL, NULL, gen_helper_sve2_histcnt_s, gen_helper_sve2_histcnt_d
46
};
47
-TRANS_FEAT(HISTCNT, aa64_sve2, gen_gvec_ool_arg_zpzz,
48
- histcnt_fns[a->esz], a, 0)
49
+TRANS_FEAT_NONSTREAMING(HISTCNT, aa64_sve2, gen_gvec_ool_arg_zpzz,
50
+ histcnt_fns[a->esz], a, 0)
51
52
-TRANS_FEAT(HISTSEG, aa64_sve2, gen_gvec_ool_arg_zzz,
53
- a->esz == 0 ? gen_helper_sve2_histseg : NULL, a, 0)
54
+TRANS_FEAT_NONSTREAMING(HISTSEG, aa64_sve2, gen_gvec_ool_arg_zzz,
55
+ a->esz == 0 ? gen_helper_sve2_histseg : NULL, a, 0)
56
57
DO_ZPZZ_FP(FADDP, aa64_sve2, sve2_faddp_zpzz)
58
DO_ZPZZ_FP(FMAXNMP, aa64_sve2, sve2_fmaxnmp_zpzz)
59
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(SQRDCMLAH_zzzz, aa64_sve2, gen_gvec_ool_zzzz,
60
TRANS_FEAT(USDOT_zzzz, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
61
a->esz == 2 ? gen_helper_gvec_usdot_b : NULL, a, 0)
62
63
-TRANS_FEAT(AESMC, aa64_sve2_aes, gen_gvec_ool_zz,
64
- gen_helper_crypto_aesmc, a->rd, a->rd, a->decrypt)
65
+TRANS_FEAT_NONSTREAMING(AESMC, aa64_sve2_aes, gen_gvec_ool_zz,
66
+ gen_helper_crypto_aesmc, a->rd, a->rd, a->decrypt)
67
68
-TRANS_FEAT(AESE, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
69
- gen_helper_crypto_aese, a, false)
70
-TRANS_FEAT(AESD, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
71
- gen_helper_crypto_aese, a, true)
72
+TRANS_FEAT_NONSTREAMING(AESE, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
73
+ gen_helper_crypto_aese, a, false)
74
+TRANS_FEAT_NONSTREAMING(AESD, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
75
+ gen_helper_crypto_aese, a, true)
76
77
-TRANS_FEAT(SM4E, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
78
- gen_helper_crypto_sm4e, a, 0)
79
-TRANS_FEAT(SM4EKEY, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
80
- gen_helper_crypto_sm4ekey, a, 0)
81
+TRANS_FEAT_NONSTREAMING(SM4E, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
82
+ gen_helper_crypto_sm4e, a, 0)
83
+TRANS_FEAT_NONSTREAMING(SM4EKEY, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
84
+ gen_helper_crypto_sm4ekey, a, 0)
85
86
-TRANS_FEAT(RAX1, aa64_sve2_sha3, gen_gvec_fn_arg_zzz, gen_gvec_rax1, a)
87
+TRANS_FEAT_NONSTREAMING(RAX1, aa64_sve2_sha3, gen_gvec_fn_arg_zzz,
88
+ gen_gvec_rax1, a)
89
90
TRANS_FEAT(FCVTNT_sh, aa64_sve2, gen_gvec_fpst_arg_zpz,
91
gen_helper_sve2_fcvtnt_sh, a, 0, FPST_FPCR)
92
--
93
2.25.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-12-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 9 ---------
12
target/arm/translate-sve.c | 6 ++++++
13
2 files changed, 6 insertions(+), 9 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
24
FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
25
FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
26
-FAIL 1000 010- -01- ---- 1--- ---- ---- ---- # SVE 32-bit gather load (vector+imm)
27
-FAIL 1000 0100 0-0- ---- 0--- ---- ---- ---- # SVE 32-bit gather load byte (scalar+vector)
28
-FAIL 1000 0100 1--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load half (scalar+vector)
29
-FAIL 1000 0101 0--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load word (scalar+vector)
30
FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
31
FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
32
FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
33
FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
34
FAIL 1100 010- ---- ---- ---- ---- ---- ---- # SVE 64-bit gather load/prefetch
35
-FAIL 1110 010- -00- ---- 001- ---- ---- ---- # SVE2 64-bit scatter NT store (vector+scalar)
36
-FAIL 1110 010- -10- ---- 001- ---- ---- ---- # SVE2 32-bit scatter NT store (vector+scalar)
37
-FAIL 1110 010- ---- ---- 1-0- ---- ---- ---- # SVE scatter store (scalar+32-bit vector)
38
-FAIL 1110 010- ---- ---- 101- ---- ---- ---- # SVE scatter store (misc)
39
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate-sve.c
42
+++ b/target/arm/translate-sve.c
43
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a)
44
if (!dc_isar_feature(aa64_sve, s)) {
45
return false;
46
}
47
+ s->is_nonstreaming = true;
48
if (!sve_access_check(s)) {
49
return true;
50
}
51
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a)
52
if (!dc_isar_feature(aa64_sve, s)) {
53
return false;
54
}
55
+ s->is_nonstreaming = true;
56
if (!sve_access_check(s)) {
57
return true;
58
}
59
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNT1_zprz(DisasContext *s, arg_LD1_zprz *a)
60
if (!dc_isar_feature(aa64_sve2, s)) {
61
return false;
62
}
63
+ s->is_nonstreaming = true;
64
if (!sve_access_check(s)) {
65
return true;
66
}
67
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a)
68
if (!dc_isar_feature(aa64_sve, s)) {
69
return false;
70
}
71
+ s->is_nonstreaming = true;
72
if (!sve_access_check(s)) {
73
return true;
74
}
75
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a)
76
if (!dc_isar_feature(aa64_sve, s)) {
77
return false;
78
}
79
+ s->is_nonstreaming = true;
80
if (!sve_access_check(s)) {
81
return true;
82
}
83
@@ -XXX,XX +XXX,XX @@ static bool trans_STNT1_zprz(DisasContext *s, arg_ST1_zprz *a)
84
if (!dc_isar_feature(aa64_sve2, s)) {
85
return false;
86
}
87
+ s->is_nonstreaming = true;
88
if (!sve_access_check(s)) {
89
return true;
90
}
91
--
92
2.25.1
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Allow the guest to determine the time set from the QEMU command line.
3
Mark these as a non-streaming instructions, which should trap if full
4
a64 support is not enabled in streaming mode. In this case, introduce
5
PRF_ns (prefetch non-streaming) to handle the checks.
4
6
5
This includes adding a trace event to debug the new time.
6
7
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220708151540.18136-13-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
include/hw/timer/xlnx-zynqmp-rtc.h | 2 ++
12
target/arm/sme-fa64.decode | 3 ---
13
hw/timer/xlnx-zynqmp-rtc.c | 58 ++++++++++++++++++++++++++++++++++++++
13
target/arm/sve.decode | 10 +++++-----
14
hw/timer/trace-events | 3 ++
14
target/arm/translate-sve.c | 11 +++++++++++
15
3 files changed, 63 insertions(+)
15
3 files changed, 16 insertions(+), 8 deletions(-)
16
16
17
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
17
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/xlnx-zynqmp-rtc.h
19
--- a/target/arm/sme-fa64.decode
20
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
20
+++ b/target/arm/sme-fa64.decode
21
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPRTC {
21
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
22
qemu_irq irq_rtc_int;
22
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
23
qemu_irq irq_addr_error_int;
23
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
24
24
25
+ uint32_t tick_offset;
25
-FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
26
+
26
-FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
27
uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
27
FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
28
RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
28
FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
29
} XlnxZynqMPRTC;
29
FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
30
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
30
FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
31
-FAIL 1100 010- ---- ---- ---- ---- ---- ---- # SVE 64-bit gather load/prefetch
32
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
31
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/xlnx-zynqmp-rtc.c
34
--- a/target/arm/sve.decode
33
+++ b/hw/timer/xlnx-zynqmp-rtc.c
35
+++ b/target/arm/sve.decode
34
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@ LD1RO_zpri 1010010 .. 01 0.... 001 ... ..... ..... \
35
#include "hw/register.h"
37
@rpri_load_msz nreg=0
36
#include "qemu/bitops.h"
38
37
#include "qemu/log.h"
39
# SVE 32-bit gather prefetch (scalar plus 32-bit scaled offsets)
38
+#include "hw/ptimer.h"
40
-PRF 1000010 00 -1 ----- 0-- --- ----- 0 ----
39
+#include "qemu/cutils.h"
41
+PRF_ns 1000010 00 -1 ----- 0-- --- ----- 0 ----
40
+#include "sysemu/sysemu.h"
42
41
+#include "trace.h"
43
# SVE 32-bit gather prefetch (vector plus immediate)
42
#include "hw/timer/xlnx-zynqmp-rtc.h"
44
-PRF 1000010 -- 00 ----- 111 --- ----- 0 ----
43
45
+PRF_ns 1000010 -- 00 ----- 111 --- ----- 0 ----
44
#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
46
45
@@ -XXX,XX +XXX,XX @@ static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
47
# SVE contiguous prefetch (scalar plus immediate)
46
qemu_set_irq(s->irq_addr_error_int, pending);
48
PRF 1000010 11 1- ----- 0-- --- ----- 0 ----
49
@@ -XXX,XX +XXX,XX @@ LD1_zpiz 1100010 .. 01 ..... 1.. ... ..... ..... \
50
@rpri_g_load esz=3
51
52
# SVE 64-bit gather prefetch (scalar plus 64-bit scaled offsets)
53
-PRF 1100010 00 11 ----- 1-- --- ----- 0 ----
54
+PRF_ns 1100010 00 11 ----- 1-- --- ----- 0 ----
55
56
# SVE 64-bit gather prefetch (scalar plus unpacked 32-bit scaled offsets)
57
-PRF 1100010 00 -1 ----- 0-- --- ----- 0 ----
58
+PRF_ns 1100010 00 -1 ----- 0-- --- ----- 0 ----
59
60
# SVE 64-bit gather prefetch (vector plus immediate)
61
-PRF 1100010 -- 00 ----- 111 --- ----- 0 ----
62
+PRF_ns 1100010 -- 00 ----- 111 --- ----- 0 ----
63
64
### SVE Memory Store Group
65
66
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate-sve.c
69
+++ b/target/arm/translate-sve.c
70
@@ -XXX,XX +XXX,XX @@ static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a)
71
return true;
47
}
72
}
48
73
49
+static uint32_t rtc_get_count(XlnxZynqMPRTC *s)
74
+static bool trans_PRF_ns(DisasContext *s, arg_PRF_ns *a)
50
+{
75
+{
51
+ int64_t now = qemu_clock_get_ns(rtc_clock);
76
+ if (!dc_isar_feature(aa64_sve, s)) {
52
+ return s->tick_offset + now / NANOSECONDS_PER_SECOND;
77
+ return false;
78
+ }
79
+ /* Prefetch is a nop within QEMU. */
80
+ s->is_nonstreaming = true;
81
+ (void)sve_access_check(s);
82
+ return true;
53
+}
83
+}
54
+
84
+
55
+static uint64_t current_time_postr(RegisterInfo *reg, uint64_t val64)
85
/*
56
+{
86
* Move Prefix
57
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
87
*
58
+
59
+ return rtc_get_count(s);
60
+}
61
+
62
static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
63
{
64
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
65
@@ -XXX,XX +XXX,XX @@ static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
66
67
static const RegisterAccessInfo rtc_regs_info[] = {
68
{ .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
69
+ .unimp = MAKE_64BIT_MASK(0, 32),
70
},{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
71
.ro = 0xffffffff,
72
+ .post_read = current_time_postr,
73
},{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
74
+ .unimp = MAKE_64BIT_MASK(0, 32),
75
},{ .name = "CALIB_READ", .addr = A_CALIB_READ,
76
.ro = 0x1fffff,
77
},{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
78
.ro = 0xffffffff,
79
+ .post_read = current_time_postr,
80
},{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
81
.ro = 0xffff,
82
},{ .name = "ALARM", .addr = A_ALARM,
83
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
84
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
85
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
86
RegisterInfoArray *reg_array;
87
+ struct tm current_tm;
88
89
memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
90
XLNX_ZYNQMP_RTC_R_MAX * 4);
91
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
92
sysbus_init_mmio(sbd, &s->iomem);
93
sysbus_init_irq(sbd, &s->irq_rtc_int);
94
sysbus_init_irq(sbd, &s->irq_addr_error_int);
95
+
96
+ qemu_get_timedate(&current_tm, 0);
97
+ s->tick_offset = mktimegm(&current_tm) -
98
+ qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
99
+
100
+ trace_xlnx_zynqmp_rtc_gettime(current_tm.tm_year, current_tm.tm_mon,
101
+ current_tm.tm_mday, current_tm.tm_hour,
102
+ current_tm.tm_min, current_tm.tm_sec);
103
+}
104
+
105
+static int rtc_pre_save(void *opaque)
106
+{
107
+ XlnxZynqMPRTC *s = opaque;
108
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
109
+
110
+ /* Add the time at migration */
111
+ s->tick_offset = s->tick_offset + now;
112
+
113
+ return 0;
114
+}
115
+
116
+static int rtc_post_load(void *opaque, int version_id)
117
+{
118
+ XlnxZynqMPRTC *s = opaque;
119
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
120
+
121
+ /* Subtract the time after migration. This combined with the pre_save
122
+ * action results in us having subtracted the time that the guest was
123
+ * stopped to the offset.
124
+ */
125
+ s->tick_offset = s->tick_offset - now;
126
+
127
+ return 0;
128
}
129
130
static const VMStateDescription vmstate_rtc = {
131
.name = TYPE_XLNX_ZYNQMP_RTC,
132
.version_id = 1,
133
.minimum_version_id = 1,
134
+ .pre_save = rtc_pre_save,
135
+ .post_load = rtc_post_load,
136
.fields = (VMStateField[]) {
137
VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
138
+ VMSTATE_UINT32(tick_offset, XlnxZynqMPRTC),
139
VMSTATE_END_OF_LIST(),
140
}
141
};
142
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
143
index XXXXXXX..XXXXXXX 100644
144
--- a/hw/timer/trace-events
145
+++ b/hw/timer/trace-events
146
@@ -XXX,XX +XXX,XX @@ systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr
147
cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
148
cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
149
cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
150
+
151
+# hw/timer/xlnx-zynqmp-rtc.c
152
+xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
153
--
88
--
154
2.16.2
89
2.25.1
155
156
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-14-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sme-fa64.decode | 2 --
12
target/arm/translate-sve.c | 2 ++
13
2 files changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
24
-FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
25
FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
26
FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
31
@@ -XXX,XX +XXX,XX @@ static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a)
32
if (!dc_isar_feature(aa64_sve, s)) {
33
return false;
34
}
35
+ s->is_nonstreaming = true;
36
if (sve_access_check(s)) {
37
TCGv_i64 addr = new_tmp_a64(s);
38
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
39
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a)
40
if (!dc_isar_feature(aa64_sve, s)) {
41
return false;
42
}
43
+ s->is_nonstreaming = true;
44
if (sve_access_check(s)) {
45
int vsz = vec_full_reg_size(s);
46
int elements = vsz >> dtype_esz[a->dtype];
47
--
48
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Happily, the bits are in the same places compared to a32.
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
4
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180228193125.20577-16-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-15-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/translate.c | 14 +++++++++++++-
11
target/arm/sme-fa64.decode | 3 ---
11
1 file changed, 13 insertions(+), 1 deletion(-)
12
target/arm/translate-sve.c | 2 ++
13
2 files changed, 2 insertions(+), 3 deletions(-)
12
14
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
17
--- a/target/arm/sme-fa64.decode
16
+++ b/target/arm/translate.c
18
+++ b/target/arm/sme-fa64.decode
17
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
18
default_exception_el(s));
20
# --11 1100 --0- ---- ---- ---- ---- ---- # Load/store FP register (unscaled imm)
19
break;
21
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
20
}
22
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
21
- if (((insn >> 24) & 3) == 3) {
23
-
22
+ if ((insn & 0xfe000a00) == 0xfc000800
24
-FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
23
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
25
-FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
24
+ /* The Thumb2 and ARM encodings are identical. */
26
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
25
+ if (disas_neon_insn_3same_ext(s, insn)) {
27
index XXXXXXX..XXXXXXX 100644
26
+ goto illegal_op;
28
--- a/target/arm/translate-sve.c
27
+ }
29
+++ b/target/arm/translate-sve.c
28
+ } else if ((insn & 0xff000a00) == 0xfe000800
30
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1RO_zprr(DisasContext *s, arg_rprr_load *a)
29
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
31
if (a->rm == 31) {
30
+ /* The Thumb2 and ARM encodings are identical. */
32
return false;
31
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
33
}
32
+ goto illegal_op;
34
+ s->is_nonstreaming = true;
33
+ }
35
if (sve_access_check(s)) {
34
+ } else if (((insn >> 24) & 3) == 3) {
36
TCGv_i64 addr = new_tmp_a64(s);
35
/* Translate into the equivalent ARM encoding. */
37
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
36
insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
38
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1RO_zpri(DisasContext *s, arg_rpri_load *a)
37
if (disas_neon_data_insn(s, insn)) {
39
if (!dc_isar_feature(aa64_sve_f64mm, s)) {
40
return false;
41
}
42
+ s->is_nonstreaming = true;
43
if (sve_access_check(s)) {
44
TCGv_i64 addr = new_tmp_a64(s);
45
tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), a->imm * 32);
38
--
46
--
39
2.16.2
47
2.25.1
40
41
diff view generated by jsdifflib
1
Add a model of the TrustZone peripheral protection controller (PPC),
1
From: Richard Henderson <richard.henderson@linaro.org>
2
which is used to gate transactions to non-TZ-aware peripherals so
3
that secure software can configure them to not be accessible to
4
non-secure software.
5
2
3
These functions will be used to verify that the cpu
4
is in the correct state for a given instruction.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-16-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: 20180220180325.29818-15-peter.maydell@linaro.org
9
---
10
---
10
hw/misc/Makefile.objs | 2 +
11
target/arm/translate-a64.h | 21 +++++++++++++++++++++
11
include/hw/misc/tz-ppc.h | 101 ++++++++++++++
12
target/arm/translate-a64.c | 34 ++++++++++++++++++++++++++++++++++
12
hw/misc/tz-ppc.c | 302 ++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 55 insertions(+)
13
default-configs/arm-softmmu.mak | 2 +
14
hw/misc/trace-events | 11 ++
15
5 files changed, 418 insertions(+)
16
create mode 100644 include/hw/misc/tz-ppc.h
17
create mode 100644 hw/misc/tz-ppc.c
18
14
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
15
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/misc/Makefile.objs
17
--- a/target/arm/translate-a64.h
22
+++ b/hw/misc/Makefile.objs
18
+++ b/target/arm/translate-a64.h
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
19
@@ -XXX,XX +XXX,XX @@ void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v);
24
obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
20
bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
21
unsigned int imms, unsigned int immr);
26
22
bool sve_access_check(DisasContext *s);
27
+obj-$(CONFIG_TZ_PPC) += tz-ppc.o
23
+bool sme_enabled_check(DisasContext *s);
24
+bool sme_enabled_check_with_svcr(DisasContext *s, unsigned);
28
+
25
+
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
26
+/* This function corresponds to CheckStreamingSVEEnabled. */
30
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
27
+static inline bool sme_sm_enabled_check(DisasContext *s)
31
obj-$(CONFIG_AUX) += auxbus.o
32
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/tz-ppc.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * ARM TrustZone peripheral protection controller emulation
40
+ *
41
+ * Copyright (c) 2018 Linaro Limited
42
+ * Written by Peter Maydell
43
+ *
44
+ * This program is free software; you can redistribute it and/or modify
45
+ * it under the terms of the GNU General Public License version 2 or
46
+ * (at your option) any later version.
47
+ */
48
+
49
+/* This is a model of the TrustZone peripheral protection controller (PPC).
50
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
51
+ * (DDI 0571G):
52
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
53
+ *
54
+ * The PPC sits in front of peripherals and allows secure software to
55
+ * configure it to either pass through or reject transactions.
56
+ * Rejected transactions may be configured to either be aborted, or to
57
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
58
+ *
59
+ * The PPC has no register interface -- it is configured purely by a
60
+ * collection of input signals from other hardware in the system. Typically
61
+ * they are either hardwired or exposed in an ad-hoc register interface by
62
+ * the SoC that uses the PPC.
63
+ *
64
+ * This QEMU model can be used to model either the AHB5 or APB4 TZ PPC,
65
+ * since the only difference between them is that the AHB version has a
66
+ * "default" port which has no security checks applied. In QEMU the default
67
+ * port can be emulated simply by wiring its downstream devices directly
68
+ * into the parent address space, since the PPC does not need to intercept
69
+ * transactions there.
70
+ *
71
+ * In the hardware, selection of which downstream port to use is done by
72
+ * the user's decode logic asserting one of the hsel[] signals. In QEMU,
73
+ * we provide 16 MMIO regions, one per port, and the user maps these into
74
+ * the desired addresses to implement the address decode.
75
+ *
76
+ * QEMU interface:
77
+ * + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
78
+ * of each of the 16 ports of the PPC
79
+ * + Property "port[0..15]": MemoryRegion defining the downstream device(s)
80
+ * for each of the 16 ports of the PPC
81
+ * + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
82
+ * accessible to NonSecure transactions
83
+ * + Named GPIO inputs "cfg_ap[0..15]": set to 1 if the port should be
84
+ * accessible to non-privileged transactions
85
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
86
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
87
+ * + Named GPIO input "irq_enable": set to 1 to enable interrupts
88
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
89
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
90
+ * + Property "NONSEC_MASK": if a bit is set in this mask then accesses to
91
+ * the associated port do not have the TZ security check performed. (This
92
+ * corresponds to the hardware allowing this to be set as a Verilog
93
+ * parameter.)
94
+ */
95
+
96
+#ifndef TZ_PPC_H
97
+#define TZ_PPC_H
98
+
99
+#include "hw/sysbus.h"
100
+
101
+#define TYPE_TZ_PPC "tz-ppc"
102
+#define TZ_PPC(obj) OBJECT_CHECK(TZPPC, (obj), TYPE_TZ_PPC)
103
+
104
+#define TZ_NUM_PORTS 16
105
+
106
+typedef struct TZPPC TZPPC;
107
+
108
+typedef struct TZPPCPort {
109
+ TZPPC *ppc;
110
+ MemoryRegion upstream;
111
+ AddressSpace downstream_as;
112
+ MemoryRegion *downstream;
113
+} TZPPCPort;
114
+
115
+struct TZPPC {
116
+ /*< private >*/
117
+ SysBusDevice parent_obj;
118
+
119
+ /*< public >*/
120
+
121
+ /* State: these just track the values of our input signals */
122
+ bool cfg_nonsec[TZ_NUM_PORTS];
123
+ bool cfg_ap[TZ_NUM_PORTS];
124
+ bool cfg_sec_resp;
125
+ bool irq_enable;
126
+ bool irq_clear;
127
+ /* State: are we asserting irq ? */
128
+ bool irq_status;
129
+
130
+ qemu_irq irq;
131
+
132
+ /* Properties */
133
+ uint32_t nonsec_mask;
134
+
135
+ TZPPCPort port[TZ_NUM_PORTS];
136
+};
137
+
138
+#endif
139
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
140
new file mode 100644
141
index XXXXXXX..XXXXXXX
142
--- /dev/null
143
+++ b/hw/misc/tz-ppc.c
144
@@ -XXX,XX +XXX,XX @@
145
+/*
146
+ * ARM TrustZone peripheral protection controller emulation
147
+ *
148
+ * Copyright (c) 2018 Linaro Limited
149
+ * Written by Peter Maydell
150
+ *
151
+ * This program is free software; you can redistribute it and/or modify
152
+ * it under the terms of the GNU General Public License version 2 or
153
+ * (at your option) any later version.
154
+ */
155
+
156
+#include "qemu/osdep.h"
157
+#include "qemu/log.h"
158
+#include "qapi/error.h"
159
+#include "trace.h"
160
+#include "hw/sysbus.h"
161
+#include "hw/registerfields.h"
162
+#include "hw/misc/tz-ppc.h"
163
+
164
+static void tz_ppc_update_irq(TZPPC *s)
165
+{
28
+{
166
+ bool level = s->irq_status && s->irq_enable;
29
+ return sme_enabled_check_with_svcr(s, R_SVCR_SM_MASK);
167
+
168
+ trace_tz_ppc_update_irq(level);
169
+ qemu_set_irq(s->irq, level);
170
+}
30
+}
171
+
31
+
172
+static void tz_ppc_cfg_nonsec(void *opaque, int n, int level)
32
+/* This function corresponds to CheckSMEAndZAEnabled. */
33
+static inline bool sme_za_enabled_check(DisasContext *s)
173
+{
34
+{
174
+ TZPPC *s = TZ_PPC(opaque);
35
+ return sme_enabled_check_with_svcr(s, R_SVCR_ZA_MASK);
175
+
176
+ assert(n < TZ_NUM_PORTS);
177
+ trace_tz_ppc_cfg_nonsec(n, level);
178
+ s->cfg_nonsec[n] = level;
179
+}
36
+}
180
+
37
+
181
+static void tz_ppc_cfg_ap(void *opaque, int n, int level)
38
+/* Note that this function corresponds to CheckStreamingSVEAndZAEnabled. */
39
+static inline bool sme_smza_enabled_check(DisasContext *s)
182
+{
40
+{
183
+ TZPPC *s = TZ_PPC(opaque);
41
+ return sme_enabled_check_with_svcr(s, R_SVCR_SM_MASK | R_SVCR_ZA_MASK);
184
+
185
+ assert(n < TZ_NUM_PORTS);
186
+ trace_tz_ppc_cfg_ap(n, level);
187
+ s->cfg_ap[n] = level;
188
+}
42
+}
189
+
43
+
190
+static void tz_ppc_cfg_sec_resp(void *opaque, int n, int level)
44
TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
45
TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
46
bool tag_checked, int log2_size);
47
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-a64.c
50
+++ b/target/arm/translate-a64.c
51
@@ -XXX,XX +XXX,XX @@ static bool sme_access_check(DisasContext *s)
52
return true;
53
}
54
55
+/* This function corresponds to CheckSMEEnabled. */
56
+bool sme_enabled_check(DisasContext *s)
191
+{
57
+{
192
+ TZPPC *s = TZ_PPC(opaque);
58
+ /*
193
+
59
+ * Note that unlike sve_excp_el, we have not constrained sme_excp_el
194
+ trace_tz_ppc_cfg_sec_resp(level);
60
+ * to be zero when fp_excp_el has priority. This is because we need
195
+ s->cfg_sec_resp = level;
61
+ * sme_excp_el by itself for cpregs access checks.
62
+ */
63
+ if (!s->fp_excp_el || s->sme_excp_el < s->fp_excp_el) {
64
+ s->fp_access_checked = true;
65
+ return sme_access_check(s);
66
+ }
67
+ return fp_access_check_only(s);
196
+}
68
+}
197
+
69
+
198
+static void tz_ppc_irq_enable(void *opaque, int n, int level)
70
+/* Common subroutine for CheckSMEAnd*Enabled. */
71
+bool sme_enabled_check_with_svcr(DisasContext *s, unsigned req)
199
+{
72
+{
200
+ TZPPC *s = TZ_PPC(opaque);
73
+ if (!sme_enabled_check(s)) {
201
+
74
+ return false;
202
+ trace_tz_ppc_irq_enable(level);
203
+ s->irq_enable = level;
204
+ tz_ppc_update_irq(s);
205
+}
206
+
207
+static void tz_ppc_irq_clear(void *opaque, int n, int level)
208
+{
209
+ TZPPC *s = TZ_PPC(opaque);
210
+
211
+ trace_tz_ppc_irq_clear(level);
212
+
213
+ s->irq_clear = level;
214
+ if (level) {
215
+ s->irq_status = false;
216
+ tz_ppc_update_irq(s);
217
+ }
75
+ }
218
+}
76
+ if (FIELD_EX64(req, SVCR, SM) && !s->pstate_sm) {
219
+
77
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
220
+static bool tz_ppc_check(TZPPC *s, int n, MemTxAttrs attrs)
78
+ syn_smetrap(SME_ET_NotStreaming, false));
221
+{
79
+ return false;
222
+ /* Check whether to allow an access to port n; return true if
80
+ }
223
+ * the check passes, and false if the transaction must be blocked.
81
+ if (FIELD_EX64(req, SVCR, ZA) && !s->pstate_za) {
224
+ * If the latter, the caller must check cfg_sec_resp to determine
82
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
225
+ * whether to abort or RAZ/WI the transaction.
83
+ syn_smetrap(SME_ET_InactiveZA, false));
226
+ * The checks are:
227
+ * + nonsec_mask suppresses any check of the secure attribute
228
+ * + otherwise, block if cfg_nonsec is 1 and transaction is secure,
229
+ * or if cfg_nonsec is 0 and transaction is non-secure
230
+ * + block if transaction is usermode and cfg_ap is 0
231
+ */
232
+ if ((attrs.secure == s->cfg_nonsec[n] && !(s->nonsec_mask & (1 << n))) ||
233
+ (attrs.user && !s->cfg_ap[n])) {
234
+ /* Block the transaction. */
235
+ if (!s->irq_clear) {
236
+ /* Note that holding irq_clear high suppresses interrupts */
237
+ s->irq_status = true;
238
+ tz_ppc_update_irq(s);
239
+ }
240
+ return false;
84
+ return false;
241
+ }
85
+ }
242
+ return true;
86
+ return true;
243
+}
87
+}
244
+
88
+
245
+static MemTxResult tz_ppc_read(void *opaque, hwaddr addr, uint64_t *pdata,
89
/*
246
+ unsigned size, MemTxAttrs attrs)
90
* This utility function is for doing register extension with an
247
+{
91
* optional shift. You will likely want to pass a temporary for the
248
+ TZPPCPort *p = opaque;
249
+ TZPPC *s = p->ppc;
250
+ int n = p - s->port;
251
+ AddressSpace *as = &p->downstream_as;
252
+ uint64_t data;
253
+ MemTxResult res;
254
+
255
+ if (!tz_ppc_check(s, n, attrs)) {
256
+ trace_tz_ppc_read_blocked(n, addr, attrs.secure, attrs.user);
257
+ if (s->cfg_sec_resp) {
258
+ return MEMTX_ERROR;
259
+ } else {
260
+ *pdata = 0;
261
+ return MEMTX_OK;
262
+ }
263
+ }
264
+
265
+ switch (size) {
266
+ case 1:
267
+ data = address_space_ldub(as, addr, attrs, &res);
268
+ break;
269
+ case 2:
270
+ data = address_space_lduw_le(as, addr, attrs, &res);
271
+ break;
272
+ case 4:
273
+ data = address_space_ldl_le(as, addr, attrs, &res);
274
+ break;
275
+ case 8:
276
+ data = address_space_ldq_le(as, addr, attrs, &res);
277
+ break;
278
+ default:
279
+ g_assert_not_reached();
280
+ }
281
+ *pdata = data;
282
+ return res;
283
+}
284
+
285
+static MemTxResult tz_ppc_write(void *opaque, hwaddr addr, uint64_t val,
286
+ unsigned size, MemTxAttrs attrs)
287
+{
288
+ TZPPCPort *p = opaque;
289
+ TZPPC *s = p->ppc;
290
+ AddressSpace *as = &p->downstream_as;
291
+ int n = p - s->port;
292
+ MemTxResult res;
293
+
294
+ if (!tz_ppc_check(s, n, attrs)) {
295
+ trace_tz_ppc_write_blocked(n, addr, attrs.secure, attrs.user);
296
+ if (s->cfg_sec_resp) {
297
+ return MEMTX_ERROR;
298
+ } else {
299
+ return MEMTX_OK;
300
+ }
301
+ }
302
+
303
+ switch (size) {
304
+ case 1:
305
+ address_space_stb(as, addr, val, attrs, &res);
306
+ break;
307
+ case 2:
308
+ address_space_stw_le(as, addr, val, attrs, &res);
309
+ break;
310
+ case 4:
311
+ address_space_stl_le(as, addr, val, attrs, &res);
312
+ break;
313
+ case 8:
314
+ address_space_stq_le(as, addr, val, attrs, &res);
315
+ break;
316
+ default:
317
+ g_assert_not_reached();
318
+ }
319
+ return res;
320
+}
321
+
322
+static const MemoryRegionOps tz_ppc_ops = {
323
+ .read_with_attrs = tz_ppc_read,
324
+ .write_with_attrs = tz_ppc_write,
325
+ .endianness = DEVICE_LITTLE_ENDIAN,
326
+};
327
+
328
+static void tz_ppc_reset(DeviceState *dev)
329
+{
330
+ TZPPC *s = TZ_PPC(dev);
331
+
332
+ trace_tz_ppc_reset();
333
+ s->cfg_sec_resp = false;
334
+ memset(s->cfg_nonsec, 0, sizeof(s->cfg_nonsec));
335
+ memset(s->cfg_ap, 0, sizeof(s->cfg_ap));
336
+}
337
+
338
+static void tz_ppc_init(Object *obj)
339
+{
340
+ DeviceState *dev = DEVICE(obj);
341
+ TZPPC *s = TZ_PPC(obj);
342
+
343
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_nonsec, "cfg_nonsec", TZ_NUM_PORTS);
344
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_ap, "cfg_ap", TZ_NUM_PORTS);
345
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_sec_resp, "cfg_sec_resp", 1);
346
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_enable, "irq_enable", 1);
347
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_clear, "irq_clear", 1);
348
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
349
+}
350
+
351
+static void tz_ppc_realize(DeviceState *dev, Error **errp)
352
+{
353
+ Object *obj = OBJECT(dev);
354
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
355
+ TZPPC *s = TZ_PPC(dev);
356
+ int i;
357
+
358
+ /* We can't create the upstream end of the port until realize,
359
+ * as we don't know the size of the MR used as the downstream until then.
360
+ */
361
+ for (i = 0; i < TZ_NUM_PORTS; i++) {
362
+ TZPPCPort *port = &s->port[i];
363
+ char *name;
364
+ uint64_t size;
365
+
366
+ if (!port->downstream) {
367
+ continue;
368
+ }
369
+
370
+ name = g_strdup_printf("tz-ppc-port[%d]", i);
371
+
372
+ port->ppc = s;
373
+ address_space_init(&port->downstream_as, port->downstream, name);
374
+
375
+ size = memory_region_size(port->downstream);
376
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_ops,
377
+ port, name, size);
378
+ sysbus_init_mmio(sbd, &port->upstream);
379
+ g_free(name);
380
+ }
381
+}
382
+
383
+static const VMStateDescription tz_ppc_vmstate = {
384
+ .name = "tz-ppc",
385
+ .version_id = 1,
386
+ .minimum_version_id = 1,
387
+ .fields = (VMStateField[]) {
388
+ VMSTATE_BOOL_ARRAY(cfg_nonsec, TZPPC, 16),
389
+ VMSTATE_BOOL_ARRAY(cfg_ap, TZPPC, 16),
390
+ VMSTATE_BOOL(cfg_sec_resp, TZPPC),
391
+ VMSTATE_BOOL(irq_enable, TZPPC),
392
+ VMSTATE_BOOL(irq_clear, TZPPC),
393
+ VMSTATE_BOOL(irq_status, TZPPC),
394
+ VMSTATE_END_OF_LIST()
395
+ }
396
+};
397
+
398
+#define DEFINE_PORT(N) \
399
+ DEFINE_PROP_LINK("port[" #N "]", TZPPC, port[N].downstream, \
400
+ TYPE_MEMORY_REGION, MemoryRegion *)
401
+
402
+static Property tz_ppc_properties[] = {
403
+ DEFINE_PROP_UINT32("NONSEC_MASK", TZPPC, nonsec_mask, 0),
404
+ DEFINE_PORT(0),
405
+ DEFINE_PORT(1),
406
+ DEFINE_PORT(2),
407
+ DEFINE_PORT(3),
408
+ DEFINE_PORT(4),
409
+ DEFINE_PORT(5),
410
+ DEFINE_PORT(6),
411
+ DEFINE_PORT(7),
412
+ DEFINE_PORT(8),
413
+ DEFINE_PORT(9),
414
+ DEFINE_PORT(10),
415
+ DEFINE_PORT(11),
416
+ DEFINE_PORT(12),
417
+ DEFINE_PORT(13),
418
+ DEFINE_PORT(14),
419
+ DEFINE_PORT(15),
420
+ DEFINE_PROP_END_OF_LIST(),
421
+};
422
+
423
+static void tz_ppc_class_init(ObjectClass *klass, void *data)
424
+{
425
+ DeviceClass *dc = DEVICE_CLASS(klass);
426
+
427
+ dc->realize = tz_ppc_realize;
428
+ dc->vmsd = &tz_ppc_vmstate;
429
+ dc->reset = tz_ppc_reset;
430
+ dc->props = tz_ppc_properties;
431
+}
432
+
433
+static const TypeInfo tz_ppc_info = {
434
+ .name = TYPE_TZ_PPC,
435
+ .parent = TYPE_SYS_BUS_DEVICE,
436
+ .instance_size = sizeof(TZPPC),
437
+ .instance_init = tz_ppc_init,
438
+ .class_init = tz_ppc_class_init,
439
+};
440
+
441
+static void tz_ppc_register_types(void)
442
+{
443
+ type_register_static(&tz_ppc_info);
444
+}
445
+
446
+type_init(tz_ppc_register_types);
447
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
448
index XXXXXXX..XXXXXXX 100644
449
--- a/default-configs/arm-softmmu.mak
450
+++ b/default-configs/arm-softmmu.mak
451
@@ -XXX,XX +XXX,XX @@ CONFIG_CMSDK_APB_UART=y
452
CONFIG_MPS2_FPGAIO=y
453
CONFIG_MPS2_SCC=y
454
455
+CONFIG_TZ_PPC=y
456
+
457
CONFIG_VERSATILE_PCI=y
458
CONFIG_VERSATILE_I2C=y
459
460
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
461
index XXXXXXX..XXXXXXX 100644
462
--- a/hw/misc/trace-events
463
+++ b/hw/misc/trace-events
464
@@ -XXX,XX +XXX,XX @@ mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta) "latch=%d co
465
mos6522_set_sr_int(void) "set sr_int"
466
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
467
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
468
+
469
+# hw/misc/tz-ppc.c
470
+tz_ppc_reset(void) "TZ PPC: reset"
471
+tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
472
+tz_ppc_cfg_ap(int n, int level) "TZ PPC: cfg_ap[%d] = %d"
473
+tz_ppc_cfg_sec_resp(int level) "TZ PPC: cfg_sec_resp = %d"
474
+tz_ppc_irq_enable(int level) "TZ PPC: int_enable = %d"
475
+tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
476
+tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
477
+tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
478
+tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
479
--
92
--
480
2.16.2
93
2.25.1
481
482
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
The pseudocode for CheckSVEEnabled gains a check for Streaming
4
SVE mode, and for SME present but SVE absent.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-7-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-17-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
---
10
---
8
target/arm/translate-a64.c | 29 +++++++++++++++++++++++++++++
11
target/arm/translate-a64.c | 22 ++++++++++++++++------
9
1 file changed, 29 insertions(+)
12
1 file changed, 16 insertions(+), 6 deletions(-)
10
13
11
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-a64.c
16
--- a/target/arm/translate-a64.c
14
+++ b/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
15
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
16
case 0x19: /* FMULX */
19
return true;
17
is_fp = true;
20
}
18
break;
21
19
+ case 0x1d: /* SQRDMLAH */
22
-/* Check that SVE access is enabled. If it is, return true.
20
+ case 0x1f: /* SQRDMLSH */
23
+/*
21
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
24
+ * Check that SVE access is enabled. If it is, return true.
22
+ unallocated_encoding(s);
25
* If not, emit code to generate an appropriate exception and return false.
23
+ return;
26
+ * This function corresponds to CheckSVEEnabled().
27
*/
28
bool sve_access_check(DisasContext *s)
29
{
30
- if (s->sve_excp_el) {
31
- assert(!s->sve_access_checked);
32
- s->sve_access_checked = true;
33
-
34
+ if (s->pstate_sm || !dc_isar_feature(aa64_sve, s)) {
35
+ assert(dc_isar_feature(aa64_sme, s));
36
+ if (!sme_sm_enabled_check(s)) {
37
+ goto fail_exit;
24
+ }
38
+ }
25
+ break;
39
+ } else if (s->sve_excp_el) {
26
default:
40
gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
27
unallocated_encoding(s);
41
syn_sve_access_trap(), s->sve_excp_el);
28
return;
42
- return false;
29
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
43
+ goto fail_exit;
30
tcg_op, tcg_idx);
44
}
31
}
45
s->sve_access_checked = true;
32
break;
46
return fp_access_check(s);
33
+ case 0x1d: /* SQRDMLAH */
47
+
34
+ read_vec_element_i32(s, tcg_res, rd, pass,
48
+ fail_exit:
35
+ is_scalar ? size : MO_32);
49
+ /* Assert that we only raise one exception per instruction. */
36
+ if (size == 1) {
50
+ assert(!s->sve_access_checked);
37
+ gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
51
+ s->sve_access_checked = true;
38
+ tcg_op, tcg_idx, tcg_res);
52
+ return false;
39
+ } else {
53
}
40
+ gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
54
41
+ tcg_op, tcg_idx, tcg_res);
55
/*
42
+ }
43
+ break;
44
+ case 0x1f: /* SQRDMLSH */
45
+ read_vec_element_i32(s, tcg_res, rd, pass,
46
+ is_scalar ? size : MO_32);
47
+ if (size == 1) {
48
+ gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
49
+ tcg_op, tcg_idx, tcg_res);
50
+ } else {
51
+ gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
52
+ tcg_op, tcg_idx, tcg_res);
53
+ }
54
+ break;
55
default:
56
g_assert_not_reached();
57
}
58
--
56
--
59
2.16.2
57
2.25.1
60
61
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
These SME instructions are nominally within the SVE decode space,
4
so we add them to sve.decode and translate-sve.c.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-6-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-18-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
---
10
---
8
target/arm/helper.h | 9 +++++
11
target/arm/translate-a64.h | 12 ++++++++++++
9
target/arm/translate-a64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++
12
target/arm/sve.decode | 5 ++++-
10
target/arm/vec_helper.c | 74 +++++++++++++++++++++++++++++++++++++++++
13
target/arm/translate-sve.c | 38 ++++++++++++++++++++++++++++++++++++++
11
3 files changed, 166 insertions(+)
14
3 files changed, 54 insertions(+), 1 deletion(-)
12
15
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
18
--- a/target/arm/translate-a64.h
16
+++ b/target/arm/helper.h
19
+++ b/target/arm/translate-a64.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(dc_zva, void, env, i64)
20
@@ -XXX,XX +XXX,XX @@ static inline int vec_full_reg_size(DisasContext *s)
18
DEF_HELPER_FLAGS_2(neon_pmull_64_lo, TCG_CALL_NO_RWG_SE, i64, i64, i64)
21
return s->vl;
19
DEF_HELPER_FLAGS_2(neon_pmull_64_hi, TCG_CALL_NO_RWG_SE, i64, i64, i64)
20
21
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s16, TCG_CALL_NO_RWG,
22
+ void, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s16, TCG_CALL_NO_RWG,
24
+ void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
28
+ void, ptr, ptr, ptr, ptr, i32)
29
+
30
#ifdef TARGET_AARCH64
31
#include "helper-a64.h"
32
#endif
33
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-a64.c
36
+++ b/target/arm/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
38
vec_full_reg_size(s), gvec_op);
39
}
22
}
40
23
41
+/* Expand a 3-operand + env pointer operation using
24
+/* Return the byte size of the vector register, SVL / 8. */
42
+ * an out-of-line helper.
25
+static inline int streaming_vec_reg_size(DisasContext *s)
43
+ */
44
+static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
45
+ int rn, int rm, gen_helper_gvec_3_ptr *fn)
46
+{
26
+{
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
27
+ return s->svl;
48
+ vec_full_reg_offset(s, rn),
49
+ vec_full_reg_offset(s, rm), cpu_env,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
51
+}
28
+}
52
+
29
+
53
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
30
/*
54
* than the 32 bit equivalent.
31
* Return the offset info CPUARMState of the predicate vector register Pn.
55
*/
32
* Note for this purpose, FFR is P16.
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
33
@@ -XXX,XX +XXX,XX @@ static inline int pred_full_reg_size(DisasContext *s)
57
clear_vec_high(s, is_q, rd);
34
return s->vl >> 3;
58
}
35
}
59
36
60
+/* AdvSIMD three same extra
37
+/* Return the byte size of the predicate register, SVL / 64. */
61
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
38
+static inline int streaming_pred_reg_size(DisasContext *s)
62
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
63
+ * | 0 | Q | U | 0 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
64
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
65
+ */
66
+static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
+{
39
+{
68
+ int rd = extract32(insn, 0, 5);
40
+ return s->svl >> 3;
69
+ int rn = extract32(insn, 5, 5);
70
+ int opcode = extract32(insn, 11, 4);
71
+ int rm = extract32(insn, 16, 5);
72
+ int size = extract32(insn, 22, 2);
73
+ bool u = extract32(insn, 29, 1);
74
+ bool is_q = extract32(insn, 30, 1);
75
+ int feature;
76
+
77
+ switch (u * 16 + opcode) {
78
+ case 0x10: /* SQRDMLAH (vector) */
79
+ case 0x11: /* SQRDMLSH (vector) */
80
+ if (size != 1 && size != 2) {
81
+ unallocated_encoding(s);
82
+ return;
83
+ }
84
+ feature = ARM_FEATURE_V8_RDM;
85
+ break;
86
+ default:
87
+ unallocated_encoding(s);
88
+ return;
89
+ }
90
+ if (!arm_dc_feature(s, feature)) {
91
+ unallocated_encoding(s);
92
+ return;
93
+ }
94
+ if (!fp_access_check(s)) {
95
+ return;
96
+ }
97
+
98
+ switch (opcode) {
99
+ case 0x0: /* SQRDMLAH (vector) */
100
+ switch (size) {
101
+ case 1:
102
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
103
+ break;
104
+ case 2:
105
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
106
+ break;
107
+ default:
108
+ g_assert_not_reached();
109
+ }
110
+ return;
111
+
112
+ case 0x1: /* SQRDMLSH (vector) */
113
+ switch (size) {
114
+ case 1:
115
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
116
+ break;
117
+ case 2:
118
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
119
+ break;
120
+ default:
121
+ g_assert_not_reached();
122
+ }
123
+ return;
124
+
125
+ default:
126
+ g_assert_not_reached();
127
+ }
128
+}
41
+}
129
+
42
+
130
static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
43
/*
131
int size, int rn, int rd)
44
* Round up the size of a register to a size allowed by
132
{
45
* the tcg vector infrastructure. Any operation which uses this
133
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
46
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
134
static const AArch64DecodeTable data_proc_simd[] = {
135
/* pattern , mask , fn */
136
{ 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
137
+ { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
138
{ 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
139
{ 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
140
{ 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
141
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
142
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
143
--- a/target/arm/vec_helper.c
48
--- a/target/arm/sve.decode
144
+++ b/target/arm/vec_helper.c
49
+++ b/target/arm/sve.decode
145
@@ -XXX,XX +XXX,XX @@
50
@@ -XXX,XX +XXX,XX @@ INDEX_ri 00000100 esz:2 1 imm:s5 010001 rn:5 rd:5
146
51
# SVE index generation (register start, register increment)
147
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
52
INDEX_rr 00000100 .. 1 ..... 010011 ..... ..... @rd_rn_rm
148
53
149
+static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
54
-### SVE Stack Allocation Group
55
+### SVE / Streaming SVE Stack Allocation Group
56
57
# SVE stack frame adjustment
58
ADDVL 00000100 001 ..... 01010 ...... ..... @rd_rn_i6
59
+ADDSVL 00000100 001 ..... 01011 ...... ..... @rd_rn_i6
60
ADDPL 00000100 011 ..... 01010 ...... ..... @rd_rn_i6
61
+ADDSPL 00000100 011 ..... 01011 ...... ..... @rd_rn_i6
62
63
# SVE stack frame size
64
RDVL 00000100 101 11111 01010 imm:s6 rd:5
65
+RDSVL 00000100 101 11111 01011 imm:s6 rd:5
66
67
### SVE Bitwise Shift - Unpredicated Group
68
69
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/translate-sve.c
72
+++ b/target/arm/translate-sve.c
73
@@ -XXX,XX +XXX,XX @@ static bool trans_ADDVL(DisasContext *s, arg_ADDVL *a)
74
return true;
75
}
76
77
+static bool trans_ADDSVL(DisasContext *s, arg_ADDSVL *a)
150
+{
78
+{
151
+ uint64_t *d = vd + opr_sz;
79
+ if (!dc_isar_feature(aa64_sme, s)) {
152
+ uintptr_t i;
80
+ return false;
153
+
154
+ for (i = opr_sz; i < max_sz; i += 8) {
155
+ *d++ = 0;
156
+ }
81
+ }
82
+ if (sme_enabled_check(s)) {
83
+ TCGv_i64 rd = cpu_reg_sp(s, a->rd);
84
+ TCGv_i64 rn = cpu_reg_sp(s, a->rn);
85
+ tcg_gen_addi_i64(rd, rn, a->imm * streaming_vec_reg_size(s));
86
+ }
87
+ return true;
157
+}
88
+}
158
+
89
+
159
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
90
static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
160
static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
91
{
161
int16_t src2, int16_t src3)
92
if (!dc_isar_feature(aa64_sve, s)) {
162
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
93
@@ -XXX,XX +XXX,XX @@ static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
163
return deposit32(e1, 16, 16, e2);
94
return true;
164
}
95
}
165
96
166
+void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
97
+static bool trans_ADDSPL(DisasContext *s, arg_ADDSPL *a)
167
+ void *ve, uint32_t desc)
168
+{
98
+{
169
+ uintptr_t opr_sz = simd_oprsz(desc);
99
+ if (!dc_isar_feature(aa64_sme, s)) {
170
+ int16_t *d = vd;
100
+ return false;
171
+ int16_t *n = vn;
172
+ int16_t *m = vm;
173
+ CPUARMState *env = ve;
174
+ uintptr_t i;
175
+
176
+ for (i = 0; i < opr_sz / 2; ++i) {
177
+ d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
178
+ }
101
+ }
179
+ clear_tail(d, opr_sz, simd_maxsz(desc));
102
+ if (sme_enabled_check(s)) {
103
+ TCGv_i64 rd = cpu_reg_sp(s, a->rd);
104
+ TCGv_i64 rn = cpu_reg_sp(s, a->rn);
105
+ tcg_gen_addi_i64(rd, rn, a->imm * streaming_pred_reg_size(s));
106
+ }
107
+ return true;
180
+}
108
+}
181
+
109
+
182
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
110
static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
183
static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
111
{
184
int16_t src2, int16_t src3)
112
if (!dc_isar_feature(aa64_sve, s)) {
185
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
113
@@ -XXX,XX +XXX,XX @@ static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
186
return deposit32(e1, 16, 16, e2);
114
return true;
187
}
115
}
188
116
189
+void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
117
+static bool trans_RDSVL(DisasContext *s, arg_RDSVL *a)
190
+ void *ve, uint32_t desc)
191
+{
118
+{
192
+ uintptr_t opr_sz = simd_oprsz(desc);
119
+ if (!dc_isar_feature(aa64_sme, s)) {
193
+ int16_t *d = vd;
120
+ return false;
194
+ int16_t *n = vn;
195
+ int16_t *m = vm;
196
+ CPUARMState *env = ve;
197
+ uintptr_t i;
198
+
199
+ for (i = 0; i < opr_sz / 2; ++i) {
200
+ d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
201
+ }
121
+ }
202
+ clear_tail(d, opr_sz, simd_maxsz(desc));
122
+ if (sme_enabled_check(s)) {
123
+ TCGv_i64 reg = cpu_reg(s, a->rd);
124
+ tcg_gen_movi_i64(reg, a->imm * streaming_vec_reg_size(s));
125
+ }
126
+ return true;
203
+}
127
+}
204
+
128
+
205
/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
129
/*
206
uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
130
*** SVE Compute Vector Address Group
207
int32_t src2, int32_t src3)
131
*/
208
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
209
return ret;
210
}
211
212
+void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
213
+ void *ve, uint32_t desc)
214
+{
215
+ uintptr_t opr_sz = simd_oprsz(desc);
216
+ int32_t *d = vd;
217
+ int32_t *n = vn;
218
+ int32_t *m = vm;
219
+ CPUARMState *env = ve;
220
+ uintptr_t i;
221
+
222
+ for (i = 0; i < opr_sz / 4; ++i) {
223
+ d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
224
+ }
225
+ clear_tail(d, opr_sz, simd_maxsz(desc));
226
+}
227
+
228
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
229
uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
230
int32_t src2, int32_t src3)
231
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
232
}
233
return ret;
234
}
235
+
236
+void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
237
+ void *ve, uint32_t desc)
238
+{
239
+ uintptr_t opr_sz = simd_oprsz(desc);
240
+ int32_t *d = vd;
241
+ int32_t *n = vn;
242
+ int32_t *m = vm;
243
+ CPUARMState *env = ve;
244
+ uintptr_t i;
245
+
246
+ for (i = 0; i < opr_sz / 4; ++i) {
247
+ d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
248
+ }
249
+ clear_tail(d, opr_sz, simd_maxsz(desc));
250
+}
251
--
132
--
252
2.16.2
133
2.25.1
253
254
diff view generated by jsdifflib
1
Model the Arm IoT Kit documented in
1
From: Richard Henderson <richard.henderson@linaro.org>
2
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
3
2
4
The Arm IoT Kit is a subsystem which includes a CPU and some devices,
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
and is intended be extended by adding extra devices to form a
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
complete system. It is used in the MPS2 board's AN505 image for the
5
Message-id: 20220708151540.18136-19-richard.henderson@linaro.org
7
Cortex-M33.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/helper-sme.h | 2 ++
9
target/arm/sme.decode | 4 ++++
10
target/arm/sme_helper.c | 25 +++++++++++++++++++++++++
11
target/arm/translate-sme.c | 13 +++++++++++++
12
4 files changed, 44 insertions(+)
8
13
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180220180325.29818-19-peter.maydell@linaro.org
12
---
13
hw/arm/Makefile.objs | 1 +
14
include/hw/arm/iotkit.h | 109 ++++++++
15
hw/arm/iotkit.c | 598 ++++++++++++++++++++++++++++++++++++++++
16
default-configs/arm-softmmu.mak | 1 +
17
4 files changed, 709 insertions(+)
18
create mode 100644 include/hw/arm/iotkit.h
19
create mode 100644 hw/arm/iotkit.c
20
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/Makefile.objs
16
--- a/target/arm/helper-sme.h
24
+++ b/hw/arm/Makefile.objs
17
+++ b/target/arm/helper-sme.h
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
26
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
27
obj-$(CONFIG_MPS2) += mps2.o
28
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
29
+obj-$(CONFIG_IOTKIT) += iotkit.o
30
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
31
new file mode 100644
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/include/hw/arm/iotkit.h
35
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
36
+/*
19
37
+ * ARM IoT Kit
20
DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
38
+ *
21
DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
39
+ * Copyright (c) 2018 Linaro Limited
40
+ * Written by Peter Maydell
41
+ *
42
+ * This program is free software; you can redistribute it and/or modify
43
+ * it under the terms of the GNU General Public License version 2 or
44
+ * (at your option) any later version.
45
+ */
46
+
22
+
47
+/* This is a model of the Arm IoT Kit which is documented in
23
+DEF_HELPER_FLAGS_3(sme_zero, TCG_CALL_NO_RWG, void, env, i32, i32)
48
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
24
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
49
+ * It contains:
25
index XXXXXXX..XXXXXXX 100644
50
+ * a Cortex-M33
26
--- a/target/arm/sme.decode
51
+ * the IDAU
27
+++ b/target/arm/sme.decode
52
+ * some timers and watchdogs
28
@@ -XXX,XX +XXX,XX @@
53
+ * two peripheral protection controllers
29
#
54
+ * a memory protection controller
30
# This file is processed by scripts/decodetree.py
55
+ * a security controller
31
#
56
+ * a bus fabric which arranges that some parts of the address
57
+ * space are secure and non-secure aliases of each other
58
+ *
59
+ * QEMU interface:
60
+ * + QOM property "memory" is a MemoryRegion containing the devices provided
61
+ * by the board model.
62
+ * + QOM property "MAINCLK" is the frequency of the main system clock
63
+ * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
64
+ * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
65
+ * are wired to the NVIC lines 32 .. n+32
66
+ * Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
67
+ * might provide:
68
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
69
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
70
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
71
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
72
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
73
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
74
+ * might provide:
75
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
76
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
77
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
78
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
79
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
80
+ */
81
+
32
+
82
+#ifndef IOTKIT_H
33
+### SME Misc
83
+#define IOTKIT_H
84
+
34
+
85
+#include "hw/sysbus.h"
35
+ZERO 11000000 00 001 00000000000 imm:8
86
+#include "hw/arm/armv7m.h"
36
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
87
+#include "hw/misc/iotkit-secctl.h"
37
index XXXXXXX..XXXXXXX 100644
88
+#include "hw/misc/tz-ppc.h"
38
--- a/target/arm/sme_helper.c
89
+#include "hw/timer/cmsdk-apb-timer.h"
39
+++ b/target/arm/sme_helper.c
90
+#include "hw/misc/unimp.h"
40
@@ -XXX,XX +XXX,XX @@ void helper_set_pstate_za(CPUARMState *env, uint32_t i)
91
+#include "hw/or-irq.h"
41
memset(env->zarray, 0, sizeof(env->zarray));
92
+#include "hw/core/split-irq.h"
42
}
43
}
93
+
44
+
94
+#define TYPE_IOTKIT "iotkit"
45
+void helper_sme_zero(CPUARMState *env, uint32_t imm, uint32_t svl)
95
+#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
46
+{
47
+ uint32_t i;
96
+
48
+
97
+/* We have an IRQ splitter and an OR gate input for each external PPC
49
+ /*
98
+ * and the 2 internal PPCs
50
+ * Special case clearing the entire ZA space.
99
+ */
51
+ * This falls into the CONSTRAINED UNPREDICTABLE zeroing of any
100
+#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
52
+ * parts of the ZA storage outside of SVL.
101
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
102
+
103
+typedef struct IoTKit {
104
+ /*< private >*/
105
+ SysBusDevice parent_obj;
106
+
107
+ /*< public >*/
108
+ ARMv7MState armv7m;
109
+ IoTKitSecCtl secctl;
110
+ TZPPC apb_ppc0;
111
+ TZPPC apb_ppc1;
112
+ CMSDKAPBTIMER timer0;
113
+ CMSDKAPBTIMER timer1;
114
+ qemu_or_irq ppc_irq_orgate;
115
+ SplitIRQ sec_resp_splitter;
116
+ SplitIRQ ppc_irq_splitter[NUM_PPCS];
117
+
118
+ UnimplementedDeviceState dualtimer;
119
+ UnimplementedDeviceState s32ktimer;
120
+
121
+ MemoryRegion container;
122
+ MemoryRegion alias1;
123
+ MemoryRegion alias2;
124
+ MemoryRegion alias3;
125
+ MemoryRegion sram0;
126
+
127
+ qemu_irq *exp_irqs;
128
+ qemu_irq ppc0_irq;
129
+ qemu_irq ppc1_irq;
130
+ qemu_irq sec_resp_cfg;
131
+ qemu_irq sec_resp_cfg_in;
132
+ qemu_irq nsc_cfg_in;
133
+
134
+ qemu_irq irq_status_in[NUM_EXTERNAL_PPCS];
135
+
136
+ uint32_t nsccfg;
137
+
138
+ /* Properties */
139
+ MemoryRegion *board_memory;
140
+ uint32_t exp_numirq;
141
+ uint32_t mainclk_frq;
142
+} IoTKit;
143
+
144
+#endif
145
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
146
new file mode 100644
147
index XXXXXXX..XXXXXXX
148
--- /dev/null
149
+++ b/hw/arm/iotkit.c
150
@@ -XXX,XX +XXX,XX @@
151
+/*
152
+ * Arm IoT Kit
153
+ *
154
+ * Copyright (c) 2018 Linaro Limited
155
+ * Written by Peter Maydell
156
+ *
157
+ * This program is free software; you can redistribute it and/or modify
158
+ * it under the terms of the GNU General Public License version 2 or
159
+ * (at your option) any later version.
160
+ */
161
+
162
+#include "qemu/osdep.h"
163
+#include "qemu/log.h"
164
+#include "qapi/error.h"
165
+#include "trace.h"
166
+#include "hw/sysbus.h"
167
+#include "hw/registerfields.h"
168
+#include "hw/arm/iotkit.h"
169
+#include "hw/misc/unimp.h"
170
+#include "hw/arm/arm.h"
171
+
172
+/* Create an alias region of @size bytes starting at @base
173
+ * which mirrors the memory starting at @orig.
174
+ */
175
+static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
176
+ hwaddr base, hwaddr size, hwaddr orig)
177
+{
178
+ memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
179
+ /* The alias is even lower priority than unimplemented_device regions */
180
+ memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
181
+}
182
+
183
+static void init_sysbus_child(Object *parent, const char *childname,
184
+ void *child, size_t childsize,
185
+ const char *childtype)
186
+{
187
+ object_initialize(child, childsize, childtype);
188
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
189
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
190
+}
191
+
192
+static void irq_status_forwarder(void *opaque, int n, int level)
193
+{
194
+ qemu_irq destirq = opaque;
195
+
196
+ qemu_set_irq(destirq, level);
197
+}
198
+
199
+static void nsccfg_handler(void *opaque, int n, int level)
200
+{
201
+ IoTKit *s = IOTKIT(opaque);
202
+
203
+ s->nsccfg = level;
204
+}
205
+
206
+static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
207
+{
208
+ /* Each of the 4 AHB and 4 APB PPCs that might be present in a
209
+ * system using the IoTKit has a collection of control lines which
210
+ * are provided by the security controller and which we want to
211
+ * expose as control lines on the IoTKit device itself, so the
212
+ * code using the IoTKit can wire them up to the PPCs.
213
+ */
53
+ */
214
+ SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
54
+ if (imm == 0xff) {
215
+ DeviceState *iotkitdev = DEVICE(s);
55
+ memset(env->zarray, 0, sizeof(env->zarray));
216
+ DeviceState *dev_secctl = DEVICE(&s->secctl);
217
+ DeviceState *dev_splitter = DEVICE(splitter);
218
+ char *name;
219
+
220
+ name = g_strdup_printf("%s_nonsec", ppcname);
221
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
222
+ g_free(name);
223
+ name = g_strdup_printf("%s_ap", ppcname);
224
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
225
+ g_free(name);
226
+ name = g_strdup_printf("%s_irq_enable", ppcname);
227
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
228
+ g_free(name);
229
+ name = g_strdup_printf("%s_irq_clear", ppcname);
230
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
231
+ g_free(name);
232
+
233
+ /* irq_status is a little more tricky, because we need to
234
+ * split it so we can send it both to the security controller
235
+ * and to our OR gate for the NVIC interrupt line.
236
+ * Connect up the splitter's outputs, and create a GPIO input
237
+ * which will pass the line state to the input splitter.
238
+ */
239
+ name = g_strdup_printf("%s_irq_status", ppcname);
240
+ qdev_connect_gpio_out(dev_splitter, 0,
241
+ qdev_get_gpio_in_named(dev_secctl,
242
+ name, 0));
243
+ qdev_connect_gpio_out(dev_splitter, 1,
244
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
245
+ s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
246
+ qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
247
+ s->irq_status_in[ppcnum], name, 1);
248
+ g_free(name);
249
+}
250
+
251
+static void iotkit_forward_sec_resp_cfg(IoTKit *s)
252
+{
253
+ /* Forward the 3rd output from the splitter device as a
254
+ * named GPIO output of the iotkit object.
255
+ */
256
+ DeviceState *dev = DEVICE(s);
257
+ DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
258
+
259
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
260
+ s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
261
+ s->sec_resp_cfg, 1);
262
+ qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
263
+}
264
+
265
+static void iotkit_init(Object *obj)
266
+{
267
+ IoTKit *s = IOTKIT(obj);
268
+ int i;
269
+
270
+ memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
271
+
272
+ init_sysbus_child(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
273
+ TYPE_ARMV7M);
274
+ qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
275
+ ARM_CPU_TYPE_NAME("cortex-m33"));
276
+
277
+ init_sysbus_child(obj, "secctl", &s->secctl, sizeof(s->secctl),
278
+ TYPE_IOTKIT_SECCTL);
279
+ init_sysbus_child(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
280
+ TYPE_TZ_PPC);
281
+ init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
282
+ TYPE_TZ_PPC);
283
+ init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
284
+ TYPE_CMSDK_APB_TIMER);
285
+ init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
286
+ TYPE_CMSDK_APB_TIMER);
287
+ init_sysbus_child(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
288
+ TYPE_UNIMPLEMENTED_DEVICE);
289
+ object_initialize(&s->ppc_irq_orgate, sizeof(s->ppc_irq_orgate),
290
+ TYPE_OR_IRQ);
291
+ object_property_add_child(obj, "ppc-irq-orgate",
292
+ OBJECT(&s->ppc_irq_orgate), &error_abort);
293
+ object_initialize(&s->sec_resp_splitter, sizeof(s->sec_resp_splitter),
294
+ TYPE_SPLIT_IRQ);
295
+ object_property_add_child(obj, "sec-resp-splitter",
296
+ OBJECT(&s->sec_resp_splitter), &error_abort);
297
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
298
+ char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
299
+ SplitIRQ *splitter = &s->ppc_irq_splitter[i];
300
+
301
+ object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ);
302
+ object_property_add_child(obj, name, OBJECT(splitter), &error_abort);
303
+ }
304
+ init_sysbus_child(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
305
+ TYPE_UNIMPLEMENTED_DEVICE);
306
+}
307
+
308
+static void iotkit_exp_irq(void *opaque, int n, int level)
309
+{
310
+ IoTKit *s = IOTKIT(opaque);
311
+
312
+ qemu_set_irq(s->exp_irqs[n], level);
313
+}
314
+
315
+static void iotkit_realize(DeviceState *dev, Error **errp)
316
+{
317
+ IoTKit *s = IOTKIT(dev);
318
+ int i;
319
+ MemoryRegion *mr;
320
+ Error *err = NULL;
321
+ SysBusDevice *sbd_apb_ppc0;
322
+ SysBusDevice *sbd_secctl;
323
+ DeviceState *dev_apb_ppc0;
324
+ DeviceState *dev_apb_ppc1;
325
+ DeviceState *dev_secctl;
326
+ DeviceState *dev_splitter;
327
+
328
+ if (!s->board_memory) {
329
+ error_setg(errp, "memory property was not set");
330
+ return;
56
+ return;
331
+ }
57
+ }
332
+
58
+
333
+ if (!s->mainclk_frq) {
59
+ /*
334
+ error_setg(errp, "MAINCLK property was not set");
60
+ * Recall that ZAnH.D[m] is spread across ZA[n+8*m],
335
+ return;
61
+ * so each row is discontiguous within ZA[].
336
+ }
337
+
338
+ /* Handling of which devices should be available only to secure
339
+ * code is usually done differently for M profile than for A profile.
340
+ * Instead of putting some devices only into the secure address space,
341
+ * devices exist in both address spaces but with hard-wired security
342
+ * permissions that will cause the CPU to fault for non-secure accesses.
343
+ *
344
+ * The IoTKit has an IDAU (Implementation Defined Access Unit),
345
+ * which specifies hard-wired security permissions for different
346
+ * areas of the physical address space. For the IoTKit IDAU, the
347
+ * top 4 bits of the physical address are the IDAU region ID, and
348
+ * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
349
+ * region, otherwise it is an S region.
350
+ *
351
+ * The various devices and RAMs are generally all mapped twice,
352
+ * once into a region that the IDAU defines as secure and once
353
+ * into a non-secure region. They sit behind either a Memory
354
+ * Protection Controller (for RAM) or a Peripheral Protection
355
+ * Controller (for devices), which allow a more fine grained
356
+ * configuration of whether non-secure accesses are permitted.
357
+ *
358
+ * (The other place that guest software can configure security
359
+ * permissions is in the architected SAU (Security Attribution
360
+ * Unit), which is entirely inside the CPU. The IDAU can upgrade
361
+ * the security attributes for a region to more restrictive than
362
+ * the SAU specifies, but cannot downgrade them.)
363
+ *
364
+ * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
365
+ * 0x20000000..0x2007ffff 32KB FPGA block RAM
366
+ * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
367
+ * 0x40000000..0x4000ffff base peripheral region 1
368
+ * 0x40010000..0x4001ffff CPU peripherals (none for IoTKit)
369
+ * 0x40020000..0x4002ffff system control element peripherals
370
+ * 0x40080000..0x400fffff base peripheral region 2
371
+ * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
372
+ */
62
+ */
373
+
63
+ for (i = 0; i < svl; i++) {
374
+ memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
64
+ if (imm & (1 << (i % 8))) {
375
+
65
+ memset(&env->zarray[i], 0, svl);
376
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
377
+ /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
378
+ * register in the IoT Kit System Control Register block, and the
379
+ * initial value of that is in turn specifiable by the FPGA that
380
+ * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
381
+ * and simply set the CPU's init-svtor to the IoT Kit default value.
382
+ */
383
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
384
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
385
+ "memory", &err);
386
+ if (err) {
387
+ error_propagate(errp, err);
388
+ return;
389
+ }
390
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
391
+ if (err) {
392
+ error_propagate(errp, err);
393
+ return;
394
+ }
395
+ object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
396
+ if (err) {
397
+ error_propagate(errp, err);
398
+ return;
399
+ }
400
+
401
+ /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
402
+ s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
403
+ for (i = 0; i < s->exp_numirq; i++) {
404
+ s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
405
+ }
406
+ qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
407
+
408
+ /* Set up the big aliases first */
409
+ make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
410
+ make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
411
+ /* The 0x50000000..0x5fffffff region is not a pure alias: it has
412
+ * a few extra devices that only appear there (generally the
413
+ * control interfaces for the protection controllers).
414
+ * We implement this by mapping those devices over the top of this
415
+ * alias MR at a higher priority.
416
+ */
417
+ make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
418
+
419
+ /* This RAM should be behind a Memory Protection Controller, but we
420
+ * don't implement that yet.
421
+ */
422
+ memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
423
+ if (err) {
424
+ error_propagate(errp, err);
425
+ return;
426
+ }
427
+ memory_region_add_subregion(&s->container, 0x20000000, &s->sram0);
428
+
429
+ /* Security controller */
430
+ object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
431
+ if (err) {
432
+ error_propagate(errp, err);
433
+ return;
434
+ }
435
+ sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
436
+ dev_secctl = DEVICE(&s->secctl);
437
+ sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
438
+ sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
439
+
440
+ s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
441
+ qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
442
+
443
+ /* The sec_resp_cfg output from the security controller must be split into
444
+ * multiple lines, one for each of the PPCs within the IoTKit and one
445
+ * that will be an output from the IoTKit to the system.
446
+ */
447
+ object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
448
+ "num-lines", &err);
449
+ if (err) {
450
+ error_propagate(errp, err);
451
+ return;
452
+ }
453
+ object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
454
+ "realized", &err);
455
+ if (err) {
456
+ error_propagate(errp, err);
457
+ return;
458
+ }
459
+ dev_splitter = DEVICE(&s->sec_resp_splitter);
460
+ qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
461
+ qdev_get_gpio_in(dev_splitter, 0));
462
+
463
+ /* Devices behind APB PPC0:
464
+ * 0x40000000: timer0
465
+ * 0x40001000: timer1
466
+ * 0x40002000: dual timer
467
+ * We must configure and realize each downstream device and connect
468
+ * it to the appropriate PPC port; then we can realize the PPC and
469
+ * map its upstream ends to the right place in the container.
470
+ */
471
+ qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
472
+ object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
473
+ if (err) {
474
+ error_propagate(errp, err);
475
+ return;
476
+ }
477
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
478
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
479
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
480
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
481
+ if (err) {
482
+ error_propagate(errp, err);
483
+ return;
484
+ }
485
+
486
+ qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
487
+ object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
488
+ if (err) {
489
+ error_propagate(errp, err);
490
+ return;
491
+ }
492
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
493
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
494
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
495
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
496
+ if (err) {
497
+ error_propagate(errp, err);
498
+ return;
499
+ }
500
+
501
+ qdev_prop_set_string(DEVICE(&s->dualtimer), "name", "Dual timer");
502
+ qdev_prop_set_uint64(DEVICE(&s->dualtimer), "size", 0x1000);
503
+ object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
504
+ if (err) {
505
+ error_propagate(errp, err);
506
+ return;
507
+ }
508
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
509
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
510
+ if (err) {
511
+ error_propagate(errp, err);
512
+ return;
513
+ }
514
+
515
+ object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
516
+ if (err) {
517
+ error_propagate(errp, err);
518
+ return;
519
+ }
520
+
521
+ sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
522
+ dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
523
+
524
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
525
+ memory_region_add_subregion(&s->container, 0x40000000, mr);
526
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
527
+ memory_region_add_subregion(&s->container, 0x40001000, mr);
528
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
529
+ memory_region_add_subregion(&s->container, 0x40002000, mr);
530
+ for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
531
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
532
+ qdev_get_gpio_in_named(dev_apb_ppc0,
533
+ "cfg_nonsec", i));
534
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
535
+ qdev_get_gpio_in_named(dev_apb_ppc0,
536
+ "cfg_ap", i));
537
+ }
538
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
539
+ qdev_get_gpio_in_named(dev_apb_ppc0,
540
+ "irq_enable", 0));
541
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
542
+ qdev_get_gpio_in_named(dev_apb_ppc0,
543
+ "irq_clear", 0));
544
+ qdev_connect_gpio_out(dev_splitter, 0,
545
+ qdev_get_gpio_in_named(dev_apb_ppc0,
546
+ "cfg_sec_resp", 0));
547
+
548
+ /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
549
+ * ones) are sent individually to the security controller, and also
550
+ * ORed together to give a single combined PPC interrupt to the NVIC.
551
+ */
552
+ object_property_set_int(OBJECT(&s->ppc_irq_orgate),
553
+ NUM_PPCS, "num-lines", &err);
554
+ if (err) {
555
+ error_propagate(errp, err);
556
+ return;
557
+ }
558
+ object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
559
+ "realized", &err);
560
+ if (err) {
561
+ error_propagate(errp, err);
562
+ return;
563
+ }
564
+ qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
565
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
566
+
567
+ /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
568
+
569
+ /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
570
+ /* Devices behind APB PPC1:
571
+ * 0x4002f000: S32K timer
572
+ */
573
+ qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER");
574
+ qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000);
575
+ object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
576
+ if (err) {
577
+ error_propagate(errp, err);
578
+ return;
579
+ }
580
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
581
+ object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
582
+ if (err) {
583
+ error_propagate(errp, err);
584
+ return;
585
+ }
586
+
587
+ object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
588
+ if (err) {
589
+ error_propagate(errp, err);
590
+ return;
591
+ }
592
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
593
+ memory_region_add_subregion(&s->container, 0x4002f000, mr);
594
+
595
+ dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
596
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
597
+ qdev_get_gpio_in_named(dev_apb_ppc1,
598
+ "cfg_nonsec", 0));
599
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
600
+ qdev_get_gpio_in_named(dev_apb_ppc1,
601
+ "cfg_ap", 0));
602
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
603
+ qdev_get_gpio_in_named(dev_apb_ppc1,
604
+ "irq_enable", 0));
605
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
606
+ qdev_get_gpio_in_named(dev_apb_ppc1,
607
+ "irq_clear", 0));
608
+ qdev_connect_gpio_out(dev_splitter, 1,
609
+ qdev_get_gpio_in_named(dev_apb_ppc1,
610
+ "cfg_sec_resp", 0));
611
+
612
+ /* Using create_unimplemented_device() maps the stub into the
613
+ * system address space rather than into our container, but the
614
+ * overall effect to the guest is the same.
615
+ */
616
+ create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
617
+
618
+ create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
619
+ create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
620
+
621
+ /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
622
+
623
+ create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
624
+ create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
625
+
626
+ create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
627
+
628
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
629
+ Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
630
+
631
+ object_property_set_int(splitter, 2, "num-lines", &err);
632
+ if (err) {
633
+ error_propagate(errp, err);
634
+ return;
635
+ }
636
+ object_property_set_bool(splitter, true, "realized", &err);
637
+ if (err) {
638
+ error_propagate(errp, err);
639
+ return;
640
+ }
66
+ }
641
+ }
67
+ }
68
+}
69
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/translate-sme.c
72
+++ b/target/arm/translate-sme.c
73
@@ -XXX,XX +XXX,XX @@
74
*/
75
76
#include "decode-sme.c.inc"
642
+
77
+
643
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
644
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
645
+
78
+
646
+ iotkit_forward_ppc(s, ppcname, i);
79
+static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
647
+ g_free(ppcname);
80
+{
81
+ if (!dc_isar_feature(aa64_sme, s)) {
82
+ return false;
648
+ }
83
+ }
649
+
84
+ if (sme_za_enabled_check(s)) {
650
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
85
+ gen_helper_sme_zero(cpu_env, tcg_constant_i32(a->imm),
651
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
86
+ tcg_constant_i32(streaming_vec_reg_size(s)));
652
+
653
+ iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
654
+ g_free(ppcname);
655
+ }
87
+ }
656
+
88
+ return true;
657
+ for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
658
+ /* Wire up IRQ splitter for internal PPCs */
659
+ DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
660
+ char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
661
+ i - NUM_EXTERNAL_PPCS);
662
+ TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
663
+
664
+ qdev_connect_gpio_out(devs, 0,
665
+ qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
666
+ qdev_connect_gpio_out(devs, 1,
667
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
668
+ qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
669
+ qdev_get_gpio_in(devs, 0));
670
+ }
671
+
672
+ iotkit_forward_sec_resp_cfg(s);
673
+
674
+ system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
675
+}
89
+}
676
+
677
+static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
678
+ int *iregion, bool *exempt, bool *ns, bool *nsc)
679
+{
680
+ /* For IoTKit systems the IDAU responses are simple logical functions
681
+ * of the address bits. The NSC attribute is guest-adjustable via the
682
+ * NSCCFG register in the security controller.
683
+ */
684
+ IoTKit *s = IOTKIT(ii);
685
+ int region = extract32(address, 28, 4);
686
+
687
+ *ns = !(region & 1);
688
+ *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
689
+ /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
690
+ *exempt = (address & 0xeff00000) == 0xe0000000;
691
+ *iregion = region;
692
+}
693
+
694
+static const VMStateDescription iotkit_vmstate = {
695
+ .name = "iotkit",
696
+ .version_id = 1,
697
+ .minimum_version_id = 1,
698
+ .fields = (VMStateField[]) {
699
+ VMSTATE_UINT32(nsccfg, IoTKit),
700
+ VMSTATE_END_OF_LIST()
701
+ }
702
+};
703
+
704
+static Property iotkit_properties[] = {
705
+ DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
706
+ MemoryRegion *),
707
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
708
+ DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
709
+ DEFINE_PROP_END_OF_LIST()
710
+};
711
+
712
+static void iotkit_reset(DeviceState *dev)
713
+{
714
+ IoTKit *s = IOTKIT(dev);
715
+
716
+ s->nsccfg = 0;
717
+}
718
+
719
+static void iotkit_class_init(ObjectClass *klass, void *data)
720
+{
721
+ DeviceClass *dc = DEVICE_CLASS(klass);
722
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
723
+
724
+ dc->realize = iotkit_realize;
725
+ dc->vmsd = &iotkit_vmstate;
726
+ dc->props = iotkit_properties;
727
+ dc->reset = iotkit_reset;
728
+ iic->check = iotkit_idau_check;
729
+}
730
+
731
+static const TypeInfo iotkit_info = {
732
+ .name = TYPE_IOTKIT,
733
+ .parent = TYPE_SYS_BUS_DEVICE,
734
+ .instance_size = sizeof(IoTKit),
735
+ .instance_init = iotkit_init,
736
+ .class_init = iotkit_class_init,
737
+ .interfaces = (InterfaceInfo[]) {
738
+ { TYPE_IDAU_INTERFACE },
739
+ { }
740
+ }
741
+};
742
+
743
+static void iotkit_register_types(void)
744
+{
745
+ type_register_static(&iotkit_info);
746
+}
747
+
748
+type_init(iotkit_register_types);
749
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
750
index XXXXXXX..XXXXXXX 100644
751
--- a/default-configs/arm-softmmu.mak
752
+++ b/default-configs/arm-softmmu.mak
753
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
754
CONFIG_MPS2_SCC=y
755
756
CONFIG_TZ_PPC=y
757
+CONFIG_IOTKIT=y
758
CONFIG_IOTKIT_SECCTL=y
759
760
CONFIG_VERSATILE_PCI=y
761
--
90
--
762
2.16.2
91
2.25.1
763
764
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We can reuse the SVE functions for implementing moves to/from
4
horizontal tile slices, but we need new ones for moves to/from
5
vertical tile slices.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20180228193125.20577-15-richard.henderson@linaro.org
9
Message-id: 20220708151540.18136-20-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/translate.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
12
target/arm/helper-sme.h | 12 +++
9
1 file changed, 61 insertions(+)
13
target/arm/helper-sve.h | 2 +
14
target/arm/translate-a64.h | 8 ++
15
target/arm/translate.h | 5 ++
16
target/arm/sme.decode | 15 ++++
17
target/arm/sme_helper.c | 151 ++++++++++++++++++++++++++++++++++++-
18
target/arm/sve_helper.c | 12 +++
19
target/arm/translate-sme.c | 127 +++++++++++++++++++++++++++++++
20
8 files changed, 331 insertions(+), 1 deletion(-)
10
21
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
22
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
12
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
24
--- a/target/arm/helper-sme.h
14
+++ b/target/arm/translate.c
25
+++ b/target/arm/helper-sme.h
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
16
return 0;
27
DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
28
29
DEF_HELPER_FLAGS_3(sme_zero, TCG_CALL_NO_RWG, void, env, i32, i32)
30
+
31
+/* Move to/from vertical array slices, i.e. columns, so 'c'. */
32
+DEF_HELPER_FLAGS_4(sme_mova_cz_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_4(sme_mova_zc_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(sme_mova_cz_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(sme_mova_zc_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_4(sme_mova_cz_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
+DEF_HELPER_FLAGS_4(sme_mova_zc_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(sme_mova_cz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(sme_mova_zc_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_4(sme_mova_cz_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
41
+DEF_HELPER_FLAGS_4(sme_mova_zc_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
42
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper-sve.h
45
+++ b/target/arm/helper-sve.h
46
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_sel_zpzz_s, TCG_CALL_NO_RWG,
47
void, ptr, ptr, ptr, ptr, i32)
48
DEF_HELPER_FLAGS_5(sve_sel_zpzz_d, TCG_CALL_NO_RWG,
49
void, ptr, ptr, ptr, ptr, i32)
50
+DEF_HELPER_FLAGS_5(sve_sel_zpzz_q, TCG_CALL_NO_RWG,
51
+ void, ptr, ptr, ptr, ptr, i32)
52
53
DEF_HELPER_FLAGS_5(sve2_addp_zpzz_b, TCG_CALL_NO_RWG,
54
void, ptr, ptr, ptr, ptr, i32)
55
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-a64.h
58
+++ b/target/arm/translate-a64.h
59
@@ -XXX,XX +XXX,XX @@ static inline int pred_gvec_reg_size(DisasContext *s)
60
return size_for_gvec(pred_full_reg_size(s));
17
}
61
}
18
62
19
+/* Advanced SIMD two registers and a scalar extension.
63
+/* Return a newly allocated pointer to the predicate register. */
20
+ * 31 24 23 22 20 16 12 11 10 9 8 3 0
64
+static inline TCGv_ptr pred_full_reg_ptr(DisasContext *s, int regno)
21
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
65
+{
22
+ * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
66
+ TCGv_ptr ret = tcg_temp_new_ptr();
23
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
67
+ tcg_gen_addi_ptr(ret, cpu_env, pred_full_reg_offset(s, regno));
24
+ *
68
+ return ret;
69
+}
70
+
71
bool disas_sve(DisasContext *, uint32_t);
72
bool disas_sme(DisasContext *, uint32_t);
73
74
diff --git a/target/arm/translate.h b/target/arm/translate.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/translate.h
77
+++ b/target/arm/translate.h
78
@@ -XXX,XX +XXX,XX @@ static inline int plus_2(DisasContext *s, int x)
79
return x + 2;
80
}
81
82
+static inline int plus_12(DisasContext *s, int x)
83
+{
84
+ return x + 12;
85
+}
86
+
87
static inline int times_2(DisasContext *s, int x)
88
{
89
return x * 2;
90
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/sme.decode
93
+++ b/target/arm/sme.decode
94
@@ -XXX,XX +XXX,XX @@
95
### SME Misc
96
97
ZERO 11000000 00 001 00000000000 imm:8
98
+
99
+### SME Move into/from Array
100
+
101
+%mova_rs 13:2 !function=plus_12
102
+&mova esz rs pg zr za_imm v:bool to_vec:bool
103
+
104
+MOVA 11000000 esz:2 00000 0 v:1 .. pg:3 zr:5 0 za_imm:4 \
105
+ &mova to_vec=0 rs=%mova_rs
106
+MOVA 11000000 11 00000 1 v:1 .. pg:3 zr:5 0 za_imm:4 \
107
+ &mova to_vec=0 rs=%mova_rs esz=4
108
+
109
+MOVA 11000000 esz:2 00001 0 v:1 .. pg:3 0 za_imm:4 zr:5 \
110
+ &mova to_vec=1 rs=%mova_rs
111
+MOVA 11000000 11 00001 1 v:1 .. pg:3 0 za_imm:4 zr:5 \
112
+ &mova to_vec=1 rs=%mova_rs esz=4
113
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/sme_helper.c
116
+++ b/target/arm/sme_helper.c
117
@@ -XXX,XX +XXX,XX @@
118
119
#include "qemu/osdep.h"
120
#include "cpu.h"
121
-#include "internals.h"
122
+#include "tcg/tcg-gvec-desc.h"
123
#include "exec/helper-proto.h"
124
+#include "qemu/int128.h"
125
+#include "vec_internal.h"
126
127
/* ResetSVEState */
128
void arm_reset_sve_state(CPUARMState *env)
129
@@ -XXX,XX +XXX,XX @@ void helper_sme_zero(CPUARMState *env, uint32_t imm, uint32_t svl)
130
}
131
}
132
}
133
+
134
+
135
+/*
136
+ * When considering the ZA storage as an array of elements of
137
+ * type T, the index within that array of the Nth element of
138
+ * a vertical slice of a tile can be calculated like this,
139
+ * regardless of the size of type T. This is because the tiles
140
+ * are interleaved, so if type T is size N bytes then row 1 of
141
+ * the tile is N rows away from row 0. The division by N to
142
+ * convert a byte offset into an array index and the multiplication
143
+ * by N to convert from vslice-index-within-the-tile to
144
+ * the index within the ZA storage cancel out.
25
+ */
145
+ */
26
+
146
+#define tile_vslice_index(i) ((i) * sizeof(ARMVectorReg))
27
+static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
147
+
28
+{
148
+/*
29
+ int rd, rn, rm, rot, size, opr_sz;
149
+ * When doing byte arithmetic on the ZA storage, the element
30
+ TCGv_ptr fpst;
150
+ * byteoff bytes away in a tile vertical slice is always this
31
+ bool q;
151
+ * many bytes away in the ZA storage, regardless of the
32
+
152
+ * size of the tile element, assuming that byteoff is a multiple
33
+ q = extract32(insn, 6, 1);
153
+ * of the element size. Again this is because of the interleaving
34
+ VFP_DREG_D(rd, insn);
154
+ * of the tiles. For instance if we have 1 byte per element then
35
+ VFP_DREG_N(rn, insn);
155
+ * each row of the ZA storage has one byte of the vslice data,
36
+ VFP_DREG_M(rm, insn);
156
+ * and (counting from 0) byte 8 goes in row 8 of the storage
37
+ if ((rd | rn) & q) {
157
+ * at offset (8 * row-size-in-bytes).
38
+ return 1;
158
+ * If we have 8 bytes per element then each row of the ZA storage
39
+ }
159
+ * has 8 bytes of the data, but there are 8 interleaved tiles and
40
+
160
+ * so byte 8 of the data goes into row 1 of the tile,
41
+ if ((insn & 0xff000f10) == 0xfe000800) {
161
+ * which is again row 8 of the storage, so the offset is still
42
+ /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
162
+ * (8 * row-size-in-bytes). Similarly for other element sizes.
43
+ rot = extract32(insn, 20, 2);
163
+ */
44
+ size = extract32(insn, 23, 1);
164
+#define tile_vslice_offset(byteoff) ((byteoff) * sizeof(ARMVectorReg))
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
165
+
46
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
166
+
47
+ return 1;
167
+/*
168
+ * Move Zreg vector to ZArray column.
169
+ */
170
+#define DO_MOVA_C(NAME, TYPE, H) \
171
+void HELPER(NAME)(void *za, void *vn, void *vg, uint32_t desc) \
172
+{ \
173
+ int i, oprsz = simd_oprsz(desc); \
174
+ for (i = 0; i < oprsz; ) { \
175
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
176
+ do { \
177
+ if (pg & 1) { \
178
+ *(TYPE *)(za + tile_vslice_offset(i)) = *(TYPE *)(vn + H(i)); \
179
+ } \
180
+ i += sizeof(TYPE); \
181
+ pg >>= sizeof(TYPE); \
182
+ } while (i & 15); \
183
+ } \
184
+}
185
+
186
+DO_MOVA_C(sme_mova_cz_b, uint8_t, H1)
187
+DO_MOVA_C(sme_mova_cz_h, uint16_t, H1_2)
188
+DO_MOVA_C(sme_mova_cz_s, uint32_t, H1_4)
189
+
190
+void HELPER(sme_mova_cz_d)(void *za, void *vn, void *vg, uint32_t desc)
191
+{
192
+ int i, oprsz = simd_oprsz(desc) / 8;
193
+ uint8_t *pg = vg;
194
+ uint64_t *n = vn;
195
+ uint64_t *a = za;
196
+
197
+ for (i = 0; i < oprsz; i++) {
198
+ if (pg[H1(i)] & 1) {
199
+ a[tile_vslice_index(i)] = n[i];
200
+ }
201
+ }
202
+}
203
+
204
+void HELPER(sme_mova_cz_q)(void *za, void *vn, void *vg, uint32_t desc)
205
+{
206
+ int i, oprsz = simd_oprsz(desc) / 16;
207
+ uint16_t *pg = vg;
208
+ Int128 *n = vn;
209
+ Int128 *a = za;
210
+
211
+ /*
212
+ * Int128 is used here simply to copy 16 bytes, and to simplify
213
+ * the address arithmetic.
214
+ */
215
+ for (i = 0; i < oprsz; i++) {
216
+ if (pg[H2(i)] & 1) {
217
+ a[tile_vslice_index(i)] = n[i];
218
+ }
219
+ }
220
+}
221
+
222
+#undef DO_MOVA_C
223
+
224
+/*
225
+ * Move ZArray column to Zreg vector.
226
+ */
227
+#define DO_MOVA_Z(NAME, TYPE, H) \
228
+void HELPER(NAME)(void *vd, void *za, void *vg, uint32_t desc) \
229
+{ \
230
+ int i, oprsz = simd_oprsz(desc); \
231
+ for (i = 0; i < oprsz; ) { \
232
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
233
+ do { \
234
+ if (pg & 1) { \
235
+ *(TYPE *)(vd + H(i)) = *(TYPE *)(za + tile_vslice_offset(i)); \
236
+ } \
237
+ i += sizeof(TYPE); \
238
+ pg >>= sizeof(TYPE); \
239
+ } while (i & 15); \
240
+ } \
241
+}
242
+
243
+DO_MOVA_Z(sme_mova_zc_b, uint8_t, H1)
244
+DO_MOVA_Z(sme_mova_zc_h, uint16_t, H1_2)
245
+DO_MOVA_Z(sme_mova_zc_s, uint32_t, H1_4)
246
+
247
+void HELPER(sme_mova_zc_d)(void *vd, void *za, void *vg, uint32_t desc)
248
+{
249
+ int i, oprsz = simd_oprsz(desc) / 8;
250
+ uint8_t *pg = vg;
251
+ uint64_t *d = vd;
252
+ uint64_t *a = za;
253
+
254
+ for (i = 0; i < oprsz; i++) {
255
+ if (pg[H1(i)] & 1) {
256
+ d[i] = a[tile_vslice_index(i)];
257
+ }
258
+ }
259
+}
260
+
261
+void HELPER(sme_mova_zc_q)(void *vd, void *za, void *vg, uint32_t desc)
262
+{
263
+ int i, oprsz = simd_oprsz(desc) / 16;
264
+ uint16_t *pg = vg;
265
+ Int128 *d = vd;
266
+ Int128 *a = za;
267
+
268
+ /*
269
+ * Int128 is used here simply to copy 16 bytes, and to simplify
270
+ * the address arithmetic.
271
+ */
272
+ for (i = 0; i < oprsz; i++, za += sizeof(ARMVectorReg)) {
273
+ if (pg[H2(i)] & 1) {
274
+ d[i] = a[tile_vslice_index(i)];
275
+ }
276
+ }
277
+}
278
+
279
+#undef DO_MOVA_Z
280
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
281
index XXXXXXX..XXXXXXX 100644
282
--- a/target/arm/sve_helper.c
283
+++ b/target/arm/sve_helper.c
284
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_sel_zpzz_d)(void *vd, void *vn, void *vm,
285
}
286
}
287
288
+void HELPER(sve_sel_zpzz_q)(void *vd, void *vn, void *vm,
289
+ void *vg, uint32_t desc)
290
+{
291
+ intptr_t i, opr_sz = simd_oprsz(desc) / 16;
292
+ Int128 *d = vd, *n = vn, *m = vm;
293
+ uint16_t *pg = vg;
294
+
295
+ for (i = 0; i < opr_sz; i += 1) {
296
+ d[i] = (pg[H2(i)] & 1 ? n : m)[i];
297
+ }
298
+}
299
+
300
/* Two operand comparison controlled by a predicate.
301
* ??? It is very tempting to want to be able to expand this inline
302
* with x86 instructions, e.g.
303
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
304
index XXXXXXX..XXXXXXX 100644
305
--- a/target/arm/translate-sme.c
306
+++ b/target/arm/translate-sme.c
307
@@ -XXX,XX +XXX,XX @@
308
#include "decode-sme.c.inc"
309
310
311
+/*
312
+ * Resolve tile.size[index] to a host pointer, where tile and index
313
+ * are always decoded together, dependent on the element size.
314
+ */
315
+static TCGv_ptr get_tile_rowcol(DisasContext *s, int esz, int rs,
316
+ int tile_index, bool vertical)
317
+{
318
+ int tile = tile_index >> (4 - esz);
319
+ int index = esz == MO_128 ? 0 : extract32(tile_index, 0, 4 - esz);
320
+ int pos, len, offset;
321
+ TCGv_i32 tmp;
322
+ TCGv_ptr addr;
323
+
324
+ /* Compute the final index, which is Rs+imm. */
325
+ tmp = tcg_temp_new_i32();
326
+ tcg_gen_trunc_tl_i32(tmp, cpu_reg(s, rs));
327
+ tcg_gen_addi_i32(tmp, tmp, index);
328
+
329
+ /* Prepare a power-of-two modulo via extraction of @len bits. */
330
+ len = ctz32(streaming_vec_reg_size(s)) - esz;
331
+
332
+ if (vertical) {
333
+ /*
334
+ * Compute the byte offset of the index within the tile:
335
+ * (index % (svl / size)) * size
336
+ * = (index % (svl >> esz)) << esz
337
+ * Perform the power-of-two modulo via extraction of the low @len bits.
338
+ * Perform the multiply by shifting left by @pos bits.
339
+ * Perform these operations simultaneously via deposit into zero.
340
+ */
341
+ pos = esz;
342
+ tcg_gen_deposit_z_i32(tmp, tmp, pos, len);
343
+
344
+ /*
345
+ * For big-endian, adjust the indexed column byte offset within
346
+ * the uint64_t host words that make up env->zarray[].
347
+ */
348
+ if (HOST_BIG_ENDIAN && esz < MO_64) {
349
+ tcg_gen_xori_i32(tmp, tmp, 8 - (1 << esz));
48
+ }
350
+ }
49
+ } else {
351
+ } else {
50
+ return 1;
352
+ /*
51
+ }
353
+ * Compute the byte offset of the index within the tile:
52
+
354
+ * (index % (svl / size)) * (size * sizeof(row))
53
+ if (s->fp_excp_el) {
355
+ * = (index % (svl >> esz)) << (esz + log2(sizeof(row)))
54
+ gen_exception_insn(s, 4, EXCP_UDEF,
356
+ */
55
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
357
+ pos = esz + ctz32(sizeof(ARMVectorReg));
56
+ return 0;
358
+ tcg_gen_deposit_z_i32(tmp, tmp, pos, len);
57
+ }
359
+
58
+ if (!s->vfp_enabled) {
360
+ /* Row slices are always aligned and need no endian adjustment. */
59
+ return 1;
361
+ }
60
+ }
362
+
61
+
363
+ /* The tile byte offset within env->zarray is the row. */
62
+ opr_sz = (1 + q) * 8;
364
+ offset = tile * sizeof(ARMVectorReg);
63
+ fpst = get_fpstatus_ptr(1);
365
+
64
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
366
+ /* Include the byte offset of zarray to make this relative to env. */
65
+ vfp_reg_offset(1, rn),
367
+ offset += offsetof(CPUARMState, zarray);
66
+ vfp_reg_offset(1, rm), fpst,
368
+ tcg_gen_addi_i32(tmp, tmp, offset);
67
+ opr_sz, opr_sz, rot,
369
+
68
+ size ? gen_helper_gvec_fcmlas_idx
370
+ /* Add the byte offset to env to produce the final pointer. */
69
+ : gen_helper_gvec_fcmlah_idx);
371
+ addr = tcg_temp_new_ptr();
70
+ tcg_temp_free_ptr(fpst);
372
+ tcg_gen_ext_i32_ptr(addr, tmp);
71
+ return 0;
373
+ tcg_temp_free_i32(tmp);
72
+}
374
+ tcg_gen_add_ptr(addr, addr, cpu_env);
73
+
375
+
74
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
376
+ return addr;
377
+}
378
+
379
static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
75
{
380
{
76
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
381
if (!dc_isar_feature(aa64_sme, s)) {
77
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
382
@@ -XXX,XX +XXX,XX @@ static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
78
goto illegal_op;
383
}
79
}
384
return true;
80
return;
385
}
81
+ } else if ((insn & 0x0f000a00) == 0x0e000800
386
+
82
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
387
+static bool trans_MOVA(DisasContext *s, arg_MOVA *a)
83
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
388
+{
84
+ goto illegal_op;
389
+ static gen_helper_gvec_4 * const h_fns[5] = {
85
+ }
390
+ gen_helper_sve_sel_zpzz_b, gen_helper_sve_sel_zpzz_h,
86
+ return;
391
+ gen_helper_sve_sel_zpzz_s, gen_helper_sve_sel_zpzz_d,
87
} else if ((insn & 0x0fe00000) == 0x0c400000) {
392
+ gen_helper_sve_sel_zpzz_q
88
/* Coprocessor double register transfer. */
393
+ };
89
ARCH(5TE);
394
+ static gen_helper_gvec_3 * const cz_fns[5] = {
395
+ gen_helper_sme_mova_cz_b, gen_helper_sme_mova_cz_h,
396
+ gen_helper_sme_mova_cz_s, gen_helper_sme_mova_cz_d,
397
+ gen_helper_sme_mova_cz_q,
398
+ };
399
+ static gen_helper_gvec_3 * const zc_fns[5] = {
400
+ gen_helper_sme_mova_zc_b, gen_helper_sme_mova_zc_h,
401
+ gen_helper_sme_mova_zc_s, gen_helper_sme_mova_zc_d,
402
+ gen_helper_sme_mova_zc_q,
403
+ };
404
+
405
+ TCGv_ptr t_za, t_zr, t_pg;
406
+ TCGv_i32 t_desc;
407
+ int svl;
408
+
409
+ if (!dc_isar_feature(aa64_sme, s)) {
410
+ return false;
411
+ }
412
+ if (!sme_smza_enabled_check(s)) {
413
+ return true;
414
+ }
415
+
416
+ t_za = get_tile_rowcol(s, a->esz, a->rs, a->za_imm, a->v);
417
+ t_zr = vec_full_reg_ptr(s, a->zr);
418
+ t_pg = pred_full_reg_ptr(s, a->pg);
419
+
420
+ svl = streaming_vec_reg_size(s);
421
+ t_desc = tcg_constant_i32(simd_desc(svl, svl, 0));
422
+
423
+ if (a->v) {
424
+ /* Vertical slice -- use sme mova helpers. */
425
+ if (a->to_vec) {
426
+ zc_fns[a->esz](t_zr, t_za, t_pg, t_desc);
427
+ } else {
428
+ cz_fns[a->esz](t_za, t_zr, t_pg, t_desc);
429
+ }
430
+ } else {
431
+ /* Horizontal slice -- reuse sve sel helpers. */
432
+ if (a->to_vec) {
433
+ h_fns[a->esz](t_zr, t_za, t_zr, t_pg, t_desc);
434
+ } else {
435
+ h_fns[a->esz](t_za, t_zr, t_za, t_pg, t_desc);
436
+ }
437
+ }
438
+
439
+ tcg_temp_free_ptr(t_za);
440
+ tcg_temp_free_ptr(t_zr);
441
+ tcg_temp_free_ptr(t_pg);
442
+
443
+ return true;
444
+}
90
--
445
--
91
2.16.2
446
2.25.1
92
93
diff view generated by jsdifflib
1
Define a new board model for the MPS2 with an AN505 FPGA image
1
From: Richard Henderson <richard.henderson@linaro.org>
2
containing a Cortex-M33. Since the FPGA images for TrustZone
3
cores (AN505, and the similar AN519 for Cortex-M23) have a
4
significantly different layout of devices to the non-TrustZone
5
images, we use a new source file rather than shoehorning them
6
into the existing mps2.c.
7
2
3
We cannot reuse the SVE functions for LD[1-4] and ST[1-4],
4
because those functions accept only a Zreg register number.
5
For SME, we want to pass a pointer into ZA storage.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220708151540.18136-21-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>
10
Message-id: 20180220180325.29818-20-peter.maydell@linaro.org
11
---
11
---
12
hw/arm/Makefile.objs | 1 +
12
target/arm/helper-sme.h | 82 +++++
13
hw/arm/mps2-tz.c | 503 +++++++++++++++++++++++++++++++++++++++++++++++++++
13
target/arm/sme.decode | 9 +
14
2 files changed, 504 insertions(+)
14
target/arm/sme_helper.c | 595 +++++++++++++++++++++++++++++++++++++
15
create mode 100644 hw/arm/mps2-tz.c
15
target/arm/translate-sme.c | 70 +++++
16
4 files changed, 756 insertions(+)
16
17
17
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
18
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/Makefile.objs
20
--- a/target/arm/helper-sme.h
20
+++ b/hw/arm/Makefile.objs
21
+++ b/target/arm/helper-sme.h
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sme_mova_cz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
23
DEF_HELPER_FLAGS_4(sme_mova_zc_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
24
DEF_HELPER_FLAGS_4(sme_mova_cz_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
obj-$(CONFIG_MPS2) += mps2.o
25
DEF_HELPER_FLAGS_4(sme_mova_zc_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+obj-$(CONFIG_MPS2) += mps2-tz.o
26
+
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
27
+DEF_HELPER_FLAGS_5(sme_ld1b_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
27
obj-$(CONFIG_IOTKIT) += iotkit.o
28
+DEF_HELPER_FLAGS_5(sme_ld1b_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
28
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
29
+DEF_HELPER_FLAGS_5(sme_ld1b_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
29
new file mode 100644
30
+DEF_HELPER_FLAGS_5(sme_ld1b_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
30
index XXXXXXX..XXXXXXX
31
+
31
--- /dev/null
32
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
32
+++ b/hw/arm/mps2-tz.c
33
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
34
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
35
+DEF_HELPER_FLAGS_5(sme_ld1h_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
36
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
37
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
38
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
39
+DEF_HELPER_FLAGS_5(sme_ld1h_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
40
+
41
+DEF_HELPER_FLAGS_5(sme_ld1s_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
42
+DEF_HELPER_FLAGS_5(sme_ld1s_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
43
+DEF_HELPER_FLAGS_5(sme_ld1s_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
44
+DEF_HELPER_FLAGS_5(sme_ld1s_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
45
+DEF_HELPER_FLAGS_5(sme_ld1s_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
46
+DEF_HELPER_FLAGS_5(sme_ld1s_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_5(sme_ld1s_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_5(sme_ld1s_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
49
+
50
+DEF_HELPER_FLAGS_5(sme_ld1d_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
51
+DEF_HELPER_FLAGS_5(sme_ld1d_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
52
+DEF_HELPER_FLAGS_5(sme_ld1d_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_5(sme_ld1d_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
54
+DEF_HELPER_FLAGS_5(sme_ld1d_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
55
+DEF_HELPER_FLAGS_5(sme_ld1d_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
56
+DEF_HELPER_FLAGS_5(sme_ld1d_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
57
+DEF_HELPER_FLAGS_5(sme_ld1d_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
58
+
59
+DEF_HELPER_FLAGS_5(sme_ld1q_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_5(sme_ld1q_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
61
+DEF_HELPER_FLAGS_5(sme_ld1q_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
62
+DEF_HELPER_FLAGS_5(sme_ld1q_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
63
+DEF_HELPER_FLAGS_5(sme_ld1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
64
+DEF_HELPER_FLAGS_5(sme_ld1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
65
+DEF_HELPER_FLAGS_5(sme_ld1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
66
+DEF_HELPER_FLAGS_5(sme_ld1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
67
+
68
+DEF_HELPER_FLAGS_5(sme_st1b_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
69
+DEF_HELPER_FLAGS_5(sme_st1b_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
70
+DEF_HELPER_FLAGS_5(sme_st1b_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
71
+DEF_HELPER_FLAGS_5(sme_st1b_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
72
+
73
+DEF_HELPER_FLAGS_5(sme_st1h_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
74
+DEF_HELPER_FLAGS_5(sme_st1h_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
75
+DEF_HELPER_FLAGS_5(sme_st1h_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
76
+DEF_HELPER_FLAGS_5(sme_st1h_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
77
+DEF_HELPER_FLAGS_5(sme_st1h_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_5(sme_st1h_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
79
+DEF_HELPER_FLAGS_5(sme_st1h_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
80
+DEF_HELPER_FLAGS_5(sme_st1h_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
81
+
82
+DEF_HELPER_FLAGS_5(sme_st1s_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
83
+DEF_HELPER_FLAGS_5(sme_st1s_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
84
+DEF_HELPER_FLAGS_5(sme_st1s_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
85
+DEF_HELPER_FLAGS_5(sme_st1s_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
86
+DEF_HELPER_FLAGS_5(sme_st1s_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
87
+DEF_HELPER_FLAGS_5(sme_st1s_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
88
+DEF_HELPER_FLAGS_5(sme_st1s_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
89
+DEF_HELPER_FLAGS_5(sme_st1s_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
90
+
91
+DEF_HELPER_FLAGS_5(sme_st1d_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
92
+DEF_HELPER_FLAGS_5(sme_st1d_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
93
+DEF_HELPER_FLAGS_5(sme_st1d_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
94
+DEF_HELPER_FLAGS_5(sme_st1d_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
95
+DEF_HELPER_FLAGS_5(sme_st1d_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
96
+DEF_HELPER_FLAGS_5(sme_st1d_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
97
+DEF_HELPER_FLAGS_5(sme_st1d_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
98
+DEF_HELPER_FLAGS_5(sme_st1d_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
99
+
100
+DEF_HELPER_FLAGS_5(sme_st1q_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
101
+DEF_HELPER_FLAGS_5(sme_st1q_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
102
+DEF_HELPER_FLAGS_5(sme_st1q_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
103
+DEF_HELPER_FLAGS_5(sme_st1q_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
104
+DEF_HELPER_FLAGS_5(sme_st1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
105
+DEF_HELPER_FLAGS_5(sme_st1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
106
+DEF_HELPER_FLAGS_5(sme_st1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
107
+DEF_HELPER_FLAGS_5(sme_st1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
108
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
109
index XXXXXXX..XXXXXXX 100644
110
--- a/target/arm/sme.decode
111
+++ b/target/arm/sme.decode
112
@@ -XXX,XX +XXX,XX @@ MOVA 11000000 esz:2 00001 0 v:1 .. pg:3 0 za_imm:4 zr:5 \
113
&mova to_vec=1 rs=%mova_rs
114
MOVA 11000000 11 00001 1 v:1 .. pg:3 0 za_imm:4 zr:5 \
115
&mova to_vec=1 rs=%mova_rs esz=4
116
+
117
+### SME Memory
118
+
119
+&ldst esz rs pg rn rm za_imm v:bool st:bool
120
+
121
+LDST1 1110000 0 esz:2 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
122
+ &ldst rs=%mova_rs
123
+LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
124
+ &ldst esz=4 rs=%mova_rs
125
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/sme_helper.c
128
+++ b/target/arm/sme_helper.c
33
@@ -XXX,XX +XXX,XX @@
129
@@ -XXX,XX +XXX,XX @@
130
131
#include "qemu/osdep.h"
132
#include "cpu.h"
133
+#include "internals.h"
134
#include "tcg/tcg-gvec-desc.h"
135
#include "exec/helper-proto.h"
136
+#include "exec/cpu_ldst.h"
137
+#include "exec/exec-all.h"
138
#include "qemu/int128.h"
139
#include "vec_internal.h"
140
+#include "sve_ldst_internal.h"
141
142
/* ResetSVEState */
143
void arm_reset_sve_state(CPUARMState *env)
144
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_mova_zc_q)(void *vd, void *za, void *vg, uint32_t desc)
145
}
146
147
#undef DO_MOVA_Z
148
+
34
+/*
149
+/*
35
+ * ARM V2M MPS2 board emulation, trustzone aware FPGA images
150
+ * Clear elements in a tile slice comprising len bytes.
36
+ *
37
+ * Copyright (c) 2017 Linaro Limited
38
+ * Written by Peter Maydell
39
+ *
40
+ * This program is free software; you can redistribute it and/or modify
41
+ * it under the terms of the GNU General Public License version 2 or
42
+ * (at your option) any later version.
43
+ */
151
+ */
44
+
152
+
45
+/* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
153
+typedef void ClearFn(void *ptr, size_t off, size_t len);
46
+ * FPGA but is otherwise the same as the 2). Since the CPU itself
154
+
47
+ * and most of the devices are in the FPGA, the details of the board
155
+static void clear_horizontal(void *ptr, size_t off, size_t len)
48
+ * as seen by the guest depend significantly on the FPGA image.
156
+{
49
+ * This source file covers the following FPGA images, for TrustZone cores:
157
+ memset(ptr + off, 0, len);
50
+ * "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
158
+}
51
+ *
159
+
52
+ * Links to the TRM for the board itself and to the various Application
160
+static void clear_vertical_b(void *vptr, size_t off, size_t len)
53
+ * Notes which document the FPGA images can be found here:
161
+{
54
+ * https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
162
+ for (size_t i = 0; i < len; ++i) {
55
+ *
163
+ *(uint8_t *)(vptr + tile_vslice_offset(i + off)) = 0;
56
+ * Board TRM:
164
+ }
57
+ * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
165
+}
58
+ * Application Note AN505:
166
+
59
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
167
+static void clear_vertical_h(void *vptr, size_t off, size_t len)
60
+ *
168
+{
61
+ * The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
169
+ for (size_t i = 0; i < len; i += 2) {
62
+ * (ARM ECM0601256) for the details of some of the device layout:
170
+ *(uint16_t *)(vptr + tile_vslice_offset(i + off)) = 0;
63
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
171
+ }
172
+}
173
+
174
+static void clear_vertical_s(void *vptr, size_t off, size_t len)
175
+{
176
+ for (size_t i = 0; i < len; i += 4) {
177
+ *(uint32_t *)(vptr + tile_vslice_offset(i + off)) = 0;
178
+ }
179
+}
180
+
181
+static void clear_vertical_d(void *vptr, size_t off, size_t len)
182
+{
183
+ for (size_t i = 0; i < len; i += 8) {
184
+ *(uint64_t *)(vptr + tile_vslice_offset(i + off)) = 0;
185
+ }
186
+}
187
+
188
+static void clear_vertical_q(void *vptr, size_t off, size_t len)
189
+{
190
+ for (size_t i = 0; i < len; i += 16) {
191
+ memset(vptr + tile_vslice_offset(i + off), 0, 16);
192
+ }
193
+}
194
+
195
+/*
196
+ * Copy elements from an array into a tile slice comprising len bytes.
64
+ */
197
+ */
65
+
198
+
66
+#include "qemu/osdep.h"
199
+typedef void CopyFn(void *dst, const void *src, size_t len);
67
+#include "qapi/error.h"
200
+
68
+#include "qemu/error-report.h"
201
+static void copy_horizontal(void *dst, const void *src, size_t len)
69
+#include "hw/arm/arm.h"
202
+{
70
+#include "hw/arm/armv7m.h"
203
+ memcpy(dst, src, len);
71
+#include "hw/or-irq.h"
204
+}
72
+#include "hw/boards.h"
205
+
73
+#include "exec/address-spaces.h"
206
+static void copy_vertical_b(void *vdst, const void *vsrc, size_t len)
74
+#include "sysemu/sysemu.h"
207
+{
75
+#include "hw/misc/unimp.h"
208
+ const uint8_t *src = vsrc;
76
+#include "hw/char/cmsdk-apb-uart.h"
209
+ uint8_t *dst = vdst;
77
+#include "hw/timer/cmsdk-apb-timer.h"
210
+ size_t i;
78
+#include "hw/misc/mps2-scc.h"
211
+
79
+#include "hw/misc/mps2-fpgaio.h"
212
+ for (i = 0; i < len; ++i) {
80
+#include "hw/arm/iotkit.h"
213
+ dst[tile_vslice_index(i)] = src[i];
81
+#include "hw/devices.h"
214
+ }
82
+#include "net/net.h"
215
+}
83
+#include "hw/core/split-irq.h"
216
+
84
+
217
+static void copy_vertical_h(void *vdst, const void *vsrc, size_t len)
85
+typedef enum MPS2TZFPGAType {
218
+{
86
+ FPGA_AN505,
219
+ const uint16_t *src = vsrc;
87
+} MPS2TZFPGAType;
220
+ uint16_t *dst = vdst;
88
+
221
+ size_t i;
89
+typedef struct {
222
+
90
+ MachineClass parent;
223
+ for (i = 0; i < len / 2; ++i) {
91
+ MPS2TZFPGAType fpga_type;
224
+ dst[tile_vslice_index(i)] = src[i];
92
+ uint32_t scc_id;
225
+ }
93
+} MPS2TZMachineClass;
226
+}
94
+
227
+
95
+typedef struct {
228
+static void copy_vertical_s(void *vdst, const void *vsrc, size_t len)
96
+ MachineState parent;
229
+{
97
+
230
+ const uint32_t *src = vsrc;
98
+ IoTKit iotkit;
231
+ uint32_t *dst = vdst;
99
+ MemoryRegion psram;
232
+ size_t i;
100
+ MemoryRegion ssram1;
233
+
101
+ MemoryRegion ssram1_m;
234
+ for (i = 0; i < len / 4; ++i) {
102
+ MemoryRegion ssram23;
235
+ dst[tile_vslice_index(i)] = src[i];
103
+ MPS2SCC scc;
236
+ }
104
+ MPS2FPGAIO fpgaio;
237
+}
105
+ TZPPC ppc[5];
238
+
106
+ UnimplementedDeviceState ssram_mpc[3];
239
+static void copy_vertical_d(void *vdst, const void *vsrc, size_t len)
107
+ UnimplementedDeviceState spi[5];
240
+{
108
+ UnimplementedDeviceState i2c[4];
241
+ const uint64_t *src = vsrc;
109
+ UnimplementedDeviceState i2s_audio;
242
+ uint64_t *dst = vdst;
110
+ UnimplementedDeviceState gpio[5];
243
+ size_t i;
111
+ UnimplementedDeviceState dma[4];
244
+
112
+ UnimplementedDeviceState gfx;
245
+ for (i = 0; i < len / 8; ++i) {
113
+ CMSDKAPBUART uart[5];
246
+ dst[tile_vslice_index(i)] = src[i];
114
+ SplitIRQ sec_resp_splitter;
247
+ }
115
+ qemu_or_irq uart_irq_orgate;
248
+}
116
+} MPS2TZMachineState;
249
+
117
+
250
+static void copy_vertical_q(void *vdst, const void *vsrc, size_t len)
118
+#define TYPE_MPS2TZ_MACHINE "mps2tz"
251
+{
119
+#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
252
+ for (size_t i = 0; i < len; i += 16) {
120
+
253
+ memcpy(vdst + tile_vslice_offset(i), vsrc + i, 16);
121
+#define MPS2TZ_MACHINE(obj) \
254
+ }
122
+ OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
255
+}
123
+#define MPS2TZ_MACHINE_GET_CLASS(obj) \
256
+
124
+ OBJECT_GET_CLASS(MPS2TZMachineClass, obj, TYPE_MPS2TZ_MACHINE)
257
+/*
125
+#define MPS2TZ_MACHINE_CLASS(klass) \
258
+ * Host and TLB primitives for vertical tile slice addressing.
126
+ OBJECT_CLASS_CHECK(MPS2TZMachineClass, klass, TYPE_MPS2TZ_MACHINE)
127
+
128
+/* Main SYSCLK frequency in Hz */
129
+#define SYSCLK_FRQ 20000000
130
+
131
+/* Initialize the auxiliary RAM region @mr and map it into
132
+ * the memory map at @base.
133
+ */
259
+ */
134
+static void make_ram(MemoryRegion *mr, const char *name,
260
+
135
+ hwaddr base, hwaddr size)
261
+#define DO_LD(NAME, TYPE, HOST, TLB) \
136
+{
262
+static inline void sme_##NAME##_v_host(void *za, intptr_t off, void *host) \
137
+ memory_region_init_ram(mr, NULL, name, size, &error_fatal);
263
+{ \
138
+ memory_region_add_subregion(get_system_memory(), base, mr);
264
+ TYPE val = HOST(host); \
139
+}
265
+ *(TYPE *)(za + tile_vslice_offset(off)) = val; \
140
+
266
+} \
141
+/* Create an alias of an entire original MemoryRegion @orig
267
+static inline void sme_##NAME##_v_tlb(CPUARMState *env, void *za, \
142
+ * located at @base in the memory map.
268
+ intptr_t off, target_ulong addr, uintptr_t ra) \
269
+{ \
270
+ TYPE val = TLB(env, useronly_clean_ptr(addr), ra); \
271
+ *(TYPE *)(za + tile_vslice_offset(off)) = val; \
272
+}
273
+
274
+#define DO_ST(NAME, TYPE, HOST, TLB) \
275
+static inline void sme_##NAME##_v_host(void *za, intptr_t off, void *host) \
276
+{ \
277
+ TYPE val = *(TYPE *)(za + tile_vslice_offset(off)); \
278
+ HOST(host, val); \
279
+} \
280
+static inline void sme_##NAME##_v_tlb(CPUARMState *env, void *za, \
281
+ intptr_t off, target_ulong addr, uintptr_t ra) \
282
+{ \
283
+ TYPE val = *(TYPE *)(za + tile_vslice_offset(off)); \
284
+ TLB(env, useronly_clean_ptr(addr), val, ra); \
285
+}
286
+
287
+/*
288
+ * The ARMVectorReg elements are stored in host-endian 64-bit units.
289
+ * For 128-bit quantities, the sequence defined by the Elem[] pseudocode
290
+ * corresponds to storing the two 64-bit pieces in little-endian order.
143
+ */
291
+ */
144
+static void make_ram_alias(MemoryRegion *mr, const char *name,
292
+#define DO_LDQ(HNAME, VNAME, BE, HOST, TLB) \
145
+ MemoryRegion *orig, hwaddr base)
293
+static inline void HNAME##_host(void *za, intptr_t off, void *host) \
146
+{
294
+{ \
147
+ memory_region_init_alias(mr, NULL, name, orig, 0,
295
+ uint64_t val0 = HOST(host), val1 = HOST(host + 8); \
148
+ memory_region_size(orig));
296
+ uint64_t *ptr = za + off; \
149
+ memory_region_add_subregion(get_system_memory(), base, mr);
297
+ ptr[0] = BE ? val1 : val0, ptr[1] = BE ? val0 : val1; \
150
+}
298
+} \
151
+
299
+static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
152
+static void init_sysbus_child(Object *parent, const char *childname,
300
+{ \
153
+ void *child, size_t childsize,
301
+ HNAME##_host(za, tile_vslice_offset(off), host); \
154
+ const char *childtype)
302
+} \
155
+{
303
+static inline void HNAME##_tlb(CPUARMState *env, void *za, intptr_t off, \
156
+ object_initialize(child, childsize, childtype);
304
+ target_ulong addr, uintptr_t ra) \
157
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
305
+{ \
158
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
306
+ uint64_t val0 = TLB(env, useronly_clean_ptr(addr), ra); \
159
+
307
+ uint64_t val1 = TLB(env, useronly_clean_ptr(addr + 8), ra); \
160
+}
308
+ uint64_t *ptr = za + off; \
161
+
309
+ ptr[0] = BE ? val1 : val0, ptr[1] = BE ? val0 : val1; \
162
+/* Most of the devices in the AN505 FPGA image sit behind
310
+} \
163
+ * Peripheral Protection Controllers. These data structures
311
+static inline void VNAME##_v_tlb(CPUARMState *env, void *za, intptr_t off, \
164
+ * define the layout of which devices sit behind which PPCs.
312
+ target_ulong addr, uintptr_t ra) \
165
+ * The devfn for each port is a function which creates, configures
313
+{ \
166
+ * and initializes the device, returning the MemoryRegion which
314
+ HNAME##_tlb(env, za, tile_vslice_offset(off), addr, ra); \
167
+ * needs to be plugged into the downstream end of the PPC port.
315
+}
316
+
317
+#define DO_STQ(HNAME, VNAME, BE, HOST, TLB) \
318
+static inline void HNAME##_host(void *za, intptr_t off, void *host) \
319
+{ \
320
+ uint64_t *ptr = za + off; \
321
+ HOST(host, ptr[BE]); \
322
+ HOST(host + 1, ptr[!BE]); \
323
+} \
324
+static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
325
+{ \
326
+ HNAME##_host(za, tile_vslice_offset(off), host); \
327
+} \
328
+static inline void HNAME##_tlb(CPUARMState *env, void *za, intptr_t off, \
329
+ target_ulong addr, uintptr_t ra) \
330
+{ \
331
+ uint64_t *ptr = za + off; \
332
+ TLB(env, useronly_clean_ptr(addr), ptr[BE], ra); \
333
+ TLB(env, useronly_clean_ptr(addr + 8), ptr[!BE], ra); \
334
+} \
335
+static inline void VNAME##_v_tlb(CPUARMState *env, void *za, intptr_t off, \
336
+ target_ulong addr, uintptr_t ra) \
337
+{ \
338
+ HNAME##_tlb(env, za, tile_vslice_offset(off), addr, ra); \
339
+}
340
+
341
+DO_LD(ld1b, uint8_t, ldub_p, cpu_ldub_data_ra)
342
+DO_LD(ld1h_be, uint16_t, lduw_be_p, cpu_lduw_be_data_ra)
343
+DO_LD(ld1h_le, uint16_t, lduw_le_p, cpu_lduw_le_data_ra)
344
+DO_LD(ld1s_be, uint32_t, ldl_be_p, cpu_ldl_be_data_ra)
345
+DO_LD(ld1s_le, uint32_t, ldl_le_p, cpu_ldl_le_data_ra)
346
+DO_LD(ld1d_be, uint64_t, ldq_be_p, cpu_ldq_be_data_ra)
347
+DO_LD(ld1d_le, uint64_t, ldq_le_p, cpu_ldq_le_data_ra)
348
+
349
+DO_LDQ(sve_ld1qq_be, sme_ld1q_be, 1, ldq_be_p, cpu_ldq_be_data_ra)
350
+DO_LDQ(sve_ld1qq_le, sme_ld1q_le, 0, ldq_le_p, cpu_ldq_le_data_ra)
351
+
352
+DO_ST(st1b, uint8_t, stb_p, cpu_stb_data_ra)
353
+DO_ST(st1h_be, uint16_t, stw_be_p, cpu_stw_be_data_ra)
354
+DO_ST(st1h_le, uint16_t, stw_le_p, cpu_stw_le_data_ra)
355
+DO_ST(st1s_be, uint32_t, stl_be_p, cpu_stl_be_data_ra)
356
+DO_ST(st1s_le, uint32_t, stl_le_p, cpu_stl_le_data_ra)
357
+DO_ST(st1d_be, uint64_t, stq_be_p, cpu_stq_be_data_ra)
358
+DO_ST(st1d_le, uint64_t, stq_le_p, cpu_stq_le_data_ra)
359
+
360
+DO_STQ(sve_st1qq_be, sme_st1q_be, 1, stq_be_p, cpu_stq_be_data_ra)
361
+DO_STQ(sve_st1qq_le, sme_st1q_le, 0, stq_le_p, cpu_stq_le_data_ra)
362
+
363
+#undef DO_LD
364
+#undef DO_ST
365
+#undef DO_LDQ
366
+#undef DO_STQ
367
+
368
+/*
369
+ * Common helper for all contiguous predicated loads.
168
+ */
370
+ */
169
+typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
371
+
170
+ const char *name, hwaddr size);
372
+static inline QEMU_ALWAYS_INLINE
171
+
373
+void sme_ld1(CPUARMState *env, void *za, uint64_t *vg,
172
+typedef struct PPCPortInfo {
374
+ const target_ulong addr, uint32_t desc, const uintptr_t ra,
173
+ const char *name;
375
+ const int esz, uint32_t mtedesc, bool vertical,
174
+ MakeDevFn *devfn;
376
+ sve_ldst1_host_fn *host_fn,
175
+ void *opaque;
377
+ sve_ldst1_tlb_fn *tlb_fn,
176
+ hwaddr addr;
378
+ ClearFn *clr_fn,
177
+ hwaddr size;
379
+ CopyFn *cpy_fn)
178
+} PPCPortInfo;
380
+{
179
+
381
+ const intptr_t reg_max = simd_oprsz(desc);
180
+typedef struct PPCInfo {
382
+ const intptr_t esize = 1 << esz;
181
+ const char *name;
383
+ intptr_t reg_off, reg_last;
182
+ PPCPortInfo ports[TZ_NUM_PORTS];
384
+ SVEContLdSt info;
183
+} PPCInfo;
385
+ void *host;
184
+
386
+ int flags;
185
+static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
387
+
186
+ void *opaque,
388
+ /* Find the active elements. */
187
+ const char *name, hwaddr size)
389
+ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, esize)) {
188
+{
390
+ /* The entire predicate was false; no load occurs. */
189
+ /* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
391
+ clr_fn(za, 0, reg_max);
190
+ * and return a pointer to its MemoryRegion.
392
+ return;
393
+ }
394
+
395
+ /* Probe the page(s). Exit with exception for any invalid page. */
396
+ sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_LOAD, ra);
397
+
398
+ /* Handle watchpoints for all active elements. */
399
+ sve_cont_ldst_watchpoints(&info, env, vg, addr, esize, esize,
400
+ BP_MEM_READ, ra);
401
+
402
+ /*
403
+ * Handle mte checks for all active elements.
404
+ * Since TBI must be set for MTE, !mtedesc => !mte_active.
191
+ */
405
+ */
192
+ UnimplementedDeviceState *uds = opaque;
406
+ if (mtedesc) {
193
+
407
+ sve_cont_ldst_mte_check(&info, env, vg, addr, esize, esize,
194
+ init_sysbus_child(OBJECT(mms), name, uds,
408
+ mtedesc, ra);
195
+ sizeof(UnimplementedDeviceState),
409
+ }
196
+ TYPE_UNIMPLEMENTED_DEVICE);
410
+
197
+ qdev_prop_set_string(DEVICE(uds), "name", name);
411
+ flags = info.page[0].flags | info.page[1].flags;
198
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
412
+ if (unlikely(flags != 0)) {
199
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
413
+#ifdef CONFIG_USER_ONLY
200
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
414
+ g_assert_not_reached();
201
+}
415
+#else
202
+
416
+ /*
203
+static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
417
+ * At least one page includes MMIO.
204
+ const char *name, hwaddr size)
418
+ * Any bus operation can fail with cpu_transaction_failed,
205
+{
419
+ * which for ARM will raise SyncExternal. Perform the load
206
+ CMSDKAPBUART *uart = opaque;
420
+ * into scratch memory to preserve register state until the end.
207
+ int i = uart - &mms->uart[0];
421
+ */
208
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
422
+ ARMVectorReg scratch = { };
209
+ int rxirqno = i * 2;
423
+
210
+ int txirqno = i * 2 + 1;
424
+ reg_off = info.reg_off_first[0];
211
+ int combirqno = i + 10;
425
+ reg_last = info.reg_off_last[1];
212
+ SysBusDevice *s;
426
+ if (reg_last < 0) {
213
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
427
+ reg_last = info.reg_off_split;
214
+ DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
428
+ if (reg_last < 0) {
215
+
429
+ reg_last = info.reg_off_last[0];
216
+ init_sysbus_child(OBJECT(mms), name, uart,
430
+ }
217
+ sizeof(mms->uart[0]), TYPE_CMSDK_APB_UART);
431
+ }
218
+ qdev_prop_set_chr(DEVICE(uart), "chardev", uartchr);
432
+
219
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
433
+ do {
220
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
434
+ uint64_t pg = vg[reg_off >> 6];
221
+ s = SYS_BUS_DEVICE(uart);
435
+ do {
222
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
436
+ if ((pg >> (reg_off & 63)) & 1) {
223
+ "EXP_IRQ", txirqno));
437
+ tlb_fn(env, &scratch, reg_off, addr + reg_off, ra);
224
+ sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
438
+ }
225
+ "EXP_IRQ", rxirqno));
439
+ reg_off += esize;
226
+ sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
440
+ } while (reg_off & 63);
227
+ sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
441
+ } while (reg_off <= reg_last);
228
+ sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
442
+
229
+ "EXP_IRQ", combirqno));
443
+ cpy_fn(za, &scratch, reg_max);
230
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
444
+ return;
231
+}
445
+#endif
232
+
446
+ }
233
+static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
447
+
234
+ const char *name, hwaddr size)
448
+ /* The entire operation is in RAM, on valid pages. */
235
+{
449
+
236
+ MPS2SCC *scc = opaque;
450
+ reg_off = info.reg_off_first[0];
237
+ DeviceState *sccdev;
451
+ reg_last = info.reg_off_last[0];
238
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
452
+ host = info.page[0].host;
239
+
453
+
240
+ object_initialize(scc, sizeof(mms->scc), TYPE_MPS2_SCC);
454
+ if (!vertical) {
241
+ sccdev = DEVICE(scc);
455
+ memset(za, 0, reg_max);
242
+ qdev_set_parent_bus(sccdev, sysbus_get_default());
456
+ } else if (reg_off) {
243
+ qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
457
+ clr_fn(za, 0, reg_off);
244
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
458
+ }
245
+ qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
459
+
246
+ object_property_set_bool(OBJECT(scc), true, "realized", &error_fatal);
460
+ while (reg_off <= reg_last) {
247
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
461
+ uint64_t pg = vg[reg_off >> 6];
248
+}
462
+ do {
249
+
463
+ if ((pg >> (reg_off & 63)) & 1) {
250
+static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
464
+ host_fn(za, reg_off, host + reg_off);
251
+ const char *name, hwaddr size)
465
+ } else if (vertical) {
252
+{
466
+ clr_fn(za, reg_off, esize);
253
+ MPS2FPGAIO *fpgaio = opaque;
467
+ }
254
+
468
+ reg_off += esize;
255
+ object_initialize(fpgaio, sizeof(mms->fpgaio), TYPE_MPS2_FPGAIO);
469
+ } while (reg_off <= reg_last && (reg_off & 63));
256
+ qdev_set_parent_bus(DEVICE(fpgaio), sysbus_get_default());
470
+ }
257
+ object_property_set_bool(OBJECT(fpgaio), true, "realized", &error_fatal);
471
+
258
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
472
+ /*
259
+}
473
+ * Use the slow path to manage the cross-page misalignment.
260
+
474
+ * But we know this is RAM and cannot trap.
261
+static void mps2tz_common_init(MachineState *machine)
262
+{
263
+ MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
264
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
265
+ MemoryRegion *system_memory = get_system_memory();
266
+ DeviceState *iotkitdev;
267
+ DeviceState *dev_splitter;
268
+ int i;
269
+
270
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
271
+ error_report("This board can only be used with CPU %s",
272
+ mc->default_cpu_type);
273
+ exit(1);
274
+ }
275
+
276
+ init_sysbus_child(OBJECT(machine), "iotkit", &mms->iotkit,
277
+ sizeof(mms->iotkit), TYPE_IOTKIT);
278
+ iotkitdev = DEVICE(&mms->iotkit);
279
+ object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
280
+ "memory", &error_abort);
281
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
282
+ qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
283
+ object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
284
+ &error_fatal);
285
+
286
+ /* The sec_resp_cfg output from the IoTKit must be split into multiple
287
+ * lines, one for each of the PPCs we create here.
288
+ */
475
+ */
289
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
476
+ reg_off = info.reg_off_split;
290
+ TYPE_SPLIT_IRQ);
477
+ if (unlikely(reg_off >= 0)) {
291
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
478
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
292
+ OBJECT(&mms->sec_resp_splitter), &error_abort);
479
+ }
293
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5,
480
+
294
+ "num-lines", &error_fatal);
481
+ reg_off = info.reg_off_first[1];
295
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
482
+ if (unlikely(reg_off >= 0)) {
296
+ "realized", &error_fatal);
483
+ reg_last = info.reg_off_last[1];
297
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
484
+ host = info.page[1].host;
298
+ qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
485
+
299
+ qdev_get_gpio_in(dev_splitter, 0));
486
+ do {
300
+
487
+ uint64_t pg = vg[reg_off >> 6];
301
+ /* The IoTKit sets up much of the memory layout, including
488
+ do {
302
+ * the aliases between secure and non-secure regions in the
489
+ if ((pg >> (reg_off & 63)) & 1) {
303
+ * address space. The FPGA itself contains:
490
+ host_fn(za, reg_off, host + reg_off);
304
+ *
491
+ } else if (vertical) {
305
+ * 0x00000000..0x003fffff SSRAM1
492
+ clr_fn(za, reg_off, esize);
306
+ * 0x00400000..0x007fffff alias of SSRAM1
493
+ }
307
+ * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
494
+ reg_off += esize;
308
+ * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
495
+ } while (reg_off & 63);
309
+ * 0x80000000..0x80ffffff 16MB PSRAM
496
+ } while (reg_off <= reg_last);
497
+ }
498
+}
499
+
500
+static inline QEMU_ALWAYS_INLINE
501
+void sme_ld1_mte(CPUARMState *env, void *za, uint64_t *vg,
502
+ target_ulong addr, uint32_t desc, uintptr_t ra,
503
+ const int esz, bool vertical,
504
+ sve_ldst1_host_fn *host_fn,
505
+ sve_ldst1_tlb_fn *tlb_fn,
506
+ ClearFn *clr_fn,
507
+ CopyFn *cpy_fn)
508
+{
509
+ uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
510
+ int bit55 = extract64(addr, 55, 1);
511
+
512
+ /* Remove mtedesc from the normal sve descriptor. */
513
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
514
+
515
+ /* Perform gross MTE suppression early. */
516
+ if (!tbi_check(desc, bit55) ||
517
+ tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
518
+ mtedesc = 0;
519
+ }
520
+
521
+ sme_ld1(env, za, vg, addr, desc, ra, esz, mtedesc, vertical,
522
+ host_fn, tlb_fn, clr_fn, cpy_fn);
523
+}
524
+
525
+#define DO_LD(L, END, ESZ) \
526
+void HELPER(sme_ld1##L##END##_h)(CPUARMState *env, void *za, void *vg, \
527
+ target_ulong addr, uint32_t desc) \
528
+{ \
529
+ sme_ld1(env, za, vg, addr, desc, GETPC(), ESZ, 0, false, \
530
+ sve_ld1##L##L##END##_host, sve_ld1##L##L##END##_tlb, \
531
+ clear_horizontal, copy_horizontal); \
532
+} \
533
+void HELPER(sme_ld1##L##END##_v)(CPUARMState *env, void *za, void *vg, \
534
+ target_ulong addr, uint32_t desc) \
535
+{ \
536
+ sme_ld1(env, za, vg, addr, desc, GETPC(), ESZ, 0, true, \
537
+ sme_ld1##L##END##_v_host, sme_ld1##L##END##_v_tlb, \
538
+ clear_vertical_##L, copy_vertical_##L); \
539
+} \
540
+void HELPER(sme_ld1##L##END##_h_mte)(CPUARMState *env, void *za, void *vg, \
541
+ target_ulong addr, uint32_t desc) \
542
+{ \
543
+ sme_ld1_mte(env, za, vg, addr, desc, GETPC(), ESZ, false, \
544
+ sve_ld1##L##L##END##_host, sve_ld1##L##L##END##_tlb, \
545
+ clear_horizontal, copy_horizontal); \
546
+} \
547
+void HELPER(sme_ld1##L##END##_v_mte)(CPUARMState *env, void *za, void *vg, \
548
+ target_ulong addr, uint32_t desc) \
549
+{ \
550
+ sme_ld1_mte(env, za, vg, addr, desc, GETPC(), ESZ, true, \
551
+ sme_ld1##L##END##_v_host, sme_ld1##L##END##_v_tlb, \
552
+ clear_vertical_##L, copy_vertical_##L); \
553
+}
554
+
555
+DO_LD(b, , MO_8)
556
+DO_LD(h, _be, MO_16)
557
+DO_LD(h, _le, MO_16)
558
+DO_LD(s, _be, MO_32)
559
+DO_LD(s, _le, MO_32)
560
+DO_LD(d, _be, MO_64)
561
+DO_LD(d, _le, MO_64)
562
+DO_LD(q, _be, MO_128)
563
+DO_LD(q, _le, MO_128)
564
+
565
+#undef DO_LD
566
+
567
+/*
568
+ * Common helper for all contiguous predicated stores.
569
+ */
570
+
571
+static inline QEMU_ALWAYS_INLINE
572
+void sme_st1(CPUARMState *env, void *za, uint64_t *vg,
573
+ const target_ulong addr, uint32_t desc, const uintptr_t ra,
574
+ const int esz, uint32_t mtedesc, bool vertical,
575
+ sve_ldst1_host_fn *host_fn,
576
+ sve_ldst1_tlb_fn *tlb_fn)
577
+{
578
+ const intptr_t reg_max = simd_oprsz(desc);
579
+ const intptr_t esize = 1 << esz;
580
+ intptr_t reg_off, reg_last;
581
+ SVEContLdSt info;
582
+ void *host;
583
+ int flags;
584
+
585
+ /* Find the active elements. */
586
+ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, esize)) {
587
+ /* The entire predicate was false; no store occurs. */
588
+ return;
589
+ }
590
+
591
+ /* Probe the page(s). Exit with exception for any invalid page. */
592
+ sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_STORE, ra);
593
+
594
+ /* Handle watchpoints for all active elements. */
595
+ sve_cont_ldst_watchpoints(&info, env, vg, addr, esize, esize,
596
+ BP_MEM_WRITE, ra);
597
+
598
+ /*
599
+ * Handle mte checks for all active elements.
600
+ * Since TBI must be set for MTE, !mtedesc => !mte_active.
310
+ */
601
+ */
311
+
602
+ if (mtedesc) {
312
+ /* The FPGA images have an odd combination of different RAMs,
603
+ sve_cont_ldst_mte_check(&info, env, vg, addr, esize, esize,
313
+ * because in hardware they are different implementations and
604
+ mtedesc, ra);
314
+ * connected to different buses, giving varying performance/size
605
+ }
315
+ * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
606
+
316
+ * call the 16MB our "system memory", as it's the largest lump.
607
+ flags = info.page[0].flags | info.page[1].flags;
608
+ if (unlikely(flags != 0)) {
609
+#ifdef CONFIG_USER_ONLY
610
+ g_assert_not_reached();
611
+#else
612
+ /*
613
+ * At least one page includes MMIO.
614
+ * Any bus operation can fail with cpu_transaction_failed,
615
+ * which for ARM will raise SyncExternal. We cannot avoid
616
+ * this fault and will leave with the store incomplete.
617
+ */
618
+ reg_off = info.reg_off_first[0];
619
+ reg_last = info.reg_off_last[1];
620
+ if (reg_last < 0) {
621
+ reg_last = info.reg_off_split;
622
+ if (reg_last < 0) {
623
+ reg_last = info.reg_off_last[0];
624
+ }
625
+ }
626
+
627
+ do {
628
+ uint64_t pg = vg[reg_off >> 6];
629
+ do {
630
+ if ((pg >> (reg_off & 63)) & 1) {
631
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
632
+ }
633
+ reg_off += esize;
634
+ } while (reg_off & 63);
635
+ } while (reg_off <= reg_last);
636
+ return;
637
+#endif
638
+ }
639
+
640
+ reg_off = info.reg_off_first[0];
641
+ reg_last = info.reg_off_last[0];
642
+ host = info.page[0].host;
643
+
644
+ while (reg_off <= reg_last) {
645
+ uint64_t pg = vg[reg_off >> 6];
646
+ do {
647
+ if ((pg >> (reg_off & 63)) & 1) {
648
+ host_fn(za, reg_off, host + reg_off);
649
+ }
650
+ reg_off += 1 << esz;
651
+ } while (reg_off <= reg_last && (reg_off & 63));
652
+ }
653
+
654
+ /*
655
+ * Use the slow path to manage the cross-page misalignment.
656
+ * But we know this is RAM and cannot trap.
317
+ */
657
+ */
318
+ memory_region_allocate_system_memory(&mms->psram,
658
+ reg_off = info.reg_off_split;
319
+ NULL, "mps.ram", 0x01000000);
659
+ if (unlikely(reg_off >= 0)) {
320
+ memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
660
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
321
+
661
+ }
322
+ /* The SSRAM memories should all be behind Memory Protection Controllers,
662
+
323
+ * but we don't implement that yet.
663
+ reg_off = info.reg_off_first[1];
664
+ if (unlikely(reg_off >= 0)) {
665
+ reg_last = info.reg_off_last[1];
666
+ host = info.page[1].host;
667
+
668
+ do {
669
+ uint64_t pg = vg[reg_off >> 6];
670
+ do {
671
+ if ((pg >> (reg_off & 63)) & 1) {
672
+ host_fn(za, reg_off, host + reg_off);
673
+ }
674
+ reg_off += 1 << esz;
675
+ } while (reg_off & 63);
676
+ } while (reg_off <= reg_last);
677
+ }
678
+}
679
+
680
+static inline QEMU_ALWAYS_INLINE
681
+void sme_st1_mte(CPUARMState *env, void *za, uint64_t *vg, target_ulong addr,
682
+ uint32_t desc, uintptr_t ra, int esz, bool vertical,
683
+ sve_ldst1_host_fn *host_fn,
684
+ sve_ldst1_tlb_fn *tlb_fn)
685
+{
686
+ uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
687
+ int bit55 = extract64(addr, 55, 1);
688
+
689
+ /* Remove mtedesc from the normal sve descriptor. */
690
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
691
+
692
+ /* Perform gross MTE suppression early. */
693
+ if (!tbi_check(desc, bit55) ||
694
+ tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
695
+ mtedesc = 0;
696
+ }
697
+
698
+ sme_st1(env, za, vg, addr, desc, ra, esz, mtedesc,
699
+ vertical, host_fn, tlb_fn);
700
+}
701
+
702
+#define DO_ST(L, END, ESZ) \
703
+void HELPER(sme_st1##L##END##_h)(CPUARMState *env, void *za, void *vg, \
704
+ target_ulong addr, uint32_t desc) \
705
+{ \
706
+ sme_st1(env, za, vg, addr, desc, GETPC(), ESZ, 0, false, \
707
+ sve_st1##L##L##END##_host, sve_st1##L##L##END##_tlb); \
708
+} \
709
+void HELPER(sme_st1##L##END##_v)(CPUARMState *env, void *za, void *vg, \
710
+ target_ulong addr, uint32_t desc) \
711
+{ \
712
+ sme_st1(env, za, vg, addr, desc, GETPC(), ESZ, 0, true, \
713
+ sme_st1##L##END##_v_host, sme_st1##L##END##_v_tlb); \
714
+} \
715
+void HELPER(sme_st1##L##END##_h_mte)(CPUARMState *env, void *za, void *vg, \
716
+ target_ulong addr, uint32_t desc) \
717
+{ \
718
+ sme_st1_mte(env, za, vg, addr, desc, GETPC(), ESZ, false, \
719
+ sve_st1##L##L##END##_host, sve_st1##L##L##END##_tlb); \
720
+} \
721
+void HELPER(sme_st1##L##END##_v_mte)(CPUARMState *env, void *za, void *vg, \
722
+ target_ulong addr, uint32_t desc) \
723
+{ \
724
+ sme_st1_mte(env, za, vg, addr, desc, GETPC(), ESZ, true, \
725
+ sme_st1##L##END##_v_host, sme_st1##L##END##_v_tlb); \
726
+}
727
+
728
+DO_ST(b, , MO_8)
729
+DO_ST(h, _be, MO_16)
730
+DO_ST(h, _le, MO_16)
731
+DO_ST(s, _be, MO_32)
732
+DO_ST(s, _le, MO_32)
733
+DO_ST(d, _be, MO_64)
734
+DO_ST(d, _le, MO_64)
735
+DO_ST(q, _be, MO_128)
736
+DO_ST(q, _le, MO_128)
737
+
738
+#undef DO_ST
739
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
740
index XXXXXXX..XXXXXXX 100644
741
--- a/target/arm/translate-sme.c
742
+++ b/target/arm/translate-sme.c
743
@@ -XXX,XX +XXX,XX @@ static bool trans_MOVA(DisasContext *s, arg_MOVA *a)
744
745
return true;
746
}
747
+
748
+static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
749
+{
750
+ typedef void GenLdSt1(TCGv_env, TCGv_ptr, TCGv_ptr, TCGv, TCGv_i32);
751
+
752
+ /*
753
+ * Indexed by [esz][be][v][mte][st], which is (except for load/store)
754
+ * also the order in which the elements appear in the function names,
755
+ * and so how we must concatenate the pieces.
324
+ */
756
+ */
325
+ make_ram(&mms->ssram1, "mps.ssram1", 0x00000000, 0x00400000);
757
+
326
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x00400000);
758
+#define FN_LS(F) { gen_helper_sme_ld1##F, gen_helper_sme_st1##F }
327
+
759
+#define FN_MTE(F) { FN_LS(F), FN_LS(F##_mte) }
328
+ make_ram(&mms->ssram23, "mps.ssram23", 0x28000000, 0x00400000);
760
+#define FN_HV(F) { FN_MTE(F##_h), FN_MTE(F##_v) }
329
+
761
+#define FN_END(L, B) { FN_HV(L), FN_HV(B) }
330
+ /* The overflow IRQs for all UARTs are ORed together.
762
+
331
+ * Tx, Rx and "combined" IRQs are sent to the NVIC separately.
763
+ static GenLdSt1 * const fns[5][2][2][2][2] = {
332
+ * Create the OR gate for this.
764
+ FN_END(b, b),
333
+ */
765
+ FN_END(h_le, h_be),
334
+ object_initialize(&mms->uart_irq_orgate, sizeof(mms->uart_irq_orgate),
766
+ FN_END(s_le, s_be),
335
+ TYPE_OR_IRQ);
767
+ FN_END(d_le, d_be),
336
+ object_property_add_child(OBJECT(mms), "uart-irq-orgate",
768
+ FN_END(q_le, q_be),
337
+ OBJECT(&mms->uart_irq_orgate), &error_abort);
338
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), 10, "num-lines",
339
+ &error_fatal);
340
+ object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
341
+ "realized", &error_fatal);
342
+ qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
343
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
344
+
345
+ /* Most of the devices in the FPGA are behind Peripheral Protection
346
+ * Controllers. The required order for initializing things is:
347
+ * + initialize the PPC
348
+ * + initialize, configure and realize downstream devices
349
+ * + connect downstream device MemoryRegions to the PPC
350
+ * + realize the PPC
351
+ * + map the PPC's MemoryRegions to the places in the address map
352
+ * where the downstream devices should appear
353
+ * + wire up the PPC's control lines to the IoTKit object
354
+ */
355
+
356
+ const PPCInfo ppcs[] = { {
357
+ .name = "apb_ppcexp0",
358
+ .ports = {
359
+ { "ssram-mpc0", make_unimp_dev, &mms->ssram_mpc[0],
360
+ 0x58007000, 0x1000 },
361
+ { "ssram-mpc1", make_unimp_dev, &mms->ssram_mpc[1],
362
+ 0x58008000, 0x1000 },
363
+ { "ssram-mpc2", make_unimp_dev, &mms->ssram_mpc[2],
364
+ 0x58009000, 0x1000 },
365
+ },
366
+ }, {
367
+ .name = "apb_ppcexp1",
368
+ .ports = {
369
+ { "spi0", make_unimp_dev, &mms->spi[0], 0x40205000, 0x1000 },
370
+ { "spi1", make_unimp_dev, &mms->spi[1], 0x40206000, 0x1000 },
371
+ { "spi2", make_unimp_dev, &mms->spi[2], 0x40209000, 0x1000 },
372
+ { "spi3", make_unimp_dev, &mms->spi[3], 0x4020a000, 0x1000 },
373
+ { "spi4", make_unimp_dev, &mms->spi[4], 0x4020b000, 0x1000 },
374
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
375
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
376
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
377
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
378
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
379
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 },
380
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 },
381
+ { "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 },
382
+ { "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 },
383
+ },
384
+ }, {
385
+ .name = "apb_ppcexp2",
386
+ .ports = {
387
+ { "scc", make_scc, &mms->scc, 0x40300000, 0x1000 },
388
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
389
+ 0x40301000, 0x1000 },
390
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x40302000, 0x1000 },
391
+ },
392
+ }, {
393
+ .name = "ahb_ppcexp0",
394
+ .ports = {
395
+ { "gfx", make_unimp_dev, &mms->gfx, 0x41000000, 0x140000 },
396
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x40100000, 0x1000 },
397
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
398
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
399
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
400
+ { "gpio4", make_unimp_dev, &mms->gpio[4], 0x40104000, 0x1000 },
401
+ },
402
+ }, {
403
+ .name = "ahb_ppcexp1",
404
+ .ports = {
405
+ { "dma0", make_unimp_dev, &mms->dma[0], 0x40110000, 0x1000 },
406
+ { "dma1", make_unimp_dev, &mms->dma[1], 0x40111000, 0x1000 },
407
+ { "dma2", make_unimp_dev, &mms->dma[2], 0x40112000, 0x1000 },
408
+ { "dma3", make_unimp_dev, &mms->dma[3], 0x40113000, 0x1000 },
409
+ },
410
+ },
411
+ };
769
+ };
412
+
770
+
413
+ for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
771
+#undef FN_LS
414
+ const PPCInfo *ppcinfo = &ppcs[i];
772
+#undef FN_MTE
415
+ TZPPC *ppc = &mms->ppc[i];
773
+#undef FN_HV
416
+ DeviceState *ppcdev;
774
+#undef FN_END
417
+ int port;
775
+
418
+ char *gpioname;
776
+ TCGv_ptr t_za, t_pg;
419
+
777
+ TCGv_i64 addr;
420
+ init_sysbus_child(OBJECT(machine), ppcinfo->name, ppc,
778
+ int svl, desc = 0;
421
+ sizeof(TZPPC), TYPE_TZ_PPC);
779
+ bool be = s->be_data == MO_BE;
422
+ ppcdev = DEVICE(ppc);
780
+ bool mte = s->mte_active[0];
423
+
781
+
424
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
782
+ if (!dc_isar_feature(aa64_sme, s)) {
425
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
783
+ return false;
426
+ MemoryRegion *mr;
784
+ }
427
+ char *portname;
785
+ if (!sme_smza_enabled_check(s)) {
428
+
786
+ return true;
429
+ if (!pinfo->devfn) {
787
+ }
430
+ continue;
788
+
431
+ }
789
+ t_za = get_tile_rowcol(s, a->esz, a->rs, a->za_imm, a->v);
432
+
790
+ t_pg = pred_full_reg_ptr(s, a->pg);
433
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
791
+ addr = tcg_temp_new_i64();
434
+ portname = g_strdup_printf("port[%d]", port);
792
+
435
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
793
+ tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), a->esz);
436
+ portname, &error_fatal);
794
+ tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
437
+ g_free(portname);
795
+
438
+ }
796
+ if (mte) {
439
+
797
+ desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s));
440
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
798
+ desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
441
+
799
+ desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
442
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
800
+ desc = FIELD_DP32(desc, MTEDESC, WRITE, a->st);
443
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
801
+ desc = FIELD_DP32(desc, MTEDESC, SIZEM1, (1 << a->esz) - 1);
444
+
802
+ desc <<= SVE_MTEDESC_SHIFT;
445
+ if (!pinfo->devfn) {
803
+ } else {
446
+ continue;
804
+ addr = clean_data_tbi(s, addr);
447
+ }
805
+ }
448
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
806
+ svl = streaming_vec_reg_size(s);
449
+
807
+ desc = simd_desc(svl, svl, desc);
450
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
808
+
451
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
809
+ fns[a->esz][be][a->v][mte][a->st](cpu_env, t_za, t_pg, addr,
452
+ qdev_get_gpio_in_named(ppcdev,
810
+ tcg_constant_i32(desc));
453
+ "cfg_nonsec",
811
+
454
+ port));
812
+ tcg_temp_free_ptr(t_za);
455
+ g_free(gpioname);
813
+ tcg_temp_free_ptr(t_pg);
456
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
814
+ tcg_temp_free_i64(addr);
457
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
815
+ return true;
458
+ qdev_get_gpio_in_named(ppcdev,
816
+}
459
+ "cfg_ap", port));
460
+ g_free(gpioname);
461
+ }
462
+
463
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
464
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
465
+ qdev_get_gpio_in_named(ppcdev,
466
+ "irq_enable", 0));
467
+ g_free(gpioname);
468
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
469
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
470
+ qdev_get_gpio_in_named(ppcdev,
471
+ "irq_clear", 0));
472
+ g_free(gpioname);
473
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
474
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
475
+ qdev_get_gpio_in_named(iotkitdev,
476
+ gpioname, 0));
477
+ g_free(gpioname);
478
+
479
+ qdev_connect_gpio_out(dev_splitter, i,
480
+ qdev_get_gpio_in_named(ppcdev,
481
+ "cfg_sec_resp", 0));
482
+ }
483
+
484
+ /* In hardware this is a LAN9220; the LAN9118 is software compatible
485
+ * except that it doesn't support the checksum-offload feature.
486
+ * The ethernet controller is not behind a PPC.
487
+ */
488
+ lan9118_init(&nd_table[0], 0x42000000,
489
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
490
+
491
+ create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
492
+
493
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
494
+}
495
+
496
+static void mps2tz_class_init(ObjectClass *oc, void *data)
497
+{
498
+ MachineClass *mc = MACHINE_CLASS(oc);
499
+
500
+ mc->init = mps2tz_common_init;
501
+ mc->max_cpus = 1;
502
+}
503
+
504
+static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
505
+{
506
+ MachineClass *mc = MACHINE_CLASS(oc);
507
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
508
+
509
+ mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
510
+ mmc->fpga_type = FPGA_AN505;
511
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
512
+ mmc->scc_id = 0x41040000 | (505 << 4);
513
+}
514
+
515
+static const TypeInfo mps2tz_info = {
516
+ .name = TYPE_MPS2TZ_MACHINE,
517
+ .parent = TYPE_MACHINE,
518
+ .abstract = true,
519
+ .instance_size = sizeof(MPS2TZMachineState),
520
+ .class_size = sizeof(MPS2TZMachineClass),
521
+ .class_init = mps2tz_class_init,
522
+};
523
+
524
+static const TypeInfo mps2tz_an505_info = {
525
+ .name = TYPE_MPS2TZ_AN505_MACHINE,
526
+ .parent = TYPE_MPS2TZ_MACHINE,
527
+ .class_init = mps2tz_an505_class_init,
528
+};
529
+
530
+static void mps2tz_machine_init(void)
531
+{
532
+ type_register_static(&mps2tz_info);
533
+ type_register_static(&mps2tz_an505_info);
534
+}
535
+
536
+type_init(mps2tz_machine_init);
537
--
817
--
538
2.16.2
818
2.25.1
539
540
diff view generated by jsdifflib
1
Add remaining easy registers to iotkit-secctl:
1
From: Richard Henderson <richard.henderson@linaro.org>
2
* NSCCFG just routes its two bits out to external GPIO lines
3
* BRGINSTAT/BRGINTCLR/BRGINTEN can be dummies, because QEMU's
4
bus fabric can never report errors
5
2
3
Add a TCGv_ptr base argument, which will be cpu_env for SVE.
4
We will reuse this for SME save and restore array insns.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-22-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
Message-id: 20180220180325.29818-18-peter.maydell@linaro.org
8
---
10
---
9
include/hw/misc/iotkit-secctl.h | 4 ++++
11
target/arm/translate-a64.h | 3 +++
10
hw/misc/iotkit-secctl.c | 32 ++++++++++++++++++++++++++------
12
target/arm/translate-sve.c | 48 ++++++++++++++++++++++++++++----------
11
2 files changed, 30 insertions(+), 6 deletions(-)
13
2 files changed, 39 insertions(+), 12 deletions(-)
12
14
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
15
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
17
--- a/target/arm/translate-a64.h
16
+++ b/include/hw/misc/iotkit-secctl.h
18
+++ b/target/arm/translate-a64.h
17
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ void gen_gvec_xar(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
18
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
20
uint32_t rm_ofs, int64_t shift,
19
* + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
21
uint32_t opr_sz, uint32_t max_sz);
20
* should RAZ/WI or bus error
22
21
+ * + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
23
+void gen_sve_ldr(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int imm);
22
* Controlling the 2 APB PPCs in the IoTKit:
24
+void gen_sve_str(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int imm);
23
* + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
25
+
24
* + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
26
#endif /* TARGET_ARM_TRANSLATE_A64_H */
25
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
26
27
/*< public >*/
28
qemu_irq sec_resp_cfg;
29
+ qemu_irq nsc_cfg_irq;
30
31
MemoryRegion s_regs;
32
MemoryRegion ns_regs;
33
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
34
uint32_t secppcintstat;
35
uint32_t secppcinten;
36
uint32_t secrespcfg;
37
+ uint32_t nsccfg;
38
+ uint32_t brginten;
39
40
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
41
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
42
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
43
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/iotkit-secctl.c
29
--- a/target/arm/translate-sve.c
45
+++ b/hw/misc/iotkit-secctl.c
30
+++ b/target/arm/translate-sve.c
46
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
31
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(UCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz,
47
case A_SECRESPCFG:
32
* The load should begin at the address Rn + IMM.
48
r = s->secrespcfg;
33
*/
49
break;
34
50
+ case A_NSCCFG:
35
-static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
51
+ r = s->nsccfg;
36
+void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
52
+ break;
37
+ int len, int rn, int imm)
53
case A_SECPPCINTSTAT:
38
{
54
r = s->secppcintstat;
39
int len_align = QEMU_ALIGN_DOWN(len, 8);
55
break;
40
int len_remain = len % 8;
56
case A_SECPPCINTEN:
41
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
57
r = s->secppcinten;
42
t0 = tcg_temp_new_i64();
58
break;
43
for (i = 0; i < len_align; i += 8) {
59
+ case A_BRGINTSTAT:
44
tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
60
+ /* QEMU's bus fabric can never report errors as it doesn't buffer
45
- tcg_gen_st_i64(t0, cpu_env, vofs + i);
61
+ * writes, so we never report bridge interrupts.
46
+ tcg_gen_st_i64(t0, base, vofs + i);
62
+ */
47
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
63
+ r = 0;
48
}
64
+ break;
49
tcg_temp_free_i64(t0);
65
+ case A_BRGINTEN:
50
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
66
+ r = s->brginten;
51
clean_addr = new_tmp_a64_local(s);
67
+ break;
52
tcg_gen_mov_i64(clean_addr, t0);
68
case A_AHBNSPPCEXP0:
53
69
case A_AHBNSPPCEXP1:
54
+ if (base != cpu_env) {
70
case A_AHBNSPPCEXP2:
55
+ TCGv_ptr b = tcg_temp_local_new_ptr();
71
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
56
+ tcg_gen_mov_ptr(b, base);
72
case A_APBSPPPCEXP3:
57
+ base = b;
73
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
58
+ }
74
break;
59
+
75
- case A_NSCCFG:
60
gen_set_label(loop);
76
case A_SECMPCINTSTATUS:
61
77
case A_SECMSCINTSTAT:
62
t0 = tcg_temp_new_i64();
78
case A_SECMSCINTEN:
63
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
79
- case A_BRGINTSTAT:
64
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
80
- case A_BRGINTEN:
65
81
case A_NSMSCEXP:
66
tp = tcg_temp_new_ptr();
82
qemu_log_mask(LOG_UNIMP,
67
- tcg_gen_add_ptr(tp, cpu_env, i);
83
"IoTKit SecCtl S block read: "
68
+ tcg_gen_add_ptr(tp, base, i);
84
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
69
tcg_gen_addi_ptr(i, i, 8);
70
tcg_gen_st_i64(t0, tp, vofs);
71
tcg_temp_free_ptr(tp);
72
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
73
74
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
75
tcg_temp_free_ptr(i);
76
+
77
+ if (base != cpu_env) {
78
+ tcg_temp_free_ptr(base);
79
+ assert(len_remain == 0);
80
+ }
85
}
81
}
86
82
87
switch (offset) {
83
/*
88
+ case A_NSCCFG:
84
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
89
+ s->nsccfg = value & 3;
85
default:
90
+ qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
86
g_assert_not_reached();
91
+ break;
87
}
92
case A_SECRESPCFG:
88
- tcg_gen_st_i64(t0, cpu_env, vofs + len_align);
93
value &= 1;
89
+ tcg_gen_st_i64(t0, base, vofs + len_align);
94
s->secrespcfg = value;
90
tcg_temp_free_i64(t0);
95
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
91
}
96
s->secppcinten = value & 0x00f000f3;
97
foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
98
break;
99
+ case A_BRGINTCLR:
100
+ break;
101
+ case A_BRGINTEN:
102
+ s->brginten = value & 0xffff0000;
103
+ break;
104
case A_AHBNSPPCEXP0:
105
case A_AHBNSPPCEXP1:
106
case A_AHBNSPPCEXP2:
107
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
108
ppc = &s->apbexp[offset_to_ppc_idx(offset)];
109
iotkit_secctl_ppc_sp_write(ppc, value);
110
break;
111
- case A_NSCCFG:
112
case A_SECMSCINTCLR:
113
case A_SECMSCINTEN:
114
- case A_BRGINTCLR:
115
- case A_BRGINTEN:
116
qemu_log_mask(LOG_UNIMP,
117
"IoTKit SecCtl S block write: "
118
"unimplemented offset 0x%x\n", offset);
119
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_reset(DeviceState *dev)
120
s->secppcintstat = 0;
121
s->secppcinten = 0;
122
s->secrespcfg = 0;
123
+ s->nsccfg = 0;
124
+ s->brginten = 0;
125
126
foreach_ppc(s, iotkit_secctl_reset_ppc);
127
}
92
}
128
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
93
94
/* Similarly for stores. */
95
-static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
96
+void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
97
+ int len, int rn, int imm)
98
{
99
int len_align = QEMU_ALIGN_DOWN(len, 8);
100
int len_remain = len % 8;
101
@@ -XXX,XX +XXX,XX @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
102
103
t0 = tcg_temp_new_i64();
104
for (i = 0; i < len_align; i += 8) {
105
- tcg_gen_ld_i64(t0, cpu_env, vofs + i);
106
+ tcg_gen_ld_i64(t0, base, vofs + i);
107
tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ);
108
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
109
}
110
@@ -XXX,XX +XXX,XX @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
111
clean_addr = new_tmp_a64_local(s);
112
tcg_gen_mov_i64(clean_addr, t0);
113
114
+ if (base != cpu_env) {
115
+ TCGv_ptr b = tcg_temp_local_new_ptr();
116
+ tcg_gen_mov_ptr(b, base);
117
+ base = b;
118
+ }
119
+
120
gen_set_label(loop);
121
122
t0 = tcg_temp_new_i64();
123
tp = tcg_temp_new_ptr();
124
- tcg_gen_add_ptr(tp, cpu_env, i);
125
+ tcg_gen_add_ptr(tp, base, i);
126
tcg_gen_ld_i64(t0, tp, vofs);
127
tcg_gen_addi_ptr(i, i, 8);
128
tcg_temp_free_ptr(tp);
129
@@ -XXX,XX +XXX,XX @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
130
131
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
132
tcg_temp_free_ptr(i);
133
+
134
+ if (base != cpu_env) {
135
+ tcg_temp_free_ptr(base);
136
+ assert(len_remain == 0);
137
+ }
129
}
138
}
130
139
131
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
140
/* Predicate register stores can be any multiple of 2. */
132
+ qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
141
if (len_remain) {
133
142
t0 = tcg_temp_new_i64();
134
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
143
- tcg_gen_ld_i64(t0, cpu_env, vofs + len_align);
135
s, "iotkit-secctl-s-regs", 0x1000);
144
+ tcg_gen_ld_i64(t0, base, vofs + len_align);
136
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
145
137
VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
146
switch (len_remain) {
138
VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
147
case 2:
139
VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
148
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_zri(DisasContext *s, arg_rri *a)
140
+ VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
149
if (sve_access_check(s)) {
141
+ VMSTATE_UINT32(brginten, IoTKitSecCtl),
150
int size = vec_full_reg_size(s);
142
VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
151
int off = vec_full_reg_offset(s, a->rd);
143
iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
152
- do_ldr(s, off, size, a->rn, a->imm * size);
144
VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
153
+ gen_sve_ldr(s, cpu_env, off, size, a->rn, a->imm * size);
154
}
155
return true;
156
}
157
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_pri(DisasContext *s, arg_rri *a)
158
if (sve_access_check(s)) {
159
int size = pred_full_reg_size(s);
160
int off = pred_full_reg_offset(s, a->rd);
161
- do_ldr(s, off, size, a->rn, a->imm * size);
162
+ gen_sve_ldr(s, cpu_env, off, size, a->rn, a->imm * size);
163
}
164
return true;
165
}
166
@@ -XXX,XX +XXX,XX @@ static bool trans_STR_zri(DisasContext *s, arg_rri *a)
167
if (sve_access_check(s)) {
168
int size = vec_full_reg_size(s);
169
int off = vec_full_reg_offset(s, a->rd);
170
- do_str(s, off, size, a->rn, a->imm * size);
171
+ gen_sve_str(s, cpu_env, off, size, a->rn, a->imm * size);
172
}
173
return true;
174
}
175
@@ -XXX,XX +XXX,XX @@ static bool trans_STR_pri(DisasContext *s, arg_rri *a)
176
if (sve_access_check(s)) {
177
int size = pred_full_reg_size(s);
178
int off = pred_full_reg_offset(s, a->rd);
179
- do_str(s, off, size, a->rn, a->imm * size);
180
+ gen_sve_str(s, cpu_env, off, size, a->rn, a->imm * size);
181
}
182
return true;
183
}
145
--
184
--
146
2.16.2
185
2.25.1
147
148
diff view generated by jsdifflib
1
Instead of loading kernels, device trees, and the like to
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the system address space, use the CPU's address space. This
3
is important if we're trying to load the file to memory or
4
via an alias memory region that is provided by an SoC
5
object and thus not mapped into the system address space.
6
2
3
We can reuse the SVE functions for LDR and STR, passing in the
4
base of the ZA vector and a zero offset.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-23-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-3-peter.maydell@linaro.org
11
---
10
---
12
hw/arm/boot.c | 119 +++++++++++++++++++++++++++++++++++++---------------------
11
target/arm/sme.decode | 7 +++++++
13
1 file changed, 76 insertions(+), 43 deletions(-)
12
target/arm/translate-sme.c | 24 ++++++++++++++++++++++++
13
2 files changed, 31 insertions(+)
14
14
15
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
15
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/boot.c
17
--- a/target/arm/sme.decode
18
+++ b/hw/arm/boot.c
18
+++ b/target/arm/sme.decode
19
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ LDST1 1110000 0 esz:2 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
20
#define ARM64_TEXT_OFFSET_OFFSET 8
20
&ldst rs=%mova_rs
21
#define ARM64_MAGIC_OFFSET 56
21
LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
22
22
&ldst esz=4 rs=%mova_rs
23
+static AddressSpace *arm_boot_address_space(ARMCPU *cpu,
23
+
24
+ const struct arm_boot_info *info)
24
+&ldstr rv rn imm
25
+@ldstr ....... ... . ...... .. ... rn:5 . imm:4 \
26
+ &ldstr rv=%mova_rs
27
+
28
+LDR 1110000 100 0 000000 .. 000 ..... 0 .... @ldstr
29
+STR 1110000 100 1 000000 .. 000 ..... 0 .... @ldstr
30
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-sme.c
33
+++ b/target/arm/translate-sme.c
34
@@ -XXX,XX +XXX,XX @@ static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
35
tcg_temp_free_i64(addr);
36
return true;
37
}
38
+
39
+typedef void GenLdStR(DisasContext *, TCGv_ptr, int, int, int, int);
40
+
41
+static bool do_ldst_r(DisasContext *s, arg_ldstr *a, GenLdStR *fn)
25
+{
42
+{
26
+ /* Return the address space to use for bootloader reads and writes.
43
+ int svl = streaming_vec_reg_size(s);
27
+ * We prefer the secure address space if the CPU has it and we're
44
+ int imm = a->imm;
28
+ * going to boot the guest into it.
45
+ TCGv_ptr base;
29
+ */
30
+ int asidx;
31
+ CPUState *cs = CPU(cpu);
32
+
46
+
33
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3) && info->secure_boot) {
47
+ if (!sme_za_enabled_check(s)) {
34
+ asidx = ARMASIdx_S;
48
+ return true;
35
+ } else {
36
+ asidx = ARMASIdx_NS;
37
+ }
49
+ }
38
+
50
+
39
+ return cpu_get_address_space(cs, asidx);
51
+ /* ZA[n] equates to ZA0H.B[n]. */
52
+ base = get_tile_rowcol(s, MO_8, a->rv, imm, false);
53
+
54
+ fn(s, base, 0, svl, a->rn, imm * svl);
55
+
56
+ tcg_temp_free_ptr(base);
57
+ return true;
40
+}
58
+}
41
+
59
+
42
typedef enum {
60
+TRANS_FEAT(LDR, aa64_sme, do_ldst_r, a, gen_sve_ldr)
43
FIXUP_NONE = 0, /* do nothing */
61
+TRANS_FEAT(STR, aa64_sme, do_ldst_r, a, gen_sve_str)
44
FIXUP_TERMINATOR, /* end of insns */
45
@@ -XXX,XX +XXX,XX @@ static const ARMInsnFixup smpboot[] = {
46
};
47
48
static void write_bootloader(const char *name, hwaddr addr,
49
- const ARMInsnFixup *insns, uint32_t *fixupcontext)
50
+ const ARMInsnFixup *insns, uint32_t *fixupcontext,
51
+ AddressSpace *as)
52
{
53
/* Fix up the specified bootloader fragment and write it into
54
* guest memory using rom_add_blob_fixed(). fixupcontext is
55
@@ -XXX,XX +XXX,XX @@ static void write_bootloader(const char *name, hwaddr addr,
56
code[i] = tswap32(insn);
57
}
58
59
- rom_add_blob_fixed(name, code, len * sizeof(uint32_t), addr);
60
+ rom_add_blob_fixed_as(name, code, len * sizeof(uint32_t), addr, as);
61
62
g_free(code);
63
}
64
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
65
const struct arm_boot_info *info)
66
{
67
uint32_t fixupcontext[FIXUP_MAX];
68
+ AddressSpace *as = arm_boot_address_space(cpu, info);
69
70
fixupcontext[FIXUP_GIC_CPU_IF] = info->gic_cpu_if_addr;
71
fixupcontext[FIXUP_BOOTREG] = info->smp_bootreg_addr;
72
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
73
}
74
75
write_bootloader("smpboot", info->smp_loader_start,
76
- smpboot, fixupcontext);
77
+ smpboot, fixupcontext, as);
78
}
79
80
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
81
const struct arm_boot_info *info,
82
hwaddr mvbar_addr)
83
{
84
+ AddressSpace *as = arm_boot_address_space(cpu, info);
85
int n;
86
uint32_t mvbar_blob[] = {
87
/* mvbar_addr: secure monitor vectors
88
@@ -XXX,XX +XXX,XX @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
89
for (n = 0; n < ARRAY_SIZE(mvbar_blob); n++) {
90
mvbar_blob[n] = tswap32(mvbar_blob[n]);
91
}
92
- rom_add_blob_fixed("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
93
- mvbar_addr);
94
+ rom_add_blob_fixed_as("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
95
+ mvbar_addr, as);
96
97
for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
98
board_setup_blob[n] = tswap32(board_setup_blob[n]);
99
}
100
- rom_add_blob_fixed("board-setup", board_setup_blob,
101
- sizeof(board_setup_blob), info->board_setup_addr);
102
+ rom_add_blob_fixed_as("board-setup", board_setup_blob,
103
+ sizeof(board_setup_blob), info->board_setup_addr, as);
104
}
105
106
static void default_reset_secondary(ARMCPU *cpu,
107
const struct arm_boot_info *info)
108
{
109
+ AddressSpace *as = arm_boot_address_space(cpu, info);
110
CPUState *cs = CPU(cpu);
111
112
- address_space_stl_notdirty(&address_space_memory, info->smp_bootreg_addr,
113
+ address_space_stl_notdirty(as, info->smp_bootreg_addr,
114
0, MEMTXATTRS_UNSPECIFIED, NULL);
115
cpu_set_pc(cs, info->smp_loader_start);
116
}
117
@@ -XXX,XX +XXX,XX @@ static inline bool have_dtb(const struct arm_boot_info *info)
118
}
119
120
#define WRITE_WORD(p, value) do { \
121
- address_space_stl_notdirty(&address_space_memory, p, value, \
122
+ address_space_stl_notdirty(as, p, value, \
123
MEMTXATTRS_UNSPECIFIED, NULL); \
124
p += 4; \
125
} while (0)
126
127
-static void set_kernel_args(const struct arm_boot_info *info)
128
+static void set_kernel_args(const struct arm_boot_info *info, AddressSpace *as)
129
{
130
int initrd_size = info->initrd_size;
131
hwaddr base = info->loader_start;
132
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
133
int cmdline_size;
134
135
cmdline_size = strlen(info->kernel_cmdline);
136
- cpu_physical_memory_write(p + 8, info->kernel_cmdline,
137
- cmdline_size + 1);
138
+ address_space_write(as, p + 8, MEMTXATTRS_UNSPECIFIED,
139
+ (const uint8_t *)info->kernel_cmdline,
140
+ cmdline_size + 1);
141
cmdline_size = (cmdline_size >> 2) + 1;
142
WRITE_WORD(p, cmdline_size + 2);
143
WRITE_WORD(p, 0x54410009);
144
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
145
atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
146
WRITE_WORD(p, (atag_board_len + 8) >> 2);
147
WRITE_WORD(p, 0x414f4d50);
148
- cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
149
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
150
+ atag_board_buf, atag_board_len);
151
p += atag_board_len;
152
}
153
/* ATAG_END */
154
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
155
WRITE_WORD(p, 0);
156
}
157
158
-static void set_kernel_args_old(const struct arm_boot_info *info)
159
+static void set_kernel_args_old(const struct arm_boot_info *info,
160
+ AddressSpace *as)
161
{
162
hwaddr p;
163
const char *s;
164
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args_old(const struct arm_boot_info *info)
165
}
166
s = info->kernel_cmdline;
167
if (s) {
168
- cpu_physical_memory_write(p, s, strlen(s) + 1);
169
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
170
+ (const uint8_t *)s, strlen(s) + 1);
171
} else {
172
WRITE_WORD(p, 0);
173
}
174
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
175
* @addr: the address to load the image at
176
* @binfo: struct describing the boot environment
177
* @addr_limit: upper limit of the available memory area at @addr
178
+ * @as: address space to load image to
179
*
180
* Load a device tree supplied by the machine or by the user with the
181
* '-dtb' command line option, and put it at offset @addr in target
182
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
183
* Note: Must not be called unless have_dtb(binfo) is true.
184
*/
185
static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
186
- hwaddr addr_limit)
187
+ hwaddr addr_limit, AddressSpace *as)
188
{
189
void *fdt = NULL;
190
int size, rc;
191
@@ -XXX,XX +XXX,XX @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
192
/* Put the DTB into the memory map as a ROM image: this will ensure
193
* the DTB is copied again upon reset, even if addr points into RAM.
194
*/
195
- rom_add_blob_fixed("dtb", fdt, size, addr);
196
+ rom_add_blob_fixed_as("dtb", fdt, size, addr, as);
197
198
g_free(fdt);
199
200
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
201
}
202
203
if (cs == first_cpu) {
204
+ AddressSpace *as = arm_boot_address_space(cpu, info);
205
+
206
cpu_set_pc(cs, info->loader_start);
207
208
if (!have_dtb(info)) {
209
if (old_param) {
210
- set_kernel_args_old(info);
211
+ set_kernel_args_old(info, as);
212
} else {
213
- set_kernel_args(info);
214
+ set_kernel_args(info, as);
215
}
216
}
217
} else {
218
@@ -XXX,XX +XXX,XX @@ static int do_arm_linux_init(Object *obj, void *opaque)
219
220
static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
221
uint64_t *lowaddr, uint64_t *highaddr,
222
- int elf_machine)
223
+ int elf_machine, AddressSpace *as)
224
{
225
bool elf_is64;
226
union {
227
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
228
}
229
}
230
231
- ret = load_elf(info->kernel_filename, NULL, NULL,
232
- pentry, lowaddr, highaddr, big_endian, elf_machine,
233
- 1, data_swab);
234
+ ret = load_elf_as(info->kernel_filename, NULL, NULL,
235
+ pentry, lowaddr, highaddr, big_endian, elf_machine,
236
+ 1, data_swab, as);
237
if (ret <= 0) {
238
/* The header loaded but the image didn't */
239
exit(1);
240
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
241
}
242
243
static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
244
- hwaddr *entry)
245
+ hwaddr *entry, AddressSpace *as)
246
{
247
hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
248
uint8_t *buffer;
249
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
250
}
251
252
*entry = mem_base + kernel_load_offset;
253
- rom_add_blob_fixed(filename, buffer, size, *entry);
254
+ rom_add_blob_fixed_as(filename, buffer, size, *entry, as);
255
256
g_free(buffer);
257
258
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
259
ARMCPU *cpu = n->cpu;
260
struct arm_boot_info *info =
261
container_of(n, struct arm_boot_info, load_kernel_notifier);
262
+ AddressSpace *as = arm_boot_address_space(cpu, info);
263
264
/* The board code is not supposed to set secure_board_setup unless
265
* running its code in secure mode is actually possible, and KVM
266
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
267
* the kernel is supposed to be loaded by the bootloader), copy the
268
* DTB to the base of RAM for the bootloader to pick up.
269
*/
270
- if (load_dtb(info->loader_start, info, 0) < 0) {
271
+ if (load_dtb(info->loader_start, info, 0, as) < 0) {
272
exit(1);
273
}
274
}
275
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
276
277
/* Assume that raw images are linux kernels, and ELF images are not. */
278
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
279
- &elf_high_addr, elf_machine);
280
+ &elf_high_addr, elf_machine, as);
281
if (kernel_size > 0 && have_dtb(info)) {
282
/* If there is still some room left at the base of RAM, try and put
283
* the DTB there like we do for images loaded with -bios or -pflash.
284
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
285
if (elf_low_addr < info->loader_start) {
286
elf_low_addr = 0;
287
}
288
- if (load_dtb(info->loader_start, info, elf_low_addr) < 0) {
289
+ if (load_dtb(info->loader_start, info, elf_low_addr, as) < 0) {
290
exit(1);
291
}
292
}
293
}
294
entry = elf_entry;
295
if (kernel_size < 0) {
296
- kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
297
- &is_linux, NULL, NULL);
298
+ kernel_size = load_uimage_as(info->kernel_filename, &entry, NULL,
299
+ &is_linux, NULL, NULL, as);
300
}
301
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
302
kernel_size = load_aarch64_image(info->kernel_filename,
303
- info->loader_start, &entry);
304
+ info->loader_start, &entry, as);
305
is_linux = 1;
306
} else if (kernel_size < 0) {
307
/* 32-bit ARM */
308
entry = info->loader_start + KERNEL_LOAD_ADDR;
309
- kernel_size = load_image_targphys(info->kernel_filename, entry,
310
- info->ram_size - KERNEL_LOAD_ADDR);
311
+ kernel_size = load_image_targphys_as(info->kernel_filename, entry,
312
+ info->ram_size - KERNEL_LOAD_ADDR,
313
+ as);
314
is_linux = 1;
315
}
316
if (kernel_size < 0) {
317
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
318
uint32_t fixupcontext[FIXUP_MAX];
319
320
if (info->initrd_filename) {
321
- initrd_size = load_ramdisk(info->initrd_filename,
322
- info->initrd_start,
323
- info->ram_size -
324
- info->initrd_start);
325
+ initrd_size = load_ramdisk_as(info->initrd_filename,
326
+ info->initrd_start,
327
+ info->ram_size - info->initrd_start,
328
+ as);
329
if (initrd_size < 0) {
330
- initrd_size = load_image_targphys(info->initrd_filename,
331
- info->initrd_start,
332
- info->ram_size -
333
- info->initrd_start);
334
+ initrd_size = load_image_targphys_as(info->initrd_filename,
335
+ info->initrd_start,
336
+ info->ram_size -
337
+ info->initrd_start,
338
+ as);
339
}
340
if (initrd_size < 0) {
341
error_report("could not load initrd '%s'",
342
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
343
344
/* Place the DTB after the initrd in memory with alignment. */
345
dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size, align);
346
- if (load_dtb(dtb_start, info, 0) < 0) {
347
+ if (load_dtb(dtb_start, info, 0, as) < 0) {
348
exit(1);
349
}
350
fixupcontext[FIXUP_ARGPTR] = dtb_start;
351
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
352
fixupcontext[FIXUP_ENTRYPOINT] = entry;
353
354
write_bootloader("bootloader", info->loader_start,
355
- primary_loader, fixupcontext);
356
+ primary_loader, fixupcontext, as);
357
358
if (info->nb_cpus > 1) {
359
info->write_secondary_boot(cpu, info);
360
--
62
--
361
2.16.2
63
2.25.1
362
363
diff view generated by jsdifflib
1
The IoTKit Security Controller includes various registers
1
From: Richard Henderson <richard.henderson@linaro.org>
2
that expose to software the controls for the Peripheral
3
Protection Controllers in the system. Implement these.
4
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220708151540.18136-24-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-17-peter.maydell@linaro.org
8
---
7
---
9
include/hw/misc/iotkit-secctl.h | 64 +++++++++-
8
target/arm/helper-sme.h | 5 +++
10
hw/misc/iotkit-secctl.c | 270 +++++++++++++++++++++++++++++++++++++---
9
target/arm/sme.decode | 11 +++++
11
2 files changed, 315 insertions(+), 19 deletions(-)
10
target/arm/sme_helper.c | 90 ++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-sme.c | 31 +++++++++++++
12
4 files changed, 137 insertions(+)
12
13
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
16
--- a/target/arm/helper-sme.h
16
+++ b/include/hw/misc/iotkit-secctl.h
17
+++ b/target/arm/helper-sme.h
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sme_st1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i
18
* QEMU interface:
19
DEF_HELPER_FLAGS_5(sme_st1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
19
* + sysbus MMIO region 0 is the "secure privilege control block" registers
20
DEF_HELPER_FLAGS_5(sme_st1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
20
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
21
DEF_HELPER_FLAGS_5(sme_st1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
21
+ * + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
22
+ * should RAZ/WI or bus error
23
+ * Controlling the 2 APB PPCs in the IoTKit:
24
+ * + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
25
+ * + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
26
+ * + named GPIO outputs apb_ppc{0,1}_irq_enable
27
+ * + named GPIO outputs apb_ppc{0,1}_irq_clear
28
+ * + named GPIO inputs apb_ppc{0,1}_irq_status
29
+ * Controlling each of the 4 expansion APB PPCs which a system using the IoTKit
30
+ * might provide:
31
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
32
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
33
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
34
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
35
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
36
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
37
+ * might provide:
38
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
39
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
40
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
41
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
42
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
43
*/
44
45
#ifndef IOTKIT_SECCTL_H
46
@@ -XXX,XX +XXX,XX @@
47
#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
48
#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
49
50
-typedef struct IoTKitSecCtl {
51
+#define IOTS_APB_PPC0_NUM_PORTS 3
52
+#define IOTS_APB_PPC1_NUM_PORTS 1
53
+#define IOTS_PPC_NUM_PORTS 16
54
+#define IOTS_NUM_APB_PPC 2
55
+#define IOTS_NUM_APB_EXP_PPC 4
56
+#define IOTS_NUM_AHB_EXP_PPC 4
57
+
22
+
58
+typedef struct IoTKitSecCtl IoTKitSecCtl;
23
+DEF_HELPER_FLAGS_5(sme_addha_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/sme.decode
30
+++ b/target/arm/sme.decode
31
@@ -XXX,XX +XXX,XX @@ LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
32
33
LDR 1110000 100 0 000000 .. 000 ..... 0 .... @ldstr
34
STR 1110000 100 1 000000 .. 000 ..... 0 .... @ldstr
59
+
35
+
60
+/* State and IRQ lines relating to a PPC. For the
36
+### SME Add Vector to Array
61
+ * PPCs in the IoTKit not all the IRQ lines are used.
62
+ */
63
+typedef struct IoTKitSecCtlPPC {
64
+ qemu_irq nonsec[IOTS_PPC_NUM_PORTS];
65
+ qemu_irq ap[IOTS_PPC_NUM_PORTS];
66
+ qemu_irq irq_enable;
67
+ qemu_irq irq_clear;
68
+
37
+
69
+ uint32_t ns;
38
+&adda zad zn pm pn
70
+ uint32_t sp;
39
+@adda_32 ........ .. ..... . pm:3 pn:3 zn:5 ... zad:2 &adda
71
+ uint32_t nsp;
40
+@adda_64 ........ .. ..... . pm:3 pn:3 zn:5 .. zad:3 &adda
72
+
41
+
73
+ /* Number of ports actually present */
42
+ADDHA_s 11000000 10 01000 0 ... ... ..... 000 .. @adda_32
74
+ int numports;
43
+ADDVA_s 11000000 10 01000 1 ... ... ..... 000 .. @adda_32
75
+ /* Offset of this PPC's interrupt bits in SECPPCINTSTAT */
44
+ADDHA_d 11000000 11 01000 0 ... ... ..... 00 ... @adda_64
76
+ int irq_bit_offset;
45
+ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
77
+ IoTKitSecCtl *parent;
46
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
78
+} IoTKitSecCtlPPC;
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/sme_helper.c
49
+++ b/target/arm/sme_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_ST(q, _be, MO_128)
51
DO_ST(q, _le, MO_128)
52
53
#undef DO_ST
79
+
54
+
80
+struct IoTKitSecCtl {
55
+void HELPER(sme_addha_s)(void *vzda, void *vzn, void *vpn,
81
/*< private >*/
56
+ void *vpm, uint32_t desc)
82
SysBusDevice parent_obj;
57
+{
83
58
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
84
/*< public >*/
59
+ uint64_t *pn = vpn, *pm = vpm;
85
+ qemu_irq sec_resp_cfg;
60
+ uint32_t *zda = vzda, *zn = vzn;
86
87
MemoryRegion s_regs;
88
MemoryRegion ns_regs;
89
-} IoTKitSecCtl;
90
+
61
+
91
+ uint32_t secppcintstat;
62
+ for (row = 0; row < oprsz; ) {
92
+ uint32_t secppcinten;
63
+ uint64_t pa = pn[row >> 4];
93
+ uint32_t secrespcfg;
64
+ do {
94
+
65
+ if (pa & 1) {
95
+ IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
66
+ for (col = 0; col < oprsz; ) {
96
+ IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
67
+ uint64_t pb = pm[col >> 4];
97
+ IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
68
+ do {
98
+};
69
+ if (pb & 1) {
99
70
+ zda[tile_vslice_index(row) + H4(col)] += zn[H4(col)];
100
#endif
71
+ }
101
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
72
+ pb >>= 4;
102
index XXXXXXX..XXXXXXX 100644
73
+ } while (++col & 15);
103
--- a/hw/misc/iotkit-secctl.c
74
+ }
104
+++ b/hw/misc/iotkit-secctl.c
75
+ }
105
@@ -XXX,XX +XXX,XX @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
76
+ pa >>= 4;
106
0x0d, 0xf0, 0x05, 0xb1,
77
+ } while (++row & 15);
107
};
108
109
+/* The register sets for the various PPCs (AHB internal, APB internal,
110
+ * AHB expansion, APB expansion) are all set up so that they are
111
+ * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
112
+ * 0, 1, 2, 3 of that type, so we can convert a register address offset
113
+ * into an an index into a PPC array easily.
114
+ */
115
+static inline int offset_to_ppc_idx(uint32_t offset)
116
+{
117
+ return extract32(offset, 2, 2);
118
+}
119
+
120
+typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
121
+
122
+static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
123
+{
124
+ int i;
125
+
126
+ for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
127
+ fn(&s->apb[i]);
128
+ }
129
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
130
+ fn(&s->apbexp[i]);
131
+ }
132
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
133
+ fn(&s->ahbexp[i]);
134
+ }
78
+ }
135
+}
79
+}
136
+
80
+
137
static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
81
+void HELPER(sme_addha_d)(void *vzda, void *vzn, void *vpn,
138
uint64_t *pdata,
82
+ void *vpm, uint32_t desc)
139
unsigned size, MemTxAttrs attrs)
140
{
141
uint64_t r;
142
uint32_t offset = addr & ~0x3;
143
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
144
145
switch (offset) {
146
case A_AHBNSPPC0:
147
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
148
r = 0;
149
break;
150
case A_SECRESPCFG:
151
- case A_NSCCFG:
152
- case A_SECMPCINTSTATUS:
153
+ r = s->secrespcfg;
154
+ break;
155
case A_SECPPCINTSTAT:
156
+ r = s->secppcintstat;
157
+ break;
158
case A_SECPPCINTEN:
159
- case A_SECMSCINTSTAT:
160
- case A_SECMSCINTEN:
161
- case A_BRGINTSTAT:
162
- case A_BRGINTEN:
163
+ r = s->secppcinten;
164
+ break;
165
case A_AHBNSPPCEXP0:
166
case A_AHBNSPPCEXP1:
167
case A_AHBNSPPCEXP2:
168
case A_AHBNSPPCEXP3:
169
+ r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
170
+ break;
171
case A_APBNSPPC0:
172
case A_APBNSPPC1:
173
+ r = s->apb[offset_to_ppc_idx(offset)].ns;
174
+ break;
175
case A_APBNSPPCEXP0:
176
case A_APBNSPPCEXP1:
177
case A_APBNSPPCEXP2:
178
case A_APBNSPPCEXP3:
179
+ r = s->apbexp[offset_to_ppc_idx(offset)].ns;
180
+ break;
181
case A_AHBSPPPCEXP0:
182
case A_AHBSPPPCEXP1:
183
case A_AHBSPPPCEXP2:
184
case A_AHBSPPPCEXP3:
185
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
186
+ break;
187
case A_APBSPPPC0:
188
case A_APBSPPPC1:
189
+ r = s->apb[offset_to_ppc_idx(offset)].sp;
190
+ break;
191
case A_APBSPPPCEXP0:
192
case A_APBSPPPCEXP1:
193
case A_APBSPPPCEXP2:
194
case A_APBSPPPCEXP3:
195
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
196
+ break;
197
+ case A_NSCCFG:
198
+ case A_SECMPCINTSTATUS:
199
+ case A_SECMSCINTSTAT:
200
+ case A_SECMSCINTEN:
201
+ case A_BRGINTSTAT:
202
+ case A_BRGINTEN:
203
case A_NSMSCEXP:
204
qemu_log_mask(LOG_UNIMP,
205
"IoTKit SecCtl S block read: "
206
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
207
return MEMTX_OK;
208
}
209
210
+static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
211
+{
83
+{
212
+ int i;
84
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
85
+ uint8_t *pn = vpn, *pm = vpm;
86
+ uint64_t *zda = vzda, *zn = vzn;
213
+
87
+
214
+ for (i = 0; i < ppc->numports; i++) {
88
+ for (row = 0; row < oprsz; ++row) {
215
+ bool v;
89
+ if (pn[H1(row)] & 1) {
216
+
90
+ for (col = 0; col < oprsz; ++col) {
217
+ if (extract32(ppc->ns, i, 1)) {
91
+ if (pm[H1(col)] & 1) {
218
+ v = extract32(ppc->nsp, i, 1);
92
+ zda[tile_vslice_index(row) + col] += zn[col];
219
+ } else {
93
+ }
220
+ v = extract32(ppc->sp, i, 1);
94
+ }
221
+ }
95
+ }
222
+ qemu_set_irq(ppc->ap[i], v);
223
+ }
96
+ }
224
+}
97
+}
225
+
98
+
226
+static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
99
+void HELPER(sme_addva_s)(void *vzda, void *vzn, void *vpn,
100
+ void *vpm, uint32_t desc)
227
+{
101
+{
228
+ int i;
102
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
103
+ uint64_t *pn = vpn, *pm = vpm;
104
+ uint32_t *zda = vzda, *zn = vzn;
229
+
105
+
230
+ ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
106
+ for (row = 0; row < oprsz; ) {
231
+ for (i = 0; i < ppc->numports; i++) {
107
+ uint64_t pa = pn[row >> 4];
232
+ qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
108
+ do {
109
+ if (pa & 1) {
110
+ uint32_t zn_row = zn[H4(row)];
111
+ for (col = 0; col < oprsz; ) {
112
+ uint64_t pb = pm[col >> 4];
113
+ do {
114
+ if (pb & 1) {
115
+ zda[tile_vslice_index(row) + H4(col)] += zn_row;
116
+ }
117
+ pb >>= 4;
118
+ } while (++col & 15);
119
+ }
120
+ }
121
+ pa >>= 4;
122
+ } while (++row & 15);
233
+ }
123
+ }
234
+ iotkit_secctl_update_ppc_ap(ppc);
235
+}
124
+}
236
+
125
+
237
+static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
126
+void HELPER(sme_addva_d)(void *vzda, void *vzn, void *vpn,
127
+ void *vpm, uint32_t desc)
238
+{
128
+{
239
+ ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
129
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
240
+ iotkit_secctl_update_ppc_ap(ppc);
130
+ uint8_t *pn = vpn, *pm = vpm;
131
+ uint64_t *zda = vzda, *zn = vzn;
132
+
133
+ for (row = 0; row < oprsz; ++row) {
134
+ if (pn[H1(row)] & 1) {
135
+ uint64_t zn_row = zn[row];
136
+ for (col = 0; col < oprsz; ++col) {
137
+ if (pm[H1(col)] & 1) {
138
+ zda[tile_vslice_index(row) + col] += zn_row;
139
+ }
140
+ }
141
+ }
142
+ }
143
+}
144
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/target/arm/translate-sme.c
147
+++ b/target/arm/translate-sme.c
148
@@ -XXX,XX +XXX,XX @@ static bool do_ldst_r(DisasContext *s, arg_ldstr *a, GenLdStR *fn)
149
150
TRANS_FEAT(LDR, aa64_sme, do_ldst_r, a, gen_sve_ldr)
151
TRANS_FEAT(STR, aa64_sme, do_ldst_r, a, gen_sve_str)
152
+
153
+static bool do_adda(DisasContext *s, arg_adda *a, MemOp esz,
154
+ gen_helper_gvec_4 *fn)
155
+{
156
+ int svl = streaming_vec_reg_size(s);
157
+ uint32_t desc = simd_desc(svl, svl, 0);
158
+ TCGv_ptr za, zn, pn, pm;
159
+
160
+ if (!sme_smza_enabled_check(s)) {
161
+ return true;
162
+ }
163
+
164
+ /* Sum XZR+zad to find ZAd. */
165
+ za = get_tile_rowcol(s, esz, 31, a->zad, false);
166
+ zn = vec_full_reg_ptr(s, a->zn);
167
+ pn = pred_full_reg_ptr(s, a->pn);
168
+ pm = pred_full_reg_ptr(s, a->pm);
169
+
170
+ fn(za, zn, pn, pm, tcg_constant_i32(desc));
171
+
172
+ tcg_temp_free_ptr(za);
173
+ tcg_temp_free_ptr(zn);
174
+ tcg_temp_free_ptr(pn);
175
+ tcg_temp_free_ptr(pm);
176
+ return true;
241
+}
177
+}
242
+
178
+
243
+static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
179
+TRANS_FEAT(ADDHA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addha_s)
244
+{
180
+TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
245
+ ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
181
+TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
246
+ iotkit_secctl_update_ppc_ap(ppc);
182
+TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
247
+}
248
+
249
+static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
250
+{
251
+ uint32_t value = ppc->parent->secppcintstat;
252
+
253
+ qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
254
+}
255
+
256
+static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
257
+{
258
+ uint32_t value = ppc->parent->secppcinten;
259
+
260
+ qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
261
+}
262
+
263
static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
264
uint64_t value,
265
unsigned size, MemTxAttrs attrs)
266
{
267
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
268
uint32_t offset = addr;
269
+ IoTKitSecCtlPPC *ppc;
270
271
trace_iotkit_secctl_s_write(offset, value, size);
272
273
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
274
275
switch (offset) {
276
case A_SECRESPCFG:
277
- case A_NSCCFG:
278
+ value &= 1;
279
+ s->secrespcfg = value;
280
+ qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
281
+ break;
282
case A_SECPPCINTCLR:
283
+ value &= 0x00f000f3;
284
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
285
+ break;
286
case A_SECPPCINTEN:
287
- case A_SECMSCINTCLR:
288
- case A_SECMSCINTEN:
289
- case A_BRGINTCLR:
290
- case A_BRGINTEN:
291
+ s->secppcinten = value & 0x00f000f3;
292
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
293
+ break;
294
case A_AHBNSPPCEXP0:
295
case A_AHBNSPPCEXP1:
296
case A_AHBNSPPCEXP2:
297
case A_AHBNSPPCEXP3:
298
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
299
+ iotkit_secctl_ppc_ns_write(ppc, value);
300
+ break;
301
case A_APBNSPPC0:
302
case A_APBNSPPC1:
303
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
304
+ iotkit_secctl_ppc_ns_write(ppc, value);
305
+ break;
306
case A_APBNSPPCEXP0:
307
case A_APBNSPPCEXP1:
308
case A_APBNSPPCEXP2:
309
case A_APBNSPPCEXP3:
310
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
311
+ iotkit_secctl_ppc_ns_write(ppc, value);
312
+ break;
313
case A_AHBSPPPCEXP0:
314
case A_AHBSPPPCEXP1:
315
case A_AHBSPPPCEXP2:
316
case A_AHBSPPPCEXP3:
317
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
318
+ iotkit_secctl_ppc_sp_write(ppc, value);
319
+ break;
320
case A_APBSPPPC0:
321
case A_APBSPPPC1:
322
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
323
+ iotkit_secctl_ppc_sp_write(ppc, value);
324
+ break;
325
case A_APBSPPPCEXP0:
326
case A_APBSPPPCEXP1:
327
case A_APBSPPPCEXP2:
328
case A_APBSPPPCEXP3:
329
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
330
+ iotkit_secctl_ppc_sp_write(ppc, value);
331
+ break;
332
+ case A_NSCCFG:
333
+ case A_SECMSCINTCLR:
334
+ case A_SECMSCINTEN:
335
+ case A_BRGINTCLR:
336
+ case A_BRGINTEN:
337
qemu_log_mask(LOG_UNIMP,
338
"IoTKit SecCtl S block write: "
339
"unimplemented offset 0x%x\n", offset);
340
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
341
uint64_t *pdata,
342
unsigned size, MemTxAttrs attrs)
343
{
344
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
345
uint64_t r;
346
uint32_t offset = addr & ~0x3;
347
348
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
349
case A_AHBNSPPPCEXP1:
350
case A_AHBNSPPPCEXP2:
351
case A_AHBNSPPPCEXP3:
352
+ r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
353
+ break;
354
case A_APBNSPPPC0:
355
case A_APBNSPPPC1:
356
+ r = s->apb[offset_to_ppc_idx(offset)].nsp;
357
+ break;
358
case A_APBNSPPPCEXP0:
359
case A_APBNSPPPCEXP1:
360
case A_APBNSPPPCEXP2:
361
case A_APBNSPPPCEXP3:
362
- qemu_log_mask(LOG_UNIMP,
363
- "IoTKit SecCtl NS block read: "
364
- "unimplemented offset 0x%x\n", offset);
365
+ r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
366
break;
367
case A_PID4:
368
case A_PID5:
369
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
370
uint64_t value,
371
unsigned size, MemTxAttrs attrs)
372
{
373
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
374
uint32_t offset = addr;
375
+ IoTKitSecCtlPPC *ppc;
376
377
trace_iotkit_secctl_ns_write(offset, value, size);
378
379
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
380
case A_AHBNSPPPCEXP1:
381
case A_AHBNSPPPCEXP2:
382
case A_AHBNSPPPCEXP3:
383
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
384
+ iotkit_secctl_ppc_nsp_write(ppc, value);
385
+ break;
386
case A_APBNSPPPC0:
387
case A_APBNSPPPC1:
388
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
389
+ iotkit_secctl_ppc_nsp_write(ppc, value);
390
+ break;
391
case A_APBNSPPPCEXP0:
392
case A_APBNSPPPCEXP1:
393
case A_APBNSPPPCEXP2:
394
case A_APBNSPPPCEXP3:
395
- qemu_log_mask(LOG_UNIMP,
396
- "IoTKit SecCtl NS block write: "
397
- "unimplemented offset 0x%x\n", offset);
398
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
399
+ iotkit_secctl_ppc_nsp_write(ppc, value);
400
break;
401
case A_AHBNSPPPC0:
402
case A_PID4:
403
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_secctl_ns_ops = {
404
.impl.max_access_size = 4,
405
};
406
407
+static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
408
+{
409
+ ppc->ns = 0;
410
+ ppc->sp = 0;
411
+ ppc->nsp = 0;
412
+}
413
+
414
static void iotkit_secctl_reset(DeviceState *dev)
415
{
416
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
417
418
+ s->secppcintstat = 0;
419
+ s->secppcinten = 0;
420
+ s->secrespcfg = 0;
421
+
422
+ foreach_ppc(s, iotkit_secctl_reset_ppc);
423
+}
424
+
425
+static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
426
+{
427
+ IoTKitSecCtlPPC *ppc = opaque;
428
+ IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
429
+ int irqbit = ppc->irq_bit_offset + n;
430
+
431
+ s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
432
+}
433
+
434
+static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
435
+ IoTKitSecCtlPPC *ppc,
436
+ const char *name,
437
+ int numports,
438
+ int irq_bit_offset)
439
+{
440
+ char *gpioname;
441
+ DeviceState *dev = DEVICE(s);
442
+
443
+ ppc->numports = numports;
444
+ ppc->irq_bit_offset = irq_bit_offset;
445
+ ppc->parent = s;
446
+
447
+ gpioname = g_strdup_printf("%s_nonsec", name);
448
+ qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
449
+ g_free(gpioname);
450
+ gpioname = g_strdup_printf("%s_ap", name);
451
+ qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
452
+ g_free(gpioname);
453
+ gpioname = g_strdup_printf("%s_irq_enable", name);
454
+ qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_irq_clear", name);
457
+ qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
458
+ g_free(gpioname);
459
+ gpioname = g_strdup_printf("%s_irq_status", name);
460
+ qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
461
+ ppc, gpioname, 1);
462
+ g_free(gpioname);
463
}
464
465
static void iotkit_secctl_init(Object *obj)
466
{
467
IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
468
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
469
+ DeviceState *dev = DEVICE(obj);
470
+ int i;
471
+
472
+ iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
473
+ IOTS_APB_PPC0_NUM_PORTS, 0);
474
+ iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
475
+ IOTS_APB_PPC1_NUM_PORTS, 1);
476
+
477
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
478
+ IoTKitSecCtlPPC *ppc = &s->apbexp[i];
479
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
480
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
481
+ g_free(ppcname);
482
+ }
483
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
484
+ IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
485
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
486
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
487
+ g_free(ppcname);
488
+ }
489
+
490
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
491
492
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
s, "iotkit-secctl-s-regs", 0x1000);
494
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
495
sysbus_init_mmio(sbd, &s->ns_regs);
496
}
497
498
+static const VMStateDescription iotkit_secctl_ppc_vmstate = {
499
+ .name = "iotkit-secctl-ppc",
500
+ .version_id = 1,
501
+ .minimum_version_id = 1,
502
+ .fields = (VMStateField[]) {
503
+ VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
504
+ VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
505
+ VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
506
+ VMSTATE_END_OF_LIST()
507
+ }
508
+};
509
+
510
static const VMStateDescription iotkit_secctl_vmstate = {
511
.name = "iotkit-secctl",
512
.version_id = 1,
513
.minimum_version_id = 1,
514
.fields = (VMStateField[]) {
515
+ VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
516
+ VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
517
+ VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
518
+ VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
519
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
520
+ VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
521
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
522
+ VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
523
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
524
VMSTATE_END_OF_LIST()
525
}
526
};
527
--
183
--
528
2.16.2
184
2.25.1
529
530
diff view generated by jsdifflib
1
Create an "init-svtor" property on the armv7m container
1
From: Richard Henderson <richard.henderson@linaro.org>
2
object which we can forward to the CPU object.
3
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20220708151540.18136-25-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20180220180325.29818-8-peter.maydell@linaro.org
7
---
7
---
8
include/hw/arm/armv7m.h | 2 ++
8
target/arm/helper-sme.h | 5 +++
9
hw/arm/armv7m.c | 9 +++++++++
9
target/arm/sme.decode | 9 +++++
10
2 files changed, 11 insertions(+)
10
target/arm/sme_helper.c | 69 ++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-sme.c | 32 ++++++++++++++++++
12
4 files changed, 115 insertions(+)
11
13
12
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armv7m.h
16
--- a/target/arm/helper-sme.h
15
+++ b/include/hw/arm/armv7m.h
17
+++ b/target/arm/helper-sme.h
16
@@ -XXX,XX +XXX,XX @@ typedef struct {
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sme_addha_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
17
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
19
DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
18
* devices will be automatically layered on top of this view.)
20
DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
* + Property "idau": IDAU interface (forwarded to CPU object)
21
DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
+ * + Property "init-svtor": secure VTOR reset value (forwarded to CPU object)
22
+
21
*/
23
+DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
22
typedef struct ARMv7MState {
24
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
23
/*< private >*/
25
+DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
24
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
26
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
25
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
27
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
26
MemoryRegion *board_memory;
27
Object *idau;
28
+ uint32_t init_svtor;
29
} ARMv7MState;
30
31
#endif
32
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
33
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/armv7m.c
29
--- a/target/arm/sme.decode
35
+++ b/hw/arm/armv7m.c
30
+++ b/target/arm/sme.decode
36
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
31
@@ -XXX,XX +XXX,XX @@ ADDHA_s 11000000 10 01000 0 ... ... ..... 000 .. @adda_32
37
return;
32
ADDVA_s 11000000 10 01000 1 ... ... ..... 000 .. @adda_32
33
ADDHA_d 11000000 11 01000 0 ... ... ..... 00 ... @adda_64
34
ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
35
+
36
+### SME Outer Product
37
+
38
+&op zad zn zm pm pn sub:bool
39
+@op_32 ........ ... zm:5 pm:3 pn:3 zn:5 sub:1 .. zad:2 &op
40
+@op_64 ........ ... zm:5 pm:3 pn:3 zn:5 sub:1 . zad:3 &op
41
+
42
+FMOPA_s 10000000 100 ..... ... ... ..... . 00 .. @op_32
43
+FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
44
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/sme_helper.c
47
+++ b/target/arm/sme_helper.c
48
@@ -XXX,XX +XXX,XX @@
49
#include "exec/cpu_ldst.h"
50
#include "exec/exec-all.h"
51
#include "qemu/int128.h"
52
+#include "fpu/softfloat.h"
53
#include "vec_internal.h"
54
#include "sve_ldst_internal.h"
55
56
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_addva_d)(void *vzda, void *vzn, void *vpn,
38
}
57
}
39
}
58
}
40
+ if (object_property_find(OBJECT(s->cpu), "init-svtor", NULL)) {
59
}
41
+ object_property_set_uint(OBJECT(s->cpu), s->init_svtor,
60
+
42
+ "init-svtor", &err);
61
+void HELPER(sme_fmopa_s)(void *vza, void *vzn, void *vzm, void *vpn,
43
+ if (err != NULL) {
62
+ void *vpm, void *vst, uint32_t desc)
44
+ error_propagate(errp, err);
63
+{
45
+ return;
64
+ intptr_t row, col, oprsz = simd_maxsz(desc);
65
+ uint32_t neg = simd_data(desc) << 31;
66
+ uint16_t *pn = vpn, *pm = vpm;
67
+ float_status fpst;
68
+
69
+ /*
70
+ * Make a copy of float_status because this operation does not
71
+ * update the cumulative fp exception status. It also produces
72
+ * default nans.
73
+ */
74
+ fpst = *(float_status *)vst;
75
+ set_default_nan_mode(true, &fpst);
76
+
77
+ for (row = 0; row < oprsz; ) {
78
+ uint16_t pa = pn[H2(row >> 4)];
79
+ do {
80
+ if (pa & 1) {
81
+ void *vza_row = vza + tile_vslice_offset(row);
82
+ uint32_t n = *(uint32_t *)(vzn + H1_4(row)) ^ neg;
83
+
84
+ for (col = 0; col < oprsz; ) {
85
+ uint16_t pb = pm[H2(col >> 4)];
86
+ do {
87
+ if (pb & 1) {
88
+ uint32_t *a = vza_row + H1_4(col);
89
+ uint32_t *m = vzm + H1_4(col);
90
+ *a = float32_muladd(n, *m, *a, 0, vst);
91
+ }
92
+ col += 4;
93
+ pb >>= 4;
94
+ } while (col & 15);
95
+ }
96
+ }
97
+ row += 4;
98
+ pa >>= 4;
99
+ } while (row & 15);
100
+ }
101
+}
102
+
103
+void HELPER(sme_fmopa_d)(void *vza, void *vzn, void *vzm, void *vpn,
104
+ void *vpm, void *vst, uint32_t desc)
105
+{
106
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
107
+ uint64_t neg = (uint64_t)simd_data(desc) << 63;
108
+ uint64_t *za = vza, *zn = vzn, *zm = vzm;
109
+ uint8_t *pn = vpn, *pm = vpm;
110
+ float_status fpst = *(float_status *)vst;
111
+
112
+ set_default_nan_mode(true, &fpst);
113
+
114
+ for (row = 0; row < oprsz; ++row) {
115
+ if (pn[H1(row)] & 1) {
116
+ uint64_t *za_row = &za[tile_vslice_index(row)];
117
+ uint64_t n = zn[row] ^ neg;
118
+
119
+ for (col = 0; col < oprsz; ++col) {
120
+ if (pm[H1(col)] & 1) {
121
+ uint64_t *a = &za_row[col];
122
+ *a = float64_muladd(n, zm[col], *a, 0, &fpst);
123
+ }
124
+ }
46
+ }
125
+ }
47
+ }
126
+ }
48
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
127
+}
49
if (err != NULL) {
128
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
50
error_propagate(errp, err);
129
index XXXXXXX..XXXXXXX 100644
51
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
130
--- a/target/arm/translate-sme.c
52
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
131
+++ b/target/arm/translate-sme.c
53
MemoryRegion *),
132
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(ADDHA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addha_s)
54
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
133
TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
55
+ DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
134
TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
56
DEFINE_PROP_END_OF_LIST(),
135
TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
57
};
136
+
58
137
+static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
138
+ gen_helper_gvec_5_ptr *fn)
139
+{
140
+ int svl = streaming_vec_reg_size(s);
141
+ uint32_t desc = simd_desc(svl, svl, a->sub);
142
+ TCGv_ptr za, zn, zm, pn, pm, fpst;
143
+
144
+ if (!sme_smza_enabled_check(s)) {
145
+ return true;
146
+ }
147
+
148
+ /* Sum XZR+zad to find ZAd. */
149
+ za = get_tile_rowcol(s, esz, 31, a->zad, false);
150
+ zn = vec_full_reg_ptr(s, a->zn);
151
+ zm = vec_full_reg_ptr(s, a->zm);
152
+ pn = pred_full_reg_ptr(s, a->pn);
153
+ pm = pred_full_reg_ptr(s, a->pm);
154
+ fpst = fpstatus_ptr(FPST_FPCR);
155
+
156
+ fn(za, zn, zm, pn, pm, fpst, tcg_constant_i32(desc));
157
+
158
+ tcg_temp_free_ptr(za);
159
+ tcg_temp_free_ptr(zn);
160
+ tcg_temp_free_ptr(pn);
161
+ tcg_temp_free_ptr(pm);
162
+ tcg_temp_free_ptr(fpst);
163
+ return true;
164
+}
165
+
166
+TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
167
+TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
59
--
168
--
60
2.16.2
169
2.25.1
61
62
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20180228193125.20577-13-richard.henderson@linaro.org
4
Message-id: 20220708151540.18136-26-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
[PMM: renamed e1/e2/e3/e4 to use the same naming as the version
7
of the pseudocode in the Arm ARM]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
---
7
---
10
target/arm/helper.h | 11 ++++
8
target/arm/helper-sme.h | 2 ++
11
target/arm/translate-a64.c | 94 +++++++++++++++++++++++++---
9
target/arm/sme.decode | 2 ++
12
target/arm/vec_helper.c | 149 +++++++++++++++++++++++++++++++++++++++++++++
10
target/arm/sme_helper.c | 56 ++++++++++++++++++++++++++++++++++++++
13
3 files changed, 246 insertions(+), 8 deletions(-)
11
target/arm/translate-sme.c | 30 ++++++++++++++++++++
12
4 files changed, 90 insertions(+)
14
13
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
16
--- a/target/arm/helper-sme.h
18
+++ b/target/arm/helper.h
17
+++ b/target/arm/helper-sme.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
20
DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
19
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
21
void, ptr, ptr, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
22
21
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_5(gvec_fcmlah, TCG_CALL_NO_RWG,
22
+DEF_HELPER_FLAGS_6(sme_bfmopa, TCG_CALL_NO_RWG,
24
+ void, ptr, ptr, ptr, ptr, i32)
23
+ void, ptr, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_fcmlah_idx, TCG_CALL_NO_RWG,
24
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
26
+ void, ptr, ptr, ptr, ptr, i32)
25
index XXXXXXX..XXXXXXX 100644
27
+DEF_HELPER_FLAGS_5(gvec_fcmlas, TCG_CALL_NO_RWG,
26
--- a/target/arm/sme.decode
28
+ void, ptr, ptr, ptr, ptr, i32)
27
+++ b/target/arm/sme.decode
29
+DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
28
@@ -XXX,XX +XXX,XX @@ ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
30
+ void, ptr, ptr, ptr, ptr, i32)
29
31
+DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
30
FMOPA_s 10000000 100 ..... ... ... ..... . 00 .. @op_32
32
+ void, ptr, ptr, ptr, ptr, i32)
31
FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
33
+
32
+
34
#ifdef TARGET_AARCH64
33
+BFMOPA 10000001 100 ..... ... ... ..... . 00 .. @op_32
35
#include "helper-a64.h"
34
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
36
#endif
37
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
38
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-a64.c
36
--- a/target/arm/sme_helper.c
40
+++ b/target/arm/translate-a64.c
37
+++ b/target/arm/sme_helper.c
41
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
38
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_fmopa_d)(void *vza, void *vzn, void *vzm, void *vpn,
42
}
39
}
43
feature = ARM_FEATURE_V8_RDM;
40
}
44
break;
41
}
45
+ case 0x8: /* FCMLA, #0 */
46
+ case 0x9: /* FCMLA, #90 */
47
+ case 0xa: /* FCMLA, #180 */
48
+ case 0xb: /* FCMLA, #270 */
49
case 0xc: /* FCADD, #90 */
50
case 0xe: /* FCADD, #270 */
51
if (size == 0
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
53
}
54
return;
55
56
+ case 0x8: /* FCMLA, #0 */
57
+ case 0x9: /* FCMLA, #90 */
58
+ case 0xa: /* FCMLA, #180 */
59
+ case 0xb: /* FCMLA, #270 */
60
+ rot = extract32(opcode, 0, 2);
61
+ switch (size) {
62
+ case 1:
63
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
64
+ gen_helper_gvec_fcmlah);
65
+ break;
66
+ case 2:
67
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
68
+ gen_helper_gvec_fcmlas);
69
+ break;
70
+ case 3:
71
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
72
+ gen_helper_gvec_fcmlad);
73
+ break;
74
+ default:
75
+ g_assert_not_reached();
76
+ }
77
+ return;
78
+
42
+
79
case 0xc: /* FCADD, #90 */
43
+/*
80
case 0xe: /* FCADD, #270 */
44
+ * Alter PAIR as needed for controlling predicates being false,
81
rot = extract32(opcode, 1, 1);
45
+ * and for NEG on an enabled row element.
82
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
46
+ */
83
int rn = extract32(insn, 5, 5);
47
+static inline uint32_t f16mop_adj_pair(uint32_t pair, uint32_t pg, uint32_t neg)
84
int rd = extract32(insn, 0, 5);
48
+{
85
bool is_long = false;
49
+ /*
86
- bool is_fp = false;
50
+ * The pseudocode uses a conditional negate after the conditional zero.
87
+ int is_fp = 0;
51
+ * It is simpler here to unconditionally negate before conditional zero.
88
bool is_fp16 = false;
52
+ */
89
int index;
53
+ pair ^= neg;
90
TCGv_ptr fpst;
54
+ if (!(pg & 1)) {
91
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
55
+ pair &= 0xffff0000u;
92
case 0x05: /* FMLS */
56
+ }
93
case 0x09: /* FMUL */
57
+ if (!(pg & 4)) {
94
case 0x19: /* FMULX */
58
+ pair &= 0x0000ffffu;
95
- is_fp = true;
59
+ }
96
+ is_fp = 1;
60
+ return pair;
97
break;
61
+}
98
case 0x1d: /* SQRDMLAH */
99
case 0x1f: /* SQRDMLSH */
100
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
101
return;
102
}
103
break;
104
+ case 0x11: /* FCMLA #0 */
105
+ case 0x13: /* FCMLA #90 */
106
+ case 0x15: /* FCMLA #180 */
107
+ case 0x17: /* FCMLA #270 */
108
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)) {
109
+ unallocated_encoding(s);
110
+ return;
111
+ }
112
+ is_fp = 2;
113
+ break;
114
default:
115
unallocated_encoding(s);
116
return;
117
}
118
119
- if (is_fp) {
120
+ switch (is_fp) {
121
+ case 1: /* normal fp */
122
/* convert insn encoded size to TCGMemOp size */
123
switch (size) {
124
case 0: /* half-precision */
125
- if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
126
- unallocated_encoding(s);
127
- return;
128
- }
129
size = MO_16;
130
+ is_fp16 = true;
131
break;
132
case MO_32: /* single precision */
133
case MO_64: /* double precision */
134
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
135
unallocated_encoding(s);
136
return;
137
}
138
- } else {
139
+ break;
140
+
62
+
141
+ case 2: /* complex fp */
63
+void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
142
+ /* Each indexable element is a complex pair. */
64
+ void *vpm, uint32_t desc)
143
+ size <<= 1;
65
+{
144
+ switch (size) {
66
+ intptr_t row, col, oprsz = simd_maxsz(desc);
145
+ case MO_32:
67
+ uint32_t neg = simd_data(desc) * 0x80008000u;
146
+ if (h && !is_q) {
68
+ uint16_t *pn = vpn, *pm = vpm;
147
+ unallocated_encoding(s);
69
+
148
+ return;
70
+ for (row = 0; row < oprsz; ) {
71
+ uint16_t prow = pn[H2(row >> 4)];
72
+ do {
73
+ void *vza_row = vza + tile_vslice_offset(row);
74
+ uint32_t n = *(uint32_t *)(vzn + H1_4(row));
75
+
76
+ n = f16mop_adj_pair(n, prow, neg);
77
+
78
+ for (col = 0; col < oprsz; ) {
79
+ uint16_t pcol = pm[H2(col >> 4)];
80
+ do {
81
+ if (prow & pcol & 0b0101) {
82
+ uint32_t *a = vza_row + H1_4(col);
83
+ uint32_t m = *(uint32_t *)(vzm + H1_4(col));
84
+
85
+ m = f16mop_adj_pair(m, pcol, 0);
86
+ *a = bfdotadd(*a, n, m);
87
+
88
+ col += 4;
89
+ pcol >>= 4;
90
+ }
91
+ } while (col & 15);
149
+ }
92
+ }
150
+ is_fp16 = true;
93
+ row += 4;
151
+ break;
94
+ prow >>= 4;
152
+ case MO_64:
95
+ } while (row & 15);
153
+ break;
96
+ }
154
+ default:
97
+}
155
+ unallocated_encoding(s);
98
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
156
+ return;
99
index XXXXXXX..XXXXXXX 100644
157
+ }
100
--- a/target/arm/translate-sme.c
158
+ break;
101
+++ b/target/arm/translate-sme.c
102
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
103
TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
104
TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
105
106
+static bool do_outprod(DisasContext *s, arg_op *a, MemOp esz,
107
+ gen_helper_gvec_5 *fn)
108
+{
109
+ int svl = streaming_vec_reg_size(s);
110
+ uint32_t desc = simd_desc(svl, svl, a->sub);
111
+ TCGv_ptr za, zn, zm, pn, pm;
159
+
112
+
160
+ default: /* integer */
113
+ if (!sme_smza_enabled_check(s)) {
161
switch (size) {
114
+ return true;
162
case MO_8:
163
case MO_64:
164
unallocated_encoding(s);
165
return;
166
}
167
+ break;
168
+ }
169
+ if (is_fp16 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
170
+ unallocated_encoding(s);
171
+ return;
172
}
173
174
/* Given TCGMemOp size, adjust register and indexing. */
175
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
176
fpst = NULL;
177
}
178
179
+ switch (16 * u + opcode) {
180
+ case 0x11: /* FCMLA #0 */
181
+ case 0x13: /* FCMLA #90 */
182
+ case 0x15: /* FCMLA #180 */
183
+ case 0x17: /* FCMLA #270 */
184
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
185
+ vec_full_reg_offset(s, rn),
186
+ vec_reg_offset(s, rm, index, size), fpst,
187
+ is_q ? 16 : 8, vec_full_reg_size(s),
188
+ extract32(insn, 13, 2), /* rot */
189
+ size == MO_64
190
+ ? gen_helper_gvec_fcmlas_idx
191
+ : gen_helper_gvec_fcmlah_idx);
192
+ tcg_temp_free_ptr(fpst);
193
+ return;
194
+ }
115
+ }
195
+
116
+
196
if (size == 3) {
117
+ /* Sum XZR+zad to find ZAd. */
197
TCGv_i64 tcg_idx = tcg_temp_new_i64();
118
+ za = get_tile_rowcol(s, esz, 31, a->zad, false);
198
int pass;
119
+ zn = vec_full_reg_ptr(s, a->zn);
199
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
120
+ zm = vec_full_reg_ptr(s, a->zm);
200
index XXXXXXX..XXXXXXX 100644
121
+ pn = pred_full_reg_ptr(s, a->pn);
201
--- a/target/arm/vec_helper.c
122
+ pm = pred_full_reg_ptr(s, a->pm);
202
+++ b/target/arm/vec_helper.c
203
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
204
}
205
clear_tail(d, opr_sz, simd_maxsz(desc));
206
}
207
+
123
+
208
+void HELPER(gvec_fcmlah)(void *vd, void *vn, void *vm,
124
+ fn(za, zn, zm, pn, pm, tcg_constant_i32(desc));
209
+ void *vfpst, uint32_t desc)
210
+{
211
+ uintptr_t opr_sz = simd_oprsz(desc);
212
+ float16 *d = vd;
213
+ float16 *n = vn;
214
+ float16 *m = vm;
215
+ float_status *fpst = vfpst;
216
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
217
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
218
+ uint32_t neg_real = flip ^ neg_imag;
219
+ uintptr_t i;
220
+
125
+
221
+ /* Shift boolean to the sign bit so we can xor to negate. */
126
+ tcg_temp_free_ptr(za);
222
+ neg_real <<= 15;
127
+ tcg_temp_free_ptr(zn);
223
+ neg_imag <<= 15;
128
+ tcg_temp_free_ptr(pn);
224
+
129
+ tcg_temp_free_ptr(pm);
225
+ for (i = 0; i < opr_sz / 2; i += 2) {
130
+ return true;
226
+ float16 e2 = n[H2(i + flip)];
227
+ float16 e1 = m[H2(i + flip)] ^ neg_real;
228
+ float16 e4 = e2;
229
+ float16 e3 = m[H2(i + 1 - flip)] ^ neg_imag;
230
+
231
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
232
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
233
+ }
234
+ clear_tail(d, opr_sz, simd_maxsz(desc));
235
+}
131
+}
236
+
132
+
237
+void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
133
static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
238
+ void *vfpst, uint32_t desc)
134
gen_helper_gvec_5_ptr *fn)
239
+{
135
{
240
+ uintptr_t opr_sz = simd_oprsz(desc);
136
@@ -XXX,XX +XXX,XX @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
241
+ float16 *d = vd;
137
242
+ float16 *n = vn;
138
TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
243
+ float16 *m = vm;
139
TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
244
+ float_status *fpst = vfpst;
245
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
246
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
247
+ uint32_t neg_real = flip ^ neg_imag;
248
+ uintptr_t i;
249
+ float16 e1 = m[H2(flip)];
250
+ float16 e3 = m[H2(1 - flip)];
251
+
140
+
252
+ /* Shift boolean to the sign bit so we can xor to negate. */
141
+/* TODO: FEAT_EBF16 */
253
+ neg_real <<= 15;
142
+TRANS_FEAT(BFMOPA, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_bfmopa)
254
+ neg_imag <<= 15;
255
+ e1 ^= neg_real;
256
+ e3 ^= neg_imag;
257
+
258
+ for (i = 0; i < opr_sz / 2; i += 2) {
259
+ float16 e2 = n[H2(i + flip)];
260
+ float16 e4 = e2;
261
+
262
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
263
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
264
+ }
265
+ clear_tail(d, opr_sz, simd_maxsz(desc));
266
+}
267
+
268
+void HELPER(gvec_fcmlas)(void *vd, void *vn, void *vm,
269
+ void *vfpst, uint32_t desc)
270
+{
271
+ uintptr_t opr_sz = simd_oprsz(desc);
272
+ float32 *d = vd;
273
+ float32 *n = vn;
274
+ float32 *m = vm;
275
+ float_status *fpst = vfpst;
276
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
277
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
278
+ uint32_t neg_real = flip ^ neg_imag;
279
+ uintptr_t i;
280
+
281
+ /* Shift boolean to the sign bit so we can xor to negate. */
282
+ neg_real <<= 31;
283
+ neg_imag <<= 31;
284
+
285
+ for (i = 0; i < opr_sz / 4; i += 2) {
286
+ float32 e2 = n[H4(i + flip)];
287
+ float32 e1 = m[H4(i + flip)] ^ neg_real;
288
+ float32 e4 = e2;
289
+ float32 e3 = m[H4(i + 1 - flip)] ^ neg_imag;
290
+
291
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
292
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
293
+ }
294
+ clear_tail(d, opr_sz, simd_maxsz(desc));
295
+}
296
+
297
+void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
298
+ void *vfpst, uint32_t desc)
299
+{
300
+ uintptr_t opr_sz = simd_oprsz(desc);
301
+ float32 *d = vd;
302
+ float32 *n = vn;
303
+ float32 *m = vm;
304
+ float_status *fpst = vfpst;
305
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
306
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
307
+ uint32_t neg_real = flip ^ neg_imag;
308
+ uintptr_t i;
309
+ float32 e1 = m[H4(flip)];
310
+ float32 e3 = m[H4(1 - flip)];
311
+
312
+ /* Shift boolean to the sign bit so we can xor to negate. */
313
+ neg_real <<= 31;
314
+ neg_imag <<= 31;
315
+ e1 ^= neg_real;
316
+ e3 ^= neg_imag;
317
+
318
+ for (i = 0; i < opr_sz / 4; i += 2) {
319
+ float32 e2 = n[H4(i + flip)];
320
+ float32 e4 = e2;
321
+
322
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
323
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
324
+ }
325
+ clear_tail(d, opr_sz, simd_maxsz(desc));
326
+}
327
+
328
+void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
329
+ void *vfpst, uint32_t desc)
330
+{
331
+ uintptr_t opr_sz = simd_oprsz(desc);
332
+ float64 *d = vd;
333
+ float64 *n = vn;
334
+ float64 *m = vm;
335
+ float_status *fpst = vfpst;
336
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
337
+ uint64_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
338
+ uint64_t neg_real = flip ^ neg_imag;
339
+ uintptr_t i;
340
+
341
+ /* Shift boolean to the sign bit so we can xor to negate. */
342
+ neg_real <<= 63;
343
+ neg_imag <<= 63;
344
+
345
+ for (i = 0; i < opr_sz / 8; i += 2) {
346
+ float64 e2 = n[i + flip];
347
+ float64 e1 = m[i + flip] ^ neg_real;
348
+ float64 e4 = e2;
349
+ float64 e3 = m[i + 1 - flip] ^ neg_imag;
350
+
351
+ d[i] = float64_muladd(e2, e1, d[i], 0, fpst);
352
+ d[i + 1] = float64_muladd(e4, e3, d[i + 1], 0, fpst);
353
+ }
354
+ clear_tail(d, opr_sz, simd_maxsz(desc));
355
+}
356
--
143
--
357
2.16.2
144
2.25.1
358
359
diff view generated by jsdifflib
1
The MPS2 AN505 FPGA image includes a "FPGA control block"
1
From: Richard Henderson <richard.henderson@linaro.org>
2
which is a small set of registers handling LEDs, buttons
3
and some counters.
4
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20220708151540.18136-27-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180220180325.29818-14-peter.maydell@linaro.org
8
---
7
---
9
hw/misc/Makefile.objs | 1 +
8
target/arm/helper-sme.h | 2 ++
10
include/hw/misc/mps2-fpgaio.h | 43 ++++++++++
9
target/arm/sme.decode | 1 +
11
hw/misc/mps2-fpgaio.c | 176 ++++++++++++++++++++++++++++++++++++++++
10
target/arm/sme_helper.c | 74 ++++++++++++++++++++++++++++++++++++++
12
default-configs/arm-softmmu.mak | 1 +
11
target/arm/translate-sme.c | 1 +
13
hw/misc/trace-events | 6 ++
12
4 files changed, 78 insertions(+)
14
5 files changed, 227 insertions(+)
15
create mode 100644 include/hw/misc/mps2-fpgaio.h
16
create mode 100644 hw/misc/mps2-fpgaio.c
17
13
18
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/Makefile.objs
16
--- a/target/arm/helper-sme.h
21
+++ b/hw/misc/Makefile.objs
17
+++ b/target/arm/helper-sme.h
22
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
19
DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
20
DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
21
26
+obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
22
+DEF_HELPER_FLAGS_7(sme_fmopa_h, TCG_CALL_NO_RWG,
27
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
23
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
28
24
DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
25
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
30
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
26
DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
31
new file mode 100644
27
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
32
index XXXXXXX..XXXXXXX
28
index XXXXXXX..XXXXXXX 100644
33
--- /dev/null
29
--- a/target/arm/sme.decode
34
+++ b/include/hw/misc/mps2-fpgaio.h
30
+++ b/target/arm/sme.decode
35
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@ FMOPA_s 10000000 100 ..... ... ... ..... . 00 .. @op_32
36
+/*
32
FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
37
+ * ARM MPS2 FPGAIO emulation
33
38
+ *
34
BFMOPA 10000001 100 ..... ... ... ..... . 00 .. @op_32
39
+ * Copyright (c) 2018 Linaro Limited
35
+FMOPA_h 10000001 101 ..... ... ... ..... . 00 .. @op_32
40
+ * Written by Peter Maydell
36
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
41
+ *
37
index XXXXXXX..XXXXXXX 100644
42
+ * This program is free software; you can redistribute it and/or modify
38
--- a/target/arm/sme_helper.c
43
+ * it under the terms of the GNU General Public License version 2 or
39
+++ b/target/arm/sme_helper.c
44
+ * (at your option) any later version.
40
@@ -XXX,XX +XXX,XX @@ static inline uint32_t f16mop_adj_pair(uint32_t pair, uint32_t pg, uint32_t neg)
45
+ */
41
return pair;
42
}
43
44
+static float32 f16_dotadd(float32 sum, uint32_t e1, uint32_t e2,
45
+ float_status *s_std, float_status *s_odd)
46
+{
47
+ float64 e1r = float16_to_float64(e1 & 0xffff, true, s_std);
48
+ float64 e1c = float16_to_float64(e1 >> 16, true, s_std);
49
+ float64 e2r = float16_to_float64(e2 & 0xffff, true, s_std);
50
+ float64 e2c = float16_to_float64(e2 >> 16, true, s_std);
51
+ float64 t64;
52
+ float32 t32;
46
+
53
+
47
+/* This is a model of the FPGAIO register block in the AN505
54
+ /*
48
+ * FPGA image for the MPS2 dev board; it is documented in the
55
+ * The ARM pseudocode function FPDot performs both multiplies
49
+ * application note:
56
+ * and the add with a single rounding operation. Emulate this
50
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
57
+ * by performing the first multiply in round-to-odd, then doing
51
+ *
58
+ * the second multiply as fused multiply-add, and rounding to
52
+ * QEMU interface:
59
+ * float32 all in one step.
53
+ * + sysbus MMIO region 0: the register bank
60
+ */
54
+ */
61
+ t64 = float64_mul(e1r, e2r, s_odd);
62
+ t64 = float64r32_muladd(e1c, e2c, t64, 0, s_std);
55
+
63
+
56
+#ifndef MPS2_FPGAIO_H
64
+ /* This conversion is exact, because we've already rounded. */
57
+#define MPS2_FPGAIO_H
65
+ t32 = float64_to_float32(t64, s_std);
58
+
66
+
59
+#include "hw/sysbus.h"
67
+ /* The final accumulation step is not fused. */
60
+
68
+ return float32_add(sum, t32, s_std);
61
+#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
62
+#define MPS2_FPGAIO(obj) OBJECT_CHECK(MPS2FPGAIO, (obj), TYPE_MPS2_FPGAIO)
63
+
64
+typedef struct {
65
+ /*< private >*/
66
+ SysBusDevice parent_obj;
67
+
68
+ /*< public >*/
69
+ MemoryRegion iomem;
70
+
71
+ uint32_t led0;
72
+ uint32_t prescale;
73
+ uint32_t misc;
74
+
75
+ uint32_t prescale_clk;
76
+} MPS2FPGAIO;
77
+
78
+#endif
79
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
80
new file mode 100644
81
index XXXXXXX..XXXXXXX
82
--- /dev/null
83
+++ b/hw/misc/mps2-fpgaio.c
84
@@ -XXX,XX +XXX,XX @@
85
+/*
86
+ * ARM MPS2 AN505 FPGAIO emulation
87
+ *
88
+ * Copyright (c) 2018 Linaro Limited
89
+ * Written by Peter Maydell
90
+ *
91
+ * This program is free software; you can redistribute it and/or modify
92
+ * it under the terms of the GNU General Public License version 2 or
93
+ * (at your option) any later version.
94
+ */
95
+
96
+/* This is a model of the "FPGA system control and I/O" block found
97
+ * in the AN505 FPGA image for the MPS2 devboard.
98
+ * It is documented in AN505:
99
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
100
+ */
101
+
102
+#include "qemu/osdep.h"
103
+#include "qemu/log.h"
104
+#include "qapi/error.h"
105
+#include "trace.h"
106
+#include "hw/sysbus.h"
107
+#include "hw/registerfields.h"
108
+#include "hw/misc/mps2-fpgaio.h"
109
+
110
+REG32(LED0, 0)
111
+REG32(BUTTON, 8)
112
+REG32(CLK1HZ, 0x10)
113
+REG32(CLK100HZ, 0x14)
114
+REG32(COUNTER, 0x18)
115
+REG32(PRESCALE, 0x1c)
116
+REG32(PSCNTR, 0x20)
117
+REG32(MISC, 0x4c)
118
+
119
+static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
120
+{
121
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
122
+ uint64_t r;
123
+
124
+ switch (offset) {
125
+ case A_LED0:
126
+ r = s->led0;
127
+ break;
128
+ case A_BUTTON:
129
+ /* User-pressable board buttons. We don't model that, so just return
130
+ * zeroes.
131
+ */
132
+ r = 0;
133
+ break;
134
+ case A_PRESCALE:
135
+ r = s->prescale;
136
+ break;
137
+ case A_MISC:
138
+ r = s->misc;
139
+ break;
140
+ case A_CLK1HZ:
141
+ case A_CLK100HZ:
142
+ case A_COUNTER:
143
+ case A_PSCNTR:
144
+ /* These are all upcounters of various frequencies. */
145
+ qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
146
+ r = 0;
147
+ break;
148
+ default:
149
+ qemu_log_mask(LOG_GUEST_ERROR,
150
+ "MPS2 FPGAIO read: bad offset %x\n", (int) offset);
151
+ r = 0;
152
+ break;
153
+ }
154
+
155
+ trace_mps2_fpgaio_read(offset, r, size);
156
+ return r;
157
+}
69
+}
158
+
70
+
159
+static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
71
+void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn,
160
+ unsigned size)
72
+ void *vpm, void *vst, uint32_t desc)
161
+{
73
+{
162
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
74
+ intptr_t row, col, oprsz = simd_maxsz(desc);
75
+ uint32_t neg = simd_data(desc) * 0x80008000u;
76
+ uint16_t *pn = vpn, *pm = vpm;
77
+ float_status fpst_odd, fpst_std;
163
+
78
+
164
+ trace_mps2_fpgaio_write(offset, value, size);
79
+ /*
80
+ * Make a copy of float_status because this operation does not
81
+ * update the cumulative fp exception status. It also produces
82
+ * default nans. Make a second copy with round-to-odd -- see above.
83
+ */
84
+ fpst_std = *(float_status *)vst;
85
+ set_default_nan_mode(true, &fpst_std);
86
+ fpst_odd = fpst_std;
87
+ set_float_rounding_mode(float_round_to_odd, &fpst_odd);
165
+
88
+
166
+ switch (offset) {
89
+ for (row = 0; row < oprsz; ) {
167
+ case A_LED0:
90
+ uint16_t prow = pn[H2(row >> 4)];
168
+ /* LED bits [1:0] control board LEDs. We don't currently have
91
+ do {
169
+ * a mechanism for displaying this graphically, so use a trace event.
92
+ void *vza_row = vza + tile_vslice_offset(row);
170
+ */
93
+ uint32_t n = *(uint32_t *)(vzn + H1_4(row));
171
+ trace_mps2_fpgaio_leds(value & 0x02 ? '*' : '.',
94
+
172
+ value & 0x01 ? '*' : '.');
95
+ n = f16mop_adj_pair(n, prow, neg);
173
+ s->led0 = value & 0x3;
96
+
174
+ break;
97
+ for (col = 0; col < oprsz; ) {
175
+ case A_PRESCALE:
98
+ uint16_t pcol = pm[H2(col >> 4)];
176
+ s->prescale = value;
99
+ do {
177
+ break;
100
+ if (prow & pcol & 0b0101) {
178
+ case A_MISC:
101
+ uint32_t *a = vza_row + H1_4(col);
179
+ /* These are control bits for some of the other devices on the
102
+ uint32_t m = *(uint32_t *)(vzm + H1_4(col));
180
+ * board (SPI, CLCD, etc). We don't implement that yet, so just
103
+
181
+ * make the bits read as written.
104
+ m = f16mop_adj_pair(m, pcol, 0);
182
+ */
105
+ *a = f16_dotadd(*a, n, m, &fpst_std, &fpst_odd);
183
+ qemu_log_mask(LOG_UNIMP,
106
+
184
+ "MPS2 FPGAIO: MISC control bits unimplemented\n");
107
+ col += 4;
185
+ s->misc = value;
108
+ pcol >>= 4;
186
+ break;
109
+ }
187
+ default:
110
+ } while (col & 15);
188
+ qemu_log_mask(LOG_GUEST_ERROR,
111
+ }
189
+ "MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
112
+ row += 4;
190
+ break;
113
+ prow >>= 4;
114
+ } while (row & 15);
191
+ }
115
+ }
192
+}
116
+}
193
+
117
+
194
+static const MemoryRegionOps mps2_fpgaio_ops = {
118
void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
195
+ .read = mps2_fpgaio_read,
119
void *vpm, uint32_t desc)
196
+ .write = mps2_fpgaio_write,
120
{
197
+ .endianness = DEVICE_LITTLE_ENDIAN,
121
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
198
+};
199
+
200
+static void mps2_fpgaio_reset(DeviceState *dev)
201
+{
202
+ MPS2FPGAIO *s = MPS2_FPGAIO(dev);
203
+
204
+ trace_mps2_fpgaio_reset();
205
+ s->led0 = 0;
206
+ s->prescale = 0;
207
+ s->misc = 0;
208
+}
209
+
210
+static void mps2_fpgaio_init(Object *obj)
211
+{
212
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
213
+ MPS2FPGAIO *s = MPS2_FPGAIO(obj);
214
+
215
+ memory_region_init_io(&s->iomem, obj, &mps2_fpgaio_ops, s,
216
+ "mps2-fpgaio", 0x1000);
217
+ sysbus_init_mmio(sbd, &s->iomem);
218
+}
219
+
220
+static const VMStateDescription mps2_fpgaio_vmstate = {
221
+ .name = "mps2-fpgaio",
222
+ .version_id = 1,
223
+ .minimum_version_id = 1,
224
+ .fields = (VMStateField[]) {
225
+ VMSTATE_UINT32(led0, MPS2FPGAIO),
226
+ VMSTATE_UINT32(prescale, MPS2FPGAIO),
227
+ VMSTATE_UINT32(misc, MPS2FPGAIO),
228
+ VMSTATE_END_OF_LIST()
229
+ }
230
+};
231
+
232
+static Property mps2_fpgaio_properties[] = {
233
+ /* Frequency of the prescale counter */
234
+ DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
235
+ DEFINE_PROP_END_OF_LIST(),
236
+};
237
+
238
+static void mps2_fpgaio_class_init(ObjectClass *klass, void *data)
239
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
241
+
242
+ dc->vmsd = &mps2_fpgaio_vmstate;
243
+ dc->reset = mps2_fpgaio_reset;
244
+ dc->props = mps2_fpgaio_properties;
245
+}
246
+
247
+static const TypeInfo mps2_fpgaio_info = {
248
+ .name = TYPE_MPS2_FPGAIO,
249
+ .parent = TYPE_SYS_BUS_DEVICE,
250
+ .instance_size = sizeof(MPS2FPGAIO),
251
+ .instance_init = mps2_fpgaio_init,
252
+ .class_init = mps2_fpgaio_class_init,
253
+};
254
+
255
+static void mps2_fpgaio_register_types(void)
256
+{
257
+ type_register_static(&mps2_fpgaio_info);
258
+}
259
+
260
+type_init(mps2_fpgaio_register_types);
261
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
262
index XXXXXXX..XXXXXXX 100644
122
index XXXXXXX..XXXXXXX 100644
263
--- a/default-configs/arm-softmmu.mak
123
--- a/target/arm/translate-sme.c
264
+++ b/default-configs/arm-softmmu.mak
124
+++ b/target/arm/translate-sme.c
265
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
125
@@ -XXX,XX +XXX,XX @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
266
CONFIG_CMSDK_APB_TIMER=y
126
return true;
267
CONFIG_CMSDK_APB_UART=y
127
}
268
128
269
+CONFIG_MPS2_FPGAIO=y
129
+TRANS_FEAT(FMOPA_h, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_h)
270
CONFIG_MPS2_SCC=y
130
TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
271
131
TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
272
CONFIG_VERSATILE_PCI=y
132
273
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
274
index XXXXXXX..XXXXXXX 100644
275
--- a/hw/misc/trace-events
276
+++ b/hw/misc/trace-events
277
@@ -XXX,XX +XXX,XX @@ mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2,
278
mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32
279
mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32
280
281
+# hw/misc/mps2_fpgaio.c
282
+mps2_fpgaio_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
283
+mps2_fpgaio_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
284
+mps2_fpgaio_reset(void) "MPS2 FPGAIO: reset"
285
+mps2_fpgaio_leds(char led1, char led0) "MPS2 FPGAIO LEDs: %c%c"
286
+
287
# hw/misc/msf2-sysreg.c
288
msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" HWADDR_PRIx " data 0x%" PRIx32 " prev 0x%" PRIx32
289
msf2_sysreg_read(uint64_t offset, uint32_t val) "msf2-sysreg read: addr 0x%08" HWADDR_PRIx " data 0x%08" PRIx32
290
--
133
--
291
2.16.2
134
2.25.1
292
293
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Initial commit of the ZynqMP RTC device.
3
This is SMOPA, SUMOPA, USMOPA_s, UMOPA, for both Int8 and Int16.
4
4
5
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220708151540.18136-28-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
---
9
hw/timer/Makefile.objs | 1 +
10
target/arm/helper-sme.h | 16 ++++++++
10
include/hw/timer/xlnx-zynqmp-rtc.h | 84 +++++++++++++++
11
target/arm/sme.decode | 10 +++++
11
hw/timer/xlnx-zynqmp-rtc.c | 214 +++++++++++++++++++++++++++++++++++++
12
target/arm/sme_helper.c | 82 ++++++++++++++++++++++++++++++++++++++
12
3 files changed, 299 insertions(+)
13
target/arm/translate-sme.c | 10 +++++
13
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
14
4 files changed, 118 insertions(+)
14
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
15
15
16
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
16
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/Makefile.objs
18
--- a/target/arm/helper-sme.h
19
+++ b/hw/timer/Makefile.objs
19
+++ b/target/arm/helper-sme.h
20
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IMX) += imx_epit.o
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
21
common-obj-$(CONFIG_IMX) += imx_gpt.o
21
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
22
common-obj-$(CONFIG_LM32) += lm32_timer.o
22
DEF_HELPER_FLAGS_6(sme_bfmopa, TCG_CALL_NO_RWG,
23
common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
23
void, ptr, ptr, ptr, ptr, ptr, i32)
24
+common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
24
+DEF_HELPER_FLAGS_6(sme_smopa_s, TCG_CALL_NO_RWG,
25
25
+ void, ptr, ptr, ptr, ptr, ptr, i32)
26
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
26
+DEF_HELPER_FLAGS_6(sme_umopa_s, TCG_CALL_NO_RWG,
27
obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
27
+ void, ptr, ptr, ptr, ptr, ptr, i32)
28
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
28
+DEF_HELPER_FLAGS_6(sme_sumopa_s, TCG_CALL_NO_RWG,
29
new file mode 100644
29
+ void, ptr, ptr, ptr, ptr, ptr, i32)
30
index XXXXXXX..XXXXXXX
30
+DEF_HELPER_FLAGS_6(sme_usmopa_s, TCG_CALL_NO_RWG,
31
--- /dev/null
31
+ void, ptr, ptr, ptr, ptr, ptr, i32)
32
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
32
+DEF_HELPER_FLAGS_6(sme_smopa_d, TCG_CALL_NO_RWG,
33
@@ -XXX,XX +XXX,XX @@
33
+ void, ptr, ptr, ptr, ptr, ptr, i32)
34
+/*
34
+DEF_HELPER_FLAGS_6(sme_umopa_d, TCG_CALL_NO_RWG,
35
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
35
+ void, ptr, ptr, ptr, ptr, ptr, i32)
36
+ *
36
+DEF_HELPER_FLAGS_6(sme_sumopa_d, TCG_CALL_NO_RWG,
37
+ * Copyright (c) 2017 Xilinx Inc.
37
+ void, ptr, ptr, ptr, ptr, ptr, i32)
38
+ *
38
+DEF_HELPER_FLAGS_6(sme_usmopa_d, TCG_CALL_NO_RWG,
39
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
39
+ void, ptr, ptr, ptr, ptr, ptr, i32)
40
+ *
40
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
41
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
41
index XXXXXXX..XXXXXXX 100644
42
+ * of this software and associated documentation files (the "Software"), to deal
42
--- a/target/arm/sme.decode
43
+ * in the Software without restriction, including without limitation the rights
43
+++ b/target/arm/sme.decode
44
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
44
@@ -XXX,XX +XXX,XX @@ FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
45
+ * copies of the Software, and to permit persons to whom the Software is
45
46
+ * furnished to do so, subject to the following conditions:
46
BFMOPA 10000001 100 ..... ... ... ..... . 00 .. @op_32
47
+ *
47
FMOPA_h 10000001 101 ..... ... ... ..... . 00 .. @op_32
48
+ * The above copyright notice and this permission notice shall be included in
49
+ * all copies or substantial portions of the Software.
50
+ *
51
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
54
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
+ * THE SOFTWARE.
58
+ */
59
+
48
+
60
+#include "hw/register.h"
49
+SMOPA_s 1010000 0 10 0 ..... ... ... ..... . 00 .. @op_32
50
+SUMOPA_s 1010000 0 10 1 ..... ... ... ..... . 00 .. @op_32
51
+USMOPA_s 1010000 1 10 0 ..... ... ... ..... . 00 .. @op_32
52
+UMOPA_s 1010000 1 10 1 ..... ... ... ..... . 00 .. @op_32
61
+
53
+
62
+#define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
54
+SMOPA_d 1010000 0 11 0 ..... ... ... ..... . 0 ... @op_64
55
+SUMOPA_d 1010000 0 11 1 ..... ... ... ..... . 0 ... @op_64
56
+USMOPA_d 1010000 1 11 0 ..... ... ... ..... . 0 ... @op_64
57
+UMOPA_d 1010000 1 11 1 ..... ... ... ..... . 0 ... @op_64
58
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/sme_helper.c
61
+++ b/target/arm/sme_helper.c
62
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
63
} while (row & 15);
64
}
65
}
63
+
66
+
64
+#define XLNX_ZYNQMP_RTC(obj) \
67
+typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
65
+ OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC)
66
+
68
+
67
+REG32(SET_TIME_WRITE, 0x0)
69
+static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
68
+REG32(SET_TIME_READ, 0x4)
70
+ uint8_t *pn, uint8_t *pm,
69
+REG32(CALIB_WRITE, 0x8)
71
+ uint32_t desc, IMOPFn *fn)
70
+ FIELD(CALIB_WRITE, FRACTION_EN, 20, 1)
72
+{
71
+ FIELD(CALIB_WRITE, FRACTION_DATA, 16, 4)
73
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
72
+ FIELD(CALIB_WRITE, MAX_TICK, 0, 16)
74
+ bool neg = simd_data(desc);
73
+REG32(CALIB_READ, 0xc)
74
+ FIELD(CALIB_READ, FRACTION_EN, 20, 1)
75
+ FIELD(CALIB_READ, FRACTION_DATA, 16, 4)
76
+ FIELD(CALIB_READ, MAX_TICK, 0, 16)
77
+REG32(CURRENT_TIME, 0x10)
78
+REG32(CURRENT_TICK, 0x14)
79
+ FIELD(CURRENT_TICK, VALUE, 0, 16)
80
+REG32(ALARM, 0x18)
81
+REG32(RTC_INT_STATUS, 0x20)
82
+ FIELD(RTC_INT_STATUS, ALARM, 1, 1)
83
+ FIELD(RTC_INT_STATUS, SECONDS, 0, 1)
84
+REG32(RTC_INT_MASK, 0x24)
85
+ FIELD(RTC_INT_MASK, ALARM, 1, 1)
86
+ FIELD(RTC_INT_MASK, SECONDS, 0, 1)
87
+REG32(RTC_INT_EN, 0x28)
88
+ FIELD(RTC_INT_EN, ALARM, 1, 1)
89
+ FIELD(RTC_INT_EN, SECONDS, 0, 1)
90
+REG32(RTC_INT_DIS, 0x2c)
91
+ FIELD(RTC_INT_DIS, ALARM, 1, 1)
92
+ FIELD(RTC_INT_DIS, SECONDS, 0, 1)
93
+REG32(ADDR_ERROR, 0x30)
94
+ FIELD(ADDR_ERROR, STATUS, 0, 1)
95
+REG32(ADDR_ERROR_INT_MASK, 0x34)
96
+ FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
97
+REG32(ADDR_ERROR_INT_EN, 0x38)
98
+ FIELD(ADDR_ERROR_INT_EN, MASK, 0, 1)
99
+REG32(ADDR_ERROR_INT_DIS, 0x3c)
100
+ FIELD(ADDR_ERROR_INT_DIS, MASK, 0, 1)
101
+REG32(CONTROL, 0x40)
102
+ FIELD(CONTROL, BATTERY_DISABLE, 31, 1)
103
+ FIELD(CONTROL, OSC_CNTRL, 24, 4)
104
+ FIELD(CONTROL, SLVERR_ENABLE, 0, 1)
105
+REG32(SAFETY_CHK, 0x50)
106
+
75
+
107
+#define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
76
+ for (row = 0; row < oprsz; ++row) {
77
+ uint8_t pa = pn[H1(row)];
78
+ uint64_t *za_row = &za[tile_vslice_index(row)];
79
+ uint64_t n = zn[row];
108
+
80
+
109
+typedef struct XlnxZynqMPRTC {
81
+ for (col = 0; col < oprsz; ++col) {
110
+ SysBusDevice parent_obj;
82
+ uint8_t pb = pm[H1(col)];
111
+ MemoryRegion iomem;
83
+ uint64_t *a = &za_row[col];
112
+ qemu_irq irq_rtc_int;
113
+ qemu_irq irq_addr_error_int;
114
+
84
+
115
+ uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
85
+ *a = fn(n, zm[col], *a, pa & pb, neg);
116
+ RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
86
+ }
117
+} XlnxZynqMPRTC;
87
+ }
118
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
119
new file mode 100644
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/hw/timer/xlnx-zynqmp-rtc.c
123
@@ -XXX,XX +XXX,XX @@
124
+/*
125
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
126
+ *
127
+ * Copyright (c) 2017 Xilinx Inc.
128
+ *
129
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
130
+ *
131
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
132
+ * of this software and associated documentation files (the "Software"), to deal
133
+ * in the Software without restriction, including without limitation the rights
134
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
135
+ * copies of the Software, and to permit persons to whom the Software is
136
+ * furnished to do so, subject to the following conditions:
137
+ *
138
+ * The above copyright notice and this permission notice shall be included in
139
+ * all copies or substantial portions of the Software.
140
+ *
141
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
142
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
143
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
144
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
145
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
146
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
147
+ * THE SOFTWARE.
148
+ */
149
+
150
+#include "qemu/osdep.h"
151
+#include "hw/sysbus.h"
152
+#include "hw/register.h"
153
+#include "qemu/bitops.h"
154
+#include "qemu/log.h"
155
+#include "hw/timer/xlnx-zynqmp-rtc.h"
156
+
157
+#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
158
+#define XLNX_ZYNQMP_RTC_ERR_DEBUG 0
159
+#endif
160
+
161
+static void rtc_int_update_irq(XlnxZynqMPRTC *s)
162
+{
163
+ bool pending = s->regs[R_RTC_INT_STATUS] & ~s->regs[R_RTC_INT_MASK];
164
+ qemu_set_irq(s->irq_rtc_int, pending);
165
+}
88
+}
166
+
89
+
167
+static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
90
+#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
168
+{
91
+static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
169
+ bool pending = s->regs[R_ADDR_ERROR] & ~s->regs[R_ADDR_ERROR_INT_MASK];
92
+{ \
170
+ qemu_set_irq(s->irq_addr_error_int, pending);
93
+ uint32_t sum0 = 0, sum1 = 0; \
94
+ /* Apply P to N as a mask, making the inactive elements 0. */ \
95
+ n &= expand_pred_b(p); \
96
+ sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
97
+ sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
98
+ sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
99
+ sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
100
+ sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
101
+ sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
102
+ sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
103
+ sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
104
+ if (neg) { \
105
+ sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
106
+ } else { \
107
+ sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
108
+ } \
109
+ return ((uint64_t)sum1 << 32) | sum0; \
171
+}
110
+}
172
+
111
+
173
+static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
112
+#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
174
+{
113
+static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
175
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
114
+{ \
176
+ rtc_int_update_irq(s);
115
+ uint64_t sum = 0; \
116
+ /* Apply P to N as a mask, making the inactive elements 0. */ \
117
+ n &= expand_pred_h(p); \
118
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
119
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
120
+ sum += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
121
+ sum += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
122
+ return neg ? a - sum : a + sum; \
177
+}
123
+}
178
+
124
+
179
+static uint64_t rtc_int_en_prew(RegisterInfo *reg, uint64_t val64)
125
+DEF_IMOP_32(smopa_s, int8_t, int8_t)
180
+{
126
+DEF_IMOP_32(umopa_s, uint8_t, uint8_t)
181
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
127
+DEF_IMOP_32(sumopa_s, int8_t, uint8_t)
128
+DEF_IMOP_32(usmopa_s, uint8_t, int8_t)
182
+
129
+
183
+ s->regs[R_RTC_INT_MASK] &= (uint32_t) ~val64;
130
+DEF_IMOP_64(smopa_d, int16_t, int16_t)
184
+ rtc_int_update_irq(s);
131
+DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
185
+ return 0;
132
+DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
186
+}
133
+DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
187
+
134
+
188
+static uint64_t rtc_int_dis_prew(RegisterInfo *reg, uint64_t val64)
135
+#define DEF_IMOPH(NAME) \
189
+{
136
+ void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
190
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
137
+ void *vpm, uint32_t desc) \
138
+ { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
191
+
139
+
192
+ s->regs[R_RTC_INT_MASK] |= (uint32_t) val64;
140
+DEF_IMOPH(smopa_s)
193
+ rtc_int_update_irq(s);
141
+DEF_IMOPH(umopa_s)
194
+ return 0;
142
+DEF_IMOPH(sumopa_s)
195
+}
143
+DEF_IMOPH(usmopa_s)
144
+DEF_IMOPH(smopa_d)
145
+DEF_IMOPH(umopa_d)
146
+DEF_IMOPH(sumopa_d)
147
+DEF_IMOPH(usmopa_d)
148
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/target/arm/translate-sme.c
151
+++ b/target/arm/translate-sme.c
152
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_f
153
154
/* TODO: FEAT_EBF16 */
155
TRANS_FEAT(BFMOPA, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_bfmopa)
196
+
156
+
197
+static void addr_error_postw(RegisterInfo *reg, uint64_t val64)
157
+TRANS_FEAT(SMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_smopa_s)
198
+{
158
+TRANS_FEAT(UMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_umopa_s)
199
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
159
+TRANS_FEAT(SUMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_sumopa_s)
200
+ addr_error_int_update_irq(s);
160
+TRANS_FEAT(USMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_usmopa_s)
201
+}
202
+
161
+
203
+static uint64_t addr_error_int_en_prew(RegisterInfo *reg, uint64_t val64)
162
+TRANS_FEAT(SMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_smopa_d)
204
+{
163
+TRANS_FEAT(UMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_umopa_d)
205
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
164
+TRANS_FEAT(SUMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_sumopa_d)
206
+
165
+TRANS_FEAT(USMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_usmopa_d)
207
+ s->regs[R_ADDR_ERROR_INT_MASK] &= (uint32_t) ~val64;
208
+ addr_error_int_update_irq(s);
209
+ return 0;
210
+}
211
+
212
+static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
213
+{
214
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
215
+
216
+ s->regs[R_ADDR_ERROR_INT_MASK] |= (uint32_t) val64;
217
+ addr_error_int_update_irq(s);
218
+ return 0;
219
+}
220
+
221
+static const RegisterAccessInfo rtc_regs_info[] = {
222
+ { .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
223
+ },{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
224
+ .ro = 0xffffffff,
225
+ },{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
226
+ },{ .name = "CALIB_READ", .addr = A_CALIB_READ,
227
+ .ro = 0x1fffff,
228
+ },{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
229
+ .ro = 0xffffffff,
230
+ },{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
231
+ .ro = 0xffff,
232
+ },{ .name = "ALARM", .addr = A_ALARM,
233
+ },{ .name = "RTC_INT_STATUS", .addr = A_RTC_INT_STATUS,
234
+ .w1c = 0x3,
235
+ .post_write = rtc_int_status_postw,
236
+ },{ .name = "RTC_INT_MASK", .addr = A_RTC_INT_MASK,
237
+ .reset = 0x3,
238
+ .ro = 0x3,
239
+ },{ .name = "RTC_INT_EN", .addr = A_RTC_INT_EN,
240
+ .pre_write = rtc_int_en_prew,
241
+ },{ .name = "RTC_INT_DIS", .addr = A_RTC_INT_DIS,
242
+ .pre_write = rtc_int_dis_prew,
243
+ },{ .name = "ADDR_ERROR", .addr = A_ADDR_ERROR,
244
+ .w1c = 0x1,
245
+ .post_write = addr_error_postw,
246
+ },{ .name = "ADDR_ERROR_INT_MASK", .addr = A_ADDR_ERROR_INT_MASK,
247
+ .reset = 0x1,
248
+ .ro = 0x1,
249
+ },{ .name = "ADDR_ERROR_INT_EN", .addr = A_ADDR_ERROR_INT_EN,
250
+ .pre_write = addr_error_int_en_prew,
251
+ },{ .name = "ADDR_ERROR_INT_DIS", .addr = A_ADDR_ERROR_INT_DIS,
252
+ .pre_write = addr_error_int_dis_prew,
253
+ },{ .name = "CONTROL", .addr = A_CONTROL,
254
+ .reset = 0x1000000,
255
+ .rsvd = 0x70fffffe,
256
+ },{ .name = "SAFETY_CHK", .addr = A_SAFETY_CHK,
257
+ }
258
+};
259
+
260
+static void rtc_reset(DeviceState *dev)
261
+{
262
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(dev);
263
+ unsigned int i;
264
+
265
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
266
+ register_reset(&s->regs_info[i]);
267
+ }
268
+
269
+ rtc_int_update_irq(s);
270
+ addr_error_int_update_irq(s);
271
+}
272
+
273
+static const MemoryRegionOps rtc_ops = {
274
+ .read = register_read_memory,
275
+ .write = register_write_memory,
276
+ .endianness = DEVICE_LITTLE_ENDIAN,
277
+ .valid = {
278
+ .min_access_size = 4,
279
+ .max_access_size = 4,
280
+ },
281
+};
282
+
283
+static void rtc_init(Object *obj)
284
+{
285
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
286
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
287
+ RegisterInfoArray *reg_array;
288
+
289
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
290
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
291
+ reg_array =
292
+ register_init_block32(DEVICE(obj), rtc_regs_info,
293
+ ARRAY_SIZE(rtc_regs_info),
294
+ s->regs_info, s->regs,
295
+ &rtc_ops,
296
+ XLNX_ZYNQMP_RTC_ERR_DEBUG,
297
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
298
+ memory_region_add_subregion(&s->iomem,
299
+ 0x0,
300
+ &reg_array->mem);
301
+ sysbus_init_mmio(sbd, &s->iomem);
302
+ sysbus_init_irq(sbd, &s->irq_rtc_int);
303
+ sysbus_init_irq(sbd, &s->irq_addr_error_int);
304
+}
305
+
306
+static const VMStateDescription vmstate_rtc = {
307
+ .name = TYPE_XLNX_ZYNQMP_RTC,
308
+ .version_id = 1,
309
+ .minimum_version_id = 1,
310
+ .fields = (VMStateField[]) {
311
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
312
+ VMSTATE_END_OF_LIST(),
313
+ }
314
+};
315
+
316
+static void rtc_class_init(ObjectClass *klass, void *data)
317
+{
318
+ DeviceClass *dc = DEVICE_CLASS(klass);
319
+
320
+ dc->reset = rtc_reset;
321
+ dc->vmsd = &vmstate_rtc;
322
+}
323
+
324
+static const TypeInfo rtc_info = {
325
+ .name = TYPE_XLNX_ZYNQMP_RTC,
326
+ .parent = TYPE_SYS_BUS_DEVICE,
327
+ .instance_size = sizeof(XlnxZynqMPRTC),
328
+ .class_init = rtc_class_init,
329
+ .instance_init = rtc_init,
330
+};
331
+
332
+static void rtc_register_types(void)
333
+{
334
+ type_register_static(&rtc_info);
335
+}
336
+
337
+type_init(rtc_register_types)
338
--
166
--
339
2.16.2
167
2.25.1
340
341
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This is an SVE instruction that operates using the SVE vector
4
length but that it is present only if SME is implemented.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220708151540.18136-29-richard.henderson@linaro.org
5
Message-id: 20180228193125.20577-14-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
---
10
---
8
target/arm/translate.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 20 +++++++++++++
9
1 file changed, 68 insertions(+)
12
target/arm/translate-sve.c | 57 ++++++++++++++++++++++++++++++++++++++
13
2 files changed, 77 insertions(+)
10
14
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
17
--- a/target/arm/sve.decode
14
+++ b/target/arm/translate.c
18
+++ b/target/arm/sve.decode
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ BFMLALT_zzxw 01100100 11 1 ..... 0100.1 ..... ..... @rrxr_3a esz=2
16
return 0;
20
17
}
21
### SVE2 floating-point bfloat16 dot-product (indexed)
18
22
BFDOT_zzxz 01100100 01 1 ..... 010000 ..... ..... @rrxr_2 esz=2
19
+/* Advanced SIMD three registers of the same length extension.
23
+
20
+ * 31 25 23 22 20 16 12 11 10 9 8 3 0
24
+### SVE broadcast predicate element
21
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
25
+
22
+ * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
26
+&psel esz pd pn pm rv imm
23
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
27
+%psel_rv 16:2 !function=plus_12
24
+ */
28
+%psel_imm_b 22:2 19:2
25
+static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
29
+%psel_imm_h 22:2 20:1
30
+%psel_imm_s 22:2
31
+%psel_imm_d 23:1
32
+@psel ........ .. . ... .. .. pn:4 . pm:4 . pd:4 \
33
+ &psel rv=%psel_rv
34
+
35
+PSEL 00100101 .. 1 ..1 .. 01 .... 0 .... 0 .... \
36
+ @psel esz=0 imm=%psel_imm_b
37
+PSEL 00100101 .. 1 .10 .. 01 .... 0 .... 0 .... \
38
+ @psel esz=1 imm=%psel_imm_h
39
+PSEL 00100101 .. 1 100 .. 01 .... 0 .... 0 .... \
40
+ @psel esz=2 imm=%psel_imm_s
41
+PSEL 00100101 .1 1 000 .. 01 .... 0 .... 0 .... \
42
+ @psel esz=3 imm=%psel_imm_d
43
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/translate-sve.c
46
+++ b/target/arm/translate-sve.c
47
@@ -XXX,XX +XXX,XX @@ static bool do_BFMLAL_zzxw(DisasContext *s, arg_rrxr_esz *a, bool sel)
48
49
TRANS_FEAT(BFMLALB_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, false)
50
TRANS_FEAT(BFMLALT_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, true)
51
+
52
+static bool trans_PSEL(DisasContext *s, arg_psel *a)
26
+{
53
+{
27
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
54
+ int vl = vec_full_reg_size(s);
28
+ int rd, rn, rm, rot, size, opr_sz;
55
+ int pl = pred_gvec_reg_size(s);
29
+ TCGv_ptr fpst;
56
+ int elements = vl >> a->esz;
30
+ bool q;
57
+ TCGv_i64 tmp, didx, dbit;
58
+ TCGv_ptr ptr;
31
+
59
+
32
+ q = extract32(insn, 6, 1);
60
+ if (!dc_isar_feature(aa64_sme, s)) {
33
+ VFP_DREG_D(rd, insn);
61
+ return false;
34
+ VFP_DREG_N(rn, insn);
62
+ }
35
+ VFP_DREG_M(rm, insn);
63
+ if (!sve_access_check(s)) {
36
+ if ((rd | rn | rm) & q) {
64
+ return true;
37
+ return 1;
38
+ }
65
+ }
39
+
66
+
40
+ if ((insn & 0xfe200f10) == 0xfc200800) {
67
+ tmp = tcg_temp_new_i64();
41
+ /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
68
+ dbit = tcg_temp_new_i64();
42
+ size = extract32(insn, 20, 1);
69
+ didx = tcg_temp_new_i64();
43
+ rot = extract32(insn, 23, 2);
70
+ ptr = tcg_temp_new_ptr();
44
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
71
+
45
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
72
+ /* Compute the predicate element. */
46
+ return 1;
73
+ tcg_gen_addi_i64(tmp, cpu_reg(s, a->rv), a->imm);
47
+ }
74
+ if (is_power_of_2(elements)) {
48
+ fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
75
+ tcg_gen_andi_i64(tmp, tmp, elements - 1);
49
+ } else if ((insn & 0xfea00f10) == 0xfc800800) {
50
+ /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
51
+ size = extract32(insn, 20, 1);
52
+ rot = extract32(insn, 24, 1);
53
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
54
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
55
+ return 1;
56
+ }
57
+ fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
58
+ } else {
76
+ } else {
59
+ return 1;
77
+ tcg_gen_remu_i64(tmp, tmp, tcg_constant_i64(elements));
60
+ }
78
+ }
61
+
79
+
62
+ if (s->fp_excp_el) {
80
+ /* Extract the predicate byte and bit indices. */
63
+ gen_exception_insn(s, 4, EXCP_UDEF,
81
+ tcg_gen_shli_i64(tmp, tmp, a->esz);
64
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
82
+ tcg_gen_andi_i64(dbit, tmp, 7);
65
+ return 0;
83
+ tcg_gen_shri_i64(didx, tmp, 3);
66
+ }
84
+ if (HOST_BIG_ENDIAN) {
67
+ if (!s->vfp_enabled) {
85
+ tcg_gen_xori_i64(didx, didx, 7);
68
+ return 1;
69
+ }
86
+ }
70
+
87
+
71
+ opr_sz = (1 + q) * 8;
88
+ /* Load the predicate word. */
72
+ fpst = get_fpstatus_ptr(1);
89
+ tcg_gen_trunc_i64_ptr(ptr, didx);
73
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
90
+ tcg_gen_add_ptr(ptr, ptr, cpu_env);
74
+ vfp_reg_offset(1, rn),
91
+ tcg_gen_ld8u_i64(tmp, ptr, pred_full_reg_offset(s, a->pm));
75
+ vfp_reg_offset(1, rm), fpst,
92
+
76
+ opr_sz, opr_sz, rot, fn_gvec_ptr);
93
+ /* Extract the predicate bit and replicate to MO_64. */
77
+ tcg_temp_free_ptr(fpst);
94
+ tcg_gen_shr_i64(tmp, tmp, dbit);
78
+ return 0;
95
+ tcg_gen_andi_i64(tmp, tmp, 1);
96
+ tcg_gen_neg_i64(tmp, tmp);
97
+
98
+ /* Apply to either copy the source, or write zeros. */
99
+ tcg_gen_gvec_ands(MO_64, pred_full_reg_offset(s, a->pd),
100
+ pred_full_reg_offset(s, a->pn), tmp, pl, pl);
101
+
102
+ tcg_temp_free_i64(tmp);
103
+ tcg_temp_free_i64(dbit);
104
+ tcg_temp_free_i64(didx);
105
+ tcg_temp_free_ptr(ptr);
106
+ return true;
79
+}
107
+}
80
+
81
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
82
{
83
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
84
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
85
}
86
}
87
}
88
+ } else if ((insn & 0x0e000a00) == 0x0c000800
89
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
90
+ if (disas_neon_insn_3same_ext(s, insn)) {
91
+ goto illegal_op;
92
+ }
93
+ return;
94
} else if ((insn & 0x0fe00000) == 0x0c400000) {
95
/* Coprocessor double register transfer. */
96
ARCH(5TE);
97
--
108
--
98
2.16.2
109
2.25.1
99
100
diff view generated by jsdifflib
1
Create an "idau" property on the armv7m container object which
1
From: Richard Henderson <richard.henderson@linaro.org>
2
we can forward to the CPU object. Annoyingly, we can't use
3
object_property_add_alias() because the CPU object we want to
4
forward to doesn't exist until the armv7m container is realized.
5
2
3
This is an SVE instruction that operates using the SVE vector
4
length but that it is present only if SME is implemented.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-30-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: 20180220180325.29818-6-peter.maydell@linaro.org
9
---
10
---
10
include/hw/arm/armv7m.h | 3 +++
11
target/arm/helper-sve.h | 2 ++
11
hw/arm/armv7m.c | 9 +++++++++
12
target/arm/sve.decode | 1 +
12
2 files changed, 12 insertions(+)
13
target/arm/sve_helper.c | 16 ++++++++++++++++
14
target/arm/translate-sve.c | 2 ++
15
4 files changed, 21 insertions(+)
13
16
14
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/armv7m.h
19
--- a/target/arm/helper-sve.h
17
+++ b/include/hw/arm/armv7m.h
20
+++ b/target/arm/helper-sve.h
18
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_revh_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
22
20
#include "hw/sysbus.h"
23
DEF_HELPER_FLAGS_4(sve_revw_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
#include "hw/intc/armv7m_nvic.h"
24
22
+#include "target/arm/idau.h"
25
+DEF_HELPER_FLAGS_4(sme_revd_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
26
+
24
#define TYPE_BITBAND "ARM,bitband-memory"
27
DEF_HELPER_FLAGS_4(sve_rbit_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
28
DEF_HELPER_FLAGS_4(sve_rbit_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
@@ -XXX,XX +XXX,XX @@ typedef struct {
29
DEF_HELPER_FLAGS_4(sve_rbit_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
* + Property "memory": MemoryRegion defining the physical address space
30
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
28
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
29
* devices will be automatically layered on top of this view.)
30
+ * + Property "idau": IDAU interface (forwarded to CPU object)
31
*/
32
typedef struct ARMv7MState {
33
/*< private >*/
34
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
35
char *cpu_type;
36
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
37
MemoryRegion *board_memory;
38
+ Object *idau;
39
} ARMv7MState;
40
41
#endif
42
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
43
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/armv7m.c
32
--- a/target/arm/sve.decode
45
+++ b/hw/arm/armv7m.c
33
+++ b/target/arm/sve.decode
46
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@ REVB 00000101 .. 1001 00 100 ... ..... ..... @rd_pg_rn
47
#include "sysemu/qtest.h"
35
REVH 00000101 .. 1001 01 100 ... ..... ..... @rd_pg_rn
48
#include "qemu/error-report.h"
36
REVW 00000101 .. 1001 10 100 ... ..... ..... @rd_pg_rn
49
#include "exec/address-spaces.h"
37
RBIT 00000101 .. 1001 11 100 ... ..... ..... @rd_pg_rn
50
+#include "target/arm/idau.h"
38
+REVD 00000101 00 1011 10 100 ... ..... ..... @rd_pg_rn_e0
51
39
52
/* Bitbanded IO. Each word corresponds to a single bit. */
40
# SVE vector splice (predicated, destructive)
53
41
SPLICE 00000101 .. 101 100 100 ... ..... ..... @rdn_pg_rm
54
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
42
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
55
43
index XXXXXXX..XXXXXXX 100644
56
object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
44
--- a/target/arm/sve_helper.c
57
&error_abort);
45
+++ b/target/arm/sve_helper.c
58
+ if (object_property_find(OBJECT(s->cpu), "idau", NULL)) {
46
@@ -XXX,XX +XXX,XX @@ DO_ZPZ_D(sve_revh_d, uint64_t, hswap64)
59
+ object_property_set_link(OBJECT(s->cpu), s->idau, "idau", &err);
47
60
+ if (err != NULL) {
48
DO_ZPZ_D(sve_revw_d, uint64_t, wswap64)
61
+ error_propagate(errp, err);
49
62
+ return;
50
+void HELPER(sme_revd_q)(void *vd, void *vn, void *vg, uint32_t desc)
51
+{
52
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
53
+ uint64_t *d = vd, *n = vn;
54
+ uint8_t *pg = vg;
55
+
56
+ for (i = 0; i < opr_sz; i += 2) {
57
+ if (pg[H1(i)] & 1) {
58
+ uint64_t n0 = n[i + 0];
59
+ uint64_t n1 = n[i + 1];
60
+ d[i + 0] = n1;
61
+ d[i + 1] = n0;
63
+ }
62
+ }
64
+ }
63
+ }
65
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
64
+}
66
if (err != NULL) {
65
+
67
error_propagate(errp, err);
66
DO_ZPZ(sve_rbit_b, uint8_t, H1, revbit8)
68
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
67
DO_ZPZ(sve_rbit_h, uint16_t, H1_2, revbit16)
69
DEFINE_PROP_STRING("cpu-type", ARMv7MState, cpu_type),
68
DO_ZPZ(sve_rbit_s, uint32_t, H1_4, revbit32)
70
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
69
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
71
MemoryRegion *),
70
index XXXXXXX..XXXXXXX 100644
72
+ DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
71
--- a/target/arm/translate-sve.c
73
DEFINE_PROP_END_OF_LIST(),
72
+++ b/target/arm/translate-sve.c
74
};
73
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(REVH, aa64_sve, gen_gvec_ool_arg_zpz, revh_fns[a->esz], a, 0)
74
TRANS_FEAT(REVW, aa64_sve, gen_gvec_ool_arg_zpz,
75
a->esz == 3 ? gen_helper_sve_revw_d : NULL, a, 0)
76
77
+TRANS_FEAT(REVD, aa64_sme, gen_gvec_ool_arg_zpz, gen_helper_sme_revd_q, a, 0)
78
+
79
TRANS_FEAT(SPLICE, aa64_sve, gen_gvec_ool_arg_zpzz,
80
gen_helper_sve_splice, a, a->esz)
75
81
76
--
82
--
77
2.16.2
83
2.25.1
78
79
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
This is an SVE instruction that operates using the SVE vector
4
length but that it is present only if SME is implemented.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-12-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-31-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
---
10
---
8
target/arm/helper.h | 7 ++++
11
target/arm/helper.h | 18 +++++++
9
target/arm/translate-a64.c | 48 ++++++++++++++++++++++-
12
target/arm/sve.decode | 5 ++
10
target/arm/vec_helper.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
13
target/arm/translate-sve.c | 102 +++++++++++++++++++++++++++++++++++++
11
3 files changed, 151 insertions(+), 1 deletion(-)
14
target/arm/vec_helper.c | 24 +++++++++
15
4 files changed, 149 insertions(+)
12
16
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
19
--- a/target/arm/helper.h
16
+++ b/target/arm/helper.h
20
+++ b/target/arm/helper.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(gvec_bfmlal, TCG_CALL_NO_RWG,
18
DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
22
DEF_HELPER_FLAGS_6(gvec_bfmlal_idx, TCG_CALL_NO_RWG,
19
void, ptr, ptr, ptr, ptr, i32)
23
void, ptr, ptr, ptr, ptr, ptr, i32)
20
24
21
+DEF_HELPER_FLAGS_5(gvec_fcaddh, TCG_CALL_NO_RWG,
25
+DEF_HELPER_FLAGS_5(gvec_sclamp_b, TCG_CALL_NO_RWG,
22
+ void, ptr, ptr, ptr, ptr, i32)
26
+ void, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
27
+DEF_HELPER_FLAGS_5(gvec_sclamp_h, TCG_CALL_NO_RWG,
24
+ void, ptr, ptr, ptr, ptr, i32)
28
+ void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
29
+DEF_HELPER_FLAGS_5(gvec_sclamp_s, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_5(gvec_sclamp_d, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+
34
+DEF_HELPER_FLAGS_5(gvec_uclamp_b, TCG_CALL_NO_RWG,
35
+ void, ptr, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_5(gvec_uclamp_h, TCG_CALL_NO_RWG,
37
+ void, ptr, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_5(gvec_uclamp_s, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_5(gvec_uclamp_d, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, i32)
41
+ void, ptr, ptr, ptr, ptr, i32)
27
+
42
+
28
#ifdef TARGET_AARCH64
43
#ifdef TARGET_AARCH64
29
#include "helper-a64.h"
44
#include "helper-a64.h"
30
#endif
45
#include "helper-sve.h"
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
46
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
32
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-a64.c
48
--- a/target/arm/sve.decode
34
+++ b/target/arm/translate-a64.c
49
+++ b/target/arm/sve.decode
35
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
50
@@ -XXX,XX +XXX,XX @@ PSEL 00100101 .. 1 100 .. 01 .... 0 .... 0 .... \
36
is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
51
@psel esz=2 imm=%psel_imm_s
52
PSEL 00100101 .1 1 000 .. 01 .... 0 .... 0 .... \
53
@psel esz=3 imm=%psel_imm_d
54
+
55
+### SVE clamp
56
+
57
+SCLAMP 01000100 .. 0 ..... 110000 ..... ..... @rda_rn_rm
58
+UCLAMP 01000100 .. 0 ..... 110001 ..... ..... @rda_rn_rm
59
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/translate-sve.c
62
+++ b/target/arm/translate-sve.c
63
@@ -XXX,XX +XXX,XX @@ static bool trans_PSEL(DisasContext *s, arg_psel *a)
64
tcg_temp_free_ptr(ptr);
65
return true;
37
}
66
}
38
67
+
39
+/* Expand a 3-operand + fpstatus pointer + simd data value operation using
68
+static void gen_sclamp_i32(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_i32 a)
40
+ * an out-of-line helper.
69
+{
41
+ */
70
+ tcg_gen_smax_i32(d, a, n);
42
+static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
71
+ tcg_gen_smin_i32(d, d, m);
43
+ int rm, bool is_fp16, int data,
72
+}
44
+ gen_helper_gvec_3_ptr *fn)
73
+
45
+{
74
+static void gen_sclamp_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 a)
46
+ TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
75
+{
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
76
+ tcg_gen_smax_i64(d, a, n);
48
+ vec_full_reg_offset(s, rn),
77
+ tcg_gen_smin_i64(d, d, m);
49
+ vec_full_reg_offset(s, rm), fpst,
78
+}
50
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
79
+
51
+ tcg_temp_free_ptr(fpst);
80
+static void gen_sclamp_vec(unsigned vece, TCGv_vec d, TCGv_vec n,
52
+}
81
+ TCGv_vec m, TCGv_vec a)
53
+
82
+{
54
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
83
+ tcg_gen_smax_vec(vece, d, a, n);
55
* than the 32 bit equivalent.
84
+ tcg_gen_smin_vec(vece, d, d, m);
56
*/
85
+}
57
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
86
+
58
int size = extract32(insn, 22, 2);
87
+static void gen_sclamp(unsigned vece, uint32_t d, uint32_t n, uint32_t m,
59
bool u = extract32(insn, 29, 1);
88
+ uint32_t a, uint32_t oprsz, uint32_t maxsz)
60
bool is_q = extract32(insn, 30, 1);
89
+{
61
- int feature;
90
+ static const TCGOpcode vecop[] = {
62
+ int feature, rot;
91
+ INDEX_op_smin_vec, INDEX_op_smax_vec, 0
63
92
+ };
64
switch (u * 16 + opcode) {
93
+ static const GVecGen4 ops[4] = {
65
case 0x10: /* SQRDMLAH (vector) */
94
+ { .fniv = gen_sclamp_vec,
66
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
95
+ .fno = gen_helper_gvec_sclamp_b,
67
}
96
+ .opt_opc = vecop,
68
feature = ARM_FEATURE_V8_RDM;
97
+ .vece = MO_8 },
69
break;
98
+ { .fniv = gen_sclamp_vec,
70
+ case 0xc: /* FCADD, #90 */
99
+ .fno = gen_helper_gvec_sclamp_h,
71
+ case 0xe: /* FCADD, #270 */
100
+ .opt_opc = vecop,
72
+ if (size == 0
101
+ .vece = MO_16 },
73
+ || (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))
102
+ { .fni4 = gen_sclamp_i32,
74
+ || (size == 3 && !is_q)) {
103
+ .fniv = gen_sclamp_vec,
75
+ unallocated_encoding(s);
104
+ .fno = gen_helper_gvec_sclamp_s,
76
+ return;
105
+ .opt_opc = vecop,
77
+ }
106
+ .vece = MO_32 },
78
+ feature = ARM_FEATURE_V8_FCMA;
107
+ { .fni8 = gen_sclamp_i64,
79
+ break;
108
+ .fniv = gen_sclamp_vec,
80
default:
109
+ .fno = gen_helper_gvec_sclamp_d,
81
unallocated_encoding(s);
110
+ .opt_opc = vecop,
82
return;
111
+ .vece = MO_64,
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
112
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64 }
84
}
113
+ };
85
return;
114
+ tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, &ops[vece]);
86
115
+}
87
+ case 0xc: /* FCADD, #90 */
116
+
88
+ case 0xe: /* FCADD, #270 */
117
+TRANS_FEAT(SCLAMP, aa64_sme, gen_gvec_fn_arg_zzzz, gen_sclamp, a)
89
+ rot = extract32(opcode, 1, 1);
118
+
90
+ switch (size) {
119
+static void gen_uclamp_i32(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_i32 a)
91
+ case 1:
120
+{
92
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
121
+ tcg_gen_umax_i32(d, a, n);
93
+ gen_helper_gvec_fcaddh);
122
+ tcg_gen_umin_i32(d, d, m);
94
+ break;
123
+}
95
+ case 2:
124
+
96
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
125
+static void gen_uclamp_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 a)
97
+ gen_helper_gvec_fcadds);
126
+{
98
+ break;
127
+ tcg_gen_umax_i64(d, a, n);
99
+ case 3:
128
+ tcg_gen_umin_i64(d, d, m);
100
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
129
+}
101
+ gen_helper_gvec_fcaddd);
130
+
102
+ break;
131
+static void gen_uclamp_vec(unsigned vece, TCGv_vec d, TCGv_vec n,
103
+ default:
132
+ TCGv_vec m, TCGv_vec a)
104
+ g_assert_not_reached();
133
+{
105
+ }
134
+ tcg_gen_umax_vec(vece, d, a, n);
106
+ return;
135
+ tcg_gen_umin_vec(vece, d, d, m);
107
+
136
+}
108
default:
137
+
109
g_assert_not_reached();
138
+static void gen_uclamp(unsigned vece, uint32_t d, uint32_t n, uint32_t m,
110
}
139
+ uint32_t a, uint32_t oprsz, uint32_t maxsz)
140
+{
141
+ static const TCGOpcode vecop[] = {
142
+ INDEX_op_umin_vec, INDEX_op_umax_vec, 0
143
+ };
144
+ static const GVecGen4 ops[4] = {
145
+ { .fniv = gen_uclamp_vec,
146
+ .fno = gen_helper_gvec_uclamp_b,
147
+ .opt_opc = vecop,
148
+ .vece = MO_8 },
149
+ { .fniv = gen_uclamp_vec,
150
+ .fno = gen_helper_gvec_uclamp_h,
151
+ .opt_opc = vecop,
152
+ .vece = MO_16 },
153
+ { .fni4 = gen_uclamp_i32,
154
+ .fniv = gen_uclamp_vec,
155
+ .fno = gen_helper_gvec_uclamp_s,
156
+ .opt_opc = vecop,
157
+ .vece = MO_32 },
158
+ { .fni8 = gen_uclamp_i64,
159
+ .fniv = gen_uclamp_vec,
160
+ .fno = gen_helper_gvec_uclamp_d,
161
+ .opt_opc = vecop,
162
+ .vece = MO_64,
163
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64 }
164
+ };
165
+ tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, &ops[vece]);
166
+}
167
+
168
+TRANS_FEAT(UCLAMP, aa64_sme, gen_gvec_fn_arg_zzzz, gen_uclamp, a)
111
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
169
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
112
index XXXXXXX..XXXXXXX 100644
170
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/vec_helper.c
171
--- a/target/arm/vec_helper.c
114
+++ b/target/arm/vec_helper.c
172
+++ b/target/arm/vec_helper.c
115
@@ -XXX,XX +XXX,XX @@
173
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_bfmlal_idx)(void *vd, void *vn, void *vm,
116
#include "exec/exec-all.h"
117
#include "exec/helper-proto.h"
118
#include "tcg/tcg-gvec-desc.h"
119
+#include "fpu/softfloat.h"
120
121
122
+/* Note that vector data is stored in host-endian 64-bit chunks,
123
+ so addressing units smaller than that needs a host-endian fixup. */
124
+#ifdef HOST_WORDS_BIGENDIAN
125
+#define H1(x) ((x) ^ 7)
126
+#define H2(x) ((x) ^ 3)
127
+#define H4(x) ((x) ^ 1)
128
+#else
129
+#define H1(x) (x)
130
+#define H2(x) (x)
131
+#define H4(x) (x)
132
+#endif
133
+
134
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
135
136
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
137
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
138
}
174
}
139
clear_tail(d, opr_sz, simd_maxsz(desc));
175
clear_tail(d, opr_sz, simd_maxsz(desc));
140
}
176
}
141
+
177
+
142
+void HELPER(gvec_fcaddh)(void *vd, void *vn, void *vm,
178
+#define DO_CLAMP(NAME, TYPE) \
143
+ void *vfpst, uint32_t desc)
179
+void HELPER(NAME)(void *d, void *n, void *m, void *a, uint32_t desc) \
144
+{
180
+{ \
145
+ uintptr_t opr_sz = simd_oprsz(desc);
181
+ intptr_t i, opr_sz = simd_oprsz(desc); \
146
+ float16 *d = vd;
182
+ for (i = 0; i < opr_sz; i += sizeof(TYPE)) { \
147
+ float16 *n = vn;
183
+ TYPE aa = *(TYPE *)(a + i); \
148
+ float16 *m = vm;
184
+ TYPE nn = *(TYPE *)(n + i); \
149
+ float_status *fpst = vfpst;
185
+ TYPE mm = *(TYPE *)(m + i); \
150
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
186
+ TYPE dd = MIN(MAX(aa, nn), mm); \
151
+ uint32_t neg_imag = neg_real ^ 1;
187
+ *(TYPE *)(d + i) = dd; \
152
+ uintptr_t i;
188
+ } \
153
+
189
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
154
+ /* Shift boolean to the sign bit so we can xor to negate. */
190
+}
155
+ neg_real <<= 15;
191
+
156
+ neg_imag <<= 15;
192
+DO_CLAMP(gvec_sclamp_b, int8_t)
157
+
193
+DO_CLAMP(gvec_sclamp_h, int16_t)
158
+ for (i = 0; i < opr_sz / 2; i += 2) {
194
+DO_CLAMP(gvec_sclamp_s, int32_t)
159
+ float16 e0 = n[H2(i)];
195
+DO_CLAMP(gvec_sclamp_d, int64_t)
160
+ float16 e1 = m[H2(i + 1)] ^ neg_imag;
196
+
161
+ float16 e2 = n[H2(i + 1)];
197
+DO_CLAMP(gvec_uclamp_b, uint8_t)
162
+ float16 e3 = m[H2(i)] ^ neg_real;
198
+DO_CLAMP(gvec_uclamp_h, uint16_t)
163
+
199
+DO_CLAMP(gvec_uclamp_s, uint32_t)
164
+ d[H2(i)] = float16_add(e0, e1, fpst);
200
+DO_CLAMP(gvec_uclamp_d, uint64_t)
165
+ d[H2(i + 1)] = float16_add(e2, e3, fpst);
166
+ }
167
+ clear_tail(d, opr_sz, simd_maxsz(desc));
168
+}
169
+
170
+void HELPER(gvec_fcadds)(void *vd, void *vn, void *vm,
171
+ void *vfpst, uint32_t desc)
172
+{
173
+ uintptr_t opr_sz = simd_oprsz(desc);
174
+ float32 *d = vd;
175
+ float32 *n = vn;
176
+ float32 *m = vm;
177
+ float_status *fpst = vfpst;
178
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
179
+ uint32_t neg_imag = neg_real ^ 1;
180
+ uintptr_t i;
181
+
182
+ /* Shift boolean to the sign bit so we can xor to negate. */
183
+ neg_real <<= 31;
184
+ neg_imag <<= 31;
185
+
186
+ for (i = 0; i < opr_sz / 4; i += 2) {
187
+ float32 e0 = n[H4(i)];
188
+ float32 e1 = m[H4(i + 1)] ^ neg_imag;
189
+ float32 e2 = n[H4(i + 1)];
190
+ float32 e3 = m[H4(i)] ^ neg_real;
191
+
192
+ d[H4(i)] = float32_add(e0, e1, fpst);
193
+ d[H4(i + 1)] = float32_add(e2, e3, fpst);
194
+ }
195
+ clear_tail(d, opr_sz, simd_maxsz(desc));
196
+}
197
+
198
+void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
199
+ void *vfpst, uint32_t desc)
200
+{
201
+ uintptr_t opr_sz = simd_oprsz(desc);
202
+ float64 *d = vd;
203
+ float64 *n = vn;
204
+ float64 *m = vm;
205
+ float_status *fpst = vfpst;
206
+ uint64_t neg_real = extract64(desc, SIMD_DATA_SHIFT, 1);
207
+ uint64_t neg_imag = neg_real ^ 1;
208
+ uintptr_t i;
209
+
210
+ /* Shift boolean to the sign bit so we can xor to negate. */
211
+ neg_real <<= 63;
212
+ neg_imag <<= 63;
213
+
214
+ for (i = 0; i < opr_sz / 8; i += 2) {
215
+ float64 e0 = n[i];
216
+ float64 e1 = m[i + 1] ^ neg_imag;
217
+ float64 e2 = n[i + 1];
218
+ float64 e3 = m[i] ^ neg_real;
219
+
220
+ d[i] = float64_add(e0, e1, fpst);
221
+ d[i + 1] = float64_add(e2, e3, fpst);
222
+ }
223
+ clear_tail(d, opr_sz, simd_maxsz(desc));
224
+}
225
--
201
--
226
2.16.2
202
2.25.1
227
228
diff view generated by jsdifflib
1
In v8M, the Implementation Defined Attribution Unit (IDAU) is
1
From: Richard Henderson <richard.henderson@linaro.org>
2
a small piece of hardware typically implemented in the SoC
3
which provides board or SoC specific security attribution
4
information for each address that the CPU performs MPU/SAU
5
checks on. For QEMU, we model this with a QOM interface which
6
is implemented by the board or SoC object and connected to
7
the CPU using a link property.
8
2
9
This commit defines the new interface class, adds the link
3
We can handle both exception entry and exception return by
10
property to the CPU object, and makes the SAU checking
4
hooking into aarch64_sve_change_el.
11
code call the IDAU interface if one is present.
12
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-32-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20180220180325.29818-5-peter.maydell@linaro.org
16
---
10
---
17
target/arm/cpu.h | 3 +++
11
target/arm/helper.c | 15 +++++++++++++--
18
target/arm/idau.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++
12
1 file changed, 13 insertions(+), 2 deletions(-)
19
target/arm/cpu.c | 15 +++++++++++++
20
target/arm/helper.c | 28 +++++++++++++++++++++---
21
4 files changed, 104 insertions(+), 3 deletions(-)
22
create mode 100644 target/arm/idau.h
23
13
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
27
+++ b/target/arm/cpu.h
28
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
29
/* MemoryRegion to use for secure physical accesses */
30
MemoryRegion *secure_memory;
31
32
+ /* For v8M, pointer to the IDAU interface provided by board/SoC */
33
+ Object *idau;
34
+
35
/* 'compatible' string for this CPU for Linux device trees */
36
const char *dtb_compatible;
37
38
diff --git a/target/arm/idau.h b/target/arm/idau.h
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/target/arm/idau.h
43
@@ -XXX,XX +XXX,XX @@
44
+/*
45
+ * QEMU ARM CPU -- interface for the Arm v8M IDAU
46
+ *
47
+ * Copyright (c) 2018 Linaro Ltd
48
+ *
49
+ * This program is free software; you can redistribute it and/or
50
+ * modify it under the terms of the GNU General Public License
51
+ * as published by the Free Software Foundation; either version 2
52
+ * of the License, or (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful,
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57
+ * GNU General Public License for more details.
58
+ *
59
+ * You should have received a copy of the GNU General Public License
60
+ * along with this program; if not, see
61
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
62
+ *
63
+ * In the v8M architecture, the IDAU is a small piece of hardware
64
+ * typically implemented in the SoC which provides board or SoC
65
+ * specific security attribution information for each address that
66
+ * the CPU performs MPU/SAU checks on. For QEMU, we model this with a
67
+ * QOM interface which is implemented by the board or SoC object and
68
+ * connected to the CPU using a link property.
69
+ */
70
+
71
+#ifndef TARGET_ARM_IDAU_H
72
+#define TARGET_ARM_IDAU_H
73
+
74
+#include "qom/object.h"
75
+
76
+#define TYPE_IDAU_INTERFACE "idau-interface"
77
+#define IDAU_INTERFACE(obj) \
78
+ INTERFACE_CHECK(IDAUInterface, (obj), TYPE_IDAU_INTERFACE)
79
+#define IDAU_INTERFACE_CLASS(class) \
80
+ OBJECT_CLASS_CHECK(IDAUInterfaceClass, (class), TYPE_IDAU_INTERFACE)
81
+#define IDAU_INTERFACE_GET_CLASS(obj) \
82
+ OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE)
83
+
84
+typedef struct IDAUInterface {
85
+ Object parent;
86
+} IDAUInterface;
87
+
88
+#define IREGION_NOTVALID -1
89
+
90
+typedef struct IDAUInterfaceClass {
91
+ InterfaceClass parent;
92
+
93
+ /* Check the specified address and return the IDAU security information
94
+ * for it by filling in iregion, exempt, ns and nsc:
95
+ * iregion: IDAU region number, or IREGION_NOTVALID if not valid
96
+ * exempt: true if address is exempt from security attribution
97
+ * ns: true if the address is NonSecure
98
+ * nsc: true if the address is NonSecure-callable
99
+ */
100
+ void (*check)(IDAUInterface *ii, uint32_t address, int *iregion,
101
+ bool *exempt, bool *ns, bool *nsc);
102
+} IDAUInterfaceClass;
103
+
104
+#endif
105
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/cpu.c
108
+++ b/target/arm/cpu.c
109
@@ -XXX,XX +XXX,XX @@
110
*/
111
112
#include "qemu/osdep.h"
113
+#include "target/arm/idau.h"
114
#include "qemu/error-report.h"
115
#include "qapi/error.h"
116
#include "cpu.h"
117
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
118
}
119
}
120
121
+ if (arm_feature(&cpu->env, ARM_FEATURE_M_SECURITY)) {
122
+ object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, &cpu->idau,
123
+ qdev_prop_allow_set_link_before_realize,
124
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
125
+ &error_abort);
126
+ }
127
+
128
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
129
&error_abort);
130
}
131
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
132
.class_init = arm_cpu_class_init,
133
};
134
135
+static const TypeInfo idau_interface_type_info = {
136
+ .name = TYPE_IDAU_INTERFACE,
137
+ .parent = TYPE_INTERFACE,
138
+ .class_size = sizeof(IDAUInterfaceClass),
139
+};
140
+
141
static void arm_cpu_register_types(void)
142
{
143
const ARMCPUInfo *info = arm_cpus;
144
145
type_register_static(&arm_cpu_type_info);
146
+ type_register_static(&idau_interface_type_info);
147
148
while (info->name) {
149
cpu_register(info);
150
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
151
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
152
--- a/target/arm/helper.c
16
--- a/target/arm/helper.c
153
+++ b/target/arm/helper.c
17
+++ b/target/arm/helper.c
154
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
155
#include "qemu/osdep.h"
156
+#include "target/arm/idau.h"
157
#include "trace.h"
158
#include "cpu.h"
159
#include "internals.h"
160
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
161
*/
162
ARMCPU *cpu = arm_env_get_cpu(env);
163
int r;
164
+ bool idau_exempt = false, idau_ns = true, idau_nsc = true;
165
+ int idau_region = IREGION_NOTVALID;
166
167
- /* TODO: implement IDAU */
168
+ if (cpu->idau) {
169
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(cpu->idau);
170
+ IDAUInterface *ii = IDAU_INTERFACE(cpu->idau);
171
+
172
+ iic->check(ii, address, &idau_region, &idau_exempt, &idau_ns,
173
+ &idau_nsc);
174
+ }
175
176
if (access_type == MMU_INST_FETCH && extract32(address, 28, 4) == 0xf) {
177
/* 0xf0000000..0xffffffff is always S for insn fetches */
178
return;
19
return;
179
}
20
}
180
21
181
- if (v8m_is_sau_exempt(env, address, access_type)) {
22
+ old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
182
+ if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) {
23
+ new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
183
sattrs->ns = !regime_is_secure(env, mmu_idx);
24
+
184
return;
25
+ /*
185
}
26
+ * Both AArch64.TakeException and AArch64.ExceptionReturn
186
27
+ * invoke ResetSVEState when taking an exception from, or
187
+ if (idau_region != IREGION_NOTVALID) {
28
+ * returning to, AArch32 state when PSTATE.SM is enabled.
188
+ sattrs->irvalid = true;
29
+ */
189
+ sattrs->iregion = idau_region;
30
+ if (old_a64 != new_a64 && FIELD_EX64(env->svcr, SVCR, SM)) {
31
+ arm_reset_sve_state(env);
32
+ return;
190
+ }
33
+ }
191
+
34
+
192
switch (env->sau.ctrl & 3) {
35
/*
193
case 0: /* SAU.ENABLE == 0, SAU.ALLNS == 0 */
36
* DDI0584A.d sec 3.2: "If SVE instructions are disabled or trapped
194
break;
37
* at ELx, or not available because the EL is in AArch32 state, then
195
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
38
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
196
}
39
* we already have the correct register contents when encountering the
197
}
40
* vq0->vq0 transition between EL0->EL1.
198
41
*/
199
- /* TODO when we support the IDAU then it may override the result here */
42
- old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
200
+ /* The IDAU will override the SAU lookup results if it specifies
43
old_len = (old_a64 && !sve_exception_el(env, old_el)
201
+ * higher security than the SAU does.
44
? sve_vqm1_for_el(env, old_el) : 0);
202
+ */
45
- new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
203
+ if (!idau_ns) {
46
new_len = (new_a64 && !sve_exception_el(env, new_el)
204
+ if (sattrs->ns || (!idau_nsc && sattrs->nsc)) {
47
? sve_vqm1_for_el(env, new_el) : 0);
205
+ sattrs->ns = false;
48
206
+ sattrs->nsc = idau_nsc;
207
+ }
208
+ }
209
break;
210
}
211
}
212
--
49
--
213
2.16.2
50
2.25.1
214
215
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
Note that SME remains effectively disabled for user-only,
4
because we do not yet set CPACR_EL1.SMEN. This needs to
5
wait until the kernel ABI is implemented.
4
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20220708151540.18136-33-richard.henderson@linaro.org
7
Message-id: 20180228193125.20577-17-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
target/arm/cpu.c | 1 +
12
docs/system/arm/emulation.rst | 4 ++++
11
target/arm/cpu64.c | 1 +
13
target/arm/cpu64.c | 11 +++++++++++
12
2 files changed, 2 insertions(+)
14
2 files changed, 15 insertions(+)
13
15
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
16
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
18
--- a/docs/system/arm/emulation.rst
17
+++ b/target/arm/cpu.c
19
+++ b/docs/system/arm/emulation.rst
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
20
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
19
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
21
- FEAT_SHA512 (Advanced SIMD SHA512 instructions)
20
set_feature(&cpu->env, ARM_FEATURE_CRC);
22
- FEAT_SM3 (Advanced SIMD SM3 instructions)
21
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
23
- FEAT_SM4 (Advanced SIMD SM4 instructions)
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
24
+- FEAT_SME (Scalable Matrix Extension)
23
cpu->midr = 0xffffffff;
25
+- FEAT_SME_FA64 (Full A64 instruction set in Streaming SVE mode)
24
}
26
+- FEAT_SME_F64F64 (Double-precision floating-point outer product instructions)
25
#endif
27
+- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product instructions)
28
- FEAT_SPECRES (Speculation restriction instructions)
29
- FEAT_SSBS (Speculative Store Bypass Safe)
30
- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
31
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
27
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu64.c
33
--- a/target/arm/cpu64.c
29
+++ b/target/arm/cpu64.c
34
+++ b/target/arm/cpu64.c
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
35
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
31
set_feature(&cpu->env, ARM_FEATURE_CRC);
36
*/
32
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
37
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
33
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
38
t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
39
+ t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */
35
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
40
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
36
cpu->dcz_blocksize = 7; /* 512 bytes */
41
cpu->isar.id_aa64pfr1 = t;
37
}
42
43
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
44
t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* FEAT_PMUv3p4 */
45
cpu->isar.id_aa64dfr0 = t;
46
47
+ t = cpu->isar.id_aa64smfr0;
48
+ t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1); /* FEAT_SME */
49
+ t = FIELD_DP64(t, ID_AA64SMFR0, B16F32, 1); /* FEAT_SME */
50
+ t = FIELD_DP64(t, ID_AA64SMFR0, F16F32, 1); /* FEAT_SME */
51
+ t = FIELD_DP64(t, ID_AA64SMFR0, I8I32, 0xf); /* FEAT_SME */
52
+ t = FIELD_DP64(t, ID_AA64SMFR0, F64F64, 1); /* FEAT_SME_F64F64 */
53
+ t = FIELD_DP64(t, ID_AA64SMFR0, I16I64, 0xf); /* FEAT_SME_I16I64 */
54
+ t = FIELD_DP64(t, ID_AA64SMFR0, FA64, 1); /* FEAT_SME_FA64 */
55
+ cpu->isar.id_aa64smfr0 = t;
56
+
57
/* Replicate the same data to the 32-bit id registers. */
58
aa32_max_features(cpu);
59
38
--
60
--
39
2.16.2
61
2.25.1
40
41
diff view generated by jsdifflib
1
The function qdev_init_gpio_in_named() passes the DeviceState pointer
1
From: Richard Henderson <richard.henderson@linaro.org>
2
as the opaque data pointor for the irq handler function. Usually
3
this is what you want, but in some cases it would be helpful to use
4
some other data pointer.
5
2
6
Add a new function qdev_init_gpio_in_named_with_opaque() which allows
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
the caller to specify the data pointer they want.
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220708151540.18136-34-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
linux-user/aarch64/target_cpu.h | 5 ++++-
9
1 file changed, 4 insertions(+), 1 deletion(-)
8
10
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180220180325.29818-12-peter.maydell@linaro.org
13
---
14
include/hw/qdev-core.h | 30 ++++++++++++++++++++++++++++--
15
hw/core/qdev.c | 8 +++++---
16
2 files changed, 33 insertions(+), 5 deletions(-)
17
18
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
19
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/qdev-core.h
13
--- a/linux-user/aarch64/target_cpu.h
21
+++ b/include/hw/qdev-core.h
14
+++ b/linux-user/aarch64/target_cpu.h
22
@@ -XXX,XX +XXX,XX @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
15
@@ -XXX,XX +XXX,XX @@ static inline void cpu_clone_regs_parent(CPUARMState *env, unsigned flags)
23
/* GPIO inputs also double as IRQ sinks. */
16
24
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
17
static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
25
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
18
{
26
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
19
- /* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
27
- const char *name, int n);
20
+ /*
28
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
21
+ * Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
29
const char *name, int n);
22
* different from AArch32 Linux, which uses TPIDRRO.
30
+/**
23
*/
31
+ * qdev_init_gpio_in_named_with_opaque: create an array of input GPIO lines
24
env->cp15.tpidr_el[0] = newtls;
32
+ * for the specified device
25
+ /* TPIDR2_EL0 is cleared with CLONE_SETTLS. */
33
+ *
26
+ env->cp15.tpidr2_el0 = 0;
34
+ * @dev: Device to create input GPIOs for
35
+ * @handler: Function to call when GPIO line value is set
36
+ * @opaque: Opaque data pointer to pass to @handler
37
+ * @name: Name of the GPIO input (must be unique for this device)
38
+ * @n: Number of GPIO lines in this input set
39
+ */
40
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
41
+ qemu_irq_handler handler,
42
+ void *opaque,
43
+ const char *name, int n);
44
+
45
+/**
46
+ * qdev_init_gpio_in_named: create an array of input GPIO lines
47
+ * for the specified device
48
+ *
49
+ * Like qdev_init_gpio_in_named_with_opaque(), but the opaque pointer
50
+ * passed to the handler is @dev (which is the most commonly desired behaviour).
51
+ */
52
+static inline void qdev_init_gpio_in_named(DeviceState *dev,
53
+ qemu_irq_handler handler,
54
+ const char *name, int n)
55
+{
56
+ qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n);
57
+}
58
59
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
60
const char *name);
61
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/core/qdev.c
64
+++ b/hw/core/qdev.c
65
@@ -XXX,XX +XXX,XX @@ static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
66
return ngl;
67
}
27
}
68
28
69
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
29
static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
70
- const char *name, int n)
71
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
72
+ qemu_irq_handler handler,
73
+ void *opaque,
74
+ const char *name, int n)
75
{
76
int i;
77
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
78
79
assert(gpio_list->num_out == 0 || !name);
80
gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
81
- dev, n);
82
+ opaque, n);
83
84
if (!name) {
85
name = "unnamed-gpio-in";
86
--
30
--
87
2.16.2
31
2.25.1
88
89
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-9-richard.henderson@linaro.org
5
Message-id: 20220708151540.18136-35-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/translate.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
8
linux-user/aarch64/cpu_loop.c | 9 +++++++++
9
1 file changed, 42 insertions(+), 4 deletions(-)
9
1 file changed, 9 insertions(+)
10
10
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
11
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
13
--- a/linux-user/aarch64/cpu_loop.c
14
+++ b/target/arm/translate.c
14
+++ b/linux-user/aarch64/cpu_loop.c
15
@@ -XXX,XX +XXX,XX @@ static const char *regnames[] =
15
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
16
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
16
17
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
17
switch (trapnr) {
18
18
case EXCP_SWI:
19
+/* Function prototypes for gen_ functions calling Neon helpers. */
19
+ /*
20
+typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
20
+ * On syscall, PSTATE.ZA is preserved, along with the ZA matrix.
21
+ TCGv_i32, TCGv_i32);
21
+ * PSTATE.SM is cleared, per SMSTOP, which does ResetSVEState.
22
+
22
+ */
23
/* initialize TCG globals. */
23
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
24
void arm_translate_init(void)
24
+ env->svcr = FIELD_DP64(env->svcr, SVCR, SM, 0);
25
{
25
+ arm_rebuild_hflags(env);
26
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
26
+ arm_reset_sve_state(env);
27
}
27
+ }
28
neon_store_reg64(cpu_V0, rd + pass);
28
ret = do_syscall(env,
29
}
29
env->xregs[8],
30
-
30
env->xregs[0],
31
-
32
break;
33
- default: /* 14 and 15 are RESERVED */
34
- return 1;
35
+ case 14: /* VQRDMLAH scalar */
36
+ case 15: /* VQRDMLSH scalar */
37
+ {
38
+ NeonGenThreeOpEnvFn *fn;
39
+
40
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
41
+ return 1;
42
+ }
43
+ if (u && ((rd | rn) & 1)) {
44
+ return 1;
45
+ }
46
+ if (op == 14) {
47
+ if (size == 1) {
48
+ fn = gen_helper_neon_qrdmlah_s16;
49
+ } else {
50
+ fn = gen_helper_neon_qrdmlah_s32;
51
+ }
52
+ } else {
53
+ if (size == 1) {
54
+ fn = gen_helper_neon_qrdmlsh_s16;
55
+ } else {
56
+ fn = gen_helper_neon_qrdmlsh_s32;
57
+ }
58
+ }
59
+
60
+ tmp2 = neon_get_scalar(size, rm);
61
+ for (pass = 0; pass < (u ? 4 : 2); pass++) {
62
+ tmp = neon_load_reg(rn, pass);
63
+ tmp3 = neon_load_reg(rd, pass);
64
+ fn(tmp, cpu_env, tmp, tmp2, tmp3);
65
+ tcg_temp_free_i32(tmp3);
66
+ neon_store_reg(rd, pass, tmp);
67
+ }
68
+ tcg_temp_free_i32(tmp2);
69
+ }
70
+ break;
71
+ default:
72
+ g_assert_not_reached();
73
}
74
}
75
} else { /* size == 3 */
76
--
31
--
77
2.16.2
32
2.25.1
78
79
diff view generated by jsdifflib
1
Instead of loading guest images to the system address space, use the
1
From: Richard Henderson <richard.henderson@linaro.org>
2
CPU's address space. This is important if we're trying to load the
3
file to memory or via an alias memory region that is provided by an
4
SoC object and thus not mapped into the system address space.
5
2
3
Make sure to zero the currently reserved fields.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220708151540.18136-36-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-4-peter.maydell@linaro.org
10
---
9
---
11
hw/arm/armv7m.c | 17 ++++++++++++++---
10
linux-user/aarch64/signal.c | 9 ++++++++-
12
1 file changed, 14 insertions(+), 3 deletions(-)
11
1 file changed, 8 insertions(+), 1 deletion(-)
13
12
14
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armv7m.c
15
--- a/linux-user/aarch64/signal.c
17
+++ b/hw/arm/armv7m.c
16
+++ b/linux-user/aarch64/signal.c
18
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
17
@@ -XXX,XX +XXX,XX @@ struct target_extra_context {
19
uint64_t entry;
18
struct target_sve_context {
20
uint64_t lowaddr;
19
struct target_aarch64_ctx head;
21
int big_endian;
20
uint16_t vl;
22
+ AddressSpace *as;
21
- uint16_t reserved[3];
23
+ int asidx;
22
+ uint16_t flags;
24
+ CPUState *cs = CPU(cpu);
23
+ uint16_t reserved[2];
25
24
/* The actual SVE data immediately follows. It is laid out
26
#ifdef TARGET_WORDS_BIGENDIAN
25
* according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
27
big_endian = 1;
26
* the original struct pointer.
28
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
27
@@ -XXX,XX +XXX,XX @@ struct target_sve_context {
29
exit(1);
28
#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
30
}
29
(TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
31
30
32
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
31
+#define TARGET_SVE_SIG_FLAG_SM 1
33
+ asidx = ARMASIdx_S;
32
+
34
+ } else {
33
struct target_rt_sigframe {
35
+ asidx = ARMASIdx_NS;
34
struct target_siginfo info;
35
struct target_ucontext uc;
36
@@ -XXX,XX +XXX,XX @@ static void target_setup_sve_record(struct target_sve_context *sve,
37
{
38
int i, j;
39
40
+ memset(sve, 0, sizeof(*sve));
41
__put_user(TARGET_SVE_MAGIC, &sve->head.magic);
42
__put_user(size, &sve->head.size);
43
__put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
44
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
45
+ __put_user(TARGET_SVE_SIG_FLAG_SM, &sve->flags);
36
+ }
46
+ }
37
+ as = cpu_get_address_space(cs, asidx);
47
38
+
48
/* Note that SVE regs are stored as a byte stream, with each byte element
39
if (kernel_filename) {
49
* at a subsequent address. This corresponds to a little-endian store
40
- image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
41
- NULL, big_endian, EM_ARM, 1, 0);
42
+ image_size = load_elf_as(kernel_filename, NULL, NULL, &entry, &lowaddr,
43
+ NULL, big_endian, EM_ARM, 1, 0, as);
44
if (image_size < 0) {
45
- image_size = load_image_targphys(kernel_filename, 0, mem_size);
46
+ image_size = load_image_targphys_as(kernel_filename, 0,
47
+ mem_size, as);
48
lowaddr = 0;
49
}
50
if (image_size < 0) {
51
--
50
--
52
2.16.2
51
2.25.1
53
54
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
3
Fold the return value setting into the goto, so each
4
point of failure need not do both.
5
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-37-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
---
10
---
8
include/hw/arm/xlnx-zynqmp.h | 2 ++
11
linux-user/aarch64/signal.c | 26 +++++++++++---------------
9
hw/arm/xlnx-zynqmp.c | 14 ++++++++++++++
12
1 file changed, 11 insertions(+), 15 deletions(-)
10
2 files changed, 16 insertions(+)
11
13
12
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
14
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/xlnx-zynqmp.h
16
--- a/linux-user/aarch64/signal.c
15
+++ b/include/hw/arm/xlnx-zynqmp.h
17
+++ b/linux-user/aarch64/signal.c
16
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
17
#include "hw/dma/xlnx_dpdma.h"
19
struct target_sve_context *sve = NULL;
18
#include "hw/display/xlnx_dp.h"
20
uint64_t extra_datap = 0;
19
#include "hw/intc/xlnx-zynqmp-ipi.h"
21
bool used_extra = false;
20
+#include "hw/timer/xlnx-zynqmp-rtc.h"
22
- bool err = false;
21
23
int vq = 0, sve_size = 0;
22
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
24
23
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
25
target_restore_general_frame(env, sf);
24
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPState {
26
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
25
XlnxDPState dp;
27
switch (magic) {
26
XlnxDPDMAState dpdma;
28
case 0:
27
XlnxZynqMPIPI ipi;
29
if (size != 0) {
28
+ XlnxZynqMPRTC rtc;
30
- err = true;
29
31
- goto exit;
30
char *boot_cpu;
32
+ goto err;
31
ARMCPU *boot_cpu_ptr;
33
}
32
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
34
if (used_extra) {
33
index XXXXXXX..XXXXXXX 100644
35
ctx = NULL;
34
--- a/hw/arm/xlnx-zynqmp.c
36
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
35
+++ b/hw/arm/xlnx-zynqmp.c
37
36
@@ -XXX,XX +XXX,XX @@
38
case TARGET_FPSIMD_MAGIC:
37
#define IPI_ADDR 0xFF300000
39
if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
38
#define IPI_IRQ 64
40
- err = true;
39
41
- goto exit;
40
+#define RTC_ADDR 0xffa60000
42
+ goto err;
41
+#define RTC_IRQ 26
43
}
44
fpsimd = (struct target_fpsimd_context *)ctx;
45
break;
46
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
47
break;
48
}
49
}
50
- err = true;
51
- goto exit;
52
+ goto err;
53
54
case TARGET_EXTRA_MAGIC:
55
if (extra || size != sizeof(struct target_extra_context)) {
56
- err = true;
57
- goto exit;
58
+ goto err;
59
}
60
__get_user(extra_datap,
61
&((struct target_extra_context *)ctx)->datap);
62
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
63
/* Unknown record -- we certainly didn't generate it.
64
* Did we in fact get out of sync?
65
*/
66
- err = true;
67
- goto exit;
68
+ goto err;
69
}
70
ctx = (void *)ctx + size;
71
}
72
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
73
if (fpsimd) {
74
target_restore_fpsimd_record(env, fpsimd);
75
} else {
76
- err = true;
77
+ goto err;
78
}
79
80
/* SVE data, if present, overwrites FPSIMD data. */
81
if (sve) {
82
target_restore_sve_record(env, sve, vq);
83
}
84
-
85
- exit:
86
unlock_user(extra, extra_datap, 0);
87
- return err;
88
+ return 0;
42
+
89
+
43
#define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
90
+ err:
44
91
+ unlock_user(extra, extra_datap, 0);
45
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
92
+ return 1;
46
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
47
48
object_initialize(&s->ipi, sizeof(s->ipi), TYPE_XLNX_ZYNQMP_IPI);
49
qdev_set_parent_bus(DEVICE(&s->ipi), sysbus_get_default());
50
+
51
+ object_initialize(&s->rtc, sizeof(s->rtc), TYPE_XLNX_ZYNQMP_RTC);
52
+ qdev_set_parent_bus(DEVICE(&s->rtc), sysbus_get_default());
53
}
93
}
54
94
55
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
95
static abi_ulong get_sigframe(struct target_sigaction *ka,
56
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
57
}
58
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ipi), 0, IPI_ADDR);
59
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ipi), 0, gic_spi[IPI_IRQ]);
60
+
61
+ object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
62
+ if (err) {
63
+ error_propagate(errp, err);
64
+ return;
65
+ }
66
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR);
67
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
68
}
69
70
static Property xlnx_zynqmp_props[] = {
71
--
96
--
72
2.16.2
97
2.25.1
73
74
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Include the U bit in the switches rather than testing separately.
3
In parse_user_sigframe, the kernel rejects duplicate sve records,
4
or records that are smaller than the header. We were silently
5
allowing these cases to pass, dropping the record.
4
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20220708151540.18136-38-richard.henderson@linaro.org
7
Message-id: 20180228193125.20577-3-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
target/arm/translate-a64.c | 129 +++++++++++++++++++++------------------------
12
linux-user/aarch64/signal.c | 5 ++++-
11
1 file changed, 61 insertions(+), 68 deletions(-)
13
1 file changed, 4 insertions(+), 1 deletion(-)
12
14
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
17
--- a/linux-user/aarch64/signal.c
16
+++ b/target/arm/translate-a64.c
18
+++ b/linux-user/aarch64/signal.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
18
int index;
20
break;
19
TCGv_ptr fpst;
21
20
22
case TARGET_SVE_MAGIC:
21
- switch (opcode) {
23
+ if (sve || size < sizeof(struct target_sve_context)) {
22
- case 0x0: /* MLA */
24
+ goto err;
23
- case 0x4: /* MLS */
25
+ }
24
- if (!u || is_scalar) {
26
if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
25
+ switch (16 * u + opcode) {
27
vq = sve_vq(env);
26
+ case 0x08: /* MUL */
28
sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
27
+ case 0x10: /* MLA */
29
- if (!sve && size == sve_size) {
28
+ case 0x14: /* MLS */
30
+ if (size == sve_size) {
29
+ if (is_scalar) {
31
sve = (struct target_sve_context *)ctx;
30
unallocated_encoding(s);
32
break;
31
return;
32
}
33
break;
34
- case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
35
- case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
36
- case 0xa: /* SMULL, SMULL2, UMULL, UMULL2 */
37
+ case 0x02: /* SMLAL, SMLAL2 */
38
+ case 0x12: /* UMLAL, UMLAL2 */
39
+ case 0x06: /* SMLSL, SMLSL2 */
40
+ case 0x16: /* UMLSL, UMLSL2 */
41
+ case 0x0a: /* SMULL, SMULL2 */
42
+ case 0x1a: /* UMULL, UMULL2 */
43
if (is_scalar) {
44
unallocated_encoding(s);
45
return;
46
}
47
is_long = true;
48
break;
49
- case 0x3: /* SQDMLAL, SQDMLAL2 */
50
- case 0x7: /* SQDMLSL, SQDMLSL2 */
51
- case 0xb: /* SQDMULL, SQDMULL2 */
52
+ case 0x03: /* SQDMLAL, SQDMLAL2 */
53
+ case 0x07: /* SQDMLSL, SQDMLSL2 */
54
+ case 0x0b: /* SQDMULL, SQDMULL2 */
55
is_long = true;
56
- /* fall through */
57
- case 0xc: /* SQDMULH */
58
- case 0xd: /* SQRDMULH */
59
- if (u) {
60
- unallocated_encoding(s);
61
- return;
62
- }
63
break;
64
- case 0x8: /* MUL */
65
- if (u || is_scalar) {
66
- unallocated_encoding(s);
67
- return;
68
- }
69
+ case 0x0c: /* SQDMULH */
70
+ case 0x0d: /* SQRDMULH */
71
break;
72
- case 0x1: /* FMLA */
73
- case 0x5: /* FMLS */
74
- if (u) {
75
- unallocated_encoding(s);
76
- return;
77
- }
78
- /* fall through */
79
- case 0x9: /* FMUL, FMULX */
80
+ case 0x01: /* FMLA */
81
+ case 0x05: /* FMLS */
82
+ case 0x09: /* FMUL */
83
+ case 0x19: /* FMULX */
84
if (size == 1) {
85
unallocated_encoding(s);
86
return;
87
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
88
89
read_vec_element(s, tcg_op, rn, pass, MO_64);
90
91
- switch (opcode) {
92
- case 0x5: /* FMLS */
93
+ switch (16 * u + opcode) {
94
+ case 0x05: /* FMLS */
95
/* As usual for ARM, separate negation for fused multiply-add */
96
gen_helper_vfp_negd(tcg_op, tcg_op);
97
/* fall through */
98
- case 0x1: /* FMLA */
99
+ case 0x01: /* FMLA */
100
read_vec_element(s, tcg_res, rd, pass, MO_64);
101
gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
102
break;
103
- case 0x9: /* FMUL, FMULX */
104
- if (u) {
105
- gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
106
- } else {
107
- gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
108
- }
109
+ case 0x09: /* FMUL */
110
+ gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
111
+ break;
112
+ case 0x19: /* FMULX */
113
+ gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
114
break;
115
default:
116
g_assert_not_reached();
117
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
118
119
read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
120
121
- switch (opcode) {
122
- case 0x0: /* MLA */
123
- case 0x4: /* MLS */
124
- case 0x8: /* MUL */
125
+ switch (16 * u + opcode) {
126
+ case 0x08: /* MUL */
127
+ case 0x10: /* MLA */
128
+ case 0x14: /* MLS */
129
{
130
static NeonGenTwoOpFn * const fns[2][2] = {
131
{ gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
132
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
133
genfn(tcg_res, tcg_op, tcg_res);
134
break;
135
}
136
- case 0x5: /* FMLS */
137
- case 0x1: /* FMLA */
138
+ case 0x05: /* FMLS */
139
+ case 0x01: /* FMLA */
140
read_vec_element_i32(s, tcg_res, rd, pass,
141
is_scalar ? size : MO_32);
142
switch (size) {
143
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
144
g_assert_not_reached();
145
}
33
}
146
break;
147
- case 0x9: /* FMUL, FMULX */
148
+ case 0x09: /* FMUL */
149
switch (size) {
150
case 1:
151
- if (u) {
152
- if (is_scalar) {
153
- gen_helper_advsimd_mulxh(tcg_res, tcg_op,
154
- tcg_idx, fpst);
155
- } else {
156
- gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
157
- tcg_idx, fpst);
158
- }
159
+ if (is_scalar) {
160
+ gen_helper_advsimd_mulh(tcg_res, tcg_op,
161
+ tcg_idx, fpst);
162
} else {
163
- if (is_scalar) {
164
- gen_helper_advsimd_mulh(tcg_res, tcg_op,
165
- tcg_idx, fpst);
166
- } else {
167
- gen_helper_advsimd_mul2h(tcg_res, tcg_op,
168
- tcg_idx, fpst);
169
- }
170
+ gen_helper_advsimd_mul2h(tcg_res, tcg_op,
171
+ tcg_idx, fpst);
172
}
173
break;
174
case 2:
175
- if (u) {
176
- gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
177
- } else {
178
- gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
179
- }
180
+ gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
181
break;
182
default:
183
g_assert_not_reached();
184
}
185
break;
186
- case 0xc: /* SQDMULH */
187
+ case 0x19: /* FMULX */
188
+ switch (size) {
189
+ case 1:
190
+ if (is_scalar) {
191
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op,
192
+ tcg_idx, fpst);
193
+ } else {
194
+ gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
195
+ tcg_idx, fpst);
196
+ }
197
+ break;
198
+ case 2:
199
+ gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
200
+ break;
201
+ default:
202
+ g_assert_not_reached();
203
+ }
204
+ break;
205
+ case 0x0c: /* SQDMULH */
206
if (size == 1) {
207
gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
208
tcg_op, tcg_idx);
209
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
210
tcg_op, tcg_idx);
211
}
212
break;
213
- case 0xd: /* SQRDMULH */
214
+ case 0x0d: /* SQRDMULH */
215
if (size == 1) {
216
gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
217
tcg_op, tcg_idx);
218
--
34
--
219
2.16.2
35
2.25.1
220
221
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-8-richard.henderson@linaro.org
5
Message-id: 20220708151540.18136-39-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/translate.c | 86 +++++++++++++++++++++++++++++++++++++++-----------
8
linux-user/aarch64/signal.c | 3 +++
9
1 file changed, 67 insertions(+), 19 deletions(-)
9
1 file changed, 3 insertions(+)
10
10
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
11
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
13
--- a/linux-user/aarch64/signal.c
14
+++ b/target/arm/translate.c
14
+++ b/linux-user/aarch64/signal.c
15
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
16
#include "disas/disas.h"
16
__get_user(extra_size,
17
#include "exec/exec-all.h"
17
&((struct target_extra_context *)ctx)->size);
18
#include "tcg-op.h"
18
extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
19
+#include "tcg-op-gvec.h"
19
+ if (!extra) {
20
#include "qemu/log.h"
20
+ return 1;
21
#include "qemu/bitops.h"
22
#include "arm_ldst.h"
23
@@ -XXX,XX +XXX,XX @@ static void gen_neon_narrow_op(int op, int u, int size,
24
#define NEON_3R_VPMAX 20
25
#define NEON_3R_VPMIN 21
26
#define NEON_3R_VQDMULH_VQRDMULH 22
27
-#define NEON_3R_VPADD 23
28
+#define NEON_3R_VPADD_VQRDMLAH 23
29
#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
30
-#define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
31
+#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
32
#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
33
#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
34
#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
35
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_3r_sizes[] = {
36
[NEON_3R_VPMAX] = 0x7,
37
[NEON_3R_VPMIN] = 0x7,
38
[NEON_3R_VQDMULH_VQRDMULH] = 0x6,
39
- [NEON_3R_VPADD] = 0x7,
40
+ [NEON_3R_VPADD_VQRDMLAH] = 0x7,
41
[NEON_3R_SHA] = 0xf, /* size field encodes op type */
42
- [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
43
+ [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
44
[NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
45
[NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
46
[NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
47
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
48
[NEON_2RM_VCVT_UF] = 0x4,
49
};
50
51
+
52
+/* Expand v8.1 simd helper. */
53
+static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
54
+ int q, int rd, int rn, int rm)
55
+{
56
+ if (arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
57
+ int opr_sz = (1 + q) * 8;
58
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
59
+ vfp_reg_offset(1, rn),
60
+ vfp_reg_offset(1, rm), cpu_env,
61
+ opr_sz, opr_sz, 0, fn);
62
+ return 0;
63
+ }
64
+ return 1;
65
+}
66
+
67
/* Translate a NEON data processing instruction. Return nonzero if the
68
instruction is invalid.
69
We process data in a mixture of 32-bit and 64-bit chunks.
70
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
71
if (q && ((rd | rn | rm) & 1)) {
72
return 1;
73
}
74
- /*
75
- * The SHA-1/SHA-256 3-register instructions require special treatment
76
- * here, as their size field is overloaded as an op type selector, and
77
- * they all consume their input in a single pass.
78
- */
79
- if (op == NEON_3R_SHA) {
80
+ switch (op) {
81
+ case NEON_3R_SHA:
82
+ /* The SHA-1/SHA-256 3-register instructions require special
83
+ * treatment here, as their size field is overloaded as an
84
+ * op type selector, and they all consume their input in a
85
+ * single pass.
86
+ */
87
if (!q) {
88
return 1;
89
}
90
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
91
tcg_temp_free_ptr(ptr2);
92
tcg_temp_free_ptr(ptr3);
93
return 0;
94
+
95
+ case NEON_3R_VPADD_VQRDMLAH:
96
+ if (!u) {
97
+ break; /* VPADD */
98
+ }
21
+ }
99
+ /* VQRDMLAH */
100
+ switch (size) {
101
+ case 1:
102
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
103
+ q, rd, rn, rm);
104
+ case 2:
105
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
106
+ q, rd, rn, rm);
107
+ }
108
+ return 1;
109
+
110
+ case NEON_3R_VFM_VQRDMLSH:
111
+ if (!u) {
112
+ /* VFM, VFMS */
113
+ if (size == 1) {
114
+ return 1;
115
+ }
116
+ break;
117
+ }
118
+ /* VQRDMLSH */
119
+ switch (size) {
120
+ case 1:
121
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
122
+ q, rd, rn, rm);
123
+ case 2:
124
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
125
+ q, rd, rn, rm);
126
+ }
127
+ return 1;
128
}
129
if (size == 3 && op != NEON_3R_LOGIC) {
130
/* 64-bit element instructions. */
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
132
rm = rtmp;
133
}
134
break;
22
break;
135
- case NEON_3R_VPADD:
23
136
- if (u) {
24
default:
137
- return 1;
138
- }
139
- /* Fall through */
140
+ case NEON_3R_VPADD_VQRDMLAH:
141
case NEON_3R_VPMAX:
142
case NEON_3R_VPMIN:
143
pairwise = 1;
144
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
145
return 1;
146
}
147
break;
148
- case NEON_3R_VFM:
149
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
150
+ case NEON_3R_VFM_VQRDMLSH:
151
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
152
return 1;
153
}
154
break;
155
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
156
}
157
}
158
break;
159
- case NEON_3R_VPADD:
160
+ case NEON_3R_VPADD_VQRDMLAH:
161
switch (size) {
162
case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
163
case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
164
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
165
}
166
}
167
break;
168
- case NEON_3R_VFM:
169
+ case NEON_3R_VFM_VQRDMLSH:
170
{
171
/* VFMA, VFMS: fused multiply-add */
172
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
173
--
25
--
174
2.16.2
26
2.25.1
175
176
diff view generated by jsdifflib
1
The Arm IoT Kit includes a "security controller" which is largely a
1
From: Richard Henderson <richard.henderson@linaro.org>
2
collection of registers for controlling the PPCs and other bits of
3
glue in the system. This commit provides the initial skeleton of the
4
device, implementing just the ID registers, and a couple of read-only
5
read-as-zero registers.
6
2
3
Move the checks out of the parsing loop and into the
4
restore function. This more closely mirrors the code
5
structure in the kernel, and is slightly clearer.
6
7
Reject rather than silently skip incorrect VL and SVE record sizes,
8
bringing our checks in to line with those the kernel does.
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20220708151540.18136-40-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-16-peter.maydell@linaro.org
10
---
14
---
11
hw/misc/Makefile.objs | 1 +
15
linux-user/aarch64/signal.c | 51 +++++++++++++++++++++++++------------
12
include/hw/misc/iotkit-secctl.h | 39 ++++
16
1 file changed, 35 insertions(+), 16 deletions(-)
13
hw/misc/iotkit-secctl.c | 448 ++++++++++++++++++++++++++++++++++++++++
14
default-configs/arm-softmmu.mak | 1 +
15
hw/misc/trace-events | 7 +
16
5 files changed, 496 insertions(+)
17
create mode 100644 include/hw/misc/iotkit-secctl.h
18
create mode 100644 hw/misc/iotkit-secctl.c
19
17
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
18
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
21
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/Makefile.objs
20
--- a/linux-user/aarch64/signal.c
23
+++ b/hw/misc/Makefile.objs
21
+++ b/linux-user/aarch64/signal.c
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
22
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
23
}
26
24
}
27
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
25
28
+obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
26
-static void target_restore_sve_record(CPUARMState *env,
29
27
- struct target_sve_context *sve, int vq)
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
28
+static bool target_restore_sve_record(CPUARMState *env,
31
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
29
+ struct target_sve_context *sve,
32
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
30
+ int size)
33
new file mode 100644
31
{
34
index XXXXXXX..XXXXXXX
32
- int i, j;
35
--- /dev/null
33
+ int i, j, vl, vq;
36
+++ b/include/hw/misc/iotkit-secctl.h
34
37
@@ -XXX,XX +XXX,XX @@
35
- /* Note that SVE regs are stored as a byte stream, with each byte element
38
+/*
36
+ if (!cpu_isar_feature(aa64_sve, env_archcpu(env))) {
39
+ * ARM IoT Kit security controller
37
+ return false;
40
+ *
41
+ * Copyright (c) 2018 Linaro Limited
42
+ * Written by Peter Maydell
43
+ *
44
+ * This program is free software; you can redistribute it and/or modify
45
+ * it under the terms of the GNU General Public License version 2 or
46
+ * (at your option) any later version.
47
+ */
48
+
49
+/* This is a model of the security controller which is part of the
50
+ * Arm IoT Kit and documented in
51
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
52
+ *
53
+ * QEMU interface:
54
+ * + sysbus MMIO region 0 is the "secure privilege control block" registers
55
+ * + sysbus MMIO region 1 is the "non-secure privilege control block" registers
56
+ */
57
+
58
+#ifndef IOTKIT_SECCTL_H
59
+#define IOTKIT_SECCTL_H
60
+
61
+#include "hw/sysbus.h"
62
+
63
+#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
64
+#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
65
+
66
+typedef struct IoTKitSecCtl {
67
+ /*< private >*/
68
+ SysBusDevice parent_obj;
69
+
70
+ /*< public >*/
71
+
72
+ MemoryRegion s_regs;
73
+ MemoryRegion ns_regs;
74
+} IoTKitSecCtl;
75
+
76
+#endif
77
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
78
new file mode 100644
79
index XXXXXXX..XXXXXXX
80
--- /dev/null
81
+++ b/hw/misc/iotkit-secctl.c
82
@@ -XXX,XX +XXX,XX @@
83
+/*
84
+ * Arm IoT Kit security controller
85
+ *
86
+ * Copyright (c) 2018 Linaro Limited
87
+ * Written by Peter Maydell
88
+ *
89
+ * This program is free software; you can redistribute it and/or modify
90
+ * it under the terms of the GNU General Public License version 2 or
91
+ * (at your option) any later version.
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qapi/error.h"
97
+#include "trace.h"
98
+#include "hw/sysbus.h"
99
+#include "hw/registerfields.h"
100
+#include "hw/misc/iotkit-secctl.h"
101
+
102
+/* Registers in the secure privilege control block */
103
+REG32(SECRESPCFG, 0x10)
104
+REG32(NSCCFG, 0x14)
105
+REG32(SECMPCINTSTATUS, 0x1c)
106
+REG32(SECPPCINTSTAT, 0x20)
107
+REG32(SECPPCINTCLR, 0x24)
108
+REG32(SECPPCINTEN, 0x28)
109
+REG32(SECMSCINTSTAT, 0x30)
110
+REG32(SECMSCINTCLR, 0x34)
111
+REG32(SECMSCINTEN, 0x38)
112
+REG32(BRGINTSTAT, 0x40)
113
+REG32(BRGINTCLR, 0x44)
114
+REG32(BRGINTEN, 0x48)
115
+REG32(AHBNSPPC0, 0x50)
116
+REG32(AHBNSPPCEXP0, 0x60)
117
+REG32(AHBNSPPCEXP1, 0x64)
118
+REG32(AHBNSPPCEXP2, 0x68)
119
+REG32(AHBNSPPCEXP3, 0x6c)
120
+REG32(APBNSPPC0, 0x70)
121
+REG32(APBNSPPC1, 0x74)
122
+REG32(APBNSPPCEXP0, 0x80)
123
+REG32(APBNSPPCEXP1, 0x84)
124
+REG32(APBNSPPCEXP2, 0x88)
125
+REG32(APBNSPPCEXP3, 0x8c)
126
+REG32(AHBSPPPC0, 0x90)
127
+REG32(AHBSPPPCEXP0, 0xa0)
128
+REG32(AHBSPPPCEXP1, 0xa4)
129
+REG32(AHBSPPPCEXP2, 0xa8)
130
+REG32(AHBSPPPCEXP3, 0xac)
131
+REG32(APBSPPPC0, 0xb0)
132
+REG32(APBSPPPC1, 0xb4)
133
+REG32(APBSPPPCEXP0, 0xc0)
134
+REG32(APBSPPPCEXP1, 0xc4)
135
+REG32(APBSPPPCEXP2, 0xc8)
136
+REG32(APBSPPPCEXP3, 0xcc)
137
+REG32(NSMSCEXP, 0xd0)
138
+REG32(PID4, 0xfd0)
139
+REG32(PID5, 0xfd4)
140
+REG32(PID6, 0xfd8)
141
+REG32(PID7, 0xfdc)
142
+REG32(PID0, 0xfe0)
143
+REG32(PID1, 0xfe4)
144
+REG32(PID2, 0xfe8)
145
+REG32(PID3, 0xfec)
146
+REG32(CID0, 0xff0)
147
+REG32(CID1, 0xff4)
148
+REG32(CID2, 0xff8)
149
+REG32(CID3, 0xffc)
150
+
151
+/* Registers in the non-secure privilege control block */
152
+REG32(AHBNSPPPC0, 0x90)
153
+REG32(AHBNSPPPCEXP0, 0xa0)
154
+REG32(AHBNSPPPCEXP1, 0xa4)
155
+REG32(AHBNSPPPCEXP2, 0xa8)
156
+REG32(AHBNSPPPCEXP3, 0xac)
157
+REG32(APBNSPPPC0, 0xb0)
158
+REG32(APBNSPPPC1, 0xb4)
159
+REG32(APBNSPPPCEXP0, 0xc0)
160
+REG32(APBNSPPPCEXP1, 0xc4)
161
+REG32(APBNSPPPCEXP2, 0xc8)
162
+REG32(APBNSPPPCEXP3, 0xcc)
163
+/* PID and CID registers are also present in the NS block */
164
+
165
+static const uint8_t iotkit_secctl_s_idregs[] = {
166
+ 0x04, 0x00, 0x00, 0x00,
167
+ 0x52, 0xb8, 0x0b, 0x00,
168
+ 0x0d, 0xf0, 0x05, 0xb1,
169
+};
170
+
171
+static const uint8_t iotkit_secctl_ns_idregs[] = {
172
+ 0x04, 0x00, 0x00, 0x00,
173
+ 0x53, 0xb8, 0x0b, 0x00,
174
+ 0x0d, 0xf0, 0x05, 0xb1,
175
+};
176
+
177
+static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
178
+ uint64_t *pdata,
179
+ unsigned size, MemTxAttrs attrs)
180
+{
181
+ uint64_t r;
182
+ uint32_t offset = addr & ~0x3;
183
+
184
+ switch (offset) {
185
+ case A_AHBNSPPC0:
186
+ case A_AHBSPPPC0:
187
+ r = 0;
188
+ break;
189
+ case A_SECRESPCFG:
190
+ case A_NSCCFG:
191
+ case A_SECMPCINTSTATUS:
192
+ case A_SECPPCINTSTAT:
193
+ case A_SECPPCINTEN:
194
+ case A_SECMSCINTSTAT:
195
+ case A_SECMSCINTEN:
196
+ case A_BRGINTSTAT:
197
+ case A_BRGINTEN:
198
+ case A_AHBNSPPCEXP0:
199
+ case A_AHBNSPPCEXP1:
200
+ case A_AHBNSPPCEXP2:
201
+ case A_AHBNSPPCEXP3:
202
+ case A_APBNSPPC0:
203
+ case A_APBNSPPC1:
204
+ case A_APBNSPPCEXP0:
205
+ case A_APBNSPPCEXP1:
206
+ case A_APBNSPPCEXP2:
207
+ case A_APBNSPPCEXP3:
208
+ case A_AHBSPPPCEXP0:
209
+ case A_AHBSPPPCEXP1:
210
+ case A_AHBSPPPCEXP2:
211
+ case A_AHBSPPPCEXP3:
212
+ case A_APBSPPPC0:
213
+ case A_APBSPPPC1:
214
+ case A_APBSPPPCEXP0:
215
+ case A_APBSPPPCEXP1:
216
+ case A_APBSPPPCEXP2:
217
+ case A_APBSPPPCEXP3:
218
+ case A_NSMSCEXP:
219
+ qemu_log_mask(LOG_UNIMP,
220
+ "IoTKit SecCtl S block read: "
221
+ "unimplemented offset 0x%x\n", offset);
222
+ r = 0;
223
+ break;
224
+ case A_PID4:
225
+ case A_PID5:
226
+ case A_PID6:
227
+ case A_PID7:
228
+ case A_PID0:
229
+ case A_PID1:
230
+ case A_PID2:
231
+ case A_PID3:
232
+ case A_CID0:
233
+ case A_CID1:
234
+ case A_CID2:
235
+ case A_CID3:
236
+ r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
237
+ break;
238
+ case A_SECPPCINTCLR:
239
+ case A_SECMSCINTCLR:
240
+ case A_BRGINTCLR:
241
+ qemu_log_mask(LOG_GUEST_ERROR,
242
+ "IotKit SecCtl S block read: write-only offset 0x%x\n",
243
+ offset);
244
+ r = 0;
245
+ break;
246
+ default:
247
+ qemu_log_mask(LOG_GUEST_ERROR,
248
+ "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
249
+ r = 0;
250
+ break;
251
+ }
38
+ }
252
+
39
+
253
+ if (size != 4) {
40
+ __get_user(vl, &sve->vl);
254
+ /* None of our registers are access-sensitive, so just pull the right
41
+ vq = sve_vq(env);
255
+ * byte out of the word read result.
42
+
256
+ */
43
+ /* Reject mismatched VL. */
257
+ r = extract32(r, (addr & 3) * 8, size * 8);
44
+ if (vl != vq * TARGET_SVE_VQ_BYTES) {
45
+ return false;
258
+ }
46
+ }
259
+
47
+
260
+ trace_iotkit_secctl_s_read(offset, r, size);
48
+ /* Accept empty record -- used to clear PSTATE.SM. */
261
+ *pdata = r;
49
+ if (size <= sizeof(*sve)) {
262
+ return MEMTX_OK;
50
+ return true;
263
+}
264
+
265
+static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
266
+ uint64_t value,
267
+ unsigned size, MemTxAttrs attrs)
268
+{
269
+ uint32_t offset = addr;
270
+
271
+ trace_iotkit_secctl_s_write(offset, value, size);
272
+
273
+ if (size != 4) {
274
+ /* Byte and halfword writes are ignored */
275
+ qemu_log_mask(LOG_GUEST_ERROR,
276
+ "IotKit SecCtl S block write: bad size, ignored\n");
277
+ return MEMTX_OK;
278
+ }
51
+ }
279
+
52
+
280
+ switch (offset) {
53
+ /* Reject non-empty but incomplete record. */
281
+ case A_SECRESPCFG:
54
+ if (size < TARGET_SVE_SIG_CONTEXT_SIZE(vq)) {
282
+ case A_NSCCFG:
55
+ return false;
283
+ case A_SECPPCINTCLR:
284
+ case A_SECPPCINTEN:
285
+ case A_SECMSCINTCLR:
286
+ case A_SECMSCINTEN:
287
+ case A_BRGINTCLR:
288
+ case A_BRGINTEN:
289
+ case A_AHBNSPPCEXP0:
290
+ case A_AHBNSPPCEXP1:
291
+ case A_AHBNSPPCEXP2:
292
+ case A_AHBNSPPCEXP3:
293
+ case A_APBNSPPC0:
294
+ case A_APBNSPPC1:
295
+ case A_APBNSPPCEXP0:
296
+ case A_APBNSPPCEXP1:
297
+ case A_APBNSPPCEXP2:
298
+ case A_APBNSPPCEXP3:
299
+ case A_AHBSPPPCEXP0:
300
+ case A_AHBSPPPCEXP1:
301
+ case A_AHBSPPPCEXP2:
302
+ case A_AHBSPPPCEXP3:
303
+ case A_APBSPPPC0:
304
+ case A_APBSPPPC1:
305
+ case A_APBSPPPCEXP0:
306
+ case A_APBSPPPCEXP1:
307
+ case A_APBSPPPCEXP2:
308
+ case A_APBSPPPCEXP3:
309
+ qemu_log_mask(LOG_UNIMP,
310
+ "IoTKit SecCtl S block write: "
311
+ "unimplemented offset 0x%x\n", offset);
312
+ break;
313
+ case A_SECMPCINTSTATUS:
314
+ case A_SECPPCINTSTAT:
315
+ case A_SECMSCINTSTAT:
316
+ case A_BRGINTSTAT:
317
+ case A_AHBNSPPC0:
318
+ case A_AHBSPPPC0:
319
+ case A_NSMSCEXP:
320
+ case A_PID4:
321
+ case A_PID5:
322
+ case A_PID6:
323
+ case A_PID7:
324
+ case A_PID0:
325
+ case A_PID1:
326
+ case A_PID2:
327
+ case A_PID3:
328
+ case A_CID0:
329
+ case A_CID1:
330
+ case A_CID2:
331
+ case A_CID3:
332
+ qemu_log_mask(LOG_GUEST_ERROR,
333
+ "IoTKit SecCtl S block write: "
334
+ "read-only offset 0x%x\n", offset);
335
+ break;
336
+ default:
337
+ qemu_log_mask(LOG_GUEST_ERROR,
338
+ "IotKit SecCtl S block write: bad offset 0x%x\n",
339
+ offset);
340
+ break;
341
+ }
56
+ }
342
+
57
+
343
+ return MEMTX_OK;
58
+ /*
344
+}
59
+ * Note that SVE regs are stored as a byte stream, with each byte element
345
+
60
* at a subsequent address. This corresponds to a little-endian load
346
+static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
61
* of our 64-bit hunks.
347
+ uint64_t *pdata,
62
*/
348
+ unsigned size, MemTxAttrs attrs)
63
@@ -XXX,XX +XXX,XX @@ static void target_restore_sve_record(CPUARMState *env,
349
+{
64
}
350
+ uint64_t r;
65
}
351
+ uint32_t offset = addr & ~0x3;
66
}
352
+
67
+ return true;
353
+ switch (offset) {
68
}
354
+ case A_AHBNSPPPC0:
69
355
+ r = 0;
70
static int target_restore_sigframe(CPUARMState *env,
356
+ break;
71
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
357
+ case A_AHBNSPPPCEXP0:
72
struct target_sve_context *sve = NULL;
358
+ case A_AHBNSPPPCEXP1:
73
uint64_t extra_datap = 0;
359
+ case A_AHBNSPPPCEXP2:
74
bool used_extra = false;
360
+ case A_AHBNSPPPCEXP3:
75
- int vq = 0, sve_size = 0;
361
+ case A_APBNSPPPC0:
76
+ int sve_size = 0;
362
+ case A_APBNSPPPC1:
77
363
+ case A_APBNSPPPCEXP0:
78
target_restore_general_frame(env, sf);
364
+ case A_APBNSPPPCEXP1:
79
365
+ case A_APBNSPPPCEXP2:
80
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
366
+ case A_APBNSPPPCEXP3:
81
if (sve || size < sizeof(struct target_sve_context)) {
367
+ qemu_log_mask(LOG_UNIMP,
82
goto err;
368
+ "IoTKit SecCtl NS block read: "
83
}
369
+ "unimplemented offset 0x%x\n", offset);
84
- if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
370
+ break;
85
- vq = sve_vq(env);
371
+ case A_PID4:
86
- sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
372
+ case A_PID5:
87
- if (size == sve_size) {
373
+ case A_PID6:
88
- sve = (struct target_sve_context *)ctx;
374
+ case A_PID7:
89
- break;
375
+ case A_PID0:
90
- }
376
+ case A_PID1:
91
- }
377
+ case A_PID2:
92
- goto err;
378
+ case A_PID3:
93
+ sve = (struct target_sve_context *)ctx;
379
+ case A_CID0:
94
+ sve_size = size;
380
+ case A_CID1:
95
+ break;
381
+ case A_CID2:
96
382
+ case A_CID3:
97
case TARGET_EXTRA_MAGIC:
383
+ r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
98
if (extra || size != sizeof(struct target_extra_context)) {
384
+ break;
99
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
385
+ default:
100
}
386
+ qemu_log_mask(LOG_GUEST_ERROR,
101
387
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
102
/* SVE data, if present, overwrites FPSIMD data. */
388
+ offset);
103
- if (sve) {
389
+ r = 0;
104
- target_restore_sve_record(env, sve, vq);
390
+ break;
105
+ if (sve && !target_restore_sve_record(env, sve, sve_size)) {
391
+ }
106
+ goto err;
392
+
107
}
393
+ if (size != 4) {
108
unlock_user(extra, extra_datap, 0);
394
+ /* None of our registers are access-sensitive, so just pull the right
109
return 0;
395
+ * byte out of the word read result.
396
+ */
397
+ r = extract32(r, (addr & 3) * 8, size * 8);
398
+ }
399
+
400
+ trace_iotkit_secctl_ns_read(offset, r, size);
401
+ *pdata = r;
402
+ return MEMTX_OK;
403
+}
404
+
405
+static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
406
+ uint64_t value,
407
+ unsigned size, MemTxAttrs attrs)
408
+{
409
+ uint32_t offset = addr;
410
+
411
+ trace_iotkit_secctl_ns_write(offset, value, size);
412
+
413
+ if (size != 4) {
414
+ /* Byte and halfword writes are ignored */
415
+ qemu_log_mask(LOG_GUEST_ERROR,
416
+ "IotKit SecCtl NS block write: bad size, ignored\n");
417
+ return MEMTX_OK;
418
+ }
419
+
420
+ switch (offset) {
421
+ case A_AHBNSPPPCEXP0:
422
+ case A_AHBNSPPPCEXP1:
423
+ case A_AHBNSPPPCEXP2:
424
+ case A_AHBNSPPPCEXP3:
425
+ case A_APBNSPPPC0:
426
+ case A_APBNSPPPC1:
427
+ case A_APBNSPPPCEXP0:
428
+ case A_APBNSPPPCEXP1:
429
+ case A_APBNSPPPCEXP2:
430
+ case A_APBNSPPPCEXP3:
431
+ qemu_log_mask(LOG_UNIMP,
432
+ "IoTKit SecCtl NS block write: "
433
+ "unimplemented offset 0x%x\n", offset);
434
+ break;
435
+ case A_AHBNSPPPC0:
436
+ case A_PID4:
437
+ case A_PID5:
438
+ case A_PID6:
439
+ case A_PID7:
440
+ case A_PID0:
441
+ case A_PID1:
442
+ case A_PID2:
443
+ case A_PID3:
444
+ case A_CID0:
445
+ case A_CID1:
446
+ case A_CID2:
447
+ case A_CID3:
448
+ qemu_log_mask(LOG_GUEST_ERROR,
449
+ "IoTKit SecCtl NS block write: "
450
+ "read-only offset 0x%x\n", offset);
451
+ break;
452
+ default:
453
+ qemu_log_mask(LOG_GUEST_ERROR,
454
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
455
+ offset);
456
+ break;
457
+ }
458
+
459
+ return MEMTX_OK;
460
+}
461
+
462
+static const MemoryRegionOps iotkit_secctl_s_ops = {
463
+ .read_with_attrs = iotkit_secctl_s_read,
464
+ .write_with_attrs = iotkit_secctl_s_write,
465
+ .endianness = DEVICE_LITTLE_ENDIAN,
466
+ .valid.min_access_size = 1,
467
+ .valid.max_access_size = 4,
468
+ .impl.min_access_size = 1,
469
+ .impl.max_access_size = 4,
470
+};
471
+
472
+static const MemoryRegionOps iotkit_secctl_ns_ops = {
473
+ .read_with_attrs = iotkit_secctl_ns_read,
474
+ .write_with_attrs = iotkit_secctl_ns_write,
475
+ .endianness = DEVICE_LITTLE_ENDIAN,
476
+ .valid.min_access_size = 1,
477
+ .valid.max_access_size = 4,
478
+ .impl.min_access_size = 1,
479
+ .impl.max_access_size = 4,
480
+};
481
+
482
+static void iotkit_secctl_reset(DeviceState *dev)
483
+{
484
+
485
+}
486
+
487
+static void iotkit_secctl_init(Object *obj)
488
+{
489
+ IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
490
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
491
+
492
+ memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
+ s, "iotkit-secctl-s-regs", 0x1000);
494
+ memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
495
+ s, "iotkit-secctl-ns-regs", 0x1000);
496
+ sysbus_init_mmio(sbd, &s->s_regs);
497
+ sysbus_init_mmio(sbd, &s->ns_regs);
498
+}
499
+
500
+static const VMStateDescription iotkit_secctl_vmstate = {
501
+ .name = "iotkit-secctl",
502
+ .version_id = 1,
503
+ .minimum_version_id = 1,
504
+ .fields = (VMStateField[]) {
505
+ VMSTATE_END_OF_LIST()
506
+ }
507
+};
508
+
509
+static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
510
+{
511
+ DeviceClass *dc = DEVICE_CLASS(klass);
512
+
513
+ dc->vmsd = &iotkit_secctl_vmstate;
514
+ dc->reset = iotkit_secctl_reset;
515
+}
516
+
517
+static const TypeInfo iotkit_secctl_info = {
518
+ .name = TYPE_IOTKIT_SECCTL,
519
+ .parent = TYPE_SYS_BUS_DEVICE,
520
+ .instance_size = sizeof(IoTKitSecCtl),
521
+ .instance_init = iotkit_secctl_init,
522
+ .class_init = iotkit_secctl_class_init,
523
+};
524
+
525
+static void iotkit_secctl_register_types(void)
526
+{
527
+ type_register_static(&iotkit_secctl_info);
528
+}
529
+
530
+type_init(iotkit_secctl_register_types);
531
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
532
index XXXXXXX..XXXXXXX 100644
533
--- a/default-configs/arm-softmmu.mak
534
+++ b/default-configs/arm-softmmu.mak
535
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
536
CONFIG_MPS2_SCC=y
537
538
CONFIG_TZ_PPC=y
539
+CONFIG_IOTKIT_SECCTL=y
540
541
CONFIG_VERSATILE_PCI=y
542
CONFIG_VERSATILE_I2C=y
543
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
544
index XXXXXXX..XXXXXXX 100644
545
--- a/hw/misc/trace-events
546
+++ b/hw/misc/trace-events
547
@@ -XXX,XX +XXX,XX @@ tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
548
tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
549
tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
550
tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
551
+
552
+# hw/misc/iotkit-secctl.c
553
+iotkit_secctl_s_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs read: offset 0x%x data 0x%" PRIx64 " size %u"
554
+iotkit_secctl_s_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs write: offset 0x%x data 0x%" PRIx64 " size %u"
555
+iotkit_secctl_ns_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs read: offset 0x%x data 0x%" PRIx64 " size %u"
556
+iotkit_secctl_ns_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs write: offset 0x%x data 0x%" PRIx64 " size %u"
557
+iotkit_secctl_reset(void) "IoTKit SecCtl: reset"
558
--
110
--
559
2.16.2
111
2.25.1
560
561
diff view generated by jsdifflib
1
In some board or SoC models it is necessary to split a qemu_irq line
1
From: Richard Henderson <richard.henderson@linaro.org>
2
so that one input can feed multiple outputs. We currently have
3
qemu_irq_split() for this, but that has several deficiencies:
4
* it can only handle splitting a line into two
5
* it unavoidably leaks memory, so it can't be used
6
in a device that can be deleted
7
2
8
Implement a qdev device that encapsulates splitting of IRQs, with a
3
Set the SM bit in the SVE record on signal delivery, create the ZA record.
9
configurable number of outputs. (This is in some ways the inverse of
4
Restore SM and ZA state according to the records present on return.
10
the TYPE_OR_IRQ device.)
11
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-41-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20180220180325.29818-13-peter.maydell@linaro.org
15
---
10
---
16
hw/core/Makefile.objs | 1 +
11
linux-user/aarch64/signal.c | 167 +++++++++++++++++++++++++++++++++---
17
include/hw/core/split-irq.h | 57 +++++++++++++++++++++++++++++
12
1 file changed, 154 insertions(+), 13 deletions(-)
18
include/hw/irq.h | 4 +-
19
hw/core/split-irq.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
20
4 files changed, 150 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/core/split-irq.h
22
create mode 100644 hw/core/split-irq.c
23
13
24
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
14
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
25
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/core/Makefile.objs
16
--- a/linux-user/aarch64/signal.c
27
+++ b/hw/core/Makefile.objs
17
+++ b/linux-user/aarch64/signal.c
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_FITLOADER) += loader-fit.o
18
@@ -XXX,XX +XXX,XX @@ struct target_sve_context {
29
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
19
30
common-obj-$(CONFIG_SOFTMMU) += register.o
20
#define TARGET_SVE_SIG_FLAG_SM 1
31
common-obj-$(CONFIG_SOFTMMU) += or-irq.o
21
32
+common-obj-$(CONFIG_SOFTMMU) += split-irq.o
22
+#define TARGET_ZA_MAGIC 0x54366345
33
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
23
+
34
24
+struct target_za_context {
35
obj-$(CONFIG_SOFTMMU) += generic-loader.o
25
+ struct target_aarch64_ctx head;
36
diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h
26
+ uint16_t vl;
37
new file mode 100644
27
+ uint16_t reserved[3];
38
index XXXXXXX..XXXXXXX
28
+ /* The actual ZA data immediately follows. */
39
--- /dev/null
40
+++ b/include/hw/core/split-irq.h
41
@@ -XXX,XX +XXX,XX @@
42
+/*
43
+ * IRQ splitter device.
44
+ *
45
+ * Copyright (c) 2018 Linaro Limited.
46
+ * Written by Peter Maydell
47
+ *
48
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
49
+ * of this software and associated documentation files (the "Software"), to deal
50
+ * in the Software without restriction, including without limitation the rights
51
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52
+ * copies of the Software, and to permit persons to whom the Software is
53
+ * furnished to do so, subject to the following conditions:
54
+ *
55
+ * The above copyright notice and this permission notice shall be included in
56
+ * all copies or substantial portions of the Software.
57
+ *
58
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
61
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64
+ * THE SOFTWARE.
65
+ */
66
+
67
+/* This is a simple device which has one GPIO input line and multiple
68
+ * GPIO output lines. Any change on the input line is forwarded to all
69
+ * of the outputs.
70
+ *
71
+ * QEMU interface:
72
+ * + one unnamed GPIO input: the input line
73
+ * + N unnamed GPIO outputs: the output lines
74
+ * + QOM property "num-lines": sets the number of output lines
75
+ */
76
+#ifndef HW_SPLIT_IRQ_H
77
+#define HW_SPLIT_IRQ_H
78
+
79
+#include "hw/irq.h"
80
+#include "hw/sysbus.h"
81
+#include "qom/object.h"
82
+
83
+#define TYPE_SPLIT_IRQ "split-irq"
84
+
85
+#define MAX_SPLIT_LINES 16
86
+
87
+typedef struct SplitIRQ SplitIRQ;
88
+
89
+#define SPLIT_IRQ(obj) OBJECT_CHECK(SplitIRQ, (obj), TYPE_SPLIT_IRQ)
90
+
91
+struct SplitIRQ {
92
+ DeviceState parent_obj;
93
+
94
+ qemu_irq out_irq[MAX_SPLIT_LINES];
95
+ uint16_t num_lines;
96
+};
29
+};
97
+
30
+
98
+#endif
31
+#define TARGET_ZA_SIG_REGS_OFFSET \
99
diff --git a/include/hw/irq.h b/include/hw/irq.h
32
+ QEMU_ALIGN_UP(sizeof(struct target_za_context), TARGET_SVE_VQ_BYTES)
100
index XXXXXXX..XXXXXXX 100644
33
+#define TARGET_ZA_SIG_ZAV_OFFSET(VQ, N) \
101
--- a/include/hw/irq.h
34
+ (TARGET_ZA_SIG_REGS_OFFSET + (VQ) * TARGET_SVE_VQ_BYTES * (N))
102
+++ b/include/hw/irq.h
35
+#define TARGET_ZA_SIG_CONTEXT_SIZE(VQ) \
103
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
36
+ TARGET_ZA_SIG_ZAV_OFFSET(VQ, VQ * TARGET_SVE_VQ_BYTES)
104
/* Returns a new IRQ with opposite polarity. */
37
+
105
qemu_irq qemu_irq_invert(qemu_irq irq);
38
struct target_rt_sigframe {
106
39
struct target_siginfo info;
107
-/* Returns a new IRQ which feeds into both the passed IRQs */
40
struct target_ucontext uc;
108
+/* Returns a new IRQ which feeds into both the passed IRQs.
41
@@ -XXX,XX +XXX,XX @@ static void target_setup_end_record(struct target_aarch64_ctx *end)
109
+ * It's probably better to use the TYPE_SPLIT_IRQ device instead.
42
}
110
+ */
43
111
qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
44
static void target_setup_sve_record(struct target_sve_context *sve,
112
45
- CPUARMState *env, int vq, int size)
113
/* Returns a new IRQ set which connects 1:1 to another IRQ set, which
46
+ CPUARMState *env, int size)
114
diff --git a/hw/core/split-irq.c b/hw/core/split-irq.c
47
{
115
new file mode 100644
48
- int i, j;
116
index XXXXXXX..XXXXXXX
49
+ int i, j, vq = sve_vq(env);
117
--- /dev/null
50
118
+++ b/hw/core/split-irq.c
51
memset(sve, 0, sizeof(*sve));
119
@@ -XXX,XX +XXX,XX @@
52
__put_user(TARGET_SVE_MAGIC, &sve->head.magic);
120
+/*
53
@@ -XXX,XX +XXX,XX @@ static void target_setup_sve_record(struct target_sve_context *sve,
121
+ * IRQ splitter device.
54
}
122
+ *
55
}
123
+ * Copyright (c) 2018 Linaro Limited.
56
124
+ * Written by Peter Maydell
57
+static void target_setup_za_record(struct target_za_context *za,
125
+ *
58
+ CPUARMState *env, int size)
126
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
127
+ * of this software and associated documentation files (the "Software"), to deal
128
+ * in the Software without restriction, including without limitation the rights
129
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
130
+ * copies of the Software, and to permit persons to whom the Software is
131
+ * furnished to do so, subject to the following conditions:
132
+ *
133
+ * The above copyright notice and this permission notice shall be included in
134
+ * all copies or substantial portions of the Software.
135
+ *
136
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
137
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
138
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
139
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
140
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
141
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
142
+ * THE SOFTWARE.
143
+ */
144
+
145
+#include "qemu/osdep.h"
146
+#include "hw/core/split-irq.h"
147
+#include "qapi/error.h"
148
+
149
+static void split_irq_handler(void *opaque, int n, int level)
150
+{
59
+{
151
+ SplitIRQ *s = SPLIT_IRQ(opaque);
60
+ int vq = sme_vq(env);
152
+ int i;
61
+ int vl = vq * TARGET_SVE_VQ_BYTES;
153
+
62
+ int i, j;
154
+ for (i = 0; i < s->num_lines; i++) {
63
+
155
+ qemu_set_irq(s->out_irq[i], level);
64
+ memset(za, 0, sizeof(*za));
65
+ __put_user(TARGET_ZA_MAGIC, &za->head.magic);
66
+ __put_user(size, &za->head.size);
67
+ __put_user(vl, &za->vl);
68
+
69
+ if (size == TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
70
+ return;
71
+ }
72
+ assert(size == TARGET_ZA_SIG_CONTEXT_SIZE(vq));
73
+
74
+ /*
75
+ * Note that ZA vectors are stored as a byte stream,
76
+ * with each byte element at a subsequent address.
77
+ */
78
+ for (i = 0; i < vl; ++i) {
79
+ uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
80
+ for (j = 0; j < vq * 2; ++j) {
81
+ __put_user_e(env->zarray[i].d[j], z + j, le);
82
+ }
156
+ }
83
+ }
157
+}
84
+}
158
+
85
+
159
+static void split_irq_init(Object *obj)
86
static void target_restore_general_frame(CPUARMState *env,
87
struct target_rt_sigframe *sf)
88
{
89
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
90
91
static bool target_restore_sve_record(CPUARMState *env,
92
struct target_sve_context *sve,
93
- int size)
94
+ int size, int *svcr)
95
{
96
- int i, j, vl, vq;
97
+ int i, j, vl, vq, flags;
98
+ bool sm;
99
100
- if (!cpu_isar_feature(aa64_sve, env_archcpu(env))) {
101
+ __get_user(vl, &sve->vl);
102
+ __get_user(flags, &sve->flags);
103
+
104
+ sm = flags & TARGET_SVE_SIG_FLAG_SM;
105
+
106
+ /* The cpu must support Streaming or Non-streaming SVE. */
107
+ if (sm
108
+ ? !cpu_isar_feature(aa64_sme, env_archcpu(env))
109
+ : !cpu_isar_feature(aa64_sve, env_archcpu(env))) {
110
return false;
111
}
112
113
- __get_user(vl, &sve->vl);
114
- vq = sve_vq(env);
115
+ /*
116
+ * Note that we cannot use sve_vq() because that depends on the
117
+ * current setting of PSTATE.SM, not the state to be restored.
118
+ */
119
+ vq = sve_vqm1_for_el_sm(env, 0, sm) + 1;
120
121
/* Reject mismatched VL. */
122
if (vl != vq * TARGET_SVE_VQ_BYTES) {
123
@@ -XXX,XX +XXX,XX @@ static bool target_restore_sve_record(CPUARMState *env,
124
return false;
125
}
126
127
+ *svcr = FIELD_DP64(*svcr, SVCR, SM, sm);
128
+
129
/*
130
* Note that SVE regs are stored as a byte stream, with each byte element
131
* at a subsequent address. This corresponds to a little-endian load
132
@@ -XXX,XX +XXX,XX @@ static bool target_restore_sve_record(CPUARMState *env,
133
return true;
134
}
135
136
+static bool target_restore_za_record(CPUARMState *env,
137
+ struct target_za_context *za,
138
+ int size, int *svcr)
160
+{
139
+{
161
+ qdev_init_gpio_in(DEVICE(obj), split_irq_handler, 1);
140
+ int i, j, vl, vq;
141
+
142
+ if (!cpu_isar_feature(aa64_sme, env_archcpu(env))) {
143
+ return false;
144
+ }
145
+
146
+ __get_user(vl, &za->vl);
147
+ vq = sme_vq(env);
148
+
149
+ /* Reject mismatched VL. */
150
+ if (vl != vq * TARGET_SVE_VQ_BYTES) {
151
+ return false;
152
+ }
153
+
154
+ /* Accept empty record -- used to clear PSTATE.ZA. */
155
+ if (size <= TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
156
+ return true;
157
+ }
158
+
159
+ /* Reject non-empty but incomplete record. */
160
+ if (size < TARGET_ZA_SIG_CONTEXT_SIZE(vq)) {
161
+ return false;
162
+ }
163
+
164
+ *svcr = FIELD_DP64(*svcr, SVCR, ZA, 1);
165
+
166
+ for (i = 0; i < vl; ++i) {
167
+ uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
168
+ for (j = 0; j < vq * 2; ++j) {
169
+ __get_user_e(env->zarray[i].d[j], z + j, le);
170
+ }
171
+ }
172
+ return true;
162
+}
173
+}
163
+
174
+
164
+static void split_irq_realize(DeviceState *dev, Error **errp)
175
static int target_restore_sigframe(CPUARMState *env,
165
+{
176
struct target_rt_sigframe *sf)
166
+ SplitIRQ *s = SPLIT_IRQ(dev);
177
{
167
+
178
struct target_aarch64_ctx *ctx, *extra = NULL;
168
+ if (s->num_lines < 1 || s->num_lines >= MAX_SPLIT_LINES) {
179
struct target_fpsimd_context *fpsimd = NULL;
169
+ error_setg(errp,
180
struct target_sve_context *sve = NULL;
170
+ "IRQ splitter number of lines %d is not between 1 and %d",
181
+ struct target_za_context *za = NULL;
171
+ s->num_lines, MAX_SPLIT_LINES);
182
uint64_t extra_datap = 0;
172
+ return;
183
bool used_extra = false;
173
+ }
184
int sve_size = 0;
174
+
185
+ int za_size = 0;
175
+ qdev_init_gpio_out(dev, s->out_irq, s->num_lines);
186
+ int svcr = 0;
176
+}
187
177
+
188
target_restore_general_frame(env, sf);
178
+static Property split_irq_properties[] = {
189
179
+ DEFINE_PROP_UINT16("num-lines", SplitIRQ, num_lines, 1),
190
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
180
+ DEFINE_PROP_END_OF_LIST(),
191
sve_size = size;
181
+};
192
break;
182
+
193
183
+static void split_irq_class_init(ObjectClass *klass, void *data)
194
+ case TARGET_ZA_MAGIC:
184
+{
195
+ if (za || size < sizeof(struct target_za_context)) {
185
+ DeviceClass *dc = DEVICE_CLASS(klass);
196
+ goto err;
186
+
197
+ }
187
+ /* No state to reset or migrate */
198
+ za = (struct target_za_context *)ctx;
188
+ dc->props = split_irq_properties;
199
+ za_size = size;
189
+ dc->realize = split_irq_realize;
200
+ break;
190
+
201
+
191
+ /* Reason: Needs to be wired up to work */
202
case TARGET_EXTRA_MAGIC:
192
+ dc->user_creatable = false;
203
if (extra || size != sizeof(struct target_extra_context)) {
193
+}
204
goto err;
194
+
205
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
195
+static const TypeInfo split_irq_type_info = {
206
}
196
+ .name = TYPE_SPLIT_IRQ,
207
197
+ .parent = TYPE_DEVICE,
208
/* SVE data, if present, overwrites FPSIMD data. */
198
+ .instance_size = sizeof(SplitIRQ),
209
- if (sve && !target_restore_sve_record(env, sve, sve_size)) {
199
+ .instance_init = split_irq_init,
210
+ if (sve && !target_restore_sve_record(env, sve, sve_size, &svcr)) {
200
+ .class_init = split_irq_class_init,
211
goto err;
201
+};
212
}
202
+
213
+ if (za && !target_restore_za_record(env, za, za_size, &svcr)) {
203
+static void split_irq_register_types(void)
214
+ goto err;
204
+{
215
+ }
205
+ type_register_static(&split_irq_type_info);
216
+ if (env->svcr != svcr) {
206
+}
217
+ env->svcr = svcr;
207
+
218
+ arm_rebuild_hflags(env);
208
+type_init(split_irq_register_types)
219
+ }
220
unlock_user(extra, extra_datap, 0);
221
return 0;
222
223
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
224
.total_size = offsetof(struct target_rt_sigframe,
225
uc.tuc_mcontext.__reserved),
226
};
227
- int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
228
+ int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0;
229
+ int sve_size = 0, za_size = 0;
230
struct target_rt_sigframe *frame;
231
struct target_rt_frame_record *fr;
232
abi_ulong frame_addr, return_addr;
233
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
234
&layout);
235
236
/* SVE state needs saving only if it exists. */
237
- if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
238
- vq = sve_vq(env);
239
- sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
240
+ if (cpu_isar_feature(aa64_sve, env_archcpu(env)) ||
241
+ cpu_isar_feature(aa64_sme, env_archcpu(env))) {
242
+ sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(sve_vq(env)), 16);
243
sve_ofs = alloc_sigframe_space(sve_size, &layout);
244
}
245
+ if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
246
+ /* ZA state needs saving only if it is enabled. */
247
+ if (FIELD_EX64(env->svcr, SVCR, ZA)) {
248
+ za_size = TARGET_ZA_SIG_CONTEXT_SIZE(sme_vq(env));
249
+ } else {
250
+ za_size = TARGET_ZA_SIG_CONTEXT_SIZE(0);
251
+ }
252
+ za_ofs = alloc_sigframe_space(za_size, &layout);
253
+ }
254
255
if (layout.extra_ofs) {
256
/* Reserve space for the extra end marker. The standard end marker
257
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
258
target_setup_end_record((void *)frame + layout.extra_end_ofs);
259
}
260
if (sve_ofs) {
261
- target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
262
+ target_setup_sve_record((void *)frame + sve_ofs, env, sve_size);
263
+ }
264
+ if (za_ofs) {
265
+ target_setup_za_record((void *)frame + za_ofs, env, za_size);
266
}
267
268
/* Set up the stack frame for unwinding. */
269
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
270
env->btype = 2;
271
}
272
273
+ /*
274
+ * Invoke the signal handler with both SM and ZA disabled.
275
+ * When clearing SM, ResetSVEState, per SMSTOP.
276
+ */
277
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
278
+ arm_reset_sve_state(env);
279
+ }
280
+ if (env->svcr) {
281
+ env->svcr = 0;
282
+ arm_rebuild_hflags(env);
283
+ }
284
+
285
if (info) {
286
tswap_siginfo(&frame->info, info);
287
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
209
--
288
--
210
2.16.2
289
2.25.1
211
212
diff view generated by jsdifflib
1
Move the definition of the struct for the unimplemented-device
1
From: Richard Henderson <richard.henderson@linaro.org>
2
from unimp.c to unimp.h, so that users can embed the struct
3
in their own device structs if they prefer.
4
2
3
Add "sve" to the sve prctl functions, to distinguish
4
them from the coming "sme" prctls with similar names.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-42-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-10-peter.maydell@linaro.org
9
---
10
---
10
include/hw/misc/unimp.h | 10 ++++++++++
11
linux-user/aarch64/target_prctl.h | 8 ++++----
11
hw/misc/unimp.c | 10 ----------
12
linux-user/syscall.c | 12 ++++++------
12
2 files changed, 10 insertions(+), 10 deletions(-)
13
2 files changed, 10 insertions(+), 10 deletions(-)
13
14
14
diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h
15
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/unimp.h
17
--- a/linux-user/aarch64/target_prctl.h
17
+++ b/include/hw/misc/unimp.h
18
+++ b/linux-user/aarch64/target_prctl.h
18
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
19
20
#ifndef AARCH64_TARGET_PRCTL_H
20
#define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device"
21
#define AARCH64_TARGET_PRCTL_H
21
22
22
+#define UNIMPLEMENTED_DEVICE(obj) \
23
-static abi_long do_prctl_get_vl(CPUArchState *env)
23
+ OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
24
+static abi_long do_prctl_sve_get_vl(CPUArchState *env)
24
+
25
{
25
+typedef struct {
26
ARMCPU *cpu = env_archcpu(env);
26
+ SysBusDevice parent_obj;
27
if (cpu_isar_feature(aa64_sve, cpu)) {
27
+ MemoryRegion iomem;
28
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_get_vl(CPUArchState *env)
28
+ char *name;
29
}
29
+ uint64_t size;
30
return -TARGET_EINVAL;
30
+} UnimplementedDeviceState;
31
}
31
+
32
-#define do_prctl_get_vl do_prctl_get_vl
32
/**
33
+#define do_prctl_sve_get_vl do_prctl_sve_get_vl
33
* create_unimplemented_device: create and map a dummy device
34
34
* @name: name of the device for debug logging
35
-static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
35
diff --git a/hw/misc/unimp.c b/hw/misc/unimp.c
36
+static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
37
{
38
/*
39
* We cannot support either PR_SVE_SET_VL_ONEXEC or PR_SVE_VL_INHERIT.
40
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
41
}
42
return -TARGET_EINVAL;
43
}
44
-#define do_prctl_set_vl do_prctl_set_vl
45
+#define do_prctl_sve_set_vl do_prctl_sve_set_vl
46
47
static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
48
{
49
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
36
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/misc/unimp.c
51
--- a/linux-user/syscall.c
38
+++ b/hw/misc/unimp.c
52
+++ b/linux-user/syscall.c
39
@@ -XXX,XX +XXX,XX @@
53
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
40
#include "qemu/log.h"
54
#ifndef do_prctl_set_fp_mode
41
#include "qapi/error.h"
55
#define do_prctl_set_fp_mode do_prctl_inval1
42
56
#endif
43
-#define UNIMPLEMENTED_DEVICE(obj) \
57
-#ifndef do_prctl_get_vl
44
- OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
58
-#define do_prctl_get_vl do_prctl_inval0
45
-
59
+#ifndef do_prctl_sve_get_vl
46
-typedef struct {
60
+#define do_prctl_sve_get_vl do_prctl_inval0
47
- SysBusDevice parent_obj;
61
#endif
48
- MemoryRegion iomem;
62
-#ifndef do_prctl_set_vl
49
- char *name;
63
-#define do_prctl_set_vl do_prctl_inval1
50
- uint64_t size;
64
+#ifndef do_prctl_sve_set_vl
51
-} UnimplementedDeviceState;
65
+#define do_prctl_sve_set_vl do_prctl_inval1
52
-
66
#endif
53
static uint64_t unimp_read(void *opaque, hwaddr offset, unsigned size)
67
#ifndef do_prctl_reset_keys
54
{
68
#define do_prctl_reset_keys do_prctl_inval1
55
UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque);
69
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
70
case PR_SET_FP_MODE:
71
return do_prctl_set_fp_mode(env, arg2);
72
case PR_SVE_GET_VL:
73
- return do_prctl_get_vl(env);
74
+ return do_prctl_sve_get_vl(env);
75
case PR_SVE_SET_VL:
76
- return do_prctl_set_vl(env, arg2);
77
+ return do_prctl_sve_set_vl(env, arg2);
78
case PR_PAC_RESET_KEYS:
79
if (arg3 || arg4 || arg5) {
80
return -TARGET_EINVAL;
56
--
81
--
57
2.16.2
82
2.25.1
58
59
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Allow the translate subroutines to return false for invalid insns.
3
These prctl set the Streaming SVE vector length, which may
4
be completely different from the Normal SVE vector length.
4
5
5
At present we can of course invoke an invalid insn exception from within
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
the translate subroutine, but in the short term this consolidates code.
7
In the long term it would allow the decodetree language to support
8
overlapping patterns for ISA extensions.
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180227232618.2908-1-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-43-richard.henderson@linaro.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
scripts/decodetree.py | 5 ++---
11
linux-user/aarch64/target_prctl.h | 54 +++++++++++++++++++++++++++++++
16
1 file changed, 2 insertions(+), 3 deletions(-)
12
linux-user/syscall.c | 16 +++++++++
13
2 files changed, 70 insertions(+)
17
14
18
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
15
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
19
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100644
20
--- a/scripts/decodetree.py
17
--- a/linux-user/aarch64/target_prctl.h
21
+++ b/scripts/decodetree.py
18
+++ b/linux-user/aarch64/target_prctl.h
22
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
19
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_get_vl(CPUArchState *env)
23
global translate_prefix
20
{
24
output('typedef ', self.base.base.struct_name(),
21
ARMCPU *cpu = env_archcpu(env);
25
' arg_', self.name, ';\n')
22
if (cpu_isar_feature(aa64_sve, cpu)) {
26
- output(translate_scope, 'void ', translate_prefix, '_', self.name,
23
+ /* PSTATE.SM is always unset on syscall entry. */
27
+ output(translate_scope, 'bool ', translate_prefix, '_', self.name,
24
return sve_vq(env) * 16;
28
'(DisasContext *ctx, arg_', self.name,
25
}
29
' *a, ', insntype, ' insn);\n')
26
return -TARGET_EINVAL;
30
27
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
31
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
28
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
32
output(ind, self.base.extract_name(), '(&u.f_', arg, ', insn);\n')
29
uint32_t vq, old_vq;
33
for n, f in self.fields.items():
30
34
output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n')
31
+ /* PSTATE.SM is always unset on syscall entry. */
35
- output(ind, translate_prefix, '_', self.name,
32
old_vq = sve_vq(env);
36
+ output(ind, 'return ', translate_prefix, '_', self.name,
33
37
'(ctx, &u.f_', arg, ', insn);\n')
34
/*
38
- output(ind, 'return true;\n')
35
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
39
# end Pattern
36
}
40
37
#define do_prctl_sve_set_vl do_prctl_sve_set_vl
41
38
39
+static abi_long do_prctl_sme_get_vl(CPUArchState *env)
40
+{
41
+ ARMCPU *cpu = env_archcpu(env);
42
+ if (cpu_isar_feature(aa64_sme, cpu)) {
43
+ return sme_vq(env) * 16;
44
+ }
45
+ return -TARGET_EINVAL;
46
+}
47
+#define do_prctl_sme_get_vl do_prctl_sme_get_vl
48
+
49
+static abi_long do_prctl_sme_set_vl(CPUArchState *env, abi_long arg2)
50
+{
51
+ /*
52
+ * We cannot support either PR_SME_SET_VL_ONEXEC or PR_SME_VL_INHERIT.
53
+ * Note the kernel definition of sve_vl_valid allows for VQ=512,
54
+ * i.e. VL=8192, even though the architectural maximum is VQ=16.
55
+ */
56
+ if (cpu_isar_feature(aa64_sme, env_archcpu(env))
57
+ && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
58
+ int vq, old_vq;
59
+
60
+ old_vq = sme_vq(env);
61
+
62
+ /*
63
+ * Bound the value of vq, so that we know that it fits into
64
+ * the 4-bit field in SMCR_EL1. Because PSTATE.SM is cleared
65
+ * on syscall entry, we are not modifying the current SVE
66
+ * vector length.
67
+ */
68
+ vq = MAX(arg2 / 16, 1);
69
+ vq = MIN(vq, 16);
70
+ env->vfp.smcr_el[1] =
71
+ FIELD_DP64(env->vfp.smcr_el[1], SMCR, LEN, vq - 1);
72
+
73
+ /* Delay rebuilding hflags until we know if ZA must change. */
74
+ vq = sve_vqm1_for_el_sm(env, 0, true) + 1;
75
+
76
+ if (vq != old_vq) {
77
+ /*
78
+ * PSTATE.ZA state is cleared on any change to SVL.
79
+ * We need not call arm_rebuild_hflags because PSTATE.SM was
80
+ * cleared on syscall entry, so this hasn't changed VL.
81
+ */
82
+ env->svcr = FIELD_DP64(env->svcr, SVCR, ZA, 0);
83
+ arm_rebuild_hflags(env);
84
+ }
85
+ return vq * 16;
86
+ }
87
+ return -TARGET_EINVAL;
88
+}
89
+#define do_prctl_sme_set_vl do_prctl_sme_set_vl
90
+
91
static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
92
{
93
ARMCPU *cpu = env_archcpu(env);
94
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/linux-user/syscall.c
97
+++ b/linux-user/syscall.c
98
@@ -XXX,XX +XXX,XX @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
99
#ifndef PR_SET_SYSCALL_USER_DISPATCH
100
# define PR_SET_SYSCALL_USER_DISPATCH 59
101
#endif
102
+#ifndef PR_SME_SET_VL
103
+# define PR_SME_SET_VL 63
104
+# define PR_SME_GET_VL 64
105
+# define PR_SME_VL_LEN_MASK 0xffff
106
+# define PR_SME_VL_INHERIT (1 << 17)
107
+#endif
108
109
#include "target_prctl.h"
110
111
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
112
#ifndef do_prctl_set_unalign
113
#define do_prctl_set_unalign do_prctl_inval1
114
#endif
115
+#ifndef do_prctl_sme_get_vl
116
+#define do_prctl_sme_get_vl do_prctl_inval0
117
+#endif
118
+#ifndef do_prctl_sme_set_vl
119
+#define do_prctl_sme_set_vl do_prctl_inval1
120
+#endif
121
122
static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
123
abi_long arg3, abi_long arg4, abi_long arg5)
124
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
125
return do_prctl_sve_get_vl(env);
126
case PR_SVE_SET_VL:
127
return do_prctl_sve_set_vl(env, arg2);
128
+ case PR_SME_GET_VL:
129
+ return do_prctl_sme_get_vl(env);
130
+ case PR_SME_SET_VL:
131
+ return do_prctl_sme_set_vl(env, arg2);
132
case PR_PAC_RESET_KEYS:
133
if (arg3 || arg4 || arg5) {
134
return -TARGET_EINVAL;
42
--
135
--
43
2.16.2
136
2.25.1
44
45
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
There's no reason to set CPACR_EL1.ZEN if SVE disabled.
4
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220708151540.18136-44-richard.henderson@linaro.org
7
Message-id: 20180228193125.20577-10-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/cpu.c | 1 +
10
target/arm/cpu.c | 7 +++----
11
target/arm/cpu64.c | 1 +
11
1 file changed, 3 insertions(+), 4 deletions(-)
12
2 files changed, 2 insertions(+)
13
12
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
15
--- a/target/arm/cpu.c
17
+++ b/target/arm/cpu.c
16
+++ b/target/arm/cpu.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
19
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
18
/* and to the FP/Neon instructions */
20
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
19
env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
21
set_feature(&cpu->env, ARM_FEATURE_CRC);
20
CPACR_EL1, FPEN, 3);
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
21
- /* and to the SVE instructions */
23
cpu->midr = 0xffffffff;
22
- env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
24
}
23
- CPACR_EL1, ZEN, 3);
25
#endif
24
- /* with reasonable vector length */
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
25
+ /* and to the SVE instructions, with default vector length */
27
index XXXXXXX..XXXXXXX 100644
26
if (cpu_isar_feature(aa64_sve, cpu)) {
28
--- a/target/arm/cpu64.c
27
+ env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
29
+++ b/target/arm/cpu64.c
28
+ CPACR_EL1, ZEN, 3);
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
29
env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
31
set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
30
}
32
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
31
/*
33
set_feature(&cpu->env, ARM_FEATURE_CRC);
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
35
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
36
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
37
cpu->dcz_blocksize = 7; /* 512 bytes */
38
--
32
--
39
2.16.2
33
2.25.1
40
41
diff view generated by jsdifflib
1
Add a Cortex-M33 definition. The M33 is an M profile CPU
1
From: Richard Henderson <richard.henderson@linaro.org>
2
which implements the ARM v8M architecture, including the
3
M profile Security Extension.
4
2
3
Enable SME, TPIDR2_EL0, and FA64 if supported by the cpu.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220708151540.18136-45-richard.henderson@linaro.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: 20180220180325.29818-9-peter.maydell@linaro.org
8
---
9
---
9
target/arm/cpu.c | 31 +++++++++++++++++++++++++++++++
10
target/arm/cpu.c | 11 +++++++++++
10
1 file changed, 31 insertions(+)
11
1 file changed, 11 insertions(+)
11
12
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
17
cpu->id_isar5 = 0x00000000;
18
CPACR_EL1, ZEN, 3);
18
}
19
env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
19
20
}
20
+static void cortex_m33_initfn(Object *obj)
21
+ /* and for SME instructions, with default vector length, and TPIDR2 */
21
+{
22
+ if (cpu_isar_feature(aa64_sme, cpu)) {
22
+ ARMCPU *cpu = ARM_CPU(obj);
23
+ env->cp15.sctlr_el[1] |= SCTLR_EnTP2;
23
+
24
+ env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
24
+ set_feature(&cpu->env, ARM_FEATURE_V8);
25
+ CPACR_EL1, SMEN, 3);
25
+ set_feature(&cpu->env, ARM_FEATURE_M);
26
+ env->vfp.smcr_el[1] = cpu->sme_default_vq - 1;
26
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
27
+ if (cpu_isar_feature(aa64_sme_fa64, cpu)) {
27
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
28
+ env->vfp.smcr_el[1] = FIELD_DP64(env->vfp.smcr_el[1],
28
+ cpu->midr = 0x410fd213; /* r0p3 */
29
+ SMCR, FA64, 1);
29
+ cpu->pmsav7_dregion = 16;
30
+ }
30
+ cpu->sau_sregion = 8;
31
+ }
31
+ cpu->id_pfr0 = 0x00000030;
32
/*
32
+ cpu->id_pfr1 = 0x00000210;
33
* Enable 48-bit address space (TODO: take reserved_va into account).
33
+ cpu->id_dfr0 = 0x00200000;
34
* Enable TBI0 but not TBI1.
34
+ cpu->id_afr0 = 0x00000000;
35
+ cpu->id_mmfr0 = 0x00101F40;
36
+ cpu->id_mmfr1 = 0x00000000;
37
+ cpu->id_mmfr2 = 0x01000000;
38
+ cpu->id_mmfr3 = 0x00000000;
39
+ cpu->id_isar0 = 0x01101110;
40
+ cpu->id_isar1 = 0x02212000;
41
+ cpu->id_isar2 = 0x20232232;
42
+ cpu->id_isar3 = 0x01111131;
43
+ cpu->id_isar4 = 0x01310132;
44
+ cpu->id_isar5 = 0x00000000;
45
+ cpu->clidr = 0x00000000;
46
+ cpu->ctr = 0x8000c000;
47
+}
48
+
49
static void arm_v7m_class_init(ObjectClass *oc, void *data)
50
{
51
CPUClass *cc = CPU_CLASS(oc);
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
53
.class_init = arm_v7m_class_init },
54
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
55
.class_init = arm_v7m_class_init },
56
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
57
+ .class_init = arm_v7m_class_init },
58
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
59
{ .name = "cortex-a7", .initfn = cortex_a7_initfn },
60
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
61
--
35
--
62
2.16.2
36
2.25.1
63
64
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not enabled anywhere yet.
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180228193125.20577-2-richard.henderson@linaro.org
5
Message-id: 20220708151540.18136-46-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
7
---
11
target/arm/cpu.h | 1 +
8
linux-user/elfload.c | 20 ++++++++++++++++++++
12
linux-user/elfload.c | 1 +
9
1 file changed, 20 insertions(+)
13
2 files changed, 2 insertions(+)
14
10
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ enum arm_features {
20
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
21
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
22
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
23
+ ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
24
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
25
};
26
27
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
11
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
28
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
29
--- a/linux-user/elfload.c
13
--- a/linux-user/elfload.c
30
+++ b/linux-user/elfload.c
14
+++ b/linux-user/elfload.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
15
@@ -XXX,XX +XXX,XX @@ enum {
32
GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
16
ARM_HWCAP2_A64_RNG = 1 << 16,
33
GET_FEATURE(ARM_FEATURE_V8_FP16,
17
ARM_HWCAP2_A64_BTI = 1 << 17,
34
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
18
ARM_HWCAP2_A64_MTE = 1 << 18,
35
+ GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
19
+ ARM_HWCAP2_A64_ECV = 1 << 19,
36
#undef GET_FEATURE
20
+ ARM_HWCAP2_A64_AFP = 1 << 20,
21
+ ARM_HWCAP2_A64_RPRES = 1 << 21,
22
+ ARM_HWCAP2_A64_MTE3 = 1 << 22,
23
+ ARM_HWCAP2_A64_SME = 1 << 23,
24
+ ARM_HWCAP2_A64_SME_I16I64 = 1 << 24,
25
+ ARM_HWCAP2_A64_SME_F64F64 = 1 << 25,
26
+ ARM_HWCAP2_A64_SME_I8I32 = 1 << 26,
27
+ ARM_HWCAP2_A64_SME_F16F32 = 1 << 27,
28
+ ARM_HWCAP2_A64_SME_B16F32 = 1 << 28,
29
+ ARM_HWCAP2_A64_SME_F32F32 = 1 << 29,
30
+ ARM_HWCAP2_A64_SME_FA64 = 1 << 30,
31
};
32
33
#define ELF_HWCAP get_elf_hwcap()
34
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap2(void)
35
GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
36
GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
37
GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
38
+ GET_FEATURE_ID(aa64_sme, (ARM_HWCAP2_A64_SME |
39
+ ARM_HWCAP2_A64_SME_F32F32 |
40
+ ARM_HWCAP2_A64_SME_B16F32 |
41
+ ARM_HWCAP2_A64_SME_F16F32 |
42
+ ARM_HWCAP2_A64_SME_I8I32));
43
+ GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64);
44
+ GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64);
45
+ GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64);
37
46
38
return hwcaps;
47
return hwcaps;
48
}
39
--
49
--
40
2.16.2
50
2.25.1
41
42
diff view generated by jsdifflib