1
Mostly this is patches from me and RTH cleaning up and doing
1
The following changes since commit 55ef0b702bc2c90c3c4ed97f97676d8f139e5ca1:
2
more decodetree conversion for AArch32 Neon. The major new feature
3
is Dongjiu Geng's patchset to report host memory errors to KVM guests;
4
also a new aspeed board from Patrick Williams.
5
2
6
thanks
3
Merge remote-tracking branch 'remotes/lvivier-gitlab/tags/linux-user-for-7.0-pull-request' into staging (2022-02-07 10:48:25 +0000)
7
-- PMM
8
9
The following changes since commit 035b448b84f3557206abc44d786c5d3db2638f7d:
10
11
Merge remote-tracking branch 'remotes/gkurz/tags/9p-next-2020-05-14' into staging (2020-05-14 10:58:30 +0100)
12
4
13
are available in the Git repository at:
5
are available in the Git repository at:
14
6
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200514
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220208
16
8
17
for you to fetch changes up to e95485f85657be21135c17a9226e297c21e73360:
9
for you to fetch changes up to 4fd1ebb10593087d45d2f56f7f3d13447d24802c:
18
10
19
target/arm: Convert NEON VFMA, VFMS 3-reg-same insns to decodetree (2020-05-14 15:03:09 +0100)
11
hw/sensor: Add lsm303dlhc magnetometer device (2022-02-08 10:56:29 +0000)
20
12
21
----------------------------------------------------------------
13
----------------------------------------------------------------
22
target-arm queue:
14
target-arm queue:
23
* target/arm: Use correct GDB XML for M-profile cores
15
* Fix handling of SVE ZCR_LEN when using VHE
24
* target/arm: Code cleanup to use gvec APIs better
16
* xlnx-zynqmp: 'Or' the QSPI / QSPI DMA IRQs
25
* aspeed: Add support for the sonorapass-bmc board
17
* Don't ever enable PSCI when booting guest in EL3
26
* target/arm: Support reporting KVM host memory errors
18
* Adhere to SMCCC 1.3 section 5.2
27
to the guest via ACPI notifications
19
* highbank: Fix issues with booting SMP
28
* target/arm: Finish conversion of Neon 3-reg-same insns to decodetree
20
* midway: Fix issues booting at all
21
* boot: Drop existing dtb /psci node rather than retaining it
22
* versal-virt: Always call arm_load_kernel()
23
* force flag recalculation when messing with DAIF
24
* hw/timer/armv7m_systick: Update clock source before enabling timer
25
* hw/arm/smmuv3: Fix device reset
26
* hw/intc/arm_gicv3_its: refactorings and minor bug fixes
27
* hw/sensor: Add lsm303dlhc magnetometer device
29
28
30
----------------------------------------------------------------
29
----------------------------------------------------------------
31
Dongjiu Geng (10):
30
Alex Bennée (1):
32
acpi: nvdimm: change NVDIMM_UUID_LE to a common macro
31
arm: force flag recalculation when messing with DAIF
33
hw/arm/virt: Introduce a RAS machine option
34
docs: APEI GHES generation and CPER record description
35
ACPI: Build related register address fields via hardware error fw_cfg blob
36
ACPI: Build Hardware Error Source Table
37
ACPI: Record the Generic Error Status Block address
38
KVM: Move hwpoison page related functions into kvm-all.c
39
ACPI: Record Generic Error Status Block(GESB) table
40
target-arm: kvm64: handle SIGBUS signal from kernel or KVM
41
MAINTAINERS: Add ACPI/HEST/GHES entries
42
32
43
Patrick Williams (1):
33
Edgar E. Iglesias (1):
44
aspeed: Add support for the sonorapass-bmc board
34
hw/arm: versal-virt: Always call arm_load_kernel()
45
35
46
Peter Maydell (18):
36
Eric Auger (1):
47
target/arm: Use correct GDB XML for M-profile cores
37
hw/arm/smmuv3: Fix device reset
48
target/arm: Convert Neon 3-reg-same VQRDMLAH/VQRDMLSH to decodetree
49
target/arm: Convert Neon 3-reg-same SHA to decodetree
50
target/arm: Convert Neon 64-bit element 3-reg-same insns
51
target/arm: Convert Neon VHADD 3-reg-same insns
52
target/arm: Convert Neon VABA/VABD 3-reg-same to decodetree
53
target/arm: Convert Neon VRHADD, VHSUB 3-reg-same insns to decodetree
54
target/arm: Convert Neon VQSHL, VRSHL, VQRSHL 3-reg-same insns to decodetree
55
target/arm: Convert Neon VPMAX/VPMIN 3-reg-same insns to decodetree
56
target/arm: Convert Neon VPADD 3-reg-same insns to decodetree
57
target/arm: Convert Neon VQDMULH/VQRDMULH 3-reg-same to decodetree
58
target/arm: Convert Neon VADD, VSUB, VABD 3-reg-same insns to decodetree
59
target/arm: Convert Neon VPMIN/VPMAX/VPADD float 3-reg-same insns to decodetree
60
target/arm: Convert Neon fp VMUL, VMLA, VMLS 3-reg-same insns to decodetree
61
target/arm: Convert Neon 3-reg-same compare insns to decodetree
62
target/arm: Move 'env' argument of recps_f32 and rsqrts_f32 helpers to usual place
63
target/arm: Convert Neon fp VMAX/VMIN/VMAXNM/VMINNM/VRECPS/VRSQRTS to decodetree
64
target/arm: Convert NEON VFMA, VFMS 3-reg-same insns to decodetree
65
38
66
Richard Henderson (16):
39
Francisco Iglesias (1):
67
target/arm: Create gen_gvec_[us]sra
40
hw/arm/xlnx-zynqmp: 'Or' the QSPI / QSPI DMA IRQs
68
target/arm: Create gen_gvec_{u,s}{rshr,rsra}
69
target/arm: Create gen_gvec_{sri,sli}
70
target/arm: Remove unnecessary range check for VSHL
71
target/arm: Tidy handle_vec_simd_shri
72
target/arm: Create gen_gvec_{ceq,clt,cle,cgt,cge}0
73
target/arm: Create gen_gvec_{mla,mls}
74
target/arm: Swap argument order for VSHL during decode
75
target/arm: Create gen_gvec_{cmtst,ushl,sshl}
76
target/arm: Create gen_gvec_{uqadd, sqadd, uqsub, sqsub}
77
target/arm: Remove fp_status from helper_{recpe, rsqrte}_u32
78
target/arm: Create gen_gvec_{qrdmla,qrdmls}
79
target/arm: Pass pointer to qc to qrdmla/qrdmls
80
target/arm: Clear tail in gvec_fmul_idx_*, gvec_fmla_idx_*
81
target/arm: Vectorize SABD/UABD
82
target/arm: Vectorize SABA/UABA
83
41
84
docs/specs/acpi_hest_ghes.rst | 110 ++
42
Kevin Townsend (1):
85
docs/specs/index.rst | 1 +
43
hw/sensor: Add lsm303dlhc magnetometer device
86
configure | 4 +-
87
default-configs/arm-softmmu.mak | 1 +
88
include/hw/acpi/aml-build.h | 1 +
89
include/hw/acpi/generic_event_device.h | 2 +
90
include/hw/acpi/ghes.h | 74 +
91
include/hw/arm/virt.h | 1 +
92
include/qemu/uuid.h | 27 +
93
include/sysemu/kvm.h | 3 +-
94
include/sysemu/kvm_int.h | 12 +
95
target/arm/cpu.h | 4 +
96
target/arm/helper.h | 78 +-
97
target/arm/internals.h | 5 +-
98
target/arm/translate.h | 84 +-
99
target/i386/cpu.h | 2 +
100
target/arm/neon-dp.decode | 119 +-
101
accel/kvm/kvm-all.c | 36 +
102
hw/acpi/aml-build.c | 2 +
103
hw/acpi/generic_event_device.c | 19 +
104
hw/acpi/ghes.c | 448 ++++++
105
hw/acpi/nvdimm.c | 10 +-
106
hw/arm/aspeed.c | 78 ++
107
hw/arm/virt-acpi-build.c | 15 +
108
hw/arm/virt.c | 23 +
109
target/arm/cpu_tcg.c | 1 +
110
target/arm/gdbstub.c | 22 +-
111
target/arm/helper.c | 2 +-
112
target/arm/kvm64.c | 77 ++
113
target/arm/neon_helper.c | 17 -
114
target/arm/tlb_helper.c | 2 +-
115
target/arm/translate-a64.c | 210 +--
116
target/arm/translate-neon.inc.c | 682 +++++++++-
117
target/arm/translate.c | 2349 +++++++++++++++++---------------
118
target/arm/vec_helper.c | 240 +++-
119
target/arm/vfp_helper.c | 9 +-
120
target/i386/kvm.c | 36 -
121
MAINTAINERS | 9 +
122
gdb-xml/arm-m-profile.xml | 27 +
123
hw/acpi/Kconfig | 4 +
124
hw/acpi/Makefile.objs | 1 +
125
41 files changed, 3402 insertions(+), 1445 deletions(-)
126
create mode 100644 docs/specs/acpi_hest_ghes.rst
127
create mode 100644 include/hw/acpi/ghes.h
128
create mode 100644 hw/acpi/ghes.c
129
create mode 100644 gdb-xml/arm-m-profile.xml
130
44
45
Peter Maydell (29):
46
target/arm: make psci-conduit settable after realize
47
cpu.c: Make start-powered-off settable after realize
48
hw/arm/boot: Support setting psci-conduit based on guest EL
49
hw/arm: imx: Don't enable PSCI conduit when booting guest in EL3
50
hw/arm: allwinner: Don't enable PSCI conduit when booting guest in EL3
51
hw/arm/xlnx-zcu102: Don't enable PSCI conduit when booting guest in EL3
52
hw/arm/versal: Let boot.c handle PSCI enablement
53
hw/arm/virt: Let boot.c handle PSCI enablement
54
hw/arm: highbank: For EL3 guests, don't enable PSCI, start all cores
55
arm: tcg: Adhere to SMCCC 1.3 section 5.2
56
hw/arm/highbank: Drop use of secure_board_setup
57
hw/arm/boot: Prevent setting both psci_conduit and secure_board_setup
58
hw/arm/boot: Don't write secondary boot stub if using PSCI
59
hw/arm/highbank: Drop unused secondary boot stub code
60
hw/arm/boot: Drop nb_cpus field from arm_boot_info
61
hw/arm/boot: Drop existing dtb /psci node rather than retaining it
62
hw/intc/arm_gicv3_its: Use address_space_map() to access command queue packets
63
hw/intc/arm_gicv3_its: Keep DTEs as a struct, not a raw uint64_t
64
hw/intc/arm_gicv3_its: Pass DTEntry to update_dte()
65
hw/intc/arm_gicv3_its: Keep CTEs as a struct, not a raw uint64_t
66
hw/intc/arm_gicv3_its: Pass CTEntry to update_cte()
67
hw/intc/arm_gicv3_its: Fix address calculation in get_ite() and update_ite()
68
hw/intc/arm_gicv3_its: Avoid nested ifs in get_ite()
69
hw/intc/arm_gicv3_its: Pass ITE values back from get_ite() via a struct
70
hw/intc/arm_gicv3_its: Make update_ite() use ITEntry
71
hw/intc/arm_gicv3_its: Drop TableDesc and CmdQDesc valid fields
72
hw/intc/arm_gicv3_its: In MAPC with V=0, don't check rdbase field
73
hw/intc/arm_gicv3_its: Don't allow intid 1023 in MAPI/MAPTI
74
hw/intc/arm_gicv3_its: Split error checks
75
76
Richard Henderson (4):
77
target/arm: Fix sve_zcr_len_for_el for VHE mode running
78
target/arm: Tidy sve_exception_el for CPACR_EL1 access
79
target/arm: Fix {fp, sve}_exception_el for VHE mode running
80
target/arm: Use CPTR_TFP with CPTR_EL3 in fp_exception_el
81
82
Richard Petri (1):
83
hw/timer/armv7m_systick: Update clock source before enabling timer
84
85
hw/intc/gicv3_internal.h | 23 +-
86
include/hw/arm/boot.h | 14 +-
87
include/hw/arm/xlnx-versal.h | 1 -
88
include/hw/arm/xlnx-zynqmp.h | 2 +
89
include/hw/intc/arm_gicv3_its_common.h | 2 -
90
cpu.c | 22 +-
91
hw/arm/allwinner-h3.c | 9 +-
92
hw/arm/aspeed.c | 1 -
93
hw/arm/boot.c | 107 ++++-
94
hw/arm/exynos4_boards.c | 1 -
95
hw/arm/fsl-imx6ul.c | 2 -
96
hw/arm/fsl-imx7.c | 8 +-
97
hw/arm/highbank.c | 72 +---
98
hw/arm/imx25_pdk.c | 3 +-
99
hw/arm/kzm.c | 1 -
100
hw/arm/mcimx6ul-evk.c | 2 +-
101
hw/arm/mcimx7d-sabre.c | 2 +-
102
hw/arm/npcm7xx.c | 3 -
103
hw/arm/orangepi.c | 5 +-
104
hw/arm/raspi.c | 1 -
105
hw/arm/realview.c | 1 -
106
hw/arm/sabrelite.c | 1 -
107
hw/arm/sbsa-ref.c | 1 -
108
hw/arm/smmuv3.c | 6 +
109
hw/arm/vexpress.c | 1 -
110
hw/arm/virt.c | 13 +-
111
hw/arm/xilinx_zynq.c | 1 -
112
hw/arm/xlnx-versal-virt.c | 17 +-
113
hw/arm/xlnx-versal.c | 5 +-
114
hw/arm/xlnx-zcu102.c | 1 +
115
hw/arm/xlnx-zynqmp.c | 25 +-
116
hw/intc/arm_gicv3_its.c | 696 +++++++++++++++------------------
117
hw/sensor/lsm303dlhc_mag.c | 556 ++++++++++++++++++++++++++
118
hw/timer/armv7m_systick.c | 8 +-
119
target/arm/cpu.c | 6 +-
120
target/arm/helper-a64.c | 2 +
121
target/arm/helper.c | 118 ++++--
122
target/arm/psci.c | 35 +-
123
tests/qtest/lsm303dlhc-mag-test.c | 148 +++++++
124
hw/sensor/Kconfig | 4 +
125
hw/sensor/meson.build | 1 +
126
tests/qtest/meson.build | 1 +
127
42 files changed, 1308 insertions(+), 620 deletions(-)
128
create mode 100644 hw/sensor/lsm303dlhc_mag.c
129
create mode 100644 tests/qtest/lsm303dlhc-mag-test.c
130
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 64-bit element size in preparation for SVE2.
3
When HCR_EL2.{E2H,TGE} == '11', ZCR_EL1 is unused.
4
4
5
Reported-by: Zenghui Yu <yuzenghui@huawei.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
7
Message-id: 20200513163245.17915-17-richard.henderson@linaro.org
9
Message-id: 20220127063428.30212-2-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/helper.h | 17 +++--
12
target/arm/helper.c | 3 ++-
11
target/arm/translate.h | 5 ++
13
1 file changed, 2 insertions(+), 1 deletion(-)
12
target/arm/neon_helper.c | 10 ---
13
target/arm/translate-a64.c | 17 ++---
14
target/arm/translate.c | 134 +++++++++++++++++++++++++++++++++++--
15
target/arm/vec_helper.c | 24 +++++++
16
6 files changed, 174 insertions(+), 33 deletions(-)
17
14
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
17
--- a/target/arm/helper.c
21
+++ b/target/arm/helper.h
18
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(neon_pmax_s8, i32, i32, i32)
19
@@ -XXX,XX +XXX,XX @@ uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
23
DEF_HELPER_2(neon_pmax_u16, i32, i32, i32)
20
ARMCPU *cpu = env_archcpu(env);
24
DEF_HELPER_2(neon_pmax_s16, i32, i32, i32)
21
uint32_t zcr_len = cpu->sve_max_vq - 1;
25
22
26
-DEF_HELPER_2(neon_abd_u8, i32, i32, i32)
23
- if (el <= 1) {
27
-DEF_HELPER_2(neon_abd_s8, i32, i32, i32)
24
+ if (el <= 1 &&
28
-DEF_HELPER_2(neon_abd_u16, i32, i32, i32)
25
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
29
-DEF_HELPER_2(neon_abd_s16, i32, i32, i32)
26
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
30
-DEF_HELPER_2(neon_abd_u32, i32, i32, i32)
27
}
31
-DEF_HELPER_2(neon_abd_s32, i32, i32, i32)
28
if (el <= 2 && arm_feature(env, ARM_FEATURE_EL2)) {
32
-
33
DEF_HELPER_2(neon_shl_u16, i32, i32, i32)
34
DEF_HELPER_2(neon_shl_s16, i32, i32, i32)
35
DEF_HELPER_2(neon_rshl_u8, i32, i32, i32)
36
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_uabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
40
+DEF_HELPER_FLAGS_4(gvec_saba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
41
+DEF_HELPER_FLAGS_4(gvec_saba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
42
+DEF_HELPER_FLAGS_4(gvec_saba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
43
+DEF_HELPER_FLAGS_4(gvec_saba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
44
+
45
+DEF_HELPER_FLAGS_4(gvec_uaba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
46
+DEF_HELPER_FLAGS_4(gvec_uaba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
47
+DEF_HELPER_FLAGS_4(gvec_uaba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
48
+DEF_HELPER_FLAGS_4(gvec_uaba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
49
+
50
#ifdef TARGET_AARCH64
51
#include "helper-a64.h"
52
#include "helper-sve.h"
53
diff --git a/target/arm/translate.h b/target/arm/translate.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/translate.h
56
+++ b/target/arm/translate.h
57
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
58
void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
59
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
60
61
+void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
62
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
63
+void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
64
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
65
+
66
/*
67
* Forward to the isar_feature_* tests given a DisasContext pointer.
68
*/
69
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/neon_helper.c
72
+++ b/target/arm/neon_helper.c
73
@@ -XXX,XX +XXX,XX @@ NEON_POP(pmax_s16, neon_s16, 2)
74
NEON_POP(pmax_u16, neon_u16, 2)
75
#undef NEON_FN
76
77
-#define NEON_FN(dest, src1, src2) \
78
- dest = (src1 > src2) ? (src1 - src2) : (src2 - src1)
79
-NEON_VOP(abd_s8, neon_s8, 4)
80
-NEON_VOP(abd_u8, neon_u8, 4)
81
-NEON_VOP(abd_s16, neon_s16, 2)
82
-NEON_VOP(abd_u16, neon_u16, 2)
83
-NEON_VOP(abd_s32, neon_s32, 1)
84
-NEON_VOP(abd_u32, neon_u32, 1)
85
-#undef NEON_FN
86
-
87
#define NEON_FN(dest, src1, src2) do { \
88
int8_t tmp; \
89
tmp = (int8_t)src2; \
90
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/translate-a64.c
93
+++ b/target/arm/translate-a64.c
94
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
95
gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size);
96
}
97
return;
98
+ case 0xf: /* SABA, UABA */
99
+ if (u) {
100
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uaba, size);
101
+ } else {
102
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_saba, size);
103
+ }
104
+ return;
105
case 0x10: /* ADD, SUB */
106
if (u) {
107
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
108
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
109
genenvfn = fns[size][u];
110
break;
111
}
112
- case 0xf: /* SABA, UABA */
113
- {
114
- static NeonGenTwoOpFn * const fns[3][2] = {
115
- { gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 },
116
- { gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 },
117
- { gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 },
118
- };
119
- genfn = fns[size][u];
120
- break;
121
- }
122
case 0x16: /* SQDMULH, SQRDMULH */
123
{
124
static NeonGenTwoOpEnvFn * const fns[2][2] = {
125
diff --git a/target/arm/translate.c b/target/arm/translate.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/translate.c
128
+++ b/target/arm/translate.c
129
@@ -XXX,XX +XXX,XX @@ void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
130
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
131
}
132
133
+static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
134
+{
135
+ TCGv_i32 t = tcg_temp_new_i32();
136
+ gen_sabd_i32(t, a, b);
137
+ tcg_gen_add_i32(d, d, t);
138
+ tcg_temp_free_i32(t);
139
+}
140
+
141
+static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
142
+{
143
+ TCGv_i64 t = tcg_temp_new_i64();
144
+ gen_sabd_i64(t, a, b);
145
+ tcg_gen_add_i64(d, d, t);
146
+ tcg_temp_free_i64(t);
147
+}
148
+
149
+static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
150
+{
151
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
152
+ gen_sabd_vec(vece, t, a, b);
153
+ tcg_gen_add_vec(vece, d, d, t);
154
+ tcg_temp_free_vec(t);
155
+}
156
+
157
+void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
158
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
159
+{
160
+ static const TCGOpcode vecop_list[] = {
161
+ INDEX_op_sub_vec, INDEX_op_add_vec,
162
+ INDEX_op_smin_vec, INDEX_op_smax_vec, 0
163
+ };
164
+ static const GVecGen3 ops[4] = {
165
+ { .fniv = gen_saba_vec,
166
+ .fno = gen_helper_gvec_saba_b,
167
+ .opt_opc = vecop_list,
168
+ .load_dest = true,
169
+ .vece = MO_8 },
170
+ { .fniv = gen_saba_vec,
171
+ .fno = gen_helper_gvec_saba_h,
172
+ .opt_opc = vecop_list,
173
+ .load_dest = true,
174
+ .vece = MO_16 },
175
+ { .fni4 = gen_saba_i32,
176
+ .fniv = gen_saba_vec,
177
+ .fno = gen_helper_gvec_saba_s,
178
+ .opt_opc = vecop_list,
179
+ .load_dest = true,
180
+ .vece = MO_32 },
181
+ { .fni8 = gen_saba_i64,
182
+ .fniv = gen_saba_vec,
183
+ .fno = gen_helper_gvec_saba_d,
184
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
185
+ .opt_opc = vecop_list,
186
+ .load_dest = true,
187
+ .vece = MO_64 },
188
+ };
189
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
190
+}
191
+
192
+static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
193
+{
194
+ TCGv_i32 t = tcg_temp_new_i32();
195
+ gen_uabd_i32(t, a, b);
196
+ tcg_gen_add_i32(d, d, t);
197
+ tcg_temp_free_i32(t);
198
+}
199
+
200
+static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
201
+{
202
+ TCGv_i64 t = tcg_temp_new_i64();
203
+ gen_uabd_i64(t, a, b);
204
+ tcg_gen_add_i64(d, d, t);
205
+ tcg_temp_free_i64(t);
206
+}
207
+
208
+static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
209
+{
210
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
211
+ gen_uabd_vec(vece, t, a, b);
212
+ tcg_gen_add_vec(vece, d, d, t);
213
+ tcg_temp_free_vec(t);
214
+}
215
+
216
+void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
217
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
218
+{
219
+ static const TCGOpcode vecop_list[] = {
220
+ INDEX_op_sub_vec, INDEX_op_add_vec,
221
+ INDEX_op_umin_vec, INDEX_op_umax_vec, 0
222
+ };
223
+ static const GVecGen3 ops[4] = {
224
+ { .fniv = gen_uaba_vec,
225
+ .fno = gen_helper_gvec_uaba_b,
226
+ .opt_opc = vecop_list,
227
+ .load_dest = true,
228
+ .vece = MO_8 },
229
+ { .fniv = gen_uaba_vec,
230
+ .fno = gen_helper_gvec_uaba_h,
231
+ .opt_opc = vecop_list,
232
+ .load_dest = true,
233
+ .vece = MO_16 },
234
+ { .fni4 = gen_uaba_i32,
235
+ .fniv = gen_uaba_vec,
236
+ .fno = gen_helper_gvec_uaba_s,
237
+ .opt_opc = vecop_list,
238
+ .load_dest = true,
239
+ .vece = MO_32 },
240
+ { .fni8 = gen_uaba_i64,
241
+ .fniv = gen_uaba_vec,
242
+ .fno = gen_helper_gvec_uaba_d,
243
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
244
+ .opt_opc = vecop_list,
245
+ .load_dest = true,
246
+ .vece = MO_64 },
247
+ };
248
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
249
+}
250
+
251
/* Translate a NEON data processing instruction. Return nonzero if the
252
instruction is invalid.
253
We process data in a mixture of 32-bit and 64-bit chunks.
254
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
255
}
256
return 0;
257
258
+ case NEON_3R_VABA:
259
+ if (u) {
260
+ gen_gvec_uaba(size, rd_ofs, rn_ofs, rm_ofs,
261
+ vec_size, vec_size);
262
+ } else {
263
+ gen_gvec_saba(size, rd_ofs, rn_ofs, rm_ofs,
264
+ vec_size, vec_size);
265
+ }
266
+ return 0;
267
+
268
case NEON_3R_VADD_VSUB:
269
case NEON_3R_LOGIC:
270
case NEON_3R_VMAX:
271
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
272
case NEON_3R_VQRSHL:
273
GEN_NEON_INTEGER_OP_ENV(qrshl);
274
break;
275
- case NEON_3R_VABA:
276
- GEN_NEON_INTEGER_OP(abd);
277
- tcg_temp_free_i32(tmp2);
278
- tmp2 = neon_load_reg(rd, pass);
279
- gen_neon_add(size, tmp, tmp2);
280
- break;
281
case NEON_3R_VPMAX:
282
GEN_NEON_INTEGER_OP(pmax);
283
break;
284
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
285
index XXXXXXX..XXXXXXX 100644
286
--- a/target/arm/vec_helper.c
287
+++ b/target/arm/vec_helper.c
288
@@ -XXX,XX +XXX,XX @@ DO_ABD(gvec_uabd_s, uint32_t)
289
DO_ABD(gvec_uabd_d, uint64_t)
290
291
#undef DO_ABD
292
+
293
+#define DO_ABA(NAME, TYPE) \
294
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
295
+{ \
296
+ intptr_t i, opr_sz = simd_oprsz(desc); \
297
+ TYPE *d = vd, *n = vn, *m = vm; \
298
+ \
299
+ for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \
300
+ d[i] += n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \
301
+ } \
302
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
303
+}
304
+
305
+DO_ABA(gvec_saba_b, int8_t)
306
+DO_ABA(gvec_saba_h, int16_t)
307
+DO_ABA(gvec_saba_s, int32_t)
308
+DO_ABA(gvec_saba_d, int64_t)
309
+
310
+DO_ABA(gvec_uaba_b, uint8_t)
311
+DO_ABA(gvec_uaba_h, uint16_t)
312
+DO_ABA(gvec_uaba_s, uint32_t)
313
+DO_ABA(gvec_uaba_d, uint64_t)
314
+
315
+#undef DO_ABA
316
--
29
--
317
2.20.1
30
2.25.1
318
31
319
32
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add a SIGBUS signal handler. In this handler, it checks the SIGBUS type,
3
Extract entire fields for ZEN and FPEN, rather than testing specific bits.
4
translates the host VA delivered by host to guest PA, then fills this PA
4
This makes it easier to follow the code versus the ARM spec.
5
to guest APEI GHES memory, then notifies guest according to the SIGBUS
6
type.
7
5
8
When guest accesses the poisoned memory, it will generate a Synchronous
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
External Abort(SEA). Then host kernel gets an APEI notification and calls
10
memory_failure() to unmapped the affected page in stage 2, finally
11
returns to guest.
12
13
Guest continues to access the PG_hwpoison page, it will trap to KVM as
14
stage2 fault, then a SIGBUS_MCEERR_AR synchronous signal is delivered to
15
Qemu, Qemu records this error address into guest APEI GHES memory and
16
notifes guest using Synchronous-External-Abort(SEA).
17
18
In order to inject a vSEA, we introduce the kvm_inject_arm_sea() function
19
in which we can setup the type of exception and the syndrome information.
20
When switching to guest, the target vcpu will jump to the synchronous
21
external abort vector table entry.
22
23
The ESR_ELx.DFSC is set to synchronous external abort(0x10), and the
24
ESR_ELx.FnV is set to not valid(0x1), which will tell guest that FAR is
25
not valid and hold an UNKNOWN value. These values will be set to KVM
26
register structures through KVM_SET_ONE_REG IOCTL.
27
28
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
29
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
30
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
31
Acked-by: Xiang Zheng <zhengxiang9@huawei.com>
32
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
33
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
8
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
34
Message-id: 20200512030609.19593-10-gengdongjiu@huawei.com
9
Message-id: 20220127063428.30212-3-richard.henderson@linaro.org
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
---
11
---
37
include/sysemu/kvm.h | 3 +-
12
target/arm/helper.c | 36 +++++++++++++++++-------------------
38
target/arm/cpu.h | 4 +++
13
1 file changed, 17 insertions(+), 19 deletions(-)
39
target/arm/internals.h | 5 +--
40
target/i386/cpu.h | 2 ++
41
target/arm/helper.c | 2 +-
42
target/arm/kvm64.c | 77 +++++++++++++++++++++++++++++++++++++++++
43
target/arm/tlb_helper.c | 2 +-
44
7 files changed, 89 insertions(+), 6 deletions(-)
45
14
46
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/include/sysemu/kvm.h
49
+++ b/include/sysemu/kvm.h
50
@@ -XXX,XX +XXX,XX @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
51
/* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
52
unsigned long kvm_arch_vcpu_id(CPUState *cpu);
53
54
-#ifdef TARGET_I386
55
-#define KVM_HAVE_MCE_INJECTION 1
56
+#ifdef KVM_HAVE_MCE_INJECTION
57
void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
58
#endif
59
60
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/cpu.h
63
+++ b/target/arm/cpu.h
64
@@ -XXX,XX +XXX,XX @@
65
/* ARM processors have a weak memory model */
66
#define TCG_GUEST_DEFAULT_MO (0)
67
68
+#ifdef TARGET_AARCH64
69
+#define KVM_HAVE_MCE_INJECTION 1
70
+#endif
71
+
72
#define EXCP_UDEF 1 /* undefined instruction */
73
#define EXCP_SWI 2 /* software interrupt */
74
#define EXCP_PREFETCH_ABORT 3
75
diff --git a/target/arm/internals.h b/target/arm/internals.h
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/internals.h
78
+++ b/target/arm/internals.h
79
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
80
| ARM_EL_IL | (ea << 9) | (s1ptw << 7) | fsc;
81
}
82
83
-static inline uint32_t syn_data_abort_no_iss(int same_el,
84
+static inline uint32_t syn_data_abort_no_iss(int same_el, int fnv,
85
int ea, int cm, int s1ptw,
86
int wnr, int fsc)
87
{
88
return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
89
| ARM_EL_IL
90
- | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
91
+ | (fnv << 10) | (ea << 9) | (cm << 8) | (s1ptw << 7)
92
+ | (wnr << 6) | fsc;
93
}
94
95
static inline uint32_t syn_data_abort_with_iss(int same_el,
96
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/i386/cpu.h
99
+++ b/target/i386/cpu.h
100
@@ -XXX,XX +XXX,XX @@
101
/* The x86 has a strong memory model with some store-after-load re-ordering */
102
#define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
103
104
+#define KVM_HAVE_MCE_INJECTION 1
105
+
106
/* Maximum instruction code size */
107
#define TARGET_MAX_INSN_SIZE 16
108
109
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
110
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
111
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
112
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
113
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
19
@@ -XXX,XX +XXX,XX @@ int sve_exception_el(CPUARMState *env, int el)
114
* Report exception with ESR indicating a fault due to a
20
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
115
* translation table walk for a cache maintenance instruction.
21
116
*/
22
if (el <= 1 && (hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
117
- syn = syn_data_abort_no_iss(current_el == target_el,
23
- bool disabled = false;
118
+ syn = syn_data_abort_no_iss(current_el == target_el, 0,
24
-
119
fi.ea, 1, fi.s1ptw, 1, fsc);
25
- /* The CPACR.ZEN controls traps to EL1:
120
env->exception.vaddress = value;
26
- * 0, 2 : trap EL0 and EL1 accesses
121
env->exception.fsr = fsr;
27
- * 1 : trap only EL0 accesses
122
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
28
- * 3 : trap no accesses
123
index XXXXXXX..XXXXXXX 100644
29
- */
124
--- a/target/arm/kvm64.c
30
- if (!extract32(env->cp15.cpacr_el1, 16, 1)) {
125
+++ b/target/arm/kvm64.c
31
- disabled = true;
126
@@ -XXX,XX +XXX,XX @@
32
- } else if (!extract32(env->cp15.cpacr_el1, 17, 1)) {
127
#include "sysemu/kvm_int.h"
33
- disabled = el == 0;
128
#include "kvm_arm.h"
34
- }
129
#include "internals.h"
35
- if (disabled) {
130
+#include "hw/acpi/acpi.h"
36
+ /* Check CPACR.ZEN. */
131
+#include "hw/acpi/ghes.h"
37
+ switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
132
+#include "hw/arm/virt.h"
38
+ case 1:
133
39
+ if (el != 0) {
134
static bool have_guest_debug;
40
+ break;
135
136
@@ -XXX,XX +XXX,XX @@ int kvm_arm_cpreg_level(uint64_t regidx)
137
return KVM_PUT_RUNTIME_STATE;
138
}
139
140
+/* Callers must hold the iothread mutex lock */
141
+static void kvm_inject_arm_sea(CPUState *c)
142
+{
143
+ ARMCPU *cpu = ARM_CPU(c);
144
+ CPUARMState *env = &cpu->env;
145
+ CPUClass *cc = CPU_GET_CLASS(c);
146
+ uint32_t esr;
147
+ bool same_el;
148
+
149
+ c->exception_index = EXCP_DATA_ABORT;
150
+ env->exception.target_el = 1;
151
+
152
+ /*
153
+ * Set the DFSC to synchronous external abort and set FnV to not valid,
154
+ * this will tell guest the FAR_ELx is UNKNOWN for this abort.
155
+ */
156
+ same_el = arm_current_el(env) == env->exception.target_el;
157
+ esr = syn_data_abort_no_iss(same_el, 1, 0, 0, 0, 0, 0x10);
158
+
159
+ env->exception.syndrome = esr;
160
+
161
+ cc->do_interrupt(c);
162
+}
163
+
164
#define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
165
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
166
167
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
168
return ret;
169
}
170
171
+void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
172
+{
173
+ ram_addr_t ram_addr;
174
+ hwaddr paddr;
175
+ Object *obj = qdev_get_machine();
176
+ VirtMachineState *vms = VIRT_MACHINE(obj);
177
+ bool acpi_enabled = virt_is_acpi_enabled(vms);
178
+
179
+ assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
180
+
181
+ if (acpi_enabled && addr &&
182
+ object_property_get_bool(obj, "ras", NULL)) {
183
+ ram_addr = qemu_ram_addr_from_host(addr);
184
+ if (ram_addr != RAM_ADDR_INVALID &&
185
+ kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
186
+ kvm_hwpoison_page_add(ram_addr);
187
+ /*
188
+ * If this is a BUS_MCEERR_AR, we know we have been called
189
+ * synchronously from the vCPU thread, so we can easily
190
+ * synchronize the state and inject an error.
191
+ *
192
+ * TODO: we currently don't tell the guest at all about
193
+ * BUS_MCEERR_AO. In that case we might either be being
194
+ * called synchronously from the vCPU thread, or a bit
195
+ * later from the main thread, so doing the injection of
196
+ * the error would be more complicated.
197
+ */
198
+ if (code == BUS_MCEERR_AR) {
199
+ kvm_cpu_synchronize_state(c);
200
+ if (!acpi_ghes_record_errors(ACPI_HEST_SRC_ID_SEA, paddr)) {
201
+ kvm_inject_arm_sea(c);
202
+ } else {
203
+ error_report("failed to record the error");
204
+ abort();
205
+ }
206
+ }
41
+ }
207
+ return;
42
+ /* fall through */
208
+ }
43
+ case 0:
209
+ if (code == BUS_MCEERR_AO) {
44
+ case 2:
210
+ error_report("Hardware memory error at addr %p for memory used by "
45
/* route_to_el2 */
211
+ "QEMU itself instead of guest system!", addr);
46
return hcr_el2 & HCR_TGE ? 2 : 1;
212
+ }
47
}
213
+ }
48
214
+
49
/* Check CPACR.FPEN. */
215
+ if (code == BUS_MCEERR_AR) {
50
- if (!extract32(env->cp15.cpacr_el1, 20, 1)) {
216
+ error_report("Hardware memory error!");
51
- disabled = true;
217
+ exit(1);
52
- } else if (!extract32(env->cp15.cpacr_el1, 21, 1)) {
218
+ }
53
- disabled = el == 0;
219
+}
54
- }
220
+
55
- if (disabled) {
221
/* C6.6.29 BRK instruction */
56
+ switch (extract32(env->cp15.cpacr_el1, 20, 2)) {
222
static const uint32_t brk_insn = 0xd4200000;
57
+ case 1:
223
58
+ if (el != 0) {
224
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
59
+ break;
225
index XXXXXXX..XXXXXXX 100644
60
+ }
226
--- a/target/arm/tlb_helper.c
61
+ /* fall through */
227
+++ b/target/arm/tlb_helper.c
62
+ case 0:
228
@@ -XXX,XX +XXX,XX @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
63
+ case 2:
229
* ISV field.
64
return 0;
230
*/
65
}
231
if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
66
}
232
- syn = syn_data_abort_no_iss(same_el,
233
+ syn = syn_data_abort_no_iss(same_el, 0,
234
ea, 0, s1ptw, is_write, fsc);
235
} else {
236
/*
237
--
67
--
238
2.20.1
68
2.25.1
239
69
240
70
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 64-bit element size in preparation for SVE2.
3
When HCR_EL2.E2H is set, the format of CPTR_EL2 changes to
4
look more like CPACR_EL1, with ZEN and FPEN fields instead
5
of TZ and TFP fields.
4
6
7
Reported-by: Zenghui Yu <yuzenghui@huawei.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220127063428.30212-4-richard.henderson@linaro.org
7
Message-id: 20200513163245.17915-16-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
target/arm/helper.h | 10 +++
13
target/arm/helper.c | 77 +++++++++++++++++++++++++++++++++++----------
11
target/arm/translate.h | 5 ++
14
1 file changed, 60 insertions(+), 17 deletions(-)
12
target/arm/translate-a64.c | 8 ++-
13
target/arm/translate.c | 133 ++++++++++++++++++++++++++++++++++++-
14
target/arm/vec_helper.c | 24 +++++++
15
5 files changed, 176 insertions(+), 4 deletions(-)
16
15
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
18
--- a/target/arm/helper.c
20
+++ b/target/arm/helper.h
19
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(gvec_sli_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
20
@@ -XXX,XX +XXX,XX @@ int sve_exception_el(CPUARMState *env, int el)
22
DEF_HELPER_FLAGS_3(gvec_sli_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
21
}
23
DEF_HELPER_FLAGS_3(gvec_sli_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
22
}
24
23
25
+DEF_HELPER_FLAGS_4(gvec_sabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
- /* CPTR_EL2. Since TZ and TFP are positive,
26
+DEF_HELPER_FLAGS_4(gvec_sabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
- * they will be zero when EL2 is not present.
27
+DEF_HELPER_FLAGS_4(gvec_sabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
+ /*
28
+DEF_HELPER_FLAGS_4(gvec_sabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
+ * CPTR_EL2 changes format with HCR_EL2.E2H (regardless of TGE).
28
*/
29
- if (el <= 2 && arm_is_el2_enabled(env)) {
30
- if (env->cp15.cptr_el[2] & CPTR_TZ) {
31
- return 2;
32
- }
33
- if (env->cp15.cptr_el[2] & CPTR_TFP) {
34
- return 0;
35
+ if (el <= 2) {
36
+ if (hcr_el2 & HCR_E2H) {
37
+ /* Check CPTR_EL2.ZEN. */
38
+ switch (extract32(env->cp15.cptr_el[2], 16, 2)) {
39
+ case 1:
40
+ if (el != 0 || !(hcr_el2 & HCR_TGE)) {
41
+ break;
42
+ }
43
+ /* fall through */
44
+ case 0:
45
+ case 2:
46
+ return 2;
47
+ }
29
+
48
+
30
+DEF_HELPER_FLAGS_4(gvec_uabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
49
+ /* Check CPTR_EL2.FPEN. */
31
+DEF_HELPER_FLAGS_4(gvec_uabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
50
+ switch (extract32(env->cp15.cptr_el[2], 20, 2)) {
32
+DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
51
+ case 1:
33
+DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
52
+ if (el == 2 || !(hcr_el2 & HCR_TGE)) {
53
+ break;
54
+ }
55
+ /* fall through */
56
+ case 0:
57
+ case 2:
58
+ return 0;
59
+ }
60
+ } else if (arm_is_el2_enabled(env)) {
61
+ if (env->cp15.cptr_el[2] & CPTR_TZ) {
62
+ return 2;
63
+ }
64
+ if (env->cp15.cptr_el[2] & CPTR_TFP) {
65
+ return 0;
66
+ }
67
}
68
}
69
70
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
71
int fp_exception_el(CPUARMState *env, int cur_el)
72
{
73
#ifndef CONFIG_USER_ONLY
74
+ uint64_t hcr_el2;
34
+
75
+
35
#ifdef TARGET_AARCH64
76
/* CPACR and the CPTR registers don't exist before v6, so FP is
36
#include "helper-a64.h"
77
* always accessible
37
#include "helper-sve.h"
78
*/
38
diff --git a/target/arm/translate.h b/target/arm/translate.h
79
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
39
index XXXXXXX..XXXXXXX 100644
80
return 0;
40
--- a/target/arm/translate.h
81
}
41
+++ b/target/arm/translate.h
82
42
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
83
+ hcr_el2 = arm_hcr_el2_eff(env);
43
void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
44
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
45
46
+void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
47
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
48
+void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
49
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
50
+
84
+
51
/*
85
/* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
52
* Forward to the isar_feature_* tests given a DisasContext pointer.
86
* 0, 2 : trap EL0 and EL1/PL1 accesses
53
*/
87
* 1 : trap only EL0 accesses
54
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
88
* 3 : trap no accesses
55
index XXXXXXX..XXXXXXX 100644
89
* This register is ignored if E2H+TGE are both set.
56
--- a/target/arm/translate-a64.c
90
*/
57
+++ b/target/arm/translate-a64.c
91
- if ((arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
58
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
92
+ if ((hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
59
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smin, size);
93
int fpen = extract32(env->cp15.cpacr_el1, 20, 2);
94
95
switch (fpen) {
96
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
60
}
97
}
61
return;
98
}
62
+ case 0xe: /* SABD, UABD */
99
63
+ if (u) {
100
- /* For the CPTR registers we don't need to guard with an ARM_FEATURE
64
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uabd, size);
101
- * check because zero bits in the registers mean "don't trap".
65
+ } else {
102
+ /*
66
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size);
103
+ * CPTR_EL2 is present in v7VE or v8, and changes format
104
+ * with HCR_EL2.E2H (regardless of TGE).
105
*/
106
-
107
- /* CPTR_EL2 : present in v7VE or v8 */
108
- if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
109
- && arm_is_el2_enabled(env)) {
110
- /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
111
- return 2;
112
+ if (cur_el <= 2) {
113
+ if (hcr_el2 & HCR_E2H) {
114
+ /* Check CPTR_EL2.FPEN. */
115
+ switch (extract32(env->cp15.cptr_el[2], 20, 2)) {
116
+ case 1:
117
+ if (cur_el != 0 || !(hcr_el2 & HCR_TGE)) {
118
+ break;
119
+ }
120
+ /* fall through */
121
+ case 0:
122
+ case 2:
123
+ return 2;
124
+ }
125
+ } else if (arm_is_el2_enabled(env)) {
126
+ if (env->cp15.cptr_el[2] & CPTR_TFP) {
127
+ return 2;
128
+ }
67
+ }
129
+ }
68
+ return;
130
}
69
case 0x10: /* ADD, SUB */
131
70
if (u) {
132
/* CPTR_EL3 : present in v8 */
71
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
72
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
73
genenvfn = fns[size][u];
74
break;
75
}
76
- case 0xe: /* SABD, UABD */
77
case 0xf: /* SABA, UABA */
78
{
79
static NeonGenTwoOpFn * const fns[3][2] = {
80
diff --git a/target/arm/translate.c b/target/arm/translate.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate.c
83
+++ b/target/arm/translate.c
84
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
85
rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
86
}
87
88
+static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
89
+{
90
+ TCGv_i32 t = tcg_temp_new_i32();
91
+
92
+ tcg_gen_sub_i32(t, a, b);
93
+ tcg_gen_sub_i32(d, b, a);
94
+ tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t);
95
+ tcg_temp_free_i32(t);
96
+}
97
+
98
+static void gen_sabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
99
+{
100
+ TCGv_i64 t = tcg_temp_new_i64();
101
+
102
+ tcg_gen_sub_i64(t, a, b);
103
+ tcg_gen_sub_i64(d, b, a);
104
+ tcg_gen_movcond_i64(TCG_COND_LT, d, a, b, d, t);
105
+ tcg_temp_free_i64(t);
106
+}
107
+
108
+static void gen_sabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
109
+{
110
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
111
+
112
+ tcg_gen_smin_vec(vece, t, a, b);
113
+ tcg_gen_smax_vec(vece, d, a, b);
114
+ tcg_gen_sub_vec(vece, d, d, t);
115
+ tcg_temp_free_vec(t);
116
+}
117
+
118
+void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
119
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
120
+{
121
+ static const TCGOpcode vecop_list[] = {
122
+ INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
123
+ };
124
+ static const GVecGen3 ops[4] = {
125
+ { .fniv = gen_sabd_vec,
126
+ .fno = gen_helper_gvec_sabd_b,
127
+ .opt_opc = vecop_list,
128
+ .vece = MO_8 },
129
+ { .fniv = gen_sabd_vec,
130
+ .fno = gen_helper_gvec_sabd_h,
131
+ .opt_opc = vecop_list,
132
+ .vece = MO_16 },
133
+ { .fni4 = gen_sabd_i32,
134
+ .fniv = gen_sabd_vec,
135
+ .fno = gen_helper_gvec_sabd_s,
136
+ .opt_opc = vecop_list,
137
+ .vece = MO_32 },
138
+ { .fni8 = gen_sabd_i64,
139
+ .fniv = gen_sabd_vec,
140
+ .fno = gen_helper_gvec_sabd_d,
141
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
142
+ .opt_opc = vecop_list,
143
+ .vece = MO_64 },
144
+ };
145
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
146
+}
147
+
148
+static void gen_uabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
149
+{
150
+ TCGv_i32 t = tcg_temp_new_i32();
151
+
152
+ tcg_gen_sub_i32(t, a, b);
153
+ tcg_gen_sub_i32(d, b, a);
154
+ tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, d, t);
155
+ tcg_temp_free_i32(t);
156
+}
157
+
158
+static void gen_uabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
159
+{
160
+ TCGv_i64 t = tcg_temp_new_i64();
161
+
162
+ tcg_gen_sub_i64(t, a, b);
163
+ tcg_gen_sub_i64(d, b, a);
164
+ tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, d, t);
165
+ tcg_temp_free_i64(t);
166
+}
167
+
168
+static void gen_uabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
169
+{
170
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
171
+
172
+ tcg_gen_umin_vec(vece, t, a, b);
173
+ tcg_gen_umax_vec(vece, d, a, b);
174
+ tcg_gen_sub_vec(vece, d, d, t);
175
+ tcg_temp_free_vec(t);
176
+}
177
+
178
+void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
179
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
180
+{
181
+ static const TCGOpcode vecop_list[] = {
182
+ INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
183
+ };
184
+ static const GVecGen3 ops[4] = {
185
+ { .fniv = gen_uabd_vec,
186
+ .fno = gen_helper_gvec_uabd_b,
187
+ .opt_opc = vecop_list,
188
+ .vece = MO_8 },
189
+ { .fniv = gen_uabd_vec,
190
+ .fno = gen_helper_gvec_uabd_h,
191
+ .opt_opc = vecop_list,
192
+ .vece = MO_16 },
193
+ { .fni4 = gen_uabd_i32,
194
+ .fniv = gen_uabd_vec,
195
+ .fno = gen_helper_gvec_uabd_s,
196
+ .opt_opc = vecop_list,
197
+ .vece = MO_32 },
198
+ { .fni8 = gen_uabd_i64,
199
+ .fniv = gen_uabd_vec,
200
+ .fno = gen_helper_gvec_uabd_d,
201
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
202
+ .opt_opc = vecop_list,
203
+ .vece = MO_64 },
204
+ };
205
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
206
+}
207
+
208
/* Translate a NEON data processing instruction. Return nonzero if the
209
instruction is invalid.
210
We process data in a mixture of 32-bit and 64-bit chunks.
211
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
212
}
213
return 1;
214
215
+ case NEON_3R_VABD:
216
+ if (u) {
217
+ gen_gvec_uabd(size, rd_ofs, rn_ofs, rm_ofs,
218
+ vec_size, vec_size);
219
+ } else {
220
+ gen_gvec_sabd(size, rd_ofs, rn_ofs, rm_ofs,
221
+ vec_size, vec_size);
222
+ }
223
+ return 0;
224
+
225
case NEON_3R_VADD_VSUB:
226
case NEON_3R_LOGIC:
227
case NEON_3R_VMAX:
228
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
229
case NEON_3R_VQRSHL:
230
GEN_NEON_INTEGER_OP_ENV(qrshl);
231
break;
232
- case NEON_3R_VABD:
233
- GEN_NEON_INTEGER_OP(abd);
234
- break;
235
case NEON_3R_VABA:
236
GEN_NEON_INTEGER_OP(abd);
237
tcg_temp_free_i32(tmp2);
238
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
239
index XXXXXXX..XXXXXXX 100644
240
--- a/target/arm/vec_helper.c
241
+++ b/target/arm/vec_helper.c
242
@@ -XXX,XX +XXX,XX @@ DO_CMP0(gvec_cgt0_h, int16_t, >)
243
DO_CMP0(gvec_cge0_h, int16_t, >=)
244
245
#undef DO_CMP0
246
+
247
+#define DO_ABD(NAME, TYPE) \
248
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
249
+{ \
250
+ intptr_t i, opr_sz = simd_oprsz(desc); \
251
+ TYPE *d = vd, *n = vn, *m = vm; \
252
+ \
253
+ for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \
254
+ d[i] = n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \
255
+ } \
256
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
257
+}
258
+
259
+DO_ABD(gvec_sabd_b, int8_t)
260
+DO_ABD(gvec_sabd_h, int16_t)
261
+DO_ABD(gvec_sabd_s, int32_t)
262
+DO_ABD(gvec_sabd_d, int64_t)
263
+
264
+DO_ABD(gvec_uabd_b, uint8_t)
265
+DO_ABD(gvec_uabd_h, uint16_t)
266
+DO_ABD(gvec_uabd_s, uint32_t)
267
+DO_ABD(gvec_uabd_d, uint64_t)
268
+
269
+#undef DO_ABD
270
--
133
--
271
2.20.1
134
2.25.1
272
135
273
136
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Provide a functional interface for the vector expansion.
3
Use the named bit rather than a bare extract32.
4
This fits better with the existing set of helpers that
5
we provide for other operations.
6
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
9
Message-id: 20200513163245.17915-13-richard.henderson@linaro.org
8
Message-id: 20220127063428.30212-5-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/translate.h | 5 ++++
11
target/arm/helper.c | 2 +-
13
target/arm/translate-a64.c | 34 ++----------------------
12
1 file changed, 1 insertion(+), 1 deletion(-)
14
target/arm/translate.c | 54 +++++++++++++++++++-------------------
15
3 files changed, 34 insertions(+), 59 deletions(-)
16
13
17
diff --git a/target/arm/translate.h b/target/arm/translate.h
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate.h
16
--- a/target/arm/helper.c
20
+++ b/target/arm/translate.h
17
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
18
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
22
void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
19
}
23
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
20
24
21
/* CPTR_EL3 : present in v8 */
25
+void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
22
- if (extract32(env->cp15.cptr_el[3], 10, 1)) {
26
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
23
+ if (env->cp15.cptr_el[3] & CPTR_TFP) {
27
+void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
24
/* Trap all FP ops to EL3 */
28
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
25
return 3;
29
+
26
}
30
/*
31
* Forward to the isar_feature_* tests given a DisasContext pointer.
32
*/
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_ool(DisasContext *s, bool is_q, int rd,
38
is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
39
}
40
41
-/* Expand a 3-operand + env pointer operation using
42
- * an out-of-line helper.
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
-{
47
- tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
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
-}
52
-
53
/* Expand a 3-operand + fpstatus pointer + simd data value operation using
54
* an out-of-line helper.
55
*/
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
57
58
switch (opcode) {
59
case 0x0: /* SQRDMLAH (vector) */
60
- switch (size) {
61
- case 1:
62
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
63
- break;
64
- case 2:
65
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
66
- break;
67
- default:
68
- g_assert_not_reached();
69
- }
70
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqrdmlah_qc, size);
71
return;
72
73
case 0x1: /* SQRDMLSH (vector) */
74
- switch (size) {
75
- case 1:
76
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
77
- break;
78
- case 2:
79
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
80
- break;
81
- default:
82
- g_assert_not_reached();
83
- }
84
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqrdmlsh_qc, size);
85
return;
86
87
case 0x2: /* SDOT / UDOT */
88
diff --git a/target/arm/translate.c b/target/arm/translate.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/translate.c
91
+++ b/target/arm/translate.c
92
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
93
[NEON_2RM_VCVT_UF] = 0x4,
94
};
95
96
-
97
-/* Expand v8.1 simd helper. */
98
-static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
99
- int q, int rd, int rn, int rm)
100
+void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
101
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
102
{
103
- if (dc_isar_feature(aa32_rdm, s)) {
104
- int opr_sz = (1 + q) * 8;
105
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
106
- vfp_reg_offset(1, rn),
107
- vfp_reg_offset(1, rm), cpu_env,
108
- opr_sz, opr_sz, 0, fn);
109
- return 0;
110
- }
111
- return 1;
112
+ static gen_helper_gvec_3_ptr * const fns[2] = {
113
+ gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
114
+ };
115
+ tcg_debug_assert(vece >= 1 && vece <= 2);
116
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
117
+ opr_sz, max_sz, 0, fns[vece - 1]);
118
+}
119
+
120
+void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
121
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
122
+{
123
+ static gen_helper_gvec_3_ptr * const fns[2] = {
124
+ gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
125
+ };
126
+ tcg_debug_assert(vece >= 1 && vece <= 2);
127
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
128
+ opr_sz, max_sz, 0, fns[vece - 1]);
129
}
130
131
#define GEN_CMP0(NAME, COND) \
132
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
133
break; /* VPADD */
134
}
135
/* VQRDMLAH */
136
- switch (size) {
137
- case 1:
138
- return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
139
- q, rd, rn, rm);
140
- case 2:
141
- return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
142
- q, rd, rn, rm);
143
+ if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) {
144
+ gen_gvec_sqrdmlah_qc(size, rd_ofs, rn_ofs, rm_ofs,
145
+ vec_size, vec_size);
146
+ return 0;
147
}
148
return 1;
149
150
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
151
break;
152
}
153
/* VQRDMLSH */
154
- switch (size) {
155
- case 1:
156
- return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
157
- q, rd, rn, rm);
158
- case 2:
159
- return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
160
- q, rd, rn, rm);
161
+ if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) {
162
+ gen_gvec_sqrdmlsh_qc(size, rd_ofs, rn_ofs, rm_ofs,
163
+ vec_size, vec_size);
164
+ return 0;
165
}
166
return 1;
167
168
--
27
--
169
2.20.1
28
2.25.1
170
29
171
30
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Francisco Iglesias <francisco.iglesias@xilinx.com>
2
2
3
Now that we've converted all cases to gvec, there is quite a bit
3
'Or' the IRQs coming from the QSPI and QSPI DMA models. This is done for
4
of dead code at the end of the function. Remove it.
4
avoiding the situation where one of the models incorrectly deasserts an
5
interrupt asserted from the other model (which will result in that the IRQ
6
is lost and will not reach guest SW).
5
7
6
Sink the call to gen_gvec_fn2i to the end, loading a function
8
Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
7
pointer within the switch statement.
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
10
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20220203151742.1457-1-francisco.iglesias@xilinx.com
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200513163245.17915-6-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
target/arm/translate-a64.c | 56 ++++++++++----------------------------
14
include/hw/arm/xlnx-zynqmp.h | 2 ++
15
1 file changed, 14 insertions(+), 42 deletions(-)
15
hw/arm/xlnx-zynqmp.c | 14 ++++++++++++--
16
2 files changed, 14 insertions(+), 2 deletions(-)
16
17
17
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
18
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate-a64.c
20
--- a/include/hw/arm/xlnx-zynqmp.h
20
+++ b/target/arm/translate-a64.c
21
+++ b/include/hw/arm/xlnx-zynqmp.h
21
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
22
@@ -XXX,XX +XXX,XX @@
22
int size = 32 - clz32(immh) - 1;
23
#include "hw/dma/xlnx_csu_dma.h"
23
int immhb = immh << 3 | immb;
24
#include "hw/nvram/xlnx-bbram.h"
24
int shift = 2 * (8 << size) - immhb;
25
#include "hw/nvram/xlnx-zynqmp-efuse.h"
25
- bool accumulate = false;
26
+#include "hw/or-irq.h"
26
- int dsize = is_q ? 128 : 64;
27
27
- int esize = 8 << size;
28
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
28
- int elements = dsize/esize;
29
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
29
- MemOp memop = size | (is_u ? 0 : MO_SIGN);
30
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
30
- TCGv_i64 tcg_rn = new_tmp_a64(s);
31
XlnxZDMA gdma[XLNX_ZYNQMP_NUM_GDMA_CH];
31
- TCGv_i64 tcg_rd = new_tmp_a64(s);
32
XlnxZDMA adma[XLNX_ZYNQMP_NUM_ADMA_CH];
32
- TCGv_i64 tcg_round;
33
XlnxCSUDMA qspi_dma;
33
- uint64_t round_const;
34
+ qemu_or_irq qspi_irq_orgate;
34
- int i;
35
35
+ GVecGen2iFn *gvec_fn;
36
char *boot_cpu;
36
37
ARMCPU *boot_cpu_ptr;
37
if (extract32(immh, 3, 1) && !is_q) {
38
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
38
unallocated_encoding(s);
39
index XXXXXXX..XXXXXXX 100644
39
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
40
--- a/hw/arm/xlnx-zynqmp.c
40
41
+++ b/hw/arm/xlnx-zynqmp.c
41
switch (opcode) {
42
@@ -XXX,XX +XXX,XX @@
42
case 0x02: /* SSRA / USRA (accumulate) */
43
#define LQSPI_ADDR 0xc0000000
43
- gen_gvec_fn2i(s, is_q, rd, rn, shift,
44
#define QSPI_IRQ 15
44
- is_u ? gen_gvec_usra : gen_gvec_ssra, size);
45
#define QSPI_DMA_ADDR 0xff0f0800
45
- return;
46
+#define NUM_QSPI_IRQ_LINES 2
46
+ gvec_fn = is_u ? gen_gvec_usra : gen_gvec_ssra;
47
47
+ break;
48
#define DP_ADDR 0xfd4a0000
48
49
#define DP_IRQ 113
49
case 0x08: /* SRI */
50
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
50
- gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sri, size);
51
- return;
52
+ gvec_fn = gen_gvec_sri;
53
+ break;
54
55
case 0x00: /* SSHR / USHR */
56
if (is_u) {
57
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
58
/* Shift count the same size as element size produces zero. */
59
tcg_gen_gvec_dup_imm(size, vec_full_reg_offset(s, rd),
60
is_q ? 16 : 8, vec_full_reg_size(s), 0);
61
- } else {
62
- gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shri, size);
63
+ return;
64
}
65
+ gvec_fn = tcg_gen_gvec_shri;
66
} else {
67
/* Shift count the same size as element size produces all sign. */
68
if (shift == 8 << size) {
69
shift -= 1;
70
}
71
- gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_sari, size);
72
+ gvec_fn = tcg_gen_gvec_sari;
73
}
74
- return;
75
+ break;
76
77
case 0x04: /* SRSHR / URSHR (rounding) */
78
- gen_gvec_fn2i(s, is_q, rd, rn, shift,
79
- is_u ? gen_gvec_urshr : gen_gvec_srshr, size);
80
- return;
81
+ gvec_fn = is_u ? gen_gvec_urshr : gen_gvec_srshr;
82
+ break;
83
84
case 0x06: /* SRSRA / URSRA (accum + rounding) */
85
- gen_gvec_fn2i(s, is_q, rd, rn, shift,
86
- is_u ? gen_gvec_ursra : gen_gvec_srsra, size);
87
- return;
88
+ gvec_fn = is_u ? gen_gvec_ursra : gen_gvec_srsra;
89
+ break;
90
91
default:
92
g_assert_not_reached();
93
}
51
}
94
52
95
- round_const = 1ULL << (shift - 1);
53
object_initialize_child(obj, "qspi-dma", &s->qspi_dma, TYPE_XLNX_CSU_DMA);
96
- tcg_round = tcg_const_i64(round_const);
54
+ object_initialize_child(obj, "qspi-irq-orgate",
97
-
55
+ &s->qspi_irq_orgate, TYPE_OR_IRQ);
98
- for (i = 0; i < elements; i++) {
99
- read_vec_element(s, tcg_rn, rn, i, memop);
100
- if (accumulate) {
101
- read_vec_element(s, tcg_rd, rd, i, memop);
102
- }
103
-
104
- handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
105
- accumulate, is_u, size, shift);
106
-
107
- write_vec_element(s, tcg_rd, rd, i, size);
108
- }
109
- tcg_temp_free_i64(tcg_round);
110
-
111
- clear_vec_high(s, is_q, rd);
112
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gvec_fn, size);
113
}
56
}
114
57
115
/* SHL/SLI - Vector shift left */
58
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
59
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
60
gic_spi[adma_ch_intr[i]]);
61
}
62
63
+ object_property_set_int(OBJECT(&s->qspi_irq_orgate),
64
+ "num-lines", NUM_QSPI_IRQ_LINES, &error_fatal);
65
+ qdev_realize(DEVICE(&s->qspi_irq_orgate), NULL, &error_fatal);
66
+ qdev_connect_gpio_out(DEVICE(&s->qspi_irq_orgate), 0, gic_spi[QSPI_IRQ]);
67
+
68
if (!object_property_set_link(OBJECT(&s->qspi_dma), "dma",
69
OBJECT(system_memory), errp)) {
70
return;
71
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
72
}
73
74
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi_dma), 0, QSPI_DMA_ADDR);
75
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi_dma), 0, gic_spi[QSPI_IRQ]);
76
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi_dma), 0,
77
+ qdev_get_gpio_in(DEVICE(&s->qspi_irq_orgate), 0));
78
79
if (!object_property_set_link(OBJECT(&s->qspi), "stream-connected-dma",
80
OBJECT(&s->qspi_dma), errp)) {
81
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
82
}
83
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 0, QSPI_ADDR);
84
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 1, LQSPI_ADDR);
85
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi), 0, gic_spi[QSPI_IRQ]);
86
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi), 0,
87
+ qdev_get_gpio_in(DEVICE(&s->qspi_irq_orgate), 1));
88
89
for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_BUS; i++) {
90
g_autofree gchar *bus_name = g_strdup_printf("qspi%d", i);
116
--
91
--
117
2.20.1
92
2.25.1
118
93
119
94
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
We want to allow the psci-conduit property to be set after realize,
2
because the parts of the code which are best placed to decide if it's
3
OK to enable QEMU's builtin PSCI emulation (the board code and the
4
arm_load_kernel() function are distant from the code which creates
5
and realizes CPUs (typically inside an SoC object's init and realize
6
method) and run afterwards.
2
7
3
Provide a functional interface for the vector expansion.
8
Since the DEFINE_PROP_* macros don't have support for creating
4
This fits better with the existing set of helpers that
9
properties which can be changed after realize, change the property to
5
we provide for other operations.
10
be created with object_property_add_uint32_ptr(), which is what we
11
already use in this function for creating settable-after-realize
12
properties like init-svtor and init-nsvtor.
6
13
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Note that it doesn't conceptually make sense to change the setting of
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
the property after the machine has been completely initialized,
9
Message-id: 20200513163245.17915-11-richard.henderson@linaro.org
16
beacuse this would mean that the behaviour of the machine when first
17
started would differ from its behaviour when the system is
18
subsequently reset. (It would also require the underlying state to
19
be migrated, which we don't do.)
20
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
24
Tested-by: Cédric Le Goater <clg@kaod.org>
25
Message-id: 20220127154639.2090164-2-peter.maydell@linaro.org
11
---
26
---
12
target/arm/translate.h | 13 +-
27
target/arm/cpu.c | 6 +++++-
13
target/arm/translate-a64.c | 22 ++-
28
1 file changed, 5 insertions(+), 1 deletion(-)
14
target/arm/translate-neon.inc.c | 19 +--
15
target/arm/translate.c | 228 +++++++++++++++++---------------
16
4 files changed, 147 insertions(+), 135 deletions(-)
17
29
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
19
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate.h
32
--- a/target/arm/cpu.c
21
+++ b/target/arm/translate.h
33
+++ b/target/arm/cpu.c
22
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
34
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
23
void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
35
OBJ_PROP_FLAG_READWRITE);
24
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
36
}
25
37
26
-extern const GVecGen4 uqadd_op[4];
38
+ /* Not DEFINE_PROP_UINT32: we want this to be settable after realize */
27
-extern const GVecGen4 sqadd_op[4];
39
+ object_property_add_uint32_ptr(obj, "psci-conduit",
28
-extern const GVecGen4 uqsub_op[4];
40
+ &cpu->psci_conduit,
29
-extern const GVecGen4 sqsub_op[4];
41
+ OBJ_PROP_FLAG_READWRITE);
30
void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
31
void gen_ushl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
32
void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
33
void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
34
void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
35
36
+void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
37
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
38
+void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
39
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
40
+void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
41
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
42
+void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
43
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
44
+
42
+
45
void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
43
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property);
46
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
44
47
void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
45
if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) {
48
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
46
@@ -XXX,XX +XXX,XX @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/translate-a64.c
51
+++ b/target/arm/translate-a64.c
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
53
54
switch (opcode) {
55
case 0x01: /* SQADD, UQADD */
56
- tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
57
- offsetof(CPUARMState, vfp.qc),
58
- vec_full_reg_offset(s, rn),
59
- vec_full_reg_offset(s, rm),
60
- is_q ? 16 : 8, vec_full_reg_size(s),
61
- (u ? uqadd_op : sqadd_op) + size);
62
+ if (u) {
63
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uqadd_qc, size);
64
+ } else {
65
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqadd_qc, size);
66
+ }
67
return;
68
case 0x05: /* SQSUB, UQSUB */
69
- tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
70
- offsetof(CPUARMState, vfp.qc),
71
- vec_full_reg_offset(s, rn),
72
- vec_full_reg_offset(s, rm),
73
- is_q ? 16 : 8, vec_full_reg_size(s),
74
- (u ? uqsub_op : sqsub_op) + size);
75
+ if (u) {
76
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uqsub_qc, size);
77
+ } else {
78
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqsub_qc, size);
79
+ }
80
return;
81
case 0x08: /* SSHL, USHL */
82
if (u) {
83
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/translate-neon.inc.c
86
+++ b/target/arm/translate-neon.inc.c
87
@@ -XXX,XX +XXX,XX @@ DO_3SAME(VORN, tcg_gen_gvec_orc)
88
DO_3SAME(VEOR, tcg_gen_gvec_xor)
89
DO_3SAME(VSHL_S, gen_gvec_sshl)
90
DO_3SAME(VSHL_U, gen_gvec_ushl)
91
+DO_3SAME(VQADD_S, gen_gvec_sqadd_qc)
92
+DO_3SAME(VQADD_U, gen_gvec_uqadd_qc)
93
+DO_3SAME(VQSUB_S, gen_gvec_sqsub_qc)
94
+DO_3SAME(VQSUB_U, gen_gvec_uqsub_qc)
95
96
/* These insns are all gvec_bitsel but with the inputs in various orders. */
97
#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \
98
@@ -XXX,XX +XXX,XX @@ DO_3SAME_CMP(VCGE_S, TCG_COND_GE)
99
DO_3SAME_CMP(VCGE_U, TCG_COND_GEU)
100
DO_3SAME_CMP(VCEQ, TCG_COND_EQ)
101
102
-#define DO_3SAME_GVEC4(INSN, OPARRAY) \
103
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
104
- uint32_t rn_ofs, uint32_t rm_ofs, \
105
- uint32_t oprsz, uint32_t maxsz) \
106
- { \
107
- tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), \
108
- rn_ofs, rm_ofs, oprsz, maxsz, &OPARRAY[vece]); \
109
- } \
110
- DO_3SAME(INSN, gen_##INSN##_3s)
111
-
112
-DO_3SAME_GVEC4(VQADD_S, sqadd_op)
113
-DO_3SAME_GVEC4(VQADD_U, uqadd_op)
114
-DO_3SAME_GVEC4(VQSUB_S, sqsub_op)
115
-DO_3SAME_GVEC4(VQSUB_U, uqsub_op)
116
-
117
static void gen_VMUL_p_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
118
uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
119
{
120
diff --git a/target/arm/translate.c b/target/arm/translate.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/target/arm/translate.c
123
+++ b/target/arm/translate.c
124
@@ -XXX,XX +XXX,XX @@ static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
125
tcg_temp_free_vec(x);
126
}
47
}
127
48
128
-static const TCGOpcode vecop_list_uqadd[] = {
49
static Property arm_cpu_properties[] = {
129
- INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
50
- DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0),
130
-};
51
DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0),
131
-
52
DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
132
-const GVecGen4 uqadd_op[4] = {
53
mp_affinity, ARM64_AFFINITY_INVALID),
133
- { .fniv = gen_uqadd_vec,
134
- .fno = gen_helper_gvec_uqadd_b,
135
- .write_aofs = true,
136
- .opt_opc = vecop_list_uqadd,
137
- .vece = MO_8 },
138
- { .fniv = gen_uqadd_vec,
139
- .fno = gen_helper_gvec_uqadd_h,
140
- .write_aofs = true,
141
- .opt_opc = vecop_list_uqadd,
142
- .vece = MO_16 },
143
- { .fniv = gen_uqadd_vec,
144
- .fno = gen_helper_gvec_uqadd_s,
145
- .write_aofs = true,
146
- .opt_opc = vecop_list_uqadd,
147
- .vece = MO_32 },
148
- { .fniv = gen_uqadd_vec,
149
- .fno = gen_helper_gvec_uqadd_d,
150
- .write_aofs = true,
151
- .opt_opc = vecop_list_uqadd,
152
- .vece = MO_64 },
153
-};
154
+void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
155
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
156
+{
157
+ static const TCGOpcode vecop_list[] = {
158
+ INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
159
+ };
160
+ static const GVecGen4 ops[4] = {
161
+ { .fniv = gen_uqadd_vec,
162
+ .fno = gen_helper_gvec_uqadd_b,
163
+ .write_aofs = true,
164
+ .opt_opc = vecop_list,
165
+ .vece = MO_8 },
166
+ { .fniv = gen_uqadd_vec,
167
+ .fno = gen_helper_gvec_uqadd_h,
168
+ .write_aofs = true,
169
+ .opt_opc = vecop_list,
170
+ .vece = MO_16 },
171
+ { .fniv = gen_uqadd_vec,
172
+ .fno = gen_helper_gvec_uqadd_s,
173
+ .write_aofs = true,
174
+ .opt_opc = vecop_list,
175
+ .vece = MO_32 },
176
+ { .fniv = gen_uqadd_vec,
177
+ .fno = gen_helper_gvec_uqadd_d,
178
+ .write_aofs = true,
179
+ .opt_opc = vecop_list,
180
+ .vece = MO_64 },
181
+ };
182
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
183
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
184
+}
185
186
static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
187
TCGv_vec a, TCGv_vec b)
188
@@ -XXX,XX +XXX,XX @@ static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
189
tcg_temp_free_vec(x);
190
}
191
192
-static const TCGOpcode vecop_list_sqadd[] = {
193
- INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
194
-};
195
-
196
-const GVecGen4 sqadd_op[4] = {
197
- { .fniv = gen_sqadd_vec,
198
- .fno = gen_helper_gvec_sqadd_b,
199
- .opt_opc = vecop_list_sqadd,
200
- .write_aofs = true,
201
- .vece = MO_8 },
202
- { .fniv = gen_sqadd_vec,
203
- .fno = gen_helper_gvec_sqadd_h,
204
- .opt_opc = vecop_list_sqadd,
205
- .write_aofs = true,
206
- .vece = MO_16 },
207
- { .fniv = gen_sqadd_vec,
208
- .fno = gen_helper_gvec_sqadd_s,
209
- .opt_opc = vecop_list_sqadd,
210
- .write_aofs = true,
211
- .vece = MO_32 },
212
- { .fniv = gen_sqadd_vec,
213
- .fno = gen_helper_gvec_sqadd_d,
214
- .opt_opc = vecop_list_sqadd,
215
- .write_aofs = true,
216
- .vece = MO_64 },
217
-};
218
+void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
219
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
220
+{
221
+ static const TCGOpcode vecop_list[] = {
222
+ INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
223
+ };
224
+ static const GVecGen4 ops[4] = {
225
+ { .fniv = gen_sqadd_vec,
226
+ .fno = gen_helper_gvec_sqadd_b,
227
+ .opt_opc = vecop_list,
228
+ .write_aofs = true,
229
+ .vece = MO_8 },
230
+ { .fniv = gen_sqadd_vec,
231
+ .fno = gen_helper_gvec_sqadd_h,
232
+ .opt_opc = vecop_list,
233
+ .write_aofs = true,
234
+ .vece = MO_16 },
235
+ { .fniv = gen_sqadd_vec,
236
+ .fno = gen_helper_gvec_sqadd_s,
237
+ .opt_opc = vecop_list,
238
+ .write_aofs = true,
239
+ .vece = MO_32 },
240
+ { .fniv = gen_sqadd_vec,
241
+ .fno = gen_helper_gvec_sqadd_d,
242
+ .opt_opc = vecop_list,
243
+ .write_aofs = true,
244
+ .vece = MO_64 },
245
+ };
246
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
247
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
248
+}
249
250
static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
251
TCGv_vec a, TCGv_vec b)
252
@@ -XXX,XX +XXX,XX @@ static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
253
tcg_temp_free_vec(x);
254
}
255
256
-static const TCGOpcode vecop_list_uqsub[] = {
257
- INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
258
-};
259
-
260
-const GVecGen4 uqsub_op[4] = {
261
- { .fniv = gen_uqsub_vec,
262
- .fno = gen_helper_gvec_uqsub_b,
263
- .opt_opc = vecop_list_uqsub,
264
- .write_aofs = true,
265
- .vece = MO_8 },
266
- { .fniv = gen_uqsub_vec,
267
- .fno = gen_helper_gvec_uqsub_h,
268
- .opt_opc = vecop_list_uqsub,
269
- .write_aofs = true,
270
- .vece = MO_16 },
271
- { .fniv = gen_uqsub_vec,
272
- .fno = gen_helper_gvec_uqsub_s,
273
- .opt_opc = vecop_list_uqsub,
274
- .write_aofs = true,
275
- .vece = MO_32 },
276
- { .fniv = gen_uqsub_vec,
277
- .fno = gen_helper_gvec_uqsub_d,
278
- .opt_opc = vecop_list_uqsub,
279
- .write_aofs = true,
280
- .vece = MO_64 },
281
-};
282
+void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
283
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
284
+{
285
+ static const TCGOpcode vecop_list[] = {
286
+ INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
287
+ };
288
+ static const GVecGen4 ops[4] = {
289
+ { .fniv = gen_uqsub_vec,
290
+ .fno = gen_helper_gvec_uqsub_b,
291
+ .opt_opc = vecop_list,
292
+ .write_aofs = true,
293
+ .vece = MO_8 },
294
+ { .fniv = gen_uqsub_vec,
295
+ .fno = gen_helper_gvec_uqsub_h,
296
+ .opt_opc = vecop_list,
297
+ .write_aofs = true,
298
+ .vece = MO_16 },
299
+ { .fniv = gen_uqsub_vec,
300
+ .fno = gen_helper_gvec_uqsub_s,
301
+ .opt_opc = vecop_list,
302
+ .write_aofs = true,
303
+ .vece = MO_32 },
304
+ { .fniv = gen_uqsub_vec,
305
+ .fno = gen_helper_gvec_uqsub_d,
306
+ .opt_opc = vecop_list,
307
+ .write_aofs = true,
308
+ .vece = MO_64 },
309
+ };
310
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
311
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
312
+}
313
314
static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
315
TCGv_vec a, TCGv_vec b)
316
@@ -XXX,XX +XXX,XX @@ static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
317
tcg_temp_free_vec(x);
318
}
319
320
-static const TCGOpcode vecop_list_sqsub[] = {
321
- INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
322
-};
323
-
324
-const GVecGen4 sqsub_op[4] = {
325
- { .fniv = gen_sqsub_vec,
326
- .fno = gen_helper_gvec_sqsub_b,
327
- .opt_opc = vecop_list_sqsub,
328
- .write_aofs = true,
329
- .vece = MO_8 },
330
- { .fniv = gen_sqsub_vec,
331
- .fno = gen_helper_gvec_sqsub_h,
332
- .opt_opc = vecop_list_sqsub,
333
- .write_aofs = true,
334
- .vece = MO_16 },
335
- { .fniv = gen_sqsub_vec,
336
- .fno = gen_helper_gvec_sqsub_s,
337
- .opt_opc = vecop_list_sqsub,
338
- .write_aofs = true,
339
- .vece = MO_32 },
340
- { .fniv = gen_sqsub_vec,
341
- .fno = gen_helper_gvec_sqsub_d,
342
- .opt_opc = vecop_list_sqsub,
343
- .write_aofs = true,
344
- .vece = MO_64 },
345
-};
346
+void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
347
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
348
+{
349
+ static const TCGOpcode vecop_list[] = {
350
+ INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
351
+ };
352
+ static const GVecGen4 ops[4] = {
353
+ { .fniv = gen_sqsub_vec,
354
+ .fno = gen_helper_gvec_sqsub_b,
355
+ .opt_opc = vecop_list,
356
+ .write_aofs = true,
357
+ .vece = MO_8 },
358
+ { .fniv = gen_sqsub_vec,
359
+ .fno = gen_helper_gvec_sqsub_h,
360
+ .opt_opc = vecop_list,
361
+ .write_aofs = true,
362
+ .vece = MO_16 },
363
+ { .fniv = gen_sqsub_vec,
364
+ .fno = gen_helper_gvec_sqsub_s,
365
+ .opt_opc = vecop_list,
366
+ .write_aofs = true,
367
+ .vece = MO_32 },
368
+ { .fniv = gen_sqsub_vec,
369
+ .fno = gen_helper_gvec_sqsub_d,
370
+ .opt_opc = vecop_list,
371
+ .write_aofs = true,
372
+ .vece = MO_64 },
373
+ };
374
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
375
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
376
+}
377
378
/* Translate a NEON data processing instruction. Return nonzero if the
379
instruction is invalid.
380
--
54
--
381
2.20.1
55
2.25.1
382
56
383
57
diff view generated by jsdifflib
1
Convert the Neon floating point VFMA and VFMS insn to decodetree.
1
The CPU object's start-powered-off property is currently only
2
These are the last insns in the 3-reg-same group so we can
2
settable before the CPU object is realized. For arm machines this is
3
remove all the support/loop code from the old decoder.
3
awkward, because we would like to decide whether the CPU should be
4
powered-off based on how we are booting the guest code, which is
5
something done in the machine model code and in common code called by
6
the machine model, which runs much later and in completely different
7
parts of the codebase from the SoC object code that is responsible
8
for creating and realizing the CPU objects.
9
10
Allow start-powered-off to be set after realize. Since this isn't
11
something that's supported by the DEFINE_PROP_* macros, we have to
12
switch the property definition to use the
13
object_class_property_add_bool() function.
14
15
Note that it doesn't conceptually make sense to change the setting of
16
the property after the machine has been completely initialized,
17
beacuse this would mean that the behaviour of the machine when first
18
started would differ from its behaviour when the system is
19
subsequently reset. (It would also require the underlying state to
20
be migrated, which we don't do.)
4
21
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-18-peter.maydell@linaro.org
24
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Tested-by: Cédric Le Goater <clg@kaod.org>
26
Message-id: 20220127154639.2090164-3-peter.maydell@linaro.org
8
---
27
---
9
target/arm/neon-dp.decode | 3 +
28
cpu.c | 22 +++++++++++++++++++++-
10
target/arm/translate-neon.inc.c | 41 ++++++++
29
1 file changed, 21 insertions(+), 1 deletion(-)
11
target/arm/translate.c | 176 +-------------------------------
12
3 files changed, 46 insertions(+), 174 deletions(-)
13
30
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
31
diff --git a/cpu.c b/cpu.c
15
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
33
--- a/cpu.c
17
+++ b/target/arm/neon-dp.decode
34
+++ b/cpu.c
18
@@ -XXX,XX +XXX,XX @@ SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \
35
@@ -XXX,XX +XXX,XX @@ static Property cpu_common_props[] = {
19
SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
36
DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
20
vm=%vm_dp vn=%vn_dp vd=%vd_dp
37
MemoryRegion *),
21
38
#endif
22
+VFMA_fp_3s 1111 001 0 0 . 0 . .... .... 1100 ... 1 .... @3same_fp
39
- DEFINE_PROP_BOOL("start-powered-off", CPUState, start_powered_off, false),
23
+VFMS_fp_3s 1111 001 0 0 . 1 . .... .... 1100 ... 1 .... @3same_fp
40
DEFINE_PROP_END_OF_LIST(),
24
+
41
};
25
VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
42
26
43
+static bool cpu_get_start_powered_off(Object *obj, Error **errp)
27
VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-neon.inc.c
31
+++ b/target/arm/translate-neon.inc.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
33
return do_3same(s, a, gen_VRSQRTS_fp_3s);
34
}
35
36
+static void gen_VFMA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
37
+ TCGv_ptr fpstatus)
38
+{
44
+{
39
+ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
45
+ CPUState *cpu = CPU(obj);
46
+ return cpu->start_powered_off;
40
+}
47
+}
41
+
48
+
42
+static bool trans_VFMA_fp_3s(DisasContext *s, arg_3same *a)
49
+static void cpu_set_start_powered_off(Object *obj, bool value, Error **errp)
43
+{
50
+{
44
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
51
+ CPUState *cpu = CPU(obj);
45
+ return false;
52
+ cpu->start_powered_off = value;
46
+ }
47
+
48
+ if (a->size != 0) {
49
+ /* TODO fp16 support */
50
+ return false;
51
+ }
52
+
53
+ return do_3same_fp(s, a, gen_VFMA_fp_3s, true);
54
+}
53
+}
55
+
54
+
56
+static void gen_VFMS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
55
void cpu_class_init_props(DeviceClass *dc)
57
+ TCGv_ptr fpstatus)
56
{
58
+{
57
+ ObjectClass *oc = OBJECT_CLASS(dc);
59
+ gen_helper_vfp_negs(vn, vn);
60
+ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
61
+}
62
+
58
+
63
+static bool trans_VFMS_fp_3s(DisasContext *s, arg_3same *a)
59
device_class_set_props(dc, cpu_common_props);
64
+{
60
+ /*
65
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
61
+ * We can't use DEFINE_PROP_BOOL in the Property array for this
66
+ return false;
62
+ * property, because we want this to be settable after realize.
67
+ }
63
+ */
68
+
64
+ object_class_property_add_bool(oc, "start-powered-off",
69
+ if (a->size != 0) {
65
+ cpu_get_start_powered_off,
70
+ /* TODO fp16 support */
66
+ cpu_set_start_powered_off);
71
+ return false;
72
+ }
73
+
74
+ return do_3same_fp(s, a, gen_VFMS_fp_3s, true);
75
+}
76
+
77
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
78
{
79
/* FP operations handled pairwise 32 bits at a time */
80
diff --git a/target/arm/translate.c b/target/arm/translate.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate.c
83
+++ b/target/arm/translate.c
84
@@ -XXX,XX +XXX,XX @@ static void gen_neon_narrow_op(int op, int u, int size,
85
}
86
}
67
}
87
68
88
-/* Symbolic constants for op fields for Neon 3-register same-length.
69
void cpu_exec_initfn(CPUState *cpu)
89
- * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
90
- * table A7-9.
91
- */
92
-#define NEON_3R_VHADD 0
93
-#define NEON_3R_VQADD 1
94
-#define NEON_3R_VRHADD 2
95
-#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
96
-#define NEON_3R_VHSUB 4
97
-#define NEON_3R_VQSUB 5
98
-#define NEON_3R_VCGT 6
99
-#define NEON_3R_VCGE 7
100
-#define NEON_3R_VSHL 8
101
-#define NEON_3R_VQSHL 9
102
-#define NEON_3R_VRSHL 10
103
-#define NEON_3R_VQRSHL 11
104
-#define NEON_3R_VMAX 12
105
-#define NEON_3R_VMIN 13
106
-#define NEON_3R_VABD 14
107
-#define NEON_3R_VABA 15
108
-#define NEON_3R_VADD_VSUB 16
109
-#define NEON_3R_VTST_VCEQ 17
110
-#define NEON_3R_VML 18 /* VMLA, VMLS */
111
-#define NEON_3R_VMUL 19
112
-#define NEON_3R_VPMAX 20
113
-#define NEON_3R_VPMIN 21
114
-#define NEON_3R_VQDMULH_VQRDMULH 22
115
-#define NEON_3R_VPADD_VQRDMLAH 23
116
-#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
117
-#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
118
-#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
119
-#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
120
-#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
121
-#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
122
-#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
123
-#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
124
-
125
-static const uint8_t neon_3r_sizes[] = {
126
- [NEON_3R_VHADD] = 0x7,
127
- [NEON_3R_VQADD] = 0xf,
128
- [NEON_3R_VRHADD] = 0x7,
129
- [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
130
- [NEON_3R_VHSUB] = 0x7,
131
- [NEON_3R_VQSUB] = 0xf,
132
- [NEON_3R_VCGT] = 0x7,
133
- [NEON_3R_VCGE] = 0x7,
134
- [NEON_3R_VSHL] = 0xf,
135
- [NEON_3R_VQSHL] = 0xf,
136
- [NEON_3R_VRSHL] = 0xf,
137
- [NEON_3R_VQRSHL] = 0xf,
138
- [NEON_3R_VMAX] = 0x7,
139
- [NEON_3R_VMIN] = 0x7,
140
- [NEON_3R_VABD] = 0x7,
141
- [NEON_3R_VABA] = 0x7,
142
- [NEON_3R_VADD_VSUB] = 0xf,
143
- [NEON_3R_VTST_VCEQ] = 0x7,
144
- [NEON_3R_VML] = 0x7,
145
- [NEON_3R_VMUL] = 0x7,
146
- [NEON_3R_VPMAX] = 0x7,
147
- [NEON_3R_VPMIN] = 0x7,
148
- [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
149
- [NEON_3R_VPADD_VQRDMLAH] = 0x7,
150
- [NEON_3R_SHA] = 0xf, /* size field encodes op type */
151
- [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
152
- [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
153
- [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
154
- [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
155
- [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
156
- [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
157
- [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
158
-};
159
-
160
/* Symbolic constants for op fields for Neon 2-register miscellaneous.
161
* The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
162
* table A7-13.
163
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
164
rm_ofs = neon_reg_offset(rm, 0);
165
166
if ((insn & (1 << 23)) == 0) {
167
- /* Three register same length. */
168
- op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
169
- /* Catch invalid op and bad size combinations: UNDEF */
170
- if ((neon_3r_sizes[op] & (1 << size)) == 0) {
171
- return 1;
172
- }
173
- /* All insns of this form UNDEF for either this condition or the
174
- * superset of cases "Q==1"; we catch the latter later.
175
- */
176
- if (q && ((rd | rn | rm) & 1)) {
177
- return 1;
178
- }
179
- switch (op) {
180
- case NEON_3R_VFM_VQRDMLSH:
181
- if (!u) {
182
- /* VFM, VFMS */
183
- if (size == 1) {
184
- return 1;
185
- }
186
- break;
187
- }
188
- /* VQRDMLSH : handled by decodetree */
189
- return 1;
190
-
191
- case NEON_3R_VADD_VSUB:
192
- case NEON_3R_LOGIC:
193
- case NEON_3R_VMAX:
194
- case NEON_3R_VMIN:
195
- case NEON_3R_VTST_VCEQ:
196
- case NEON_3R_VCGT:
197
- case NEON_3R_VCGE:
198
- case NEON_3R_VQADD:
199
- case NEON_3R_VQSUB:
200
- case NEON_3R_VMUL:
201
- case NEON_3R_VML:
202
- case NEON_3R_VSHL:
203
- case NEON_3R_SHA:
204
- case NEON_3R_VHADD:
205
- case NEON_3R_VRHADD:
206
- case NEON_3R_VHSUB:
207
- case NEON_3R_VABD:
208
- case NEON_3R_VABA:
209
- case NEON_3R_VQSHL:
210
- case NEON_3R_VRSHL:
211
- case NEON_3R_VQRSHL:
212
- case NEON_3R_VPMAX:
213
- case NEON_3R_VPMIN:
214
- case NEON_3R_VPADD_VQRDMLAH:
215
- case NEON_3R_VQDMULH_VQRDMULH:
216
- case NEON_3R_FLOAT_ARITH:
217
- case NEON_3R_FLOAT_MULTIPLY:
218
- case NEON_3R_FLOAT_CMP:
219
- case NEON_3R_FLOAT_ACMP:
220
- case NEON_3R_FLOAT_MINMAX:
221
- case NEON_3R_FLOAT_MISC:
222
- /* Already handled by decodetree */
223
- return 1;
224
- }
225
-
226
- if (size == 3) {
227
- /* 64-bit element instructions: handled by decodetree */
228
- return 1;
229
- }
230
- switch (op) {
231
- case NEON_3R_VFM_VQRDMLSH:
232
- if (!dc_isar_feature(aa32_simdfmac, s)) {
233
- return 1;
234
- }
235
- break;
236
- default:
237
- break;
238
- }
239
-
240
- for (pass = 0; pass < (q ? 4 : 2); pass++) {
241
-
242
- /* Elementwise. */
243
- tmp = neon_load_reg(rn, pass);
244
- tmp2 = neon_load_reg(rm, pass);
245
- switch (op) {
246
- case NEON_3R_VFM_VQRDMLSH:
247
- {
248
- /* VFMA, VFMS: fused multiply-add */
249
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
250
- TCGv_i32 tmp3 = neon_load_reg(rd, pass);
251
- if (size) {
252
- /* VFMS */
253
- gen_helper_vfp_negs(tmp, tmp);
254
- }
255
- gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
256
- tcg_temp_free_i32(tmp3);
257
- tcg_temp_free_ptr(fpstatus);
258
- break;
259
- }
260
- default:
261
- abort();
262
- }
263
- tcg_temp_free_i32(tmp2);
264
-
265
- neon_store_reg(rd, pass, tmp);
266
-
267
- } /* for pass */
268
- /* End of 3 register same size operations. */
269
+ /* Three register same length: handled by decodetree */
270
+ return 1;
271
} else if (insn & (1 << 4)) {
272
if ((insn & 0x00380080) != 0) {
273
/* Two registers and shift. */
274
--
70
--
275
2.20.1
71
2.25.1
276
72
277
73
diff view generated by jsdifflib
1
Convert the Neon integer VPMAX and VPMIN 3-reg-same insns to
1
Currently we expect board code to set the psci-conduit property on
2
decodetree. These are 'pairwise' operations.
2
CPUs and ensure that secondary CPUs are created with the
3
start-powered-off property set to false, if the board wishes to use
4
QEMU's builtin PSCI emulation. This worked OK for the virt board
5
where we first wanted to use it, because the virt board directly
6
creates its CPUs and is in a reasonable position to set those
7
properties. For other boards which model real hardware and use a
8
separate SoC object, however, it is more awkward. Most PSCI-using
9
boards just set the psci-conduit board unconditionally.
10
11
This was never strictly speaking correct (because you would not be
12
able to run EL3 guest firmware that itself provided the PSCI
13
interface, as the QEMU implementation would overrule it), but mostly
14
worked in practice because for non-PSCI SMC calls QEMU would emulate
15
the SMC instruction as normal (by trapping to guest EL3). However,
16
we would like to make our PSCI emulation follow the part of the SMCC
17
specification that mandates that SMC calls with unknown function
18
identifiers return a failure code, which means that all SMC calls
19
will be handled by the PSCI code and the "emulate as normal" path
20
will no longer be taken.
21
22
We tried to implement that in commit 9fcd15b9193e81
23
("arm: tcg: Adhere to SMCCC 1.3 section 5.2"), but this
24
regressed attempts to run EL3 guest code on the affected boards:
25
* mcimx6ul-evk, mcimx7d-sabre, orangepi, xlnx-zcu102
26
* for the case only of EL3 code loaded via -kernel (and
27
not via -bios or -pflash), virt and xlnx-versal-virt
28
so for the 7.0 release we reverted it (in commit 4825eaae4fdd56f).
29
30
This commit provides a mechanism that boards can use to arrange that
31
psci-conduit is set if running guest code at a low enough EL but not
32
if it would be running at the same EL that the conduit implies that
33
the QEMU PSCI implementation is using. (Later commits will convert
34
individual board models to use this mechanism.)
35
36
We do this by moving the setting of the psci-conduit and
37
start-powered-off properties to arm_load_kernel(). Boards which want
38
to potentially use emulated PSCI must set a psci_conduit field in the
39
arm_boot_info struct to the type of conduit they want to use (SMC or
40
HVC); arm_load_kernel() will then set the CPUs up accordingly if it
41
is not going to start the guest code at the same or higher EL as the
42
fake QEMU firmware would be at.
43
44
Board/SoC code which uses this mechanism should no longer set the CPU
45
psci-conduit property directly. It should only set the
46
start-powered-off property for secondaries if EL3 guest firmware
47
running bare metal expects that rather than the alternative "all CPUs
48
start executing the firmware at once".
49
50
Note that when calculating whether we are going to run guest
51
code at EL3, we ignore the setting of arm_boot_info::secure_board_setup,
52
which might cause us to run a stub bit of guest code at EL3 which
53
does some board-specific setup before dropping to EL2 or EL1 to
54
run the guest kernel. This is OK because only one board that
55
enables PSCI sets secure_board_setup (the highbank board), and
56
the stub code it writes will behave the same way whether the
57
one SMC call it makes is handled by "emulate the SMC" or by
58
"PSCI default returns an error code". So we can leave that stub
59
code in place until after we've changed the PSCI default behaviour;
60
at that point we will remove it.
3
61
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
62
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
63
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200512163904.10918-9-peter.maydell@linaro.org
64
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
65
Tested-by: Cédric Le Goater <clg@kaod.org>
66
Message-id: 20220127154639.2090164-4-peter.maydell@linaro.org
7
---
67
---
8
target/arm/neon-dp.decode | 9 +++++
68
include/hw/arm/boot.h | 10 +++++++++
9
target/arm/translate-neon.inc.c | 71 +++++++++++++++++++++++++++++++++
69
hw/arm/boot.c | 50 +++++++++++++++++++++++++++++++++++++++++++
10
target/arm/translate.c | 17 +-------
70
2 files changed, 60 insertions(+)
11
3 files changed, 82 insertions(+), 15 deletions(-)
12
71
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
72
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
14
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
74
--- a/include/hw/arm/boot.h
16
+++ b/target/arm/neon-dp.decode
75
+++ b/include/hw/arm/boot.h
17
@@ -XXX,XX +XXX,XX @@
76
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info {
18
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
77
* the user it should implement this hook.
19
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
78
*/
20
79
void (*modify_dtb)(const struct arm_boot_info *info, void *fdt);
21
+@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
80
+ /*
22
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
81
+ * If a board wants to use the QEMU emulated-firmware PSCI support,
82
+ * it should set this to QEMU_PSCI_CONDUIT_HVC or QEMU_PSCI_CONDUIT_SMC
83
+ * as appropriate. arm_load_kernel() will set the psci-conduit and
84
+ * start-powered-off properties on the CPUs accordingly.
85
+ * Note that if the guest image is started at the same exception level
86
+ * as the conduit specifies calls should go to (eg guest firmware booted
87
+ * to EL3) then PSCI will not be enabled.
88
+ */
89
+ int psci_conduit;
90
/* Used internally by arm_boot.c */
91
int is_linux;
92
hwaddr initrd_start;
93
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/hw/arm/boot.c
96
+++ b/hw/arm/boot.c
97
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
98
{
99
CPUState *cs;
100
AddressSpace *as = arm_boot_address_space(cpu, info);
101
+ int boot_el;
102
+ CPUARMState *env = &cpu->env;
103
104
/*
105
* CPU objects (unlike devices) are not automatically reset on system
106
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
107
arm_setup_direct_kernel_boot(cpu, info);
108
}
109
110
+ /*
111
+ * Disable the PSCI conduit if it is set up to target the same
112
+ * or a lower EL than the one we're going to start the guest code in.
113
+ * This logic needs to agree with the code in do_cpu_reset() which
114
+ * decides whether we're going to boot the guest in the highest
115
+ * supported exception level or in a lower one.
116
+ */
23
+
117
+
24
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
118
+ /* Boot into highest supported EL ... */
25
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
119
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
26
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
120
+ boot_el = 3;
27
@@ -XXX,XX +XXX,XX @@ VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same
121
+ } else if (arm_feature(env, ARM_FEATURE_EL2)) {
28
VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
122
+ boot_el = 2;
29
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
123
+ } else {
30
124
+ boot_el = 1;
31
+VPMAX_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 0 .... @3same_q0
125
+ }
32
+VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
126
+ /* ...except that if we're booting Linux we adjust the EL we boot into */
33
+
127
+ if (info->is_linux && !info->secure_boot) {
34
+VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
128
+ boot_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
35
+VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
36
+
37
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
38
39
SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
40
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/translate-neon.inc.c
43
+++ b/target/arm/translate-neon.inc.c
44
@@ -XXX,XX +XXX,XX @@ DO_3SAME_32_ENV(VQSHL_S, qshl_s)
45
DO_3SAME_32_ENV(VQSHL_U, qshl_u)
46
DO_3SAME_32_ENV(VQRSHL_S, qrshl_s)
47
DO_3SAME_32_ENV(VQRSHL_U, qrshl_u)
48
+
49
+static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn)
50
+{
51
+ /* Operations handled pairwise 32 bits at a time */
52
+ TCGv_i32 tmp, tmp2, tmp3;
53
+
54
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
55
+ return false;
56
+ }
129
+ }
57
+
130
+
58
+ /* UNDEF accesses to D16-D31 if they don't exist. */
131
+ if ((info->psci_conduit == QEMU_PSCI_CONDUIT_HVC && boot_el >= 2) ||
59
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
132
+ (info->psci_conduit == QEMU_PSCI_CONDUIT_SMC && boot_el == 3)) {
60
+ ((a->vd | a->vn | a->vm) & 0x10)) {
133
+ info->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
61
+ return false;
62
+ }
134
+ }
63
+
135
+
64
+ if (a->size == 3) {
136
+ if (info->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
65
+ return false;
137
+ for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
138
+ Object *cpuobj = OBJECT(cs);
139
+
140
+ object_property_set_int(cpuobj, "psci-conduit", info->psci_conduit,
141
+ &error_abort);
142
+ /*
143
+ * Secondary CPUs start in PSCI powered-down state. Like the
144
+ * code in do_cpu_reset(), we assume first_cpu is the primary
145
+ * CPU.
146
+ */
147
+ if (cs != first_cpu) {
148
+ object_property_set_bool(cpuobj, "start-powered-off", true,
149
+ &error_abort);
150
+ }
151
+ }
66
+ }
152
+ }
67
+
153
+
68
+ if (!vfp_access_check(s)) {
69
+ return true;
70
+ }
71
+
72
+ assert(a->q == 0); /* enforced by decode patterns */
73
+
74
+ /*
154
+ /*
75
+ * Note that we have to be careful not to clobber the source operands
155
+ * arm_load_dtb() may add a PSCI node so it must be called after we have
76
+ * in the "vm == vd" case by storing the result of the first pass too
156
+ * decided whether to enable PSCI and set the psci-conduit CPU properties.
77
+ * early. Since Q is 0 there are always just two passes, so instead
78
+ * of a complicated loop over each pass we just unroll.
79
+ */
157
+ */
80
+ tmp = neon_load_reg(a->vn, 0);
158
if (!info->skip_dtb_autoload && have_dtb(info)) {
81
+ tmp2 = neon_load_reg(a->vn, 1);
159
if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) {
82
+ fn(tmp, tmp, tmp2);
160
exit(1);
83
+ tcg_temp_free_i32(tmp2);
84
+
85
+ tmp3 = neon_load_reg(a->vm, 0);
86
+ tmp2 = neon_load_reg(a->vm, 1);
87
+ fn(tmp3, tmp3, tmp2);
88
+ tcg_temp_free_i32(tmp2);
89
+
90
+ neon_store_reg(a->vd, 0, tmp);
91
+ neon_store_reg(a->vd, 1, tmp3);
92
+ return true;
93
+}
94
+
95
+#define DO_3SAME_PAIR(INSN, func) \
96
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
97
+ { \
98
+ static NeonGenTwoOpFn * const fns[] = { \
99
+ gen_helper_neon_##func##8, \
100
+ gen_helper_neon_##func##16, \
101
+ gen_helper_neon_##func##32, \
102
+ }; \
103
+ if (a->size > 2) { \
104
+ return false; \
105
+ } \
106
+ return do_3same_pair(s, a, fns[a->size]); \
107
+ }
108
+
109
+/* 32-bit pairwise ops end up the same as the elementwise versions. */
110
+#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
111
+#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
112
+#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
113
+#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
114
+
115
+DO_3SAME_PAIR(VPMAX_S, pmax_s)
116
+DO_3SAME_PAIR(VPMIN_S, pmin_s)
117
+DO_3SAME_PAIR(VPMAX_U, pmax_u)
118
+DO_3SAME_PAIR(VPMIN_U, pmin_u)
119
diff --git a/target/arm/translate.c b/target/arm/translate.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/target/arm/translate.c
122
+++ b/target/arm/translate.c
123
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
124
}
125
}
126
127
-/* 32-bit pairwise ops end up the same as the elementwise versions. */
128
-#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
129
-#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
130
-#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
131
-#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
132
-
133
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
134
switch ((size << 1) | u) { \
135
case 0: \
136
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
137
case NEON_3R_VQSHL:
138
case NEON_3R_VRSHL:
139
case NEON_3R_VQRSHL:
140
+ case NEON_3R_VPMAX:
141
+ case NEON_3R_VPMIN:
142
/* Already handled by decodetree */
143
return 1;
144
}
145
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
146
pairwise = 0;
147
switch (op) {
148
case NEON_3R_VPADD_VQRDMLAH:
149
- case NEON_3R_VPMAX:
150
- case NEON_3R_VPMIN:
151
pairwise = 1;
152
break;
153
case NEON_3R_FLOAT_ARITH:
154
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
155
tmp2 = neon_load_reg(rm, pass);
156
}
157
switch (op) {
158
- break;
159
- case NEON_3R_VPMAX:
160
- GEN_NEON_INTEGER_OP(pmax);
161
- break;
162
- case NEON_3R_VPMIN:
163
- GEN_NEON_INTEGER_OP(pmin);
164
- break;
165
case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
166
if (!u) { /* VQDMULH */
167
switch (size) {
168
--
161
--
169
2.20.1
162
2.25.1
170
163
171
164
diff view generated by jsdifflib
1
Convert the Neon VQDMULH and VQRDMULH 3-reg-same insns to
1
Change the iMX-SoC based boards to use the new boot.c functionality
2
decodetree. These are the last integer operations in the
2
to allow us to enable psci-conduit only if the guest is being booted
3
3-reg-same group.
3
in EL1 or EL2, so that if the user runs guest EL3 firmware code our
4
PSCI emulation doesn't get in its way.
5
6
To do this we stop setting the psci-conduit property on the CPU
7
objects in the SoC code, and instead set the psci_conduit field in
8
the arm_boot_info struct to tell the common boot loader code that
9
we'd like PSCI if the guest is starting at an EL that it makes
10
sense with.
11
12
This affects the mcimx6ul-evk and mcimx7d-sabre boards.
13
14
Note that for the mcimx7d board, this means that when running guest
15
code at EL3 there is currently no way to power on the secondary CPUs,
16
because we do not currently have a model of the system reset
17
controller module which should be used to do that for the imx7 SoC,
18
only for the imx6 SoC. (Previously EL3 code which knew it was
19
running on QEMU could use a PSCI call to do this.) This doesn't
20
affect the imx6ul-evk board because it is uniprocessor.
4
21
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-11-peter.maydell@linaro.org
24
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Tested-by: Cédric Le Goater <clg@kaod.org>
26
Acked-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20220127154639.2090164-5-peter.maydell@linaro.org
8
---
28
---
9
target/arm/neon-dp.decode | 3 +++
29
hw/arm/fsl-imx6ul.c | 2 --
10
target/arm/translate-neon.inc.c | 24 ++++++++++++++++++++++++
30
hw/arm/fsl-imx7.c | 8 ++++----
11
target/arm/translate.c | 24 +-----------------------
31
hw/arm/mcimx6ul-evk.c | 1 +
12
3 files changed, 28 insertions(+), 23 deletions(-)
32
hw/arm/mcimx7d-sabre.c | 1 +
33
4 files changed, 6 insertions(+), 6 deletions(-)
13
34
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
35
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
15
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
37
--- a/hw/arm/fsl-imx6ul.c
17
+++ b/target/arm/neon-dp.decode
38
+++ b/hw/arm/fsl-imx6ul.c
18
@@ -XXX,XX +XXX,XX @@ VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
39
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
19
VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
40
return;
20
VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
41
}
21
42
22
+VQDMULH_3s 1111 001 0 0 . .. .... .... 1011 . . . 0 .... @3same
43
- object_property_set_int(OBJECT(&s->cpu), "psci-conduit",
23
+VQRDMULH_3s 1111 001 1 0 . .. .... .... 1011 . . . 0 .... @3same
44
- QEMU_PSCI_CONDUIT_SMC, &error_abort);
24
+
45
qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
25
VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0
46
26
47
/*
27
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
48
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
29
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-neon.inc.c
50
--- a/hw/arm/fsl-imx7.c
31
+++ b/target/arm/translate-neon.inc.c
51
+++ b/hw/arm/fsl-imx7.c
32
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPMIN_S, pmin_s)
52
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
33
DO_3SAME_PAIR(VPMAX_U, pmax_u)
53
for (i = 0; i < smp_cpus; i++) {
34
DO_3SAME_PAIR(VPMIN_U, pmin_u)
54
o = OBJECT(&s->cpu[i]);
35
DO_3SAME_PAIR(VPADD, padd_u)
55
36
+
56
- object_property_set_int(o, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
37
+#define DO_3SAME_VQDMULH(INSN, FUNC) \
57
- &error_abort);
38
+ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##_s16); \
58
-
39
+ WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##_s32); \
59
/* On uniprocessor, the CBAR is set to 0 */
40
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
60
if (smp_cpus > 1) {
41
+ uint32_t rn_ofs, uint32_t rm_ofs, \
61
object_property_set_int(o, "reset-cbar", FSL_IMX7_A7MPCORE_ADDR,
42
+ uint32_t oprsz, uint32_t maxsz) \
62
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
43
+ { \
63
}
44
+ static const GVecGen3 ops[2] = { \
64
45
+ { .fni4 = gen_##INSN##_tramp16 }, \
65
if (i) {
46
+ { .fni4 = gen_##INSN##_tramp32 }, \
66
- /* Secondary CPUs start in PSCI powered-down state */
47
+ }; \
67
+ /*
48
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece - 1]); \
68
+ * Secondary CPUs start in powered-down state (and can be
49
+ } \
69
+ * powered up via the SRC system reset controller)
50
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
70
+ */
51
+ { \
71
object_property_set_bool(o, "start-powered-off", true,
52
+ if (a->size != 1 && a->size != 2) { \
72
&error_abort);
53
+ return false; \
73
}
54
+ } \
74
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
55
+ return do_3same(s, a, gen_##INSN##_3s); \
56
+ }
57
+
58
+DO_3SAME_VQDMULH(VQDMULH, qdmulh)
59
+DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
60
diff --git a/target/arm/translate.c b/target/arm/translate.c
61
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/translate.c
76
--- a/hw/arm/mcimx6ul-evk.c
63
+++ b/target/arm/translate.c
77
+++ b/hw/arm/mcimx6ul-evk.c
64
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
78
@@ -XXX,XX +XXX,XX @@ static void mcimx6ul_evk_init(MachineState *machine)
65
case NEON_3R_VPMAX:
79
.board_id = -1,
66
case NEON_3R_VPMIN:
80
.ram_size = machine->ram_size,
67
case NEON_3R_VPADD_VQRDMLAH:
81
.nb_cpus = machine->smp.cpus,
68
+ case NEON_3R_VQDMULH_VQRDMULH:
82
+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
69
/* Already handled by decodetree */
83
};
70
return 1;
84
71
}
85
s = FSL_IMX6UL(object_new(TYPE_FSL_IMX6UL));
72
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
86
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
73
tmp2 = neon_load_reg(rm, pass);
87
index XXXXXXX..XXXXXXX 100644
74
}
88
--- a/hw/arm/mcimx7d-sabre.c
75
switch (op) {
89
+++ b/hw/arm/mcimx7d-sabre.c
76
- case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
90
@@ -XXX,XX +XXX,XX @@ static void mcimx7d_sabre_init(MachineState *machine)
77
- if (!u) { /* VQDMULH */
91
.board_id = -1,
78
- switch (size) {
92
.ram_size = machine->ram_size,
79
- case 1:
93
.nb_cpus = machine->smp.cpus,
80
- gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
94
+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
81
- break;
95
};
82
- case 2:
96
83
- gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
97
s = FSL_IMX7(object_new(TYPE_FSL_IMX7));
84
- break;
85
- default: abort();
86
- }
87
- } else { /* VQRDMULH */
88
- switch (size) {
89
- case 1:
90
- gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
91
- break;
92
- case 2:
93
- gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
94
- break;
95
- default: abort();
96
- }
97
- }
98
- break;
99
case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
100
{
101
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
102
--
98
--
103
2.20.1
99
2.25.1
104
100
105
101
diff view generated by jsdifflib
1
The usual location for the env argument in the argument list of a TCG helper
1
Change the allwinner-h3 based board to use the new boot.c
2
is immediately after the return-value argument. recps_f32 and rsqrts_f32
2
functionality to allow us to enable psci-conduit only if the guest is
3
differ in that they put it at the end.
3
being booted in EL1 or EL2, so that if the user runs guest EL3
4
firmware code our PSCI emulation doesn't get in its way.
4
5
5
Move the env argument to its usual place; this will allow us to
6
To do this we stop setting the psci-conduit property on the CPU
6
more easily use these helper functions with the gvec APIs.
7
objects in the SoC code, and instead set the psci_conduit field in
8
the arm_boot_info struct to tell the common boot loader code that
9
we'd like PSCI if the guest is starting at an EL that it makes sense
10
with.
11
12
This affects the orangepi-pc board.
13
14
This commit leaves the secondary CPUs in the powered-down state if
15
the guest is booting at EL3, which is the same behaviour as before
16
this commit. The secondaries can no longer be started by that EL3
17
code making a PSCI call but can still be started via the CPU
18
Configuration Module registers (which we model in
19
hw/misc/allwinner-cpucfg.c).
7
20
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200512163904.10918-16-peter.maydell@linaro.org
23
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
24
Tested-by: Cédric Le Goater <clg@kaod.org>
25
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
26
Message-id: 20220127154639.2090164-6-peter.maydell@linaro.org
11
---
27
---
12
target/arm/helper.h | 4 ++--
28
hw/arm/allwinner-h3.c | 9 ++++-----
13
target/arm/translate.c | 4 ++--
29
hw/arm/orangepi.c | 1 +
14
target/arm/vfp_helper.c | 4 ++--
30
2 files changed, 5 insertions(+), 5 deletions(-)
15
3 files changed, 6 insertions(+), 6 deletions(-)
16
31
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
32
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
18
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
34
--- a/hw/arm/allwinner-h3.c
20
+++ b/target/arm/helper.h
35
+++ b/hw/arm/allwinner-h3.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, f16, f64, ptr, i32)
36
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
22
DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
37
/* CPUs */
23
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
38
for (i = 0; i < AW_H3_NUM_CPUS; i++) {
24
39
25
-DEF_HELPER_3(recps_f32, f32, f32, f32, env)
40
- /* Provide Power State Coordination Interface */
26
-DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
41
- qdev_prop_set_int32(DEVICE(&s->cpus[i]), "psci-conduit",
27
+DEF_HELPER_3(recps_f32, f32, env, f32, f32)
42
- QEMU_PSCI_CONDUIT_SMC);
28
+DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
43
-
29
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
44
- /* Disable secondary CPUs */
30
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
45
+ /*
31
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
46
+ * Disable secondary CPUs. Guest EL3 firmware will start
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
47
+ * them via CPU reset control registers.
48
+ */
49
qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
50
i > 0);
51
52
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
33
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate.c
54
--- a/hw/arm/orangepi.c
35
+++ b/target/arm/translate.c
55
+++ b/hw/arm/orangepi.c
36
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
56
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
37
tcg_temp_free_ptr(fpstatus);
57
}
38
} else {
58
orangepi_binfo.loader_start = h3->memmap[AW_H3_DEV_SDRAM];
39
if (size == 0) {
59
orangepi_binfo.ram_size = machine->ram_size;
40
- gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
60
+ orangepi_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
41
+ gen_helper_recps_f32(tmp, cpu_env, tmp, tmp2);
61
arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
42
} else {
43
- gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
44
+ gen_helper_rsqrts_f32(tmp, cpu_env, tmp, tmp2);
45
}
46
}
47
break;
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/vfp_helper.c
51
+++ b/target/arm/vfp_helper.c
52
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
53
#define float32_three make_float32(0x40400000)
54
#define float32_one_point_five make_float32(0x3fc00000)
55
56
-float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
57
+float32 HELPER(recps_f32)(CPUARMState *env, float32 a, float32 b)
58
{
59
float_status *s = &env->vfp.standard_fp_status;
60
if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
61
@@ -XXX,XX +XXX,XX @@ float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
62
return float32_sub(float32_two, float32_mul(a, b, s), s);
63
}
62
}
64
63
65
-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
66
+float32 HELPER(rsqrts_f32)(CPUARMState *env, float32 a, float32 b)
67
{
68
float_status *s = &env->vfp.standard_fp_status;
69
float32 product;
70
--
64
--
71
2.20.1
65
2.25.1
72
66
73
67
diff view generated by jsdifflib
1
GDB's remote protocol requires M-profile cores to use the feature
1
Change the Xilinx ZynqMP-based board xlnx-zcu102 to use the new
2
name 'org.gnu.gdb.arm.m-profile' instead of the 'org.gnu.gdb.arm.core'
2
boot.c functionality to allow us to enable psci-conduit only if
3
feature used for A- and R-profile cores. We weren't doing this, which
3
the guest is being booted in EL1 or EL2, so that if the user runs
4
meant GDB treated our M-profile cores like A-profile ones. This mostly
4
guest EL3 firmware code our PSCI emulation doesn't get in its
5
doesn't matter, but for instance means that it doesn't correctly
5
way.
6
handle backtraces where an M-profile exception frame is involved.
7
6
8
Ship a copy of GDB's arm-m-profile.xml and use it on the M-profile
7
To do this we stop setting the psci-conduit property on the CPU
9
cores. The integer registers have the same offsets as the
8
objects in the SoC code, and instead set the psci_conduit field in
10
arm-core.xml, but register 25 is the M-profile XPSR rather than the
9
the arm_boot_info struct to tell the common boot loader code that
11
A-profile CPSR, so we need to update arm_cpu_gdb_read_register() and
10
we'd like PSCI if the guest is starting at an EL that it makes
12
arm_cpu_gdb_write_register() to handle XSPR reads and writes.
11
sense with.
13
12
14
Fixes: https://bugs.launchpad.net/qemu/+bug/1877136
13
Note that this means that EL3 guest code will have no way
14
to power on secondary cores, because we don't model any
15
kind of power controller that does that on this SoC.
16
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
17
Message-id: 20200507134755.13997-1-peter.maydell@linaro.org
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
21
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
22
Tested-by: Cédric Le Goater <clg@kaod.org>
23
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
24
Acked-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20220127154639.2090164-7-peter.maydell@linaro.org
18
---
26
---
19
configure | 4 ++--
27
hw/arm/xlnx-zcu102.c | 1 +
20
target/arm/cpu_tcg.c | 1 +
28
hw/arm/xlnx-zynqmp.c | 11 ++++++-----
21
target/arm/gdbstub.c | 22 ++++++++++++++++++----
29
2 files changed, 7 insertions(+), 5 deletions(-)
22
gdb-xml/arm-m-profile.xml | 27 +++++++++++++++++++++++++++
23
4 files changed, 48 insertions(+), 6 deletions(-)
24
create mode 100644 gdb-xml/arm-m-profile.xml
25
30
26
diff --git a/configure b/configure
31
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
27
index XXXXXXX..XXXXXXX 100755
28
--- a/configure
29
+++ b/configure
30
@@ -XXX,XX +XXX,XX @@ case "$target_name" in
31
TARGET_SYSTBL_ABI=common,oabi
32
bflt="yes"
33
mttcg="yes"
34
- gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
35
+ gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
36
;;
37
aarch64|aarch64_be)
38
TARGET_ARCH=aarch64
39
TARGET_BASE_ARCH=arm
40
bflt="yes"
41
mttcg="yes"
42
- gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
43
+ gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
44
;;
45
cris)
46
;;
47
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
48
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/cpu_tcg.c
33
--- a/hw/arm/xlnx-zcu102.c
50
+++ b/target/arm/cpu_tcg.c
34
+++ b/hw/arm/xlnx-zcu102.c
51
@@ -XXX,XX +XXX,XX @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
35
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
52
#endif
36
s->binfo.ram_size = ram_size;
53
37
s->binfo.loader_start = 0;
54
cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
38
s->binfo.modify_dtb = zcu102_modify_dtb;
55
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
39
+ s->binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
40
arm_load_kernel(s->soc.boot_cpu_ptr, machine, &s->binfo);
56
}
41
}
57
42
58
static const ARMCPUInfo arm_tcg_cpus[] = {
43
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
59
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
60
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/gdbstub.c
45
--- a/hw/arm/xlnx-zynqmp.c
62
+++ b/target/arm/gdbstub.c
46
+++ b/hw/arm/xlnx-zynqmp.c
63
@@ -XXX,XX +XXX,XX @@ int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
47
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s,
64
}
48
65
return gdb_get_reg32(mem_buf, 0);
49
name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
66
case 25:
50
if (strcmp(name, boot_cpu)) {
67
- /* CPSR */
51
- /* Secondary CPUs start in PSCI powered-down state */
68
- return gdb_get_reg32(mem_buf, cpsr_read(env));
69
+ /* CPSR, or XPSR for M-profile */
70
+ if (arm_feature(env, ARM_FEATURE_M)) {
71
+ return gdb_get_reg32(mem_buf, xpsr_read(env));
72
+ } else {
73
+ return gdb_get_reg32(mem_buf, cpsr_read(env));
74
+ }
75
}
76
/* Unknown register. */
77
return 0;
78
@@ -XXX,XX +XXX,XX @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
79
}
80
return 4;
81
case 25:
82
- /* CPSR */
83
- cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
84
+ /* CPSR, or XPSR for M-profile */
85
+ if (arm_feature(env, ARM_FEATURE_M)) {
86
+ /*
52
+ /*
87
+ * Don't allow writing to XPSR.Exception as it can cause
53
+ * Secondary CPUs start in powered-down state.
88
+ * a transition into or out of handler mode (it's not
89
+ * writeable via the MSR insn so this is a reasonable
90
+ * restriction). Other fields are safe to update.
91
+ */
54
+ */
92
+ xpsr_write(env, tmp, ~XPSR_EXCP);
55
object_property_set_bool(OBJECT(&s->rpu_cpu[i]),
93
+ } else {
56
"start-powered-off", true, &error_abort);
94
+ cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
57
} else {
95
+ }
58
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
96
return 4;
59
for (i = 0; i < num_apus; i++) {
97
}
60
const char *name;
98
/* Unknown register. */
61
99
diff --git a/gdb-xml/arm-m-profile.xml b/gdb-xml/arm-m-profile.xml
62
- object_property_set_int(OBJECT(&s->apu_cpu[i]), "psci-conduit",
100
new file mode 100644
63
- QEMU_PSCI_CONDUIT_SMC, &error_abort);
101
index XXXXXXX..XXXXXXX
64
-
102
--- /dev/null
65
name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i]));
103
+++ b/gdb-xml/arm-m-profile.xml
66
if (strcmp(name, boot_cpu)) {
104
@@ -XXX,XX +XXX,XX @@
67
- /* Secondary CPUs start in PSCI powered-down state */
105
+<?xml version="1.0"?>
68
+ /*
106
+<!-- Copyright (C) 2010-2020 Free Software Foundation, Inc.
69
+ * Secondary CPUs start in powered-down state.
107
+
70
+ */
108
+ Copying and distribution of this file, with or without modification,
71
object_property_set_bool(OBJECT(&s->apu_cpu[i]),
109
+ are permitted in any medium without royalty provided the copyright
72
"start-powered-off", true, &error_abort);
110
+ notice and this notice are preserved. -->
73
} else {
111
+
112
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
113
+<feature name="org.gnu.gdb.arm.m-profile">
114
+ <reg name="r0" bitsize="32"/>
115
+ <reg name="r1" bitsize="32"/>
116
+ <reg name="r2" bitsize="32"/>
117
+ <reg name="r3" bitsize="32"/>
118
+ <reg name="r4" bitsize="32"/>
119
+ <reg name="r5" bitsize="32"/>
120
+ <reg name="r6" bitsize="32"/>
121
+ <reg name="r7" bitsize="32"/>
122
+ <reg name="r8" bitsize="32"/>
123
+ <reg name="r9" bitsize="32"/>
124
+ <reg name="r10" bitsize="32"/>
125
+ <reg name="r11" bitsize="32"/>
126
+ <reg name="r12" bitsize="32"/>
127
+ <reg name="sp" bitsize="32" type="data_ptr"/>
128
+ <reg name="lr" bitsize="32"/>
129
+ <reg name="pc" bitsize="32" type="code_ptr"/>
130
+ <reg name="xpsr" bitsize="32" regnum="25"/>
131
+</feature>
132
--
74
--
133
2.20.1
75
2.25.1
134
76
135
77
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
Instead of setting the CPU psci-conduit and start-powered-off
2
properties in the xlnx-versal-virt board code, set the arm_boot_info
3
psci_conduit field so that the boot.c code can do it.
2
4
3
Record the GHEB address via fw_cfg file, when recording
5
This will fix a corner case where we were incorrectly enabling PSCI
4
a error to CPER, it will use this address to find out
6
emulation when booting guest code into EL3 because it was an ELF file
5
Generic Error Data Entries and write the error.
7
passed to -kernel. (EL3 guest code started via -bios, -pflash, or
8
the generic loader was already being run with PSCI emulation
9
disabled.)
6
10
7
In order to avoid migration failure, make hardware
11
Note that EL3 guest code has no way to turn on the secondary CPUs
8
error table address to a part of GED device instead
12
because there's no emulated power controller, but this was already
9
of global variable, then this address will be migrated
13
true for EL3 guest code run via -bios, -pflash, or the generic
10
to target QEMU.
14
loader.
11
15
12
Acked-by: Xiang Zheng <zhengxiang9@huawei.com>
13
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
14
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
15
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
16
Message-id: 20200512030609.19593-7-gengdongjiu@huawei.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
20
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
21
Tested-by: Cédric Le Goater <clg@kaod.org>
22
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
23
Message-id: 20220127154639.2090164-8-peter.maydell@linaro.org
18
---
24
---
19
include/hw/acpi/generic_event_device.h | 2 ++
25
include/hw/arm/xlnx-versal.h | 1 -
20
include/hw/acpi/ghes.h | 6 ++++++
26
hw/arm/xlnx-versal-virt.c | 6 ++++--
21
hw/acpi/generic_event_device.c | 19 +++++++++++++++++++
27
hw/arm/xlnx-versal.c | 5 +----
22
hw/acpi/ghes.c | 14 ++++++++++++++
28
3 files changed, 5 insertions(+), 7 deletions(-)
23
hw/arm/virt-acpi-build.c | 8 ++++++++
24
5 files changed, 49 insertions(+)
25
29
26
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
30
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
27
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/acpi/generic_event_device.h
32
--- a/include/hw/arm/xlnx-versal.h
29
+++ b/include/hw/acpi/generic_event_device.h
33
+++ b/include/hw/arm/xlnx-versal.h
30
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@ struct Versal {
31
35
32
#include "hw/sysbus.h"
36
struct {
33
#include "hw/acpi/memory_hotplug.h"
37
MemoryRegion *mr_ddr;
34
+#include "hw/acpi/ghes.h"
38
- uint32_t psci_conduit;
35
39
} cfg;
36
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
40
};
37
41
38
@@ -XXX,XX +XXX,XX @@ typedef struct AcpiGedState {
42
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
39
GEDState ged_state;
40
uint32_t ged_event_bitmap;
41
qemu_irq irq;
42
+ AcpiGhesState ghes_state;
43
} AcpiGedState;
44
45
void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev,
46
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
47
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
48
--- a/include/hw/acpi/ghes.h
44
--- a/hw/arm/xlnx-versal-virt.c
49
+++ b/include/hw/acpi/ghes.h
45
+++ b/hw/arm/xlnx-versal-virt.c
50
@@ -XXX,XX +XXX,XX @@ enum {
46
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
51
ACPI_HEST_SRC_ID_RESERVED,
47
* When loading an OS, we turn on QEMU's PSCI implementation with SMC
48
* as the PSCI conduit. When there's no -kernel, we assume the user
49
* provides EL3 firmware to handle PSCI.
50
+ *
51
+ * Even if the user provides a kernel filename, arm_load_kernel()
52
+ * may suppress PSCI if it's going to boot that guest code at EL3.
53
*/
54
if (machine->kernel_filename) {
55
psci_conduit = QEMU_PSCI_CONDUIT_SMC;
56
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
57
TYPE_XLNX_VERSAL);
58
object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
59
&error_abort);
60
- object_property_set_int(OBJECT(&s->soc), "psci-conduit", psci_conduit,
61
- &error_abort);
62
sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
63
64
fdt_create(s);
65
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
66
s->binfo.loader_start = 0x0;
67
s->binfo.get_dtb = versal_virt_get_dtb;
68
s->binfo.modify_dtb = versal_virt_modify_dtb;
69
+ s->binfo.psci_conduit = psci_conduit;
70
if (machine->kernel_filename) {
71
arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
72
} else {
73
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/arm/xlnx-versal.c
76
+++ b/hw/arm/xlnx-versal.c
77
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
78
object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
79
XLNX_VERSAL_ACPU_TYPE);
80
obj = OBJECT(&s->fpd.apu.cpu[i]);
81
- object_property_set_int(obj, "psci-conduit", s->cfg.psci_conduit,
82
- &error_abort);
83
if (i) {
84
- /* Secondary CPUs start in PSCI powered-down state */
85
+ /* Secondary CPUs start in powered-down state */
86
object_property_set_bool(obj, "start-powered-off", true,
87
&error_abort);
88
}
89
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
90
static Property versal_properties[] = {
91
DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
92
MemoryRegion *),
93
- DEFINE_PROP_UINT32("psci-conduit", Versal, cfg.psci_conduit, 0),
94
DEFINE_PROP_END_OF_LIST()
52
};
95
};
53
96
54
+typedef struct AcpiGhesState {
55
+ uint64_t ghes_addr_le;
56
+} AcpiGhesState;
57
+
58
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
59
void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
60
+void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
61
+ GArray *hardware_errors);
62
#endif
63
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/acpi/generic_event_device.c
66
+++ b/hw/acpi/generic_event_device.c
67
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_ged_state = {
68
}
69
};
70
71
+static bool ghes_needed(void *opaque)
72
+{
73
+ AcpiGedState *s = opaque;
74
+ return s->ghes_state.ghes_addr_le;
75
+}
76
+
77
+static const VMStateDescription vmstate_ghes_state = {
78
+ .name = "acpi-ged/ghes",
79
+ .version_id = 1,
80
+ .minimum_version_id = 1,
81
+ .needed = ghes_needed,
82
+ .fields = (VMStateField[]) {
83
+ VMSTATE_STRUCT(ghes_state, AcpiGedState, 1,
84
+ vmstate_ghes_state, AcpiGhesState),
85
+ VMSTATE_END_OF_LIST()
86
+ }
87
+};
88
+
89
static const VMStateDescription vmstate_acpi_ged = {
90
.name = "acpi-ged",
91
.version_id = 1,
92
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_acpi_ged = {
93
},
94
.subsections = (const VMStateDescription * []) {
95
&vmstate_memhp_state,
96
+ &vmstate_ghes_state,
97
NULL
98
}
99
};
100
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/hw/acpi/ghes.c
103
+++ b/hw/acpi/ghes.c
104
@@ -XXX,XX +XXX,XX @@
105
#include "hw/acpi/ghes.h"
106
#include "hw/acpi/aml-build.h"
107
#include "qemu/error-report.h"
108
+#include "hw/acpi/generic_event_device.h"
109
+#include "hw/nvram/fw_cfg.h"
110
111
#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
112
#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
113
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker)
114
build_header(linker, table_data, (void *)(table_data->data + hest_start),
115
"HEST", table_data->len - hest_start, 1, NULL, NULL);
116
}
117
+
118
+void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
119
+ GArray *hardware_error)
120
+{
121
+ /* Create a read-only fw_cfg file for GHES */
122
+ fw_cfg_add_file(s, ACPI_GHES_ERRORS_FW_CFG_FILE, hardware_error->data,
123
+ hardware_error->len);
124
+
125
+ /* Create a read-write fw_cfg file for Address */
126
+ fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
127
+ NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
128
+}
129
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/virt-acpi-build.c
132
+++ b/hw/arm/virt-acpi-build.c
133
@@ -XXX,XX +XXX,XX @@ void virt_acpi_setup(VirtMachineState *vms)
134
{
135
AcpiBuildTables tables;
136
AcpiBuildState *build_state;
137
+ AcpiGedState *acpi_ged_state;
138
139
if (!vms->fw_cfg) {
140
trace_virt_acpi_setup();
141
@@ -XXX,XX +XXX,XX @@ void virt_acpi_setup(VirtMachineState *vms)
142
fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
143
acpi_data_len(tables.tcpalog));
144
145
+ if (vms->ras) {
146
+ assert(vms->acpi_dev);
147
+ acpi_ged_state = ACPI_GED(vms->acpi_dev);
148
+ acpi_ghes_add_fw_cfg(&acpi_ged_state->ghes_state,
149
+ vms->fw_cfg, tables.hardware_errors);
150
+ }
151
+
152
build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update,
153
build_state, tables.rsdp,
154
ACPI_BUILD_RSDP_FILE, 0);
155
--
97
--
156
2.20.1
98
2.25.1
157
99
158
100
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
Instead of setting the CPU psci-conduit and start-powered-off
2
properties in the virt board code, set the arm_boot_info psci_conduit
3
field so that the boot.c code can do it.
2
4
3
RAS Virtualization feature is not supported now, so
5
This will fix a corner case where we were incorrectly enabling PSCI
4
add a RAS machine option and disable it by default.
6
emulation when booting guest code into EL3 because it was an ELF file
7
passed to -kernel or to the generic loader. (EL3 guest code started
8
via -bios or -pflash was already being run with PSCI emulation
9
disabled.)
5
10
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
8
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
9
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
10
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
11
Message-id: 20200512030609.19593-3-gengdongjiu@huawei.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
Tested-by: Cédric Le Goater <clg@kaod.org>
15
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
16
Message-id: 20220127154639.2090164-9-peter.maydell@linaro.org
13
---
17
---
14
include/hw/arm/virt.h | 1 +
18
hw/arm/virt.c | 12 +-----------
15
hw/arm/virt.c | 23 +++++++++++++++++++++++
19
1 file changed, 1 insertion(+), 11 deletions(-)
16
2 files changed, 24 insertions(+)
17
20
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/virt.h
21
+++ b/include/hw/arm/virt.h
22
@@ -XXX,XX +XXX,XX @@ typedef struct {
23
bool highmem_ecam;
24
bool its;
25
bool virt;
26
+ bool ras;
27
OnOffAuto acpi;
28
VirtGICType gic_version;
29
VirtIOMMUType iommu;
30
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
21
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
31
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/virt.c
23
--- a/hw/arm/virt.c
33
+++ b/hw/arm/virt.c
24
+++ b/hw/arm/virt.c
34
@@ -XXX,XX +XXX,XX @@ static void virt_set_acpi(Object *obj, Visitor *v, const char *name,
25
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
35
visit_type_OnOffAuto(v, name, &vms->acpi, errp);
26
object_property_set_bool(cpuobj, "has_el2", false, NULL);
36
}
27
}
37
28
38
+static bool virt_get_ras(Object *obj, Error **errp)
29
- if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
39
+{
30
- object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit,
40
+ VirtMachineState *vms = VIRT_MACHINE(obj);
31
- NULL);
41
+
32
-
42
+ return vms->ras;
33
- /* Secondary CPUs start in PSCI powered-down state */
43
+}
34
- if (n > 0) {
44
+
35
- object_property_set_bool(cpuobj, "start-powered-off", true,
45
+static void virt_set_ras(Object *obj, bool value, Error **errp)
36
- NULL);
46
+{
37
- }
47
+ VirtMachineState *vms = VIRT_MACHINE(obj);
38
- }
48
+
39
-
49
+ vms->ras = value;
40
if (vmc->kvm_no_adjvtime &&
50
+}
41
object_property_find(cpuobj, "kvm-no-adjvtime")) {
51
+
42
object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL);
52
static char *virt_get_gic_version(Object *obj, Error **errp)
43
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
53
{
44
vms->bootinfo.get_dtb = machvirt_dtb;
54
VirtMachineState *vms = VIRT_MACHINE(obj);
45
vms->bootinfo.skip_dtb_autoload = true;
55
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
46
vms->bootinfo.firmware_loaded = firmware_loaded;
56
"Valid values are none and smmuv3",
47
+ vms->bootinfo.psci_conduit = vms->psci_conduit;
57
NULL);
48
arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo);
58
49
59
+ /* Default disallows RAS instantiation */
50
vms->machine_done.notify = virt_machine_done;
60
+ vms->ras = false;
61
+ object_property_add_bool(obj, "ras", virt_get_ras,
62
+ virt_set_ras, NULL);
63
+ object_property_set_description(obj, "ras",
64
+ "Set on/off to enable/disable reporting host memory errors "
65
+ "to a KVM guest using ACPI and guest external abort exceptions",
66
+ NULL);
67
+
68
vms->irqmap = a15irqmap;
69
70
virt_flash_create(vms);
71
--
51
--
72
2.20.1
52
2.25.1
73
53
74
54
diff view generated by jsdifflib
1
Convert the Neon float VPMIN, VPMAX and VPADD 3-reg-same insns to
1
Change the highbank/midway boards to use the new boot.c functionality
2
decodetree. These are the only remaining 'pairwise' operations,
2
to allow us to enable psci-conduit only if the guest is being booted
3
so we can delete the pairwise-specific bits of the old decoder's
3
in EL1 or EL2, so that if the user runs guest EL3 firmware code our
4
for-each-element loop now.
4
PSCI emulation doesn't get in its way.
5
6
To do this we stop setting the psci-conduit and start-powered-off
7
properties on the CPU objects in the board code, and instead set the
8
psci_conduit field in the arm_boot_info struct to tell the common
9
boot loader code that we'd like PSCI if the guest is starting at an
10
EL that it makes sense with (in which case it will set these
11
properties).
12
13
This means that when running guest code at EL3, all the cores
14
will start execution at once on poweron. This matches the
15
real hardware behaviour. (A brief description of the hardware
16
boot process is in the u-boot documentation for these boards:
17
https://u-boot.readthedocs.io/en/latest/board/highbank/highbank.html#boot-process
18
-- in theory one might run the 'a9boot'/'a15boot' secure monitor
19
code in QEMU, though we probably don't emulate enough for that.)
20
21
This affects the highbank and midway boards.
5
22
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200512163904.10918-13-peter.maydell@linaro.org
25
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
26
Tested-by: Cédric Le Goater <clg@kaod.org>
27
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
28
Message-id: 20220127154639.2090164-10-peter.maydell@linaro.org
9
---
29
---
10
target/arm/neon-dp.decode | 5 +++
30
hw/arm/highbank.c | 7 +------
11
target/arm/translate-neon.inc.c | 63 +++++++++++++++++++++++++++++++++
31
1 file changed, 1 insertion(+), 6 deletions(-)
12
target/arm/translate.c | 63 +++++----------------------------
13
3 files changed, 76 insertions(+), 55 deletions(-)
14
32
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
33
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
16
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
35
--- a/hw/arm/highbank.c
18
+++ b/target/arm/neon-dp.decode
36
+++ b/hw/arm/highbank.c
19
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
20
# For FP insns the high bit of 'size' is used as part of opcode decode
38
object_property_set_int(cpuobj, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
21
@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
39
&error_abort);
22
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
40
23
+@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \
41
- if (n) {
24
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
42
- /* Secondary CPUs start in PSCI powered-down state */
25
43
- object_property_set_bool(cpuobj, "start-powered-off", true,
26
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
44
- &error_abort);
27
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
28
@@ -XXX,XX +XXX,XX @@ VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
29
30
VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
31
VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
32
+VPADD_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 0 .... @3same_fp_q0
33
VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
34
+VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
35
+VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
36
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-neon.inc.c
39
+++ b/target/arm/translate-neon.inc.c
40
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
41
DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
42
DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
43
DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
44
+
45
+static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
46
+{
47
+ /* FP operations handled pairwise 32 bits at a time */
48
+ TCGv_i32 tmp, tmp2, tmp3;
49
+ TCGv_ptr fpstatus;
50
+
51
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
52
+ return false;
53
+ }
54
+
55
+ /* UNDEF accesses to D16-D31 if they don't exist. */
56
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
57
+ ((a->vd | a->vn | a->vm) & 0x10)) {
58
+ return false;
59
+ }
60
+
61
+ if (!vfp_access_check(s)) {
62
+ return true;
63
+ }
64
+
65
+ assert(a->q == 0); /* enforced by decode patterns */
66
+
67
+ /*
68
+ * Note that we have to be careful not to clobber the source operands
69
+ * in the "vm == vd" case by storing the result of the first pass too
70
+ * early. Since Q is 0 there are always just two passes, so instead
71
+ * of a complicated loop over each pass we just unroll.
72
+ */
73
+ fpstatus = get_fpstatus_ptr(1);
74
+ tmp = neon_load_reg(a->vn, 0);
75
+ tmp2 = neon_load_reg(a->vn, 1);
76
+ fn(tmp, tmp, tmp2, fpstatus);
77
+ tcg_temp_free_i32(tmp2);
78
+
79
+ tmp3 = neon_load_reg(a->vm, 0);
80
+ tmp2 = neon_load_reg(a->vm, 1);
81
+ fn(tmp3, tmp3, tmp2, fpstatus);
82
+ tcg_temp_free_i32(tmp2);
83
+ tcg_temp_free_ptr(fpstatus);
84
+
85
+ neon_store_reg(a->vd, 0, tmp);
86
+ neon_store_reg(a->vd, 1, tmp3);
87
+ return true;
88
+}
89
+
90
+/*
91
+ * For all the functions using this macro, size == 1 means fp16,
92
+ * which is an architecture extension we don't implement yet.
93
+ */
94
+#define DO_3S_FP_PAIR(INSN,FUNC) \
95
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
96
+ { \
97
+ if (a->size != 0) { \
98
+ /* TODO fp16 support */ \
99
+ return false; \
100
+ } \
101
+ return do_3same_fp_pair(s, a, FUNC); \
102
+ }
103
+
104
+DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds)
105
+DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs)
106
+DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins)
107
diff --git a/target/arm/translate.c b/target/arm/translate.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/translate.c
110
+++ b/target/arm/translate.c
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
112
int shift;
113
int pass;
114
int count;
115
- int pairwise;
116
int u;
117
int vec_size;
118
uint32_t imm;
119
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
120
case NEON_3R_VPMIN:
121
case NEON_3R_VPADD_VQRDMLAH:
122
case NEON_3R_VQDMULH_VQRDMULH:
123
+ case NEON_3R_FLOAT_ARITH:
124
/* Already handled by decodetree */
125
return 1;
126
}
127
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
128
/* 64-bit element instructions: handled by decodetree */
129
return 1;
130
}
131
- pairwise = 0;
132
switch (op) {
133
- case NEON_3R_FLOAT_ARITH:
134
- pairwise = (u && size < 2); /* if VPADD (float) */
135
- if (!pairwise) {
136
- return 1; /* handled by decodetree */
137
- }
138
- break;
139
case NEON_3R_FLOAT_MINMAX:
140
- pairwise = u; /* if VPMIN/VPMAX (float) */
141
+ if (u) {
142
+ return 1; /* VPMIN/VPMAX handled by decodetree */
143
+ }
144
break;
145
case NEON_3R_FLOAT_CMP:
146
if (!u && size) {
147
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
148
break;
149
}
150
151
- if (pairwise && q) {
152
- /* All the pairwise insns UNDEF if Q is set */
153
- return 1;
154
- }
45
- }
155
-
46
-
156
for (pass = 0; pass < (q ? 4 : 2); pass++) {
47
if (object_property_find(cpuobj, "reset-cbar")) {
157
48
object_property_set_int(cpuobj, "reset-cbar", MPCORE_PERIPHBASE,
158
- if (pairwise) {
49
&error_abort);
159
- /* Pairwise. */
50
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
160
- if (pass < 1) {
51
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
161
- tmp = neon_load_reg(rn, 0);
52
highbank_binfo.write_board_setup = hb_write_board_setup;
162
- tmp2 = neon_load_reg(rn, 1);
53
highbank_binfo.secure_board_setup = true;
163
- } else {
54
+ highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
164
- tmp = neon_load_reg(rm, 0);
55
165
- tmp2 = neon_load_reg(rm, 1);
56
arm_load_kernel(ARM_CPU(first_cpu), machine, &highbank_binfo);
166
- }
57
}
167
- } else {
168
- /* Elementwise. */
169
- tmp = neon_load_reg(rn, pass);
170
- tmp2 = neon_load_reg(rm, pass);
171
- }
172
+ /* Elementwise. */
173
+ tmp = neon_load_reg(rn, pass);
174
+ tmp2 = neon_load_reg(rm, pass);
175
switch (op) {
176
- case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
177
- {
178
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
179
- switch ((u << 2) | size) {
180
- case 4: /* VPADD */
181
- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
182
- break;
183
- default:
184
- abort();
185
- }
186
- tcg_temp_free_ptr(fpstatus);
187
- break;
188
- }
189
case NEON_3R_FLOAT_MULTIPLY:
190
{
191
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
192
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
193
}
194
tcg_temp_free_i32(tmp2);
195
196
- /* Save the result. For elementwise operations we can put it
197
- straight into the destination register. For pairwise operations
198
- we have to be careful to avoid clobbering the source operands. */
199
- if (pairwise && rd == rm) {
200
- neon_store_scratch(pass, tmp);
201
- } else {
202
- neon_store_reg(rd, pass, tmp);
203
- }
204
+ neon_store_reg(rd, pass, tmp);
205
206
} /* for pass */
207
- if (pairwise && rd == rm) {
208
- for (pass = 0; pass < (q ? 4 : 2); pass++) {
209
- tmp = neon_load_scratch(pass);
210
- neon_store_reg(rd, pass, tmp);
211
- }
212
- }
213
/* End of 3 register same size operations. */
214
} else if (insn & (1 << 4)) {
215
if ((insn & 0x00380080) != 0) {
216
--
58
--
217
2.20.1
59
2.25.1
218
60
219
61
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
The SMCCC 1.3 spec section 5.2 says
2
2
3
This patch builds Hardware Error Source Table(HEST) via fw_cfg blobs.
3
The Unknown SMC Function Identifier is a sign-extended value of (-1)
4
Now it only supports ARMv8 SEA, a type of Generic Hardware Error
4
that is returned in the R0, W0 or X0 registers. An implementation must
5
Source version 2(GHESv2) error source. Afterwards, we can extend
5
return this error code when it receives:
6
the supported types if needed. For the CPER section, currently it
7
is memory section because kernel mainly wants userspace to handle
8
the memory errors.
9
6
10
This patch follows the spec ACPI 6.2 to build the Hardware Error
7
* An SMC or HVC call with an unknown Function Identifier
11
Source table. For more detailed information, please refer to
8
* An SMC or HVC call for a removed Function Identifier
12
document: docs/specs/acpi_hest_ghes.rst
9
* An SMC64/HVC64 call from AArch32 state
13
10
14
build_ghes_hw_error_notification() helper will help to add Hardware
11
To comply with these statements, let's always return -1 when we encounter
15
Error Notification to ACPI tables without using packed C structures
12
an unknown HVC or SMC call.
16
and avoid endianness issues as API doesn't need explicit conversion.
17
13
18
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
14
[PMM:
19
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
15
This is a reinstatement of commit 9fcd15b9193e819b, previously
20
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
reverted in commit 4825eaae4fdd56fba0f; we can do this now that we
21
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
17
have arranged for all the affected board models to not enable the
22
Message-id: 20200512030609.19593-6-gengdongjiu@huawei.com
18
PSCI emulation if they are running guest code at EL3. This avoids
19
the regressions that caused us to revert the change for 7.0.]
20
21
Signed-off-by: Alexander Graf <agraf@csgraf.de>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
24
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Tested-by: Cédric Le Goater <clg@kaod.org>
26
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
27
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
29
---
25
include/hw/acpi/ghes.h | 39 ++++++++++++
30
target/arm/psci.c | 35 ++++++-----------------------------
26
hw/acpi/ghes.c | 126 +++++++++++++++++++++++++++++++++++++++
31
1 file changed, 6 insertions(+), 29 deletions(-)
27
hw/arm/virt-acpi-build.c | 2 +
28
3 files changed, 167 insertions(+)
29
32
30
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
33
diff --git a/target/arm/psci.c b/target/arm/psci.c
31
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/acpi/ghes.h
35
--- a/target/arm/psci.c
33
+++ b/include/hw/acpi/ghes.h
36
+++ b/target/arm/psci.c
34
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
35
38
36
#include "hw/acpi/bios-linker-loader.h"
39
bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
37
40
{
38
+/*
41
- /* Return true if the r0/x0 value indicates a PSCI call and
39
+ * Values for Hardware Error Notification Type field
42
- * the exception type matches the configured PSCI conduit. This is
40
+ */
43
- * called before the SMC/HVC instruction is executed, to decide whether
41
+enum AcpiGhesNotifyType {
44
- * we should treat it as a PSCI call or with the architecturally
42
+ /* Polled */
43
+ ACPI_GHES_NOTIFY_POLLED = 0,
44
+ /* External Interrupt */
45
+ ACPI_GHES_NOTIFY_EXTERNAL = 1,
46
+ /* Local Interrupt */
47
+ ACPI_GHES_NOTIFY_LOCAL = 2,
48
+ /* SCI */
49
+ ACPI_GHES_NOTIFY_SCI = 3,
50
+ /* NMI */
51
+ ACPI_GHES_NOTIFY_NMI = 4,
52
+ /* CMCI, ACPI 5.0: 18.3.2.7, Table 18-290 */
53
+ ACPI_GHES_NOTIFY_CMCI = 5,
54
+ /* MCE, ACPI 5.0: 18.3.2.7, Table 18-290 */
55
+ ACPI_GHES_NOTIFY_MCE = 6,
56
+ /* GPIO-Signal, ACPI 6.0: 18.3.2.7, Table 18-332 */
57
+ ACPI_GHES_NOTIFY_GPIO = 7,
58
+ /* ARMv8 SEA, ACPI 6.1: 18.3.2.9, Table 18-345 */
59
+ ACPI_GHES_NOTIFY_SEA = 8,
60
+ /* ARMv8 SEI, ACPI 6.1: 18.3.2.9, Table 18-345 */
61
+ ACPI_GHES_NOTIFY_SEI = 9,
62
+ /* External Interrupt - GSIV, ACPI 6.1: 18.3.2.9, Table 18-345 */
63
+ ACPI_GHES_NOTIFY_GSIV = 10,
64
+ /* Software Delegated Exception, ACPI 6.2: 18.3.2.9, Table 18-383 */
65
+ ACPI_GHES_NOTIFY_SDEI = 11,
66
+ /* 12 and greater are reserved */
67
+ ACPI_GHES_NOTIFY_RESERVED = 12
68
+};
69
+
70
+enum {
71
+ ACPI_HEST_SRC_ID_SEA = 0,
72
+ /* future ids go here */
73
+ ACPI_HEST_SRC_ID_RESERVED,
74
+};
75
+
76
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
77
+void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
78
#endif
79
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/acpi/ghes.c
82
+++ b/hw/acpi/ghes.c
83
@@ -XXX,XX +XXX,XX @@
84
#include "qemu/units.h"
85
#include "hw/acpi/ghes.h"
86
#include "hw/acpi/aml-build.h"
87
+#include "qemu/error-report.h"
88
89
#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
90
#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
91
@@ -XXX,XX +XXX,XX @@
92
/* Now only support ARMv8 SEA notification type error source */
93
#define ACPI_GHES_ERROR_SOURCE_COUNT 1
94
95
+/* Generic Hardware Error Source version 2 */
96
+#define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10
97
+
98
+/* Address offset in Generic Address Structure(GAS) */
99
+#define GAS_ADDR_OFFSET 4
100
+
101
+/*
102
+ * Hardware Error Notification
103
+ * ACPI 4.0: 17.3.2.7 Hardware Error Notification
104
+ * Composes dummy Hardware Error Notification descriptor of specified type
105
+ */
106
+static void build_ghes_hw_error_notification(GArray *table, const uint8_t type)
107
+{
108
+ /* Type */
109
+ build_append_int_noprefix(table, type, 1);
110
+ /*
45
+ /*
111
+ * Length:
46
+ * Return true if the exception type matches the configured PSCI conduit.
112
+ * Total length of the structure in bytes
47
+ * This is called before the SMC/HVC instruction is executed, to decide
113
+ */
48
+ * whether we should treat it as a PSCI call or with the architecturally
114
+ build_append_int_noprefix(table, 28, 1);
49
* defined behaviour for an SMC or HVC (which might be UNDEF or trap
115
+ /* Configuration Write Enable */
50
* to EL2 or to EL3).
116
+ build_append_int_noprefix(table, 0, 2);
51
*/
117
+ /* Poll Interval */
52
- CPUARMState *env = &cpu->env;
118
+ build_append_int_noprefix(table, 0, 4);
53
- uint64_t param = is_a64(env) ? env->xregs[0] : env->regs[0];
119
+ /* Vector */
54
120
+ build_append_int_noprefix(table, 0, 4);
55
switch (excp_type) {
121
+ /* Switch To Polling Threshold Value */
56
case EXCP_HVC:
122
+ build_append_int_noprefix(table, 0, 4);
57
@@ -XXX,XX +XXX,XX @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
123
+ /* Switch To Polling Threshold Window */
58
return false;
124
+ build_append_int_noprefix(table, 0, 4);
59
}
125
+ /* Error Threshold Value */
60
126
+ build_append_int_noprefix(table, 0, 4);
61
- switch (param) {
127
+ /* Error Threshold Window */
62
- case QEMU_PSCI_0_2_FN_PSCI_VERSION:
128
+ build_append_int_noprefix(table, 0, 4);
63
- case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
129
+}
64
- case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
130
+
65
- case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
131
/*
66
- case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
132
* Build table for the hardware error fw_cfg blob.
67
- case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
133
* Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
68
- case QEMU_PSCI_0_1_FN_CPU_ON:
134
@@ -XXX,XX +XXX,XX @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
69
- case QEMU_PSCI_0_2_FN_CPU_ON:
135
bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE,
70
- case QEMU_PSCI_0_2_FN64_CPU_ON:
136
0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0);
71
- case QEMU_PSCI_0_1_FN_CPU_OFF:
72
- case QEMU_PSCI_0_2_FN_CPU_OFF:
73
- case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
74
- case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
75
- case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
76
- case QEMU_PSCI_0_1_FN_MIGRATE:
77
- case QEMU_PSCI_0_2_FN_MIGRATE:
78
- return true;
79
- default:
80
- return false;
81
- }
82
+ return true;
137
}
83
}
138
+
84
139
+/* Build Generic Hardware Error Source version 2 (GHESv2) */
85
void arm_handle_psci_call(ARMCPU *cpu)
140
+static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
86
@@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu)
141
+{
87
break;
142
+ uint64_t address_offset;
88
case QEMU_PSCI_0_1_FN_MIGRATE:
143
+ /*
89
case QEMU_PSCI_0_2_FN_MIGRATE:
144
+ * Type:
145
+ * Generic Hardware Error Source version 2(GHESv2 - Type 10)
146
+ */
147
+ build_append_int_noprefix(table_data, ACPI_GHES_SOURCE_GENERIC_ERROR_V2, 2);
148
+ /* Source Id */
149
+ build_append_int_noprefix(table_data, source_id, 2);
150
+ /* Related Source Id */
151
+ build_append_int_noprefix(table_data, 0xffff, 2);
152
+ /* Flags */
153
+ build_append_int_noprefix(table_data, 0, 1);
154
+ /* Enabled */
155
+ build_append_int_noprefix(table_data, 1, 1);
156
+
157
+ /* Number of Records To Pre-allocate */
158
+ build_append_int_noprefix(table_data, 1, 4);
159
+ /* Max Sections Per Record */
160
+ build_append_int_noprefix(table_data, 1, 4);
161
+ /* Max Raw Data Length */
162
+ build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4);
163
+
164
+ address_offset = table_data->len;
165
+ /* Error Status Address */
166
+ build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
167
+ 4 /* QWord access */, 0);
168
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
169
+ address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t),
170
+ ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t));
171
+
172
+ switch (source_id) {
173
+ case ACPI_HEST_SRC_ID_SEA:
174
+ /*
175
+ * Notification Structure
176
+ * Now only enable ARMv8 SEA notification type
177
+ */
178
+ build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA);
179
+ break;
180
+ default:
90
+ default:
181
+ error_report("Not support this error source");
91
ret = QEMU_PSCI_RET_NOT_SUPPORTED;
182
+ abort();
92
break;
183
+ }
93
- default:
184
+
94
- g_assert_not_reached();
185
+ /* Error Status Block Length */
186
+ build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4);
187
+
188
+ /*
189
+ * Read Ack Register
190
+ * ACPI 6.1: 18.3.2.8 Generic Hardware Error Source
191
+ * version 2 (GHESv2 - Type 10)
192
+ */
193
+ address_offset = table_data->len;
194
+ build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
195
+ 4 /* QWord access */, 0);
196
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
197
+ address_offset + GAS_ADDR_OFFSET,
198
+ sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
199
+ (ACPI_GHES_ERROR_SOURCE_COUNT + source_id) * sizeof(uint64_t));
200
+
201
+ /*
202
+ * Read Ack Preserve field
203
+ * We only provide the first bit in Read Ack Register to OSPM to write
204
+ * while the other bits are preserved.
205
+ */
206
+ build_append_int_noprefix(table_data, ~0x1ULL, 8);
207
+ /* Read Ack Write */
208
+ build_append_int_noprefix(table_data, 0x1, 8);
209
+}
210
+
211
+/* Build Hardware Error Source Table */
212
+void acpi_build_hest(GArray *table_data, BIOSLinker *linker)
213
+{
214
+ uint64_t hest_start = table_data->len;
215
+
216
+ /* Hardware Error Source Table header*/
217
+ acpi_data_push(table_data, sizeof(AcpiTableHeader));
218
+
219
+ /* Error Source Count */
220
+ build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
221
+
222
+ build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker);
223
+
224
+ build_header(linker, table_data, (void *)(table_data->data + hest_start),
225
+ "HEST", table_data->len - hest_start, 1, NULL, NULL);
226
+}
227
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
228
index XXXXXXX..XXXXXXX 100644
229
--- a/hw/arm/virt-acpi-build.c
230
+++ b/hw/arm/virt-acpi-build.c
231
@@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
232
233
if (vms->ras) {
234
build_ghes_error_table(tables->hardware_errors, tables->linker);
235
+ acpi_add_table(table_offsets, tables_blob);
236
+ acpi_build_hest(tables_blob, tables->linker);
237
}
95
}
238
96
239
if (ms->numa_state->num_nodes > 0) {
97
err:
240
--
98
--
241
2.20.1
99
2.25.1
242
100
243
101
diff view generated by jsdifflib
1
Convert the Neon VRHADD and VHSUB 3-reg-same insns to decodetree.
1
Guest code on highbank may make non-PSCI SMC calls in order to
2
(These are all the other insns in 3-reg-same which were using
2
enable/disable the L2x0 cache controller (see the Linux kernel's
3
GEN_NEON_INTEGER_OP() and which are not pairwise or
3
arch/arm/mach-highbank/highbank.c highbank_l2c310_write_sec()
4
reversed-operands.)
4
function). The ABI for this is documented in kernel commit
5
8e56130dcb as being borrowed from the OMAP44xx ROM. The OMAP44xx TRM
6
documents this function ID as having no return value and potentially
7
trashing all guest registers except SP and PC. For QEMU's purposes
8
(where our L2x0 model is a stub and enabling or disabling it doesn't
9
affect the guest behaviour) a simple "do nothing" SMC is fine.
10
11
We currently implement this NOP behaviour using a little bit of
12
Secure code we run before jumping to the guest kernel, which is
13
written by arm_write_secure_board_setup_dummy_smc(). The code sets
14
up a set of Secure vectors where the SMC entry point returns without
15
doing anything.
16
17
Now that the PSCI SMC emulation handles all SMC calls (setting r0 to
18
an error code if the input r0 function identifier is not recognized),
19
we can use that default behaviour as sufficient for the highbank
20
cache controller call. (Because the guest code assumes r0 has no
21
interesting value on exit it doesn't matter that we set it to the
22
error code). We can therefore delete the highbank board code that
23
sets secure_board_setup to true and writes the secure-code bootstub.
24
25
(Note that because the OMAP44xx ABI puts function-identifiers in
26
r12 and PSCI uses r0, we only avoid a clash because Linux's code
27
happens to put the function-identifier in both registers. But this
28
is true also when the kernel is running on real firmware that
29
implements both ABIs as far as I can see.)
30
31
This change fixes in passing booting on the 'midway' board model,
32
which has been completely broken since we added support for Hyp
33
mode to the Cortex-A15 CPU. When we did that boot.c was made to
34
start running the guest code in Hyp mode; this includes the
35
board_setup hook, which instantly UNDEFs because the NSACR is
36
not accessible from Hyp. (Put another way, we never made the
37
secure_board_setup hook support cope with Hyp mode.)
5
38
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200512163904.10918-7-peter.maydell@linaro.org
41
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
42
Tested-by: Cédric Le Goater <clg@kaod.org>
43
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
44
Message-id: 20220127154639.2090164-12-peter.maydell@linaro.org
9
---
45
---
10
target/arm/neon-dp.decode | 6 ++++++
46
hw/arm/highbank.c | 8 --------
11
target/arm/translate-neon.inc.c | 4 ++++
47
1 file changed, 8 deletions(-)
12
target/arm/translate.c | 8 ++------
13
3 files changed, 12 insertions(+), 6 deletions(-)
14
48
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
49
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
16
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
51
--- a/hw/arm/highbank.c
18
+++ b/target/arm/neon-dp.decode
52
+++ b/hw/arm/highbank.c
19
@@ -XXX,XX +XXX,XX @@ VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
53
@@ -XXX,XX +XXX,XX @@
20
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
54
21
VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same
55
/* Board init. */
22
56
23
+VRHADD_S_3s 1111 001 0 0 . .. .... .... 0001 . . . 0 .... @3same
57
-static void hb_write_board_setup(ARMCPU *cpu,
24
+VRHADD_U_3s 1111 001 1 0 . .. .... .... 0001 . . . 0 .... @3same
58
- const struct arm_boot_info *info)
25
+
59
-{
26
@3same_logic .... ... . . . .. .... .... .... . q:1 .. .... \
60
- arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR);
27
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0
61
-}
28
62
-
29
@@ -XXX,XX +XXX,XX @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic
63
static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
30
VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic
64
{
31
VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic
65
int n;
32
66
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
33
+VHSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 0 .... @3same
67
highbank_binfo.write_secondary_boot = hb_write_secondary;
34
+VHSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 0 .... @3same
68
highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
35
+
69
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
36
VQSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 1 .... @3same
70
- highbank_binfo.write_board_setup = hb_write_board_setup;
37
VQSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 1 .... @3same
71
- highbank_binfo.secure_board_setup = true;
38
72
highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
39
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
73
40
index XXXXXXX..XXXXXXX 100644
74
arm_load_kernel(ARM_CPU(first_cpu), machine, &highbank_binfo);
41
--- a/target/arm/translate-neon.inc.c
42
+++ b/target/arm/translate-neon.inc.c
43
@@ -XXX,XX +XXX,XX @@ DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
44
45
DO_3SAME_32(VHADD_S, hadd_s)
46
DO_3SAME_32(VHADD_U, hadd_u)
47
+DO_3SAME_32(VHSUB_S, hsub_s)
48
+DO_3SAME_32(VHSUB_U, hsub_u)
49
+DO_3SAME_32(VRHADD_S, rhadd_s)
50
+DO_3SAME_32(VRHADD_U, rhadd_u)
51
diff --git a/target/arm/translate.c b/target/arm/translate.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate.c
54
+++ b/target/arm/translate.c
55
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
56
case NEON_3R_VSHL:
57
case NEON_3R_SHA:
58
case NEON_3R_VHADD:
59
+ case NEON_3R_VRHADD:
60
+ case NEON_3R_VHSUB:
61
case NEON_3R_VABD:
62
case NEON_3R_VABA:
63
/* Already handled by decodetree */
64
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
65
tmp2 = neon_load_reg(rm, pass);
66
}
67
switch (op) {
68
- case NEON_3R_VRHADD:
69
- GEN_NEON_INTEGER_OP(rhadd);
70
- break;
71
- case NEON_3R_VHSUB:
72
- GEN_NEON_INTEGER_OP(hsub);
73
- break;
74
case NEON_3R_VQSHL:
75
GEN_NEON_INTEGER_OP_ENV(qshl);
76
break;
77
--
75
--
78
2.20.1
76
2.25.1
79
77
80
78
diff view generated by jsdifflib
1
Convert the Neon VABA and VABD insns in the 3-reg-same group to
1
Now that we have dealt with the one special case (highbank) that needed
2
decodetree.
2
to set both psci_conduit and secure_board_setup, we don't need to
3
allow that combination any more. It doesn't make sense in general,
4
so use an assertion to ensure we don't add new boards that do it
5
by accident without thinking through the consequences.
3
6
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200512163904.10918-6-peter.maydell@linaro.org
9
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Tested-by: Cédric Le Goater <clg@kaod.org>
11
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
12
Message-id: 20220127154639.2090164-13-peter.maydell@linaro.org
7
---
13
---
8
target/arm/neon-dp.decode | 6 ++++++
14
hw/arm/boot.c | 10 ++++++++++
9
target/arm/translate-neon.inc.c | 4 ++++
15
1 file changed, 10 insertions(+)
10
target/arm/translate.c | 22 ++--------------------
11
3 files changed, 12 insertions(+), 20 deletions(-)
12
16
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
17
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
19
--- a/hw/arm/boot.c
16
+++ b/target/arm/neon-dp.decode
20
+++ b/hw/arm/boot.c
17
@@ -XXX,XX +XXX,XX @@ VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
21
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
18
VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
22
* supported exception level or in a lower one.
19
VMIN_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 1 .... @3same
23
*/
20
24
21
+VABD_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 0 .... @3same
25
+ /*
22
+VABD_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 0 .... @3same
26
+ * If PSCI is enabled, then SMC calls all go to the PSCI handler and
27
+ * are never emulated to trap into guest code. It therefore does not
28
+ * make sense for the board to have a setup code fragment that runs
29
+ * in Secure, because this will probably need to itself issue an SMC of some
30
+ * kind as part of its operation.
31
+ */
32
+ assert(info->psci_conduit == QEMU_PSCI_CONDUIT_DISABLED ||
33
+ !info->secure_board_setup);
23
+
34
+
24
+VABA_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 1 .... @3same
35
/* Boot into highest supported EL ... */
25
+VABA_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 1 .... @3same
36
if (arm_feature(env, ARM_FEATURE_EL3)) {
26
+
37
boot_el = 3;
27
VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same
28
VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
29
30
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-neon.inc.c
33
+++ b/target/arm/translate-neon.inc.c
34
@@ -XXX,XX +XXX,XX @@ DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
35
DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla)
36
DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls)
37
DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst)
38
+DO_3SAME_NO_SZ_3(VABD_S, gen_gvec_sabd)
39
+DO_3SAME_NO_SZ_3(VABA_S, gen_gvec_saba)
40
+DO_3SAME_NO_SZ_3(VABD_U, gen_gvec_uabd)
41
+DO_3SAME_NO_SZ_3(VABA_U, gen_gvec_uaba)
42
43
#define DO_3SAME_CMP(INSN, COND) \
44
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
45
diff --git a/target/arm/translate.c b/target/arm/translate.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate.c
48
+++ b/target/arm/translate.c
49
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
50
/* VQRDMLSH : handled by decodetree */
51
return 1;
52
53
- case NEON_3R_VABD:
54
- if (u) {
55
- gen_gvec_uabd(size, rd_ofs, rn_ofs, rm_ofs,
56
- vec_size, vec_size);
57
- } else {
58
- gen_gvec_sabd(size, rd_ofs, rn_ofs, rm_ofs,
59
- vec_size, vec_size);
60
- }
61
- return 0;
62
-
63
- case NEON_3R_VABA:
64
- if (u) {
65
- gen_gvec_uaba(size, rd_ofs, rn_ofs, rm_ofs,
66
- vec_size, vec_size);
67
- } else {
68
- gen_gvec_saba(size, rd_ofs, rn_ofs, rm_ofs,
69
- vec_size, vec_size);
70
- }
71
- return 0;
72
-
73
case NEON_3R_VADD_VSUB:
74
case NEON_3R_LOGIC:
75
case NEON_3R_VMAX:
76
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
77
case NEON_3R_VSHL:
78
case NEON_3R_SHA:
79
case NEON_3R_VHADD:
80
+ case NEON_3R_VABD:
81
+ case NEON_3R_VABA:
82
/* Already handled by decodetree */
83
return 1;
84
}
85
--
38
--
86
2.20.1
39
2.25.1
87
40
88
41
diff view generated by jsdifflib
1
Convert the VQSHL, VRSHL and VQRSHL insns in the 3-reg-same
1
If we're using PSCI emulation to start secondary CPUs, there is no
2
group to decodetree. We have already implemented the size==0b11
2
point in writing the "secondary boot" stub code, because it will
3
case of these insns; this commit handles the remaining sizes.
3
never be used -- secondary CPUs start powered-off, and when powered
4
on are set to begin execution at the address specified by the guest's
5
power-on PSCI call, not at the stub.
6
7
Move the call to the hook that writes the secondary boot stub code so
8
that we can do it only if we're starting a Linux kernel and not using
9
PSCI.
10
11
(None of the users of the hook care about the ordering of its call
12
relative to anything else: they only use it to write a rom blob to
13
guest memory.)
4
14
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-8-peter.maydell@linaro.org
17
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
18
Tested-by: Cédric Le Goater <clg@kaod.org>
19
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
20
Message-id: 20220127154639.2090164-14-peter.maydell@linaro.org
8
---
21
---
9
target/arm/neon-dp.decode | 30 ++++++++++++++++++-----
22
include/hw/arm/boot.h | 3 +++
10
target/arm/translate-neon.inc.c | 43 +++++++++++++++++++++++++++++++++
23
hw/arm/boot.c | 35 ++++++++++++++++++++++++-----------
11
target/arm/translate.c | 22 +++--------------
24
2 files changed, 27 insertions(+), 11 deletions(-)
12
3 files changed, 70 insertions(+), 25 deletions(-)
13
25
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
26
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
15
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
28
--- a/include/hw/arm/boot.h
17
+++ b/target/arm/neon-dp.decode
29
+++ b/include/hw/arm/boot.h
18
@@ -XXX,XX +XXX,XX @@ VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
30
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info {
19
@3same_64_rev .... ... . . . 11 .... .... .... . q:1 . . .... \
31
* boot loader/boot ROM code, and secondary_cpu_reset_hook() should
20
&3same vm=%vn_dp vn=%vm_dp vd=%vd_dp size=3
32
* perform any necessary CPU reset handling and set the PC for the
21
33
* secondary CPUs to point at this boot blob.
22
-VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
34
+ *
23
-VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
35
+ * These hooks won't be called if secondary CPUs are booting via
24
-VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
36
+ * emulated PSCI (see psci_conduit below).
25
-VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
37
*/
26
-VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
38
void (*write_secondary_boot)(ARMCPU *cpu,
27
-VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
39
const struct arm_boot_info *info);
28
+{
40
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
29
+ VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
30
+ VQSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_rev
31
+}
32
+{
33
+ VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
34
+ VQSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_rev
35
+}
36
+{
37
+ VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
38
+ VRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_rev
39
+}
40
+{
41
+ VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
42
+ VRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_rev
43
+}
44
+{
45
+ VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
46
+ VQRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_rev
47
+}
48
+{
49
+ VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
50
+ VQRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_rev
51
+}
52
53
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
54
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
55
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
56
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-neon.inc.c
42
--- a/hw/arm/boot.c
58
+++ b/target/arm/translate-neon.inc.c
43
+++ b/hw/arm/boot.c
59
@@ -XXX,XX +XXX,XX @@ DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
44
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
60
return do_3same(s, a, gen_##INSN##_3s); \
45
set_kernel_args(info, as);
46
}
47
}
48
- } else {
49
+ } else if (info->secondary_cpu_reset_hook) {
50
info->secondary_cpu_reset_hook(cpu, info);
51
}
52
}
53
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
54
elf_machine = EM_ARM;
61
}
55
}
62
56
63
+/*
57
- if (!info->secondary_cpu_reset_hook) {
64
+ * Some helper functions need to be passed the cpu_env. In order
58
- info->secondary_cpu_reset_hook = default_reset_secondary;
65
+ * to use those with the gvec APIs like tcg_gen_gvec_3() we need
59
- }
66
+ * to create wrapper functions whose prototype is a NeonGenTwoOpFn()
60
- if (!info->write_secondary_boot) {
67
+ * and which call a NeonGenTwoOpEnvFn().
61
- info->write_secondary_boot = default_write_secondary;
68
+ */
62
- }
69
+#define WRAP_ENV_FN(WRAPNAME, FUNC) \
63
-
70
+ static void WRAPNAME(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m) \
64
if (info->nb_cpus == 0)
71
+ { \
65
info->nb_cpus = 1;
72
+ FUNC(d, cpu_env, n, m); \
66
67
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
68
write_bootloader("bootloader", info->loader_start,
69
primary_loader, fixupcontext, as);
70
71
- if (info->nb_cpus > 1) {
72
- info->write_secondary_boot(cpu, info);
73
- }
74
if (info->write_board_setup) {
75
info->write_board_setup(cpu, info);
76
}
77
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
78
}
79
}
80
81
+ if (info->psci_conduit == QEMU_PSCI_CONDUIT_DISABLED &&
82
+ info->is_linux && info->nb_cpus > 1) {
83
+ /*
84
+ * We're booting Linux but not using PSCI, so for SMP we need
85
+ * to write a custom secondary CPU boot loader stub, and arrange
86
+ * for the secondary CPU reset to make the accompanying initialization.
87
+ */
88
+ if (!info->secondary_cpu_reset_hook) {
89
+ info->secondary_cpu_reset_hook = default_reset_secondary;
90
+ }
91
+ if (!info->write_secondary_boot) {
92
+ info->write_secondary_boot = default_write_secondary;
93
+ }
94
+ info->write_secondary_boot(cpu, info);
95
+ } else {
96
+ /*
97
+ * No secondary boot stub; don't use the reset hook that would
98
+ * have set the CPU up to call it
99
+ */
100
+ info->write_secondary_boot = NULL;
101
+ info->secondary_cpu_reset_hook = NULL;
73
+ }
102
+ }
74
+
103
+
75
+#define DO_3SAME_32_ENV(INSN, FUNC) \
104
/*
76
+ WRAP_ENV_FN(gen_##INSN##_tramp8, gen_helper_neon_##FUNC##8); \
105
* arm_load_dtb() may add a PSCI node so it must be called after we have
77
+ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##16); \
106
* decided whether to enable PSCI and set the psci-conduit CPU properties.
78
+ WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##32); \
79
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
80
+ uint32_t rn_ofs, uint32_t rm_ofs, \
81
+ uint32_t oprsz, uint32_t maxsz) \
82
+ { \
83
+ static const GVecGen3 ops[4] = { \
84
+ { .fni4 = gen_##INSN##_tramp8 }, \
85
+ { .fni4 = gen_##INSN##_tramp16 }, \
86
+ { .fni4 = gen_##INSN##_tramp32 }, \
87
+ { 0 }, \
88
+ }; \
89
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \
90
+ } \
91
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
92
+ { \
93
+ if (a->size > 2) { \
94
+ return false; \
95
+ } \
96
+ return do_3same(s, a, gen_##INSN##_3s); \
97
+ }
98
+
99
DO_3SAME_32(VHADD_S, hadd_s)
100
DO_3SAME_32(VHADD_U, hadd_u)
101
DO_3SAME_32(VHSUB_S, hsub_s)
102
DO_3SAME_32(VHSUB_U, hsub_u)
103
DO_3SAME_32(VRHADD_S, rhadd_s)
104
DO_3SAME_32(VRHADD_U, rhadd_u)
105
+DO_3SAME_32(VRSHL_S, rshl_s)
106
+DO_3SAME_32(VRSHL_U, rshl_u)
107
+
108
+DO_3SAME_32_ENV(VQSHL_S, qshl_s)
109
+DO_3SAME_32_ENV(VQSHL_U, qshl_u)
110
+DO_3SAME_32_ENV(VQRSHL_S, qrshl_s)
111
+DO_3SAME_32_ENV(VQRSHL_U, qrshl_u)
112
diff --git a/target/arm/translate.c b/target/arm/translate.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/translate.c
115
+++ b/target/arm/translate.c
116
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
117
case NEON_3R_VHSUB:
118
case NEON_3R_VABD:
119
case NEON_3R_VABA:
120
+ case NEON_3R_VQSHL:
121
+ case NEON_3R_VRSHL:
122
+ case NEON_3R_VQRSHL:
123
/* Already handled by decodetree */
124
return 1;
125
}
126
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
127
}
128
pairwise = 0;
129
switch (op) {
130
- case NEON_3R_VQSHL:
131
- case NEON_3R_VRSHL:
132
- case NEON_3R_VQRSHL:
133
- {
134
- int rtmp;
135
- /* Shift instruction operands are reversed. */
136
- rtmp = rn;
137
- rn = rm;
138
- rm = rtmp;
139
- }
140
- break;
141
case NEON_3R_VPADD_VQRDMLAH:
142
case NEON_3R_VPMAX:
143
case NEON_3R_VPMIN:
144
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
145
tmp2 = neon_load_reg(rm, pass);
146
}
147
switch (op) {
148
- case NEON_3R_VQSHL:
149
- GEN_NEON_INTEGER_OP_ENV(qshl);
150
- break;
151
- case NEON_3R_VRSHL:
152
- GEN_NEON_INTEGER_OP(rshl);
153
- break;
154
- case NEON_3R_VQRSHL:
155
- GEN_NEON_INTEGER_OP_ENV(qrshl);
156
break;
157
case NEON_3R_VPMAX:
158
GEN_NEON_INTEGER_OP(pmax);
159
--
107
--
160
2.20.1
108
2.25.1
161
109
162
110
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The highbank and midway board code includes boot-stub code for
2
handling secondary CPU boot which keeps the secondaries in a pen
3
until the primary writes to a known location with the address they
4
should jump to.
2
5
3
Provide a functional interface for the vector expansion.
6
This code is never used, because the boards enable QEMU's PSCI
4
This fits better with the existing set of helpers that
7
emulation, so secondary CPUs are kept powered off until the PSCI call
5
we provide for other operations.
8
which turns them on, and then start execution from the address given
9
by the guest in that PSCI call. Delete the unreachable code.
6
10
7
Macro-ize the 5 nearly identical comparisons.
11
(The code was wrong for midway in any case -- on the Cortex-A15 the
12
GIC CPU interface registers are at a different offset from PERIPHBASE
13
compared to the Cortex-A9, and the code baked-in the offsets for
14
highbank's A9.)
8
15
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Note that this commit implicitly depends on the preceding "Don't
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
write secondary boot stub if using PSCI" commit -- the default
11
Message-id: 20200513163245.17915-7-richard.henderson@linaro.org
18
secondary-boot stub code overlaps with one of the highbank-specific
19
bootcode rom blobs, so we must suppress the secondary-boot
20
stub code entirely, not merely replace the highbank-specific
21
version with the default.
22
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
26
Tested-by: Cédric Le Goater <clg@kaod.org>
27
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
28
Message-id: 20220127154639.2090164-15-peter.maydell@linaro.org
13
---
29
---
14
target/arm/translate.h | 16 ++-
30
hw/arm/highbank.c | 56 -----------------------------------------------
15
target/arm/translate-a64.c | 22 ++--
31
1 file changed, 56 deletions(-)
16
target/arm/translate.c | 254 ++++++++-----------------------------
17
3 files changed, 74 insertions(+), 218 deletions(-)
18
32
19
diff --git a/target/arm/translate.h b/target/arm/translate.h
33
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
20
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate.h
35
--- a/hw/arm/highbank.c
22
+++ b/target/arm/translate.h
36
+++ b/hw/arm/highbank.c
23
@@ -XXX,XX +XXX,XX @@ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
37
@@ -XXX,XX +XXX,XX @@
24
uint64_t vfp_expand_imm(int size, uint8_t imm8);
38
25
39
/* Board init. */
26
/* Vector operations shared between ARM and AArch64. */
40
27
-extern const GVecGen2 ceq0_op[4];
41
-static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
28
-extern const GVecGen2 clt0_op[4];
29
-extern const GVecGen2 cgt0_op[4];
30
-extern const GVecGen2 cle0_op[4];
31
-extern const GVecGen2 cge0_op[4];
32
+void gen_gvec_ceq0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
33
+ uint32_t opr_sz, uint32_t max_sz);
34
+void gen_gvec_clt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
35
+ uint32_t opr_sz, uint32_t max_sz);
36
+void gen_gvec_cgt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
37
+ uint32_t opr_sz, uint32_t max_sz);
38
+void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
39
+ uint32_t opr_sz, uint32_t max_sz);
40
+void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
41
+ uint32_t opr_sz, uint32_t max_sz);
42
+
43
extern const GVecGen3 mla_op[4];
44
extern const GVecGen3 mls_op[4];
45
extern const GVecGen3 cmtst_op[4];
46
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-a64.c
49
+++ b/target/arm/translate-a64.c
50
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
51
is_q ? 16 : 8, vec_full_reg_size(s));
52
}
53
54
-/* Expand a 2-operand AdvSIMD vector operation using an op descriptor. */
55
-static void gen_gvec_op2(DisasContext *s, bool is_q, int rd,
56
- int rn, const GVecGen2 *gvec_op)
57
-{
42
-{
58
- tcg_gen_gvec_2(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
43
- int n;
59
- is_q ? 16 : 8, vec_full_reg_size(s), gvec_op);
44
- uint32_t smpboot[] = {
45
- 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
46
- 0xe210000f, /* ands r0, r0, #0x0f */
47
- 0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
48
- 0xe0830200, /* add r0, r3, r0, lsl #4 */
49
- 0xe59f2024, /* ldr r2, privbase */
50
- 0xe3a01001, /* mov r1, #1 */
51
- 0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
52
- 0xe3a010ff, /* mov r1, #0xff */
53
- 0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
54
- 0xf57ff04f, /* dsb */
55
- 0xe320f003, /* wfi */
56
- 0xe5901000, /* ldr r1, [r0] */
57
- 0xe1110001, /* tst r1, r1 */
58
- 0x0afffffb, /* beq <wfi> */
59
- 0xe12fff11, /* bx r1 */
60
- MPCORE_PERIPHBASE /* privbase: MPCore peripheral base address. */
61
- };
62
- for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
63
- smpboot[n] = tswap32(smpboot[n]);
64
- }
65
- rom_add_blob_fixed_as("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR,
66
- arm_boot_address_space(cpu, info));
60
-}
67
-}
61
-
68
-
62
/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
69
-static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
63
static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
64
int rn, int rm, const GVecGen3 *gvec_op)
65
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
66
}
67
break;
68
case 0x8: /* CMGT, CMGE */
69
- gen_gvec_op2(s, is_q, rd, rn, u ? &cge0_op[size] : &cgt0_op[size]);
70
+ if (u) {
71
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cge0, size);
72
+ } else {
73
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cgt0, size);
74
+ }
75
return;
76
case 0x9: /* CMEQ, CMLE */
77
- gen_gvec_op2(s, is_q, rd, rn, u ? &cle0_op[size] : &ceq0_op[size]);
78
+ if (u) {
79
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cle0, size);
80
+ } else {
81
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_ceq0, size);
82
+ }
83
return;
84
case 0xa: /* CMLT */
85
- gen_gvec_op2(s, is_q, rd, rn, &clt0_op[size]);
86
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_clt0, size);
87
return;
88
case 0xb:
89
if (u) { /* ABS, NEG */
90
diff --git a/target/arm/translate.c b/target/arm/translate.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/translate.c
93
+++ b/target/arm/translate.c
94
@@ -XXX,XX +XXX,XX @@ static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
95
return 1;
96
}
97
98
-static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a)
99
-{
70
-{
100
- tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0);
71
- CPUARMState *env = &cpu->env;
101
- tcg_gen_neg_i32(d, d);
72
-
73
- switch (info->nb_cpus) {
74
- case 4:
75
- address_space_stl_notdirty(&address_space_memory,
76
- SMP_BOOT_REG + 0x30, 0,
77
- MEMTXATTRS_UNSPECIFIED, NULL);
78
- /* fallthrough */
79
- case 3:
80
- address_space_stl_notdirty(&address_space_memory,
81
- SMP_BOOT_REG + 0x20, 0,
82
- MEMTXATTRS_UNSPECIFIED, NULL);
83
- /* fallthrough */
84
- case 2:
85
- address_space_stl_notdirty(&address_space_memory,
86
- SMP_BOOT_REG + 0x10, 0,
87
- MEMTXATTRS_UNSPECIFIED, NULL);
88
- env->regs[15] = SMP_BOOT_ADDR;
89
- break;
90
- default:
91
- break;
92
- }
102
-}
93
-}
103
-
94
-
104
-static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a)
95
#define NUM_REGS 0x200
105
-{
96
static void hb_regs_write(void *opaque, hwaddr offset,
106
- tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0);
97
uint64_t value, unsigned size)
107
- tcg_gen_neg_i64(d, d);
98
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
108
-}
99
highbank_binfo.board_id = -1;
109
-
100
highbank_binfo.nb_cpus = smp_cpus;
110
-static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
101
highbank_binfo.loader_start = 0;
111
-{
102
- highbank_binfo.write_secondary_boot = hb_write_secondary;
112
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
103
- highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
113
- tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero);
104
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
114
- tcg_temp_free_vec(zero);
105
highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
115
-}
106
116
+#define GEN_CMP0(NAME, COND) \
117
+ static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
118
+ { \
119
+ tcg_gen_setcondi_i32(COND, d, a, 0); \
120
+ tcg_gen_neg_i32(d, d); \
121
+ } \
122
+ static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
123
+ { \
124
+ tcg_gen_setcondi_i64(COND, d, a, 0); \
125
+ tcg_gen_neg_i64(d, d); \
126
+ } \
127
+ static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
128
+ { \
129
+ TCGv_vec zero = tcg_const_zeros_vec_matching(d); \
130
+ tcg_gen_cmp_vec(COND, vece, d, a, zero); \
131
+ tcg_temp_free_vec(zero); \
132
+ } \
133
+ void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \
134
+ uint32_t opr_sz, uint32_t max_sz) \
135
+ { \
136
+ const GVecGen2 op[4] = { \
137
+ { .fno = gen_helper_gvec_##NAME##0_b, \
138
+ .fniv = gen_##NAME##0_vec, \
139
+ .opt_opc = vecop_list_cmp, \
140
+ .vece = MO_8 }, \
141
+ { .fno = gen_helper_gvec_##NAME##0_h, \
142
+ .fniv = gen_##NAME##0_vec, \
143
+ .opt_opc = vecop_list_cmp, \
144
+ .vece = MO_16 }, \
145
+ { .fni4 = gen_##NAME##0_i32, \
146
+ .fniv = gen_##NAME##0_vec, \
147
+ .opt_opc = vecop_list_cmp, \
148
+ .vece = MO_32 }, \
149
+ { .fni8 = gen_##NAME##0_i64, \
150
+ .fniv = gen_##NAME##0_vec, \
151
+ .opt_opc = vecop_list_cmp, \
152
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64, \
153
+ .vece = MO_64 }, \
154
+ }; \
155
+ tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \
156
+ }
157
158
static const TCGOpcode vecop_list_cmp[] = {
159
INDEX_op_cmp_vec, 0
160
};
161
162
-const GVecGen2 ceq0_op[4] = {
163
- { .fno = gen_helper_gvec_ceq0_b,
164
- .fniv = gen_ceq0_vec,
165
- .opt_opc = vecop_list_cmp,
166
- .vece = MO_8 },
167
- { .fno = gen_helper_gvec_ceq0_h,
168
- .fniv = gen_ceq0_vec,
169
- .opt_opc = vecop_list_cmp,
170
- .vece = MO_16 },
171
- { .fni4 = gen_ceq0_i32,
172
- .fniv = gen_ceq0_vec,
173
- .opt_opc = vecop_list_cmp,
174
- .vece = MO_32 },
175
- { .fni8 = gen_ceq0_i64,
176
- .fniv = gen_ceq0_vec,
177
- .opt_opc = vecop_list_cmp,
178
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
179
- .vece = MO_64 },
180
-};
181
+GEN_CMP0(ceq, TCG_COND_EQ)
182
+GEN_CMP0(cle, TCG_COND_LE)
183
+GEN_CMP0(cge, TCG_COND_GE)
184
+GEN_CMP0(clt, TCG_COND_LT)
185
+GEN_CMP0(cgt, TCG_COND_GT)
186
187
-static void gen_cle0_i32(TCGv_i32 d, TCGv_i32 a)
188
-{
189
- tcg_gen_setcondi_i32(TCG_COND_LE, d, a, 0);
190
- tcg_gen_neg_i32(d, d);
191
-}
192
-
193
-static void gen_cle0_i64(TCGv_i64 d, TCGv_i64 a)
194
-{
195
- tcg_gen_setcondi_i64(TCG_COND_LE, d, a, 0);
196
- tcg_gen_neg_i64(d, d);
197
-}
198
-
199
-static void gen_cle0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
200
-{
201
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
202
- tcg_gen_cmp_vec(TCG_COND_LE, vece, d, a, zero);
203
- tcg_temp_free_vec(zero);
204
-}
205
-
206
-const GVecGen2 cle0_op[4] = {
207
- { .fno = gen_helper_gvec_cle0_b,
208
- .fniv = gen_cle0_vec,
209
- .opt_opc = vecop_list_cmp,
210
- .vece = MO_8 },
211
- { .fno = gen_helper_gvec_cle0_h,
212
- .fniv = gen_cle0_vec,
213
- .opt_opc = vecop_list_cmp,
214
- .vece = MO_16 },
215
- { .fni4 = gen_cle0_i32,
216
- .fniv = gen_cle0_vec,
217
- .opt_opc = vecop_list_cmp,
218
- .vece = MO_32 },
219
- { .fni8 = gen_cle0_i64,
220
- .fniv = gen_cle0_vec,
221
- .opt_opc = vecop_list_cmp,
222
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
223
- .vece = MO_64 },
224
-};
225
-
226
-static void gen_cge0_i32(TCGv_i32 d, TCGv_i32 a)
227
-{
228
- tcg_gen_setcondi_i32(TCG_COND_GE, d, a, 0);
229
- tcg_gen_neg_i32(d, d);
230
-}
231
-
232
-static void gen_cge0_i64(TCGv_i64 d, TCGv_i64 a)
233
-{
234
- tcg_gen_setcondi_i64(TCG_COND_GE, d, a, 0);
235
- tcg_gen_neg_i64(d, d);
236
-}
237
-
238
-static void gen_cge0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
239
-{
240
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
241
- tcg_gen_cmp_vec(TCG_COND_GE, vece, d, a, zero);
242
- tcg_temp_free_vec(zero);
243
-}
244
-
245
-const GVecGen2 cge0_op[4] = {
246
- { .fno = gen_helper_gvec_cge0_b,
247
- .fniv = gen_cge0_vec,
248
- .opt_opc = vecop_list_cmp,
249
- .vece = MO_8 },
250
- { .fno = gen_helper_gvec_cge0_h,
251
- .fniv = gen_cge0_vec,
252
- .opt_opc = vecop_list_cmp,
253
- .vece = MO_16 },
254
- { .fni4 = gen_cge0_i32,
255
- .fniv = gen_cge0_vec,
256
- .opt_opc = vecop_list_cmp,
257
- .vece = MO_32 },
258
- { .fni8 = gen_cge0_i64,
259
- .fniv = gen_cge0_vec,
260
- .opt_opc = vecop_list_cmp,
261
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
262
- .vece = MO_64 },
263
-};
264
-
265
-static void gen_clt0_i32(TCGv_i32 d, TCGv_i32 a)
266
-{
267
- tcg_gen_setcondi_i32(TCG_COND_LT, d, a, 0);
268
- tcg_gen_neg_i32(d, d);
269
-}
270
-
271
-static void gen_clt0_i64(TCGv_i64 d, TCGv_i64 a)
272
-{
273
- tcg_gen_setcondi_i64(TCG_COND_LT, d, a, 0);
274
- tcg_gen_neg_i64(d, d);
275
-}
276
-
277
-static void gen_clt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
278
-{
279
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
280
- tcg_gen_cmp_vec(TCG_COND_LT, vece, d, a, zero);
281
- tcg_temp_free_vec(zero);
282
-}
283
-
284
-const GVecGen2 clt0_op[4] = {
285
- { .fno = gen_helper_gvec_clt0_b,
286
- .fniv = gen_clt0_vec,
287
- .opt_opc = vecop_list_cmp,
288
- .vece = MO_8 },
289
- { .fno = gen_helper_gvec_clt0_h,
290
- .fniv = gen_clt0_vec,
291
- .opt_opc = vecop_list_cmp,
292
- .vece = MO_16 },
293
- { .fni4 = gen_clt0_i32,
294
- .fniv = gen_clt0_vec,
295
- .opt_opc = vecop_list_cmp,
296
- .vece = MO_32 },
297
- { .fni8 = gen_clt0_i64,
298
- .fniv = gen_clt0_vec,
299
- .opt_opc = vecop_list_cmp,
300
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
301
- .vece = MO_64 },
302
-};
303
-
304
-static void gen_cgt0_i32(TCGv_i32 d, TCGv_i32 a)
305
-{
306
- tcg_gen_setcondi_i32(TCG_COND_GT, d, a, 0);
307
- tcg_gen_neg_i32(d, d);
308
-}
309
-
310
-static void gen_cgt0_i64(TCGv_i64 d, TCGv_i64 a)
311
-{
312
- tcg_gen_setcondi_i64(TCG_COND_GT, d, a, 0);
313
- tcg_gen_neg_i64(d, d);
314
-}
315
-
316
-static void gen_cgt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
317
-{
318
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
319
- tcg_gen_cmp_vec(TCG_COND_GT, vece, d, a, zero);
320
- tcg_temp_free_vec(zero);
321
-}
322
-
323
-const GVecGen2 cgt0_op[4] = {
324
- { .fno = gen_helper_gvec_cgt0_b,
325
- .fniv = gen_cgt0_vec,
326
- .opt_opc = vecop_list_cmp,
327
- .vece = MO_8 },
328
- { .fno = gen_helper_gvec_cgt0_h,
329
- .fniv = gen_cgt0_vec,
330
- .opt_opc = vecop_list_cmp,
331
- .vece = MO_16 },
332
- { .fni4 = gen_cgt0_i32,
333
- .fniv = gen_cgt0_vec,
334
- .opt_opc = vecop_list_cmp,
335
- .vece = MO_32 },
336
- { .fni8 = gen_cgt0_i64,
337
- .fniv = gen_cgt0_vec,
338
- .opt_opc = vecop_list_cmp,
339
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
340
- .vece = MO_64 },
341
-};
342
+#undef GEN_CMP0
343
344
static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
345
{
346
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
347
break;
348
349
case NEON_2RM_VCEQ0:
350
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
351
- vec_size, &ceq0_op[size]);
352
+ gen_gvec_ceq0(size, rd_ofs, rm_ofs, vec_size, vec_size);
353
break;
354
case NEON_2RM_VCGT0:
355
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
356
- vec_size, &cgt0_op[size]);
357
+ gen_gvec_cgt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
358
break;
359
case NEON_2RM_VCLE0:
360
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
361
- vec_size, &cle0_op[size]);
362
+ gen_gvec_cle0(size, rd_ofs, rm_ofs, vec_size, vec_size);
363
break;
364
case NEON_2RM_VCGE0:
365
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
366
- vec_size, &cge0_op[size]);
367
+ gen_gvec_cge0(size, rd_ofs, rm_ofs, vec_size, vec_size);
368
break;
369
case NEON_2RM_VCLT0:
370
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
371
- vec_size, &clt0_op[size]);
372
+ gen_gvec_clt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
373
break;
374
375
default:
376
--
107
--
377
2.20.1
108
2.25.1
378
109
379
110
diff view generated by jsdifflib
1
From: Patrick Williams <patrick@stwcx.xyz>
1
We use the arm_boot_info::nb_cpus field in only one place, and that
2
2
place can easily get the number of CPUs locally rather than relying
3
Sonora Pass is a 2 socket x86 motherboard designed by Facebook
3
on the board code to have set the field correctly. (At least one
4
and supported by OpenBMC. Strapping configuration was obtained
4
board, xlnx-versal-virt, does not set the field despite having more
5
from hardware and i2c configuration is based on dts found at:
5
than one CPU.)
6
6
7
https://github.com/facebook/openbmc-linux/blob/1633c87b8ba7c162095787c988979b748ba65dc8/arch/arm/boot/dts/aspeed-bmc-facebook-sonorapass.dts
8
9
Booted a test image of http://github.com/facebook/openbmc to login
10
prompt.
11
12
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
13
Reviewed-by: Amithash Prasad <amithash@fb.com>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
15
[PMM: fixed block comment style nit]
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Tested-by: Cédric Le Goater <clg@kaod.org>
11
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
12
Message-id: 20220127154639.2090164-16-peter.maydell@linaro.org
17
---
13
---
18
hw/arm/aspeed.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++
14
include/hw/arm/boot.h | 1 -
19
1 file changed, 78 insertions(+)
15
hw/arm/aspeed.c | 1 -
20
16
hw/arm/boot.c | 7 +++----
17
hw/arm/exynos4_boards.c | 1 -
18
hw/arm/highbank.c | 1 -
19
hw/arm/imx25_pdk.c | 3 +--
20
hw/arm/kzm.c | 1 -
21
hw/arm/mcimx6ul-evk.c | 1 -
22
hw/arm/mcimx7d-sabre.c | 1 -
23
hw/arm/npcm7xx.c | 3 ---
24
hw/arm/orangepi.c | 4 +---
25
hw/arm/raspi.c | 1 -
26
hw/arm/realview.c | 1 -
27
hw/arm/sabrelite.c | 1 -
28
hw/arm/sbsa-ref.c | 1 -
29
hw/arm/vexpress.c | 1 -
30
hw/arm/virt.c | 1 -
31
hw/arm/xilinx_zynq.c | 1 -
32
18 files changed, 5 insertions(+), 26 deletions(-)
33
34
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/boot.h
37
+++ b/include/hw/arm/boot.h
38
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info {
39
hwaddr smp_loader_start;
40
hwaddr smp_bootreg_addr;
41
hwaddr gic_cpu_if_addr;
42
- int nb_cpus;
43
int board_id;
44
/* ARM machines that support the ARM Security Extensions use this field to
45
* control whether Linux is booted as secure(true) or non-secure(false).
21
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
46
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
22
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/aspeed.c
48
--- a/hw/arm/aspeed.c
24
+++ b/hw/arm/aspeed.c
49
+++ b/hw/arm/aspeed.c
25
@@ -XXX,XX +XXX,XX @@ struct AspeedBoardState {
50
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
26
SCU_AST2500_HW_STRAP_ACPI_ENABLE | \
51
27
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
52
aspeed_board_binfo.ram_size = machine->ram_size;
28
53
aspeed_board_binfo.loader_start = sc->memmap[ASPEED_DEV_SDRAM];
29
+/* Sonorapass hardware value: 0xF100D216 */
54
- aspeed_board_binfo.nb_cpus = sc->num_cpus;
30
+#define SONORAPASS_BMC_HW_STRAP1 ( \
55
31
+ SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
56
if (amc->i2c_init) {
32
+ SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \
57
amc->i2c_init(bmc);
33
+ SCU_AST2500_HW_STRAP_UART_DEBUG | \
58
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
34
+ SCU_AST2500_HW_STRAP_RESERVED28 | \
59
index XXXXXXX..XXXXXXX 100644
35
+ SCU_AST2500_HW_STRAP_DDR4_ENABLE | \
60
--- a/hw/arm/boot.c
36
+ SCU_HW_STRAP_VGA_CLASS_CODE | \
61
+++ b/hw/arm/boot.c
37
+ SCU_HW_STRAP_LPC_RESET_PIN | \
62
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
38
+ SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER) | \
63
elf_machine = EM_ARM;
39
+ SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) | \
64
}
40
+ SCU_HW_STRAP_VGA_BIOS_ROM | \
65
41
+ SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
66
- if (info->nb_cpus == 0)
42
+ SCU_AST2500_HW_STRAP_RESERVED1)
67
- info->nb_cpus = 1;
43
+
68
-
44
/* Swift hardware value: 0xF11AD206 */
69
/* Assume that raw images are linux kernels, and ELF images are not. */
45
#define SWIFT_BMC_HW_STRAP1 ( \
70
kernel_size = arm_load_elf(info, &elf_entry, &image_low_addr,
46
AST2500_HW_STRAP1_DEFAULTS | \
71
&image_high_addr, elf_machine, as);
47
@@ -XXX,XX +XXX,XX @@ static void swift_bmc_i2c_init(AspeedBoardState *bmc)
72
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
48
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x4a);
73
AddressSpace *as = arm_boot_address_space(cpu, info);
74
int boot_el;
75
CPUARMState *env = &cpu->env;
76
+ int nb_cpus = 0;
77
78
/*
79
* CPU objects (unlike devices) are not automatically reset on system
80
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
81
*/
82
for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
83
qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
84
+ nb_cpus++;
85
}
86
87
/*
88
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
89
}
90
91
if (info->psci_conduit == QEMU_PSCI_CONDUIT_DISABLED &&
92
- info->is_linux && info->nb_cpus > 1) {
93
+ info->is_linux && nb_cpus > 1) {
94
/*
95
* We're booting Linux but not using PSCI, so for SMP we need
96
* to write a custom secondary CPU boot loader stub, and arrange
97
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/hw/arm/exynos4_boards.c
100
+++ b/hw/arm/exynos4_boards.c
101
@@ -XXX,XX +XXX,XX @@ static unsigned long exynos4_board_ram_size[EXYNOS4_NUM_OF_BOARDS] = {
102
static struct arm_boot_info exynos4_board_binfo = {
103
.loader_start = EXYNOS4210_BASE_BOOT_ADDR,
104
.smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
105
- .nb_cpus = EXYNOS4210_NCPUS,
106
.write_secondary_boot = exynos4210_write_secondary,
107
};
108
109
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/hw/arm/highbank.c
112
+++ b/hw/arm/highbank.c
113
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
114
* clear that the value is meaningless.
115
*/
116
highbank_binfo.board_id = -1;
117
- highbank_binfo.nb_cpus = smp_cpus;
118
highbank_binfo.loader_start = 0;
119
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
120
highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
121
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/arm/imx25_pdk.c
124
+++ b/hw/arm/imx25_pdk.c
125
@@ -XXX,XX +XXX,XX @@ static void imx25_pdk_init(MachineState *machine)
126
127
imx25_pdk_binfo.ram_size = machine->ram_size;
128
imx25_pdk_binfo.loader_start = FSL_IMX25_SDRAM0_ADDR;
129
- imx25_pdk_binfo.board_id = 1771,
130
- imx25_pdk_binfo.nb_cpus = 1;
131
+ imx25_pdk_binfo.board_id = 1771;
132
133
for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
134
BusState *bus;
135
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/arm/kzm.c
138
+++ b/hw/arm/kzm.c
139
@@ -XXX,XX +XXX,XX @@ static void kzm_init(MachineState *machine)
140
}
141
142
kzm_binfo.ram_size = machine->ram_size;
143
- kzm_binfo.nb_cpus = 1;
144
145
if (!qtest_enabled()) {
146
arm_load_kernel(&s->soc.cpu, machine, &kzm_binfo);
147
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/hw/arm/mcimx6ul-evk.c
150
+++ b/hw/arm/mcimx6ul-evk.c
151
@@ -XXX,XX +XXX,XX @@ static void mcimx6ul_evk_init(MachineState *machine)
152
.loader_start = FSL_IMX6UL_MMDC_ADDR,
153
.board_id = -1,
154
.ram_size = machine->ram_size,
155
- .nb_cpus = machine->smp.cpus,
156
.psci_conduit = QEMU_PSCI_CONDUIT_SMC,
157
};
158
159
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/hw/arm/mcimx7d-sabre.c
162
+++ b/hw/arm/mcimx7d-sabre.c
163
@@ -XXX,XX +XXX,XX @@ static void mcimx7d_sabre_init(MachineState *machine)
164
.loader_start = FSL_IMX7_MMDC_ADDR,
165
.board_id = -1,
166
.ram_size = machine->ram_size,
167
- .nb_cpus = machine->smp.cpus,
168
.psci_conduit = QEMU_PSCI_CONDUIT_SMC,
169
};
170
171
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/hw/arm/npcm7xx.c
174
+++ b/hw/arm/npcm7xx.c
175
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info npcm7xx_binfo = {
176
177
void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
178
{
179
- NPCM7xxClass *sc = NPCM7XX_GET_CLASS(soc);
180
-
181
npcm7xx_binfo.ram_size = machine->ram_size;
182
- npcm7xx_binfo.nb_cpus = sc->num_cpus;
183
184
arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
49
}
185
}
50
186
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
51
+static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc)
187
index XXXXXXX..XXXXXXX 100644
52
+{
188
--- a/hw/arm/orangepi.c
53
+ AspeedSoCState *soc = &bmc->soc;
189
+++ b/hw/arm/orangepi.c
54
+
190
@@ -XXX,XX +XXX,XX @@
55
+ /* bus 2 : */
191
#include "hw/qdev-properties.h"
56
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x48);
192
#include "hw/arm/allwinner-h3.h"
57
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x49);
193
58
+ /* bus 2 : pca9546 @ 0x73 */
194
-static struct arm_boot_info orangepi_binfo = {
59
+
195
- .nb_cpus = AW_H3_NUM_CPUS,
60
+ /* bus 3 : pca9548 @ 0x70 */
196
-};
61
+
197
+static struct arm_boot_info orangepi_binfo;
62
+ /* bus 4 : */
198
63
+ uint8_t *eeprom4_54 = g_malloc0(8 * 1024);
199
static void orangepi_init(MachineState *machine)
64
+ smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), 0x54,
65
+ eeprom4_54);
66
+ /* PCA9539 @ 0x76, but PCA9552 is compatible */
67
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x76);
68
+ /* PCA9539 @ 0x77, but PCA9552 is compatible */
69
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x77);
70
+
71
+ /* bus 6 : */
72
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x48);
73
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x49);
74
+ /* bus 6 : pca9546 @ 0x73 */
75
+
76
+ /* bus 8 : */
77
+ uint8_t *eeprom8_56 = g_malloc0(8 * 1024);
78
+ smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), 0x56,
79
+ eeprom8_56);
80
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x60);
81
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x61);
82
+ /* bus 8 : adc128d818 @ 0x1d */
83
+ /* bus 8 : adc128d818 @ 0x1f */
84
+
85
+ /*
86
+ * bus 13 : pca9548 @ 0x71
87
+ * - channel 3:
88
+ * - tmm421 @ 0x4c
89
+ * - tmp421 @ 0x4e
90
+ * - tmp421 @ 0x4f
91
+ */
92
+
93
+}
94
+
95
static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
96
{
200
{
97
AspeedSoCState *soc = &bmc->soc;
201
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
98
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
202
index XXXXXXX..XXXXXXX 100644
99
mc->default_ram_size = 512 * MiB;
203
--- a/hw/arm/raspi.c
100
};
204
+++ b/hw/arm/raspi.c
101
205
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, RaspiProcessorId processor_id,
102
+static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
206
103
+{
207
s->binfo.board_id = MACH_TYPE_BCM2708;
104
+ MachineClass *mc = MACHINE_CLASS(oc);
208
s->binfo.ram_size = ram_size;
105
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
209
- s->binfo.nb_cpus = machine->smp.cpus;
106
+
210
107
+ mc->desc = "OCP SonoraPass BMC (ARM1176)";
211
if (processor_id <= PROCESSOR_ID_BCM2836) {
108
+ amc->soc_name = "ast2500-a1";
212
/*
109
+ amc->hw_strap1 = SONORAPASS_BMC_HW_STRAP1;
213
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
110
+ amc->fmc_model = "mx66l1g45g";
214
index XXXXXXX..XXXXXXX 100644
111
+ amc->spi_model = "mx66l1g45g";
215
--- a/hw/arm/realview.c
112
+ amc->num_cs = 2;
216
+++ b/hw/arm/realview.c
113
+ amc->i2c_init = sonorapass_bmc_i2c_init;
217
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
114
+ mc->default_ram_size = 512 * MiB;
218
memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
115
+};
219
116
+
220
realview_binfo.ram_size = ram_size;
117
static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data)
221
- realview_binfo.nb_cpus = smp_cpus;
118
{
222
realview_binfo.board_id = realview_board_id[board_type];
119
MachineClass *mc = MACHINE_CLASS(oc);
223
realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
120
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = {
224
arm_load_kernel(ARM_CPU(first_cpu), machine, &realview_binfo);
121
.name = MACHINE_TYPE_NAME("swift-bmc"),
225
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
122
.parent = TYPE_ASPEED_MACHINE,
226
index XXXXXXX..XXXXXXX 100644
123
.class_init = aspeed_machine_swift_class_init,
227
--- a/hw/arm/sabrelite.c
124
+ }, {
228
+++ b/hw/arm/sabrelite.c
125
+ .name = MACHINE_TYPE_NAME("sonorapass-bmc"),
229
@@ -XXX,XX +XXX,XX @@ static void sabrelite_init(MachineState *machine)
126
+ .parent = TYPE_ASPEED_MACHINE,
230
}
127
+ .class_init = aspeed_machine_sonorapass_class_init,
231
128
}, {
232
sabrelite_binfo.ram_size = machine->ram_size;
129
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
233
- sabrelite_binfo.nb_cpus = machine->smp.cpus;
130
.parent = TYPE_ASPEED_MACHINE,
234
sabrelite_binfo.secure_boot = true;
235
sabrelite_binfo.write_secondary_boot = sabrelite_write_secondary;
236
sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary;
237
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/hw/arm/sbsa-ref.c
240
+++ b/hw/arm/sbsa-ref.c
241
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
242
create_secure_ec(secure_sysmem);
243
244
sms->bootinfo.ram_size = machine->ram_size;
245
- sms->bootinfo.nb_cpus = smp_cpus;
246
sms->bootinfo.board_id = -1;
247
sms->bootinfo.loader_start = sbsa_ref_memmap[SBSA_MEM].base;
248
sms->bootinfo.get_dtb = sbsa_ref_dtb;
249
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
250
index XXXXXXX..XXXXXXX 100644
251
--- a/hw/arm/vexpress.c
252
+++ b/hw/arm/vexpress.c
253
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
254
}
255
256
daughterboard->bootinfo.ram_size = machine->ram_size;
257
- daughterboard->bootinfo.nb_cpus = machine->smp.cpus;
258
daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID;
259
daughterboard->bootinfo.loader_start = daughterboard->loader_start;
260
daughterboard->bootinfo.smp_loader_start = map[VE_SRAM];
261
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
262
index XXXXXXX..XXXXXXX 100644
263
--- a/hw/arm/virt.c
264
+++ b/hw/arm/virt.c
265
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
266
}
267
268
vms->bootinfo.ram_size = machine->ram_size;
269
- vms->bootinfo.nb_cpus = smp_cpus;
270
vms->bootinfo.board_id = -1;
271
vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base;
272
vms->bootinfo.get_dtb = machvirt_dtb;
273
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
274
index XXXXXXX..XXXXXXX 100644
275
--- a/hw/arm/xilinx_zynq.c
276
+++ b/hw/arm/xilinx_zynq.c
277
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
278
sysbus_mmio_map(busdev, 0, 0xF8007000);
279
280
zynq_binfo.ram_size = machine->ram_size;
281
- zynq_binfo.nb_cpus = 1;
282
zynq_binfo.board_id = 0xd32;
283
zynq_binfo.loader_start = 0;
284
zynq_binfo.board_setup_addr = BOARD_SETUP_ADDR;
131
--
285
--
132
2.20.1
286
2.25.1
133
287
134
288
diff view generated by jsdifflib
1
Convert the Neon VHADD insns in the 3-reg-same group to decodetree.
1
If we're using PSCI emulation, we add a /psci node to the device tree
2
we pass to the guest. At the moment, if the dtb already has a /psci
3
node in it, we retain it, rather than replacing it. (This behaviour
4
was added in commit c39770cd637765 in 2018.)
5
6
This is a problem if the existing node doesn't match our PSCI
7
emulation. In particular, it might specify the wrong method (HVC vs
8
SMC), or wrong function IDs for cpu_suspend/cpu_off/etc, in which
9
case the guest will not get the behaviour it wants when it makes PSCI
10
calls.
11
12
An example of this is trying to boot the highbank or midway board
13
models using the device tree supplied in the kernel sources: this
14
device tree includes a /psci node that specifies function IDs that
15
don't match the (PSCI 0.2 compliant) IDs that QEMU uses. The dtb
16
cpu_suspend function ID happens to match the PSCI 0.2 cpu_off ID, so
17
the guest hangs after booting when the kernel tries to idle the CPU
18
and instead it gets turned off.
19
20
Instead of retaining an existing /psci node, delete it entirely
21
and replace it with a node whose properties match QEMU's PSCI
22
emulation behaviour. This matches the way we handle /memory nodes,
23
where we also delete any existing nodes and write in ones that
24
match the way QEMU is going to behave.
2
25
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200512163904.10918-5-peter.maydell@linaro.org
28
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
29
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
30
Tested-by: Cédric Le Goater <clg@kaod.org>
31
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
32
Message-id: 20220127154639.2090164-17-peter.maydell@linaro.org
6
---
33
---
7
target/arm/neon-dp.decode | 2 ++
34
hw/arm/boot.c | 7 ++++---
8
target/arm/translate-neon.inc.c | 24 ++++++++++++++++++++++++
35
1 file changed, 4 insertions(+), 3 deletions(-)
9
target/arm/translate.c | 4 +---
10
3 files changed, 27 insertions(+), 3 deletions(-)
11
36
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
37
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
13
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
39
--- a/hw/arm/boot.c
15
+++ b/target/arm/neon-dp.decode
40
+++ b/hw/arm/boot.c
16
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
17
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
42
}
18
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
43
19
44
/*
20
+VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
45
- * If /psci node is present in provided DTB, assume that no fixup
21
+VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
46
- * is necessary and all PSCI configuration should be taken as-is
22
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
47
+ * A pre-existing /psci node might specify function ID values
23
VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same
48
+ * that don't match QEMU's PSCI implementation. Delete the whole
24
49
+ * node and put our own in instead.
25
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
50
*/
26
index XXXXXXX..XXXXXXX 100644
51
rc = fdt_path_offset(fdt, "/psci");
27
--- a/target/arm/translate-neon.inc.c
52
if (rc >= 0) {
28
+++ b/target/arm/translate-neon.inc.c
53
- return;
29
@@ -XXX,XX +XXX,XX @@ DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64)
54
+ qemu_fdt_nop_node(fdt, "/psci");
30
DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64)
55
}
31
DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64)
56
32
DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
57
qemu_fdt_add_subnode(fdt, "/psci");
33
+
34
+#define DO_3SAME_32(INSN, FUNC) \
35
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
36
+ uint32_t rn_ofs, uint32_t rm_ofs, \
37
+ uint32_t oprsz, uint32_t maxsz) \
38
+ { \
39
+ static const GVecGen3 ops[4] = { \
40
+ { .fni4 = gen_helper_neon_##FUNC##8 }, \
41
+ { .fni4 = gen_helper_neon_##FUNC##16 }, \
42
+ { .fni4 = gen_helper_neon_##FUNC##32 }, \
43
+ { 0 }, \
44
+ }; \
45
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \
46
+ } \
47
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
48
+ { \
49
+ if (a->size > 2) { \
50
+ return false; \
51
+ } \
52
+ return do_3same(s, a, gen_##INSN##_3s); \
53
+ }
54
+
55
+DO_3SAME_32(VHADD_S, hadd_s)
56
+DO_3SAME_32(VHADD_U, hadd_u)
57
diff --git a/target/arm/translate.c b/target/arm/translate.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/translate.c
60
+++ b/target/arm/translate.c
61
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
62
case NEON_3R_VML:
63
case NEON_3R_VSHL:
64
case NEON_3R_SHA:
65
+ case NEON_3R_VHADD:
66
/* Already handled by decodetree */
67
return 1;
68
}
69
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
70
tmp2 = neon_load_reg(rm, pass);
71
}
72
switch (op) {
73
- case NEON_3R_VHADD:
74
- GEN_NEON_INTEGER_OP(hadd);
75
- break;
76
case NEON_3R_VRHADD:
77
GEN_NEON_INTEGER_OP(rhadd);
78
break;
79
--
58
--
80
2.20.1
59
2.25.1
81
60
82
61
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
The little end UUID is used in many places, so make
3
Always call arm_load_kernel() regardless of kernel_filename being
4
NVDIMM_UUID_LE to a common macro to convert the UUID
4
set. This is needed because arm_load_kernel() sets up reset for
5
to a little end array.
5
the CPUs.
6
6
7
Reviewed-by: Xiang Zheng <zhengxiang9@huawei.com>
7
Fixes: 6f16da53ff (hw/arm: versal: Add a virtual Xilinx Versal board)
8
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20200512030609.19593-2-gengdongjiu@huawei.com
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 20220130110313.4045351-2-edgar.iglesias@gmail.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
include/qemu/uuid.h | 27 +++++++++++++++++++++++++++
14
hw/arm/xlnx-versal-virt.c | 11 ++---------
14
hw/acpi/nvdimm.c | 10 +++-------
15
1 file changed, 2 insertions(+), 9 deletions(-)
15
2 files changed, 30 insertions(+), 7 deletions(-)
16
16
17
diff --git a/include/qemu/uuid.h b/include/qemu/uuid.h
17
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/qemu/uuid.h
19
--- a/hw/arm/xlnx-versal-virt.c
20
+++ b/include/qemu/uuid.h
20
+++ b/hw/arm/xlnx-versal-virt.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
22
};
22
s->binfo.get_dtb = versal_virt_get_dtb;
23
} QemuUUID;
23
s->binfo.modify_dtb = versal_virt_modify_dtb;
24
24
s->binfo.psci_conduit = psci_conduit;
25
+/**
25
- if (machine->kernel_filename) {
26
+ * UUID_LE - converts the fields of UUID to little-endian array,
26
- arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
27
+ * each of parameters is the filed of UUID.
27
- } else {
28
+ *
28
- AddressSpace *as = arm_boot_address_space(&s->soc.fpd.apu.cpu[0],
29
+ * @time_low: The low field of the timestamp
29
- &s->binfo);
30
+ * @time_mid: The middle field of the timestamp
30
+ if (!machine->kernel_filename) {
31
+ * @time_hi_and_version: The high field of the timestamp
31
/* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
32
+ * multiplexed with the version number
32
* Offset things by 4K. */
33
+ * @clock_seq_hi_and_reserved: The high field of the clock
33
s->binfo.loader_start = 0x1000;
34
+ * sequence multiplexed with the variant
34
s->binfo.dtb_limit = 0x1000000;
35
+ * @clock_seq_low: The low field of the clock sequence
35
- if (arm_load_dtb(s->binfo.loader_start,
36
+ * @node0: The spatially unique node0 identifier
36
- &s->binfo, s->binfo.dtb_limit, as, machine) < 0) {
37
+ * @node1: The spatially unique node1 identifier
37
- exit(EXIT_FAILURE);
38
+ * @node2: The spatially unique node2 identifier
38
- }
39
+ * @node3: The spatially unique node3 identifier
39
}
40
+ * @node4: The spatially unique node4 identifier
40
+ arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
41
+ * @node5: The spatially unique node5 identifier
41
42
+ */
42
for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
43
+#define UUID_LE(time_low, time_mid, time_hi_and_version, \
43
BusState *spi_bus;
44
+ clock_seq_hi_and_reserved, clock_seq_low, node0, node1, node2, \
45
+ node3, node4, node5) \
46
+ { (time_low) & 0xff, ((time_low) >> 8) & 0xff, ((time_low) >> 16) & 0xff, \
47
+ ((time_low) >> 24) & 0xff, (time_mid) & 0xff, ((time_mid) >> 8) & 0xff, \
48
+ (time_hi_and_version) & 0xff, ((time_hi_and_version) >> 8) & 0xff, \
49
+ (clock_seq_hi_and_reserved), (clock_seq_low), (node0), (node1), (node2),\
50
+ (node3), (node4), (node5) }
51
+
52
#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-" \
53
"%02hhx%02hhx-%02hhx%02hhx-" \
54
"%02hhx%02hhx-" \
55
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/acpi/nvdimm.c
58
+++ b/hw/acpi/nvdimm.c
59
@@ -XXX,XX +XXX,XX @@
60
*/
61
62
#include "qemu/osdep.h"
63
+#include "qemu/uuid.h"
64
#include "hw/acpi/acpi.h"
65
#include "hw/acpi/aml-build.h"
66
#include "hw/acpi/bios-linker-loader.h"
67
@@ -XXX,XX +XXX,XX @@
68
#include "hw/mem/nvdimm.h"
69
#include "qemu/nvdimm-utils.h"
70
71
-#define NVDIMM_UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
72
- { (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
73
- (b) & 0xff, ((b) >> 8) & 0xff, (c) & 0xff, ((c) >> 8) & 0xff, \
74
- (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }
75
-
76
/*
77
* define Byte Addressable Persistent Memory (PM) Region according to
78
* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure.
79
*/
80
static const uint8_t nvdimm_nfit_spa_uuid[] =
81
- NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
82
- 0x18, 0xb7, 0x8c, 0xdb);
83
+ UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
84
+ 0x18, 0xb7, 0x8c, 0xdb);
85
86
/*
87
* NVDIMM Firmware Interface Table
88
--
44
--
89
2.20.1
45
2.25.1
90
46
91
47
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
Must clear the tail for AdvSIMD when SVE is enabled.
3
The recently introduced debug tests in kvm-unit-tests exposed an error
4
in our handling of singlestep cause by stale hflags. This is caught by
5
--enable-debug-tcg when running the tests.
4
6
5
Fixes: ca40a6e6e39
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Cc: qemu-stable@nongnu.org
8
Reported-by: Andrew Jones <drjones@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Andrew Jones <drjones@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-15-richard.henderson@linaro.org
11
Message-id: 20220202122353.457084-1-alex.bennee@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/vec_helper.c | 2 ++
14
target/arm/helper-a64.c | 2 ++
13
1 file changed, 2 insertions(+)
15
1 file changed, 2 insertions(+)
14
16
15
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
17
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/vec_helper.c
19
--- a/target/arm/helper-a64.c
18
+++ b/target/arm/vec_helper.c
20
+++ b/target/arm/helper-a64.c
19
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
21
@@ -XXX,XX +XXX,XX @@ void HELPER(msr_i_daifset)(CPUARMState *env, uint32_t imm)
20
d[i + j] = TYPE##_mul(n[i + j], mm, stat); \
22
{
21
} \
23
daif_check(env, 0x1e, imm, GETPC());
22
} \
24
env->daif |= (imm << 6) & PSTATE_DAIF;
23
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
25
+ arm_rebuild_hflags(env);
24
}
26
}
25
27
26
DO_MUL_IDX(gvec_fmul_idx_h, float16, H2)
28
void HELPER(msr_i_daifclear)(CPUARMState *env, uint32_t imm)
27
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \
29
{
28
mm, a[i + j], 0, stat); \
30
daif_check(env, 0x1f, imm, GETPC());
29
} \
31
env->daif &= ~((imm << 6) & PSTATE_DAIF);
30
} \
32
+ arm_rebuild_hflags(env);
31
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
32
}
33
}
33
34
34
DO_FMLA_IDX(gvec_fmla_idx_h, float16, H2)
35
/* Convert a softfloat float_relation_ (as returned by
35
--
36
--
36
2.20.1
37
2.25.1
37
38
38
39
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Richard Petri <git@rpls.de>
2
2
3
kvm_arch_on_sigbus_vcpu() error injection uses source_id as
3
Starting the SysTick timer and changing the clock source a the same time
4
index in etc/hardware_errors to find out Error Status Data
4
will result in an error, if the previous clock period was zero. For exmaple,
5
Block entry corresponding to error source. So supported source_id
5
on the mps2-tz platforms, no refclk is present. Right after reset, the
6
values should be assigned here and not be changed afterwards to
6
configured ptimer period is zero, and trying to enabling it will turn it off
7
make sure that guest will write error into expected Error Status
7
right away. E.g., code running on the platform setting
8
Data Block.
9
8
10
Before QEMU writes a new error to ACPI table, it will check whether
9
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
11
previous error has been acknowledged. If not acknowledged, the new
12
errors will be ignored and not be recorded. For the errors section
13
type, QEMU simulate it to memory section error.
14
10
15
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
11
should change the clock source and enable the timer on real hardware, but
16
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
12
resulted in an error in qemu.
17
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
13
18
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
14
Signed-off-by: Richard Petri <git@rpls.de>
19
Message-id: 20200512030609.19593-9-gengdongjiu@huawei.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 20220201192650.289584-1-git@rpls.de
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
18
---
22
include/hw/acpi/ghes.h | 1 +
19
hw/timer/armv7m_systick.c | 8 ++++----
23
hw/acpi/ghes.c | 219 +++++++++++++++++++++++++++++++++++++++++
20
1 file changed, 4 insertions(+), 4 deletions(-)
24
2 files changed, 220 insertions(+)
25
21
26
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
22
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
27
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/acpi/ghes.h
24
--- a/hw/timer/armv7m_systick.c
29
+++ b/include/hw/acpi/ghes.h
25
+++ b/hw/timer/armv7m_systick.c
30
@@ -XXX,XX +XXX,XX @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
26
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_write(void *opaque, hwaddr addr,
31
void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
27
s->control &= 0xfffffff8;
32
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
28
s->control |= value & 7;
33
GArray *hardware_errors);
29
34
+int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
30
+ if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
35
#endif
31
+ systick_set_period_from_clock(s);
36
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/acpi/ghes.c
39
+++ b/hw/acpi/ghes.c
40
@@ -XXX,XX +XXX,XX @@
41
#include "qemu/error-report.h"
42
#include "hw/acpi/generic_event_device.h"
43
#include "hw/nvram/fw_cfg.h"
44
+#include "qemu/uuid.h"
45
46
#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
47
#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
48
@@ -XXX,XX +XXX,XX @@
49
/* Address offset in Generic Address Structure(GAS) */
50
#define GAS_ADDR_OFFSET 4
51
52
+/*
53
+ * The total size of Generic Error Data Entry
54
+ * ACPI 6.1/6.2: 18.3.2.7.1 Generic Error Data,
55
+ * Table 18-343 Generic Error Data Entry
56
+ */
57
+#define ACPI_GHES_DATA_LENGTH 72
58
+
59
+/* The memory section CPER size, UEFI 2.6: N.2.5 Memory Error Section */
60
+#define ACPI_GHES_MEM_CPER_LENGTH 80
61
+
62
+/* Masks for block_status flags */
63
+#define ACPI_GEBS_UNCORRECTABLE 1
64
+
65
+/*
66
+ * Total size for Generic Error Status Block except Generic Error Data Entries
67
+ * ACPI 6.2: 18.3.2.7.1 Generic Error Data,
68
+ * Table 18-380 Generic Error Status Block
69
+ */
70
+#define ACPI_GHES_GESB_SIZE 20
71
+
72
+/*
73
+ * Values for error_severity field
74
+ */
75
+enum AcpiGenericErrorSeverity {
76
+ ACPI_CPER_SEV_RECOVERABLE = 0,
77
+ ACPI_CPER_SEV_FATAL = 1,
78
+ ACPI_CPER_SEV_CORRECTED = 2,
79
+ ACPI_CPER_SEV_NONE = 3,
80
+};
81
+
82
/*
83
* Hardware Error Notification
84
* ACPI 4.0: 17.3.2.7 Hardware Error Notification
85
@@ -XXX,XX +XXX,XX @@ static void build_ghes_hw_error_notification(GArray *table, const uint8_t type)
86
build_append_int_noprefix(table, 0, 4);
87
}
88
89
+/*
90
+ * Generic Error Data Entry
91
+ * ACPI 6.1: 18.3.2.7.1 Generic Error Data
92
+ */
93
+static void acpi_ghes_generic_error_data(GArray *table,
94
+ const uint8_t *section_type, uint32_t error_severity,
95
+ uint8_t validation_bits, uint8_t flags,
96
+ uint32_t error_data_length, QemuUUID fru_id,
97
+ uint64_t time_stamp)
98
+{
99
+ const uint8_t fru_text[20] = {0};
100
+
101
+ /* Section Type */
102
+ g_array_append_vals(table, section_type, 16);
103
+
104
+ /* Error Severity */
105
+ build_append_int_noprefix(table, error_severity, 4);
106
+ /* Revision */
107
+ build_append_int_noprefix(table, 0x300, 2);
108
+ /* Validation Bits */
109
+ build_append_int_noprefix(table, validation_bits, 1);
110
+ /* Flags */
111
+ build_append_int_noprefix(table, flags, 1);
112
+ /* Error Data Length */
113
+ build_append_int_noprefix(table, error_data_length, 4);
114
+
115
+ /* FRU Id */
116
+ g_array_append_vals(table, fru_id.data, ARRAY_SIZE(fru_id.data));
117
+
118
+ /* FRU Text */
119
+ g_array_append_vals(table, fru_text, sizeof(fru_text));
120
+
121
+ /* Timestamp */
122
+ build_append_int_noprefix(table, time_stamp, 8);
123
+}
124
+
125
+/*
126
+ * Generic Error Status Block
127
+ * ACPI 6.1: 18.3.2.7.1 Generic Error Data
128
+ */
129
+static void acpi_ghes_generic_error_status(GArray *table, uint32_t block_status,
130
+ uint32_t raw_data_offset, uint32_t raw_data_length,
131
+ uint32_t data_length, uint32_t error_severity)
132
+{
133
+ /* Block Status */
134
+ build_append_int_noprefix(table, block_status, 4);
135
+ /* Raw Data Offset */
136
+ build_append_int_noprefix(table, raw_data_offset, 4);
137
+ /* Raw Data Length */
138
+ build_append_int_noprefix(table, raw_data_length, 4);
139
+ /* Data Length */
140
+ build_append_int_noprefix(table, data_length, 4);
141
+ /* Error Severity */
142
+ build_append_int_noprefix(table, error_severity, 4);
143
+}
144
+
145
+/* UEFI 2.6: N.2.5 Memory Error Section */
146
+static void acpi_ghes_build_append_mem_cper(GArray *table,
147
+ uint64_t error_physical_addr)
148
+{
149
+ /*
150
+ * Memory Error Record
151
+ */
152
+
153
+ /* Validation Bits */
154
+ build_append_int_noprefix(table,
155
+ (1ULL << 14) | /* Type Valid */
156
+ (1ULL << 1) /* Physical Address Valid */,
157
+ 8);
158
+ /* Error Status */
159
+ build_append_int_noprefix(table, 0, 8);
160
+ /* Physical Address */
161
+ build_append_int_noprefix(table, error_physical_addr, 8);
162
+ /* Skip all the detailed information normally found in such a record */
163
+ build_append_int_noprefix(table, 0, 48);
164
+ /* Memory Error Type */
165
+ build_append_int_noprefix(table, 0 /* Unknown error */, 1);
166
+ /* Skip all the detailed information normally found in such a record */
167
+ build_append_int_noprefix(table, 0, 7);
168
+}
169
+
170
+static int acpi_ghes_record_mem_error(uint64_t error_block_address,
171
+ uint64_t error_physical_addr)
172
+{
173
+ GArray *block;
174
+
175
+ /* Memory Error Section Type */
176
+ const uint8_t uefi_cper_mem_sec[] =
177
+ UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
178
+ 0xED, 0x7C, 0x83, 0xB1);
179
+
180
+ /* invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data,
181
+ * Table 17-13 Generic Error Data Entry
182
+ */
183
+ QemuUUID fru_id = {};
184
+ uint32_t data_length;
185
+
186
+ block = g_array_new(false, true /* clear */, 1);
187
+
188
+ /* This is the length if adding a new generic error data entry*/
189
+ data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
190
+
191
+ /*
192
+ * Check whether it will run out of the preallocated memory if adding a new
193
+ * generic error data entry
194
+ */
195
+ if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) {
196
+ error_report("Not enough memory to record new CPER!!!");
197
+ g_array_free(block, true);
198
+ return -1;
199
+ }
200
+
201
+ /* Build the new generic error status block header */
202
+ acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
203
+ 0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE);
204
+
205
+ /* Build this new generic error data entry header */
206
+ acpi_ghes_generic_error_data(block, uefi_cper_mem_sec,
207
+ ACPI_CPER_SEV_RECOVERABLE, 0, 0,
208
+ ACPI_GHES_MEM_CPER_LENGTH, fru_id, 0);
209
+
210
+ /* Build the memory section CPER for above new generic error data entry */
211
+ acpi_ghes_build_append_mem_cper(block, error_physical_addr);
212
+
213
+ /* Write the generic error data entry into guest memory */
214
+ cpu_physical_memory_write(error_block_address, block->data, block->len);
215
+
216
+ g_array_free(block, true);
217
+
218
+ return 0;
219
+}
220
+
221
/*
222
* Build table for the hardware error fw_cfg blob.
223
* Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
224
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
225
fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
226
NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
227
}
228
+
229
+int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
230
+{
231
+ uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0;
232
+ uint64_t start_addr;
233
+ bool ret = -1;
234
+ AcpiGedState *acpi_ged_state;
235
+ AcpiGhesState *ags;
236
+
237
+ assert(source_id < ACPI_HEST_SRC_ID_RESERVED);
238
+
239
+ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
240
+ NULL));
241
+ g_assert(acpi_ged_state);
242
+ ags = &acpi_ged_state->ghes_state;
243
+
244
+ start_addr = le64_to_cpu(ags->ghes_addr_le);
245
+
246
+ if (physical_address) {
247
+
248
+ if (source_id < ACPI_HEST_SRC_ID_RESERVED) {
249
+ start_addr += source_id * sizeof(uint64_t);
250
+ }
32
+ }
251
+
33
+
252
+ cpu_physical_memory_read(start_addr, &error_block_addr,
34
if ((oldval ^ value) & SYSTICK_ENABLE) {
253
+ sizeof(error_block_addr));
35
if (value & SYSTICK_ENABLE) {
254
+
36
ptimer_run(s->ptimer, 0);
255
+ error_block_addr = le64_to_cpu(error_block_addr);
37
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_write(void *opaque, hwaddr addr,
256
+
38
ptimer_stop(s->ptimer);
257
+ read_ack_register_addr = start_addr +
39
}
258
+ ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
40
}
259
+
41
-
260
+ cpu_physical_memory_read(read_ack_register_addr,
42
- if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
261
+ &read_ack_register, sizeof(read_ack_register));
43
- systick_set_period_from_clock(s);
262
+
44
- }
263
+ /* zero means OSPM does not acknowledge the error */
45
ptimer_transaction_commit(s->ptimer);
264
+ if (!read_ack_register) {
46
break;
265
+ error_report("OSPM does not acknowledge previous error,"
47
}
266
+ " so can not record CPER for current error anymore");
267
+ } else if (error_block_addr) {
268
+ read_ack_register = cpu_to_le64(0);
269
+ /*
270
+ * Clear the Read Ack Register, OSPM will write it to 1 when
271
+ * it acknowledges this error.
272
+ */
273
+ cpu_physical_memory_write(read_ack_register_addr,
274
+ &read_ack_register, sizeof(uint64_t));
275
+
276
+ ret = acpi_ghes_record_mem_error(error_block_addr,
277
+ physical_address);
278
+ } else
279
+ error_report("can not find Generic Error Status Block");
280
+ }
281
+
282
+ return ret;
283
+}
284
--
48
--
285
2.20.1
49
2.25.1
286
50
287
51
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
These operations do not touch fp_status.
3
We currently miss a bunch of register resets in the device reset
4
function. This sometimes prevents the guest from rebooting after
5
a system_reset (with virtio-blk-pci). For instance, we may get
6
the following errors:
4
7
8
invalid STE
9
smmuv3-iommu-memory-region-0-0 translation failed for iova=0x13a9d2000(SMMU_EVT_C_BAD_STE)
10
Invalid read at addr 0x13A9D2000, size 2, region '(null)', reason: rejected
11
invalid STE
12
smmuv3-iommu-memory-region-0-0 translation failed for iova=0x13a9d2000(SMMU_EVT_C_BAD_STE)
13
Invalid write at addr 0x13A9D2000, size 2, region '(null)', reason: rejected
14
invalid STE
15
16
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
Message-id: 20220202111602.627429-1-eric.auger@redhat.com
18
Fixes: 10a83cb988 ("hw/arm/smmuv3: Skeleton")
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200513163245.17915-12-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
21
---
10
target/arm/helper.h | 4 ++--
22
hw/arm/smmuv3.c | 6 ++++++
11
target/arm/translate-a64.c | 5 ++---
23
1 file changed, 6 insertions(+)
12
target/arm/translate.c | 12 ++----------
13
target/arm/vfp_helper.c | 5 ++---
14
4 files changed, 8 insertions(+), 18 deletions(-)
15
24
16
diff --git a/target/arm/helper.h b/target/arm/helper.h
25
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
17
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.h
27
--- a/hw/arm/smmuv3.c
19
+++ b/target/arm/helper.h
28
+++ b/hw/arm/smmuv3.c
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
29
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
21
DEF_HELPER_FLAGS_2(rsqrte_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
30
s->features = 0;
22
DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
31
s->sid_split = 0;
23
DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
32
s->aidr = 0x1;
24
-DEF_HELPER_2(recpe_u32, i32, i32, ptr)
33
+ s->cr[0] = 0;
25
-DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr)
34
+ s->cr0ack = 0;
26
+DEF_HELPER_FLAGS_1(recpe_u32, TCG_CALL_NO_RWG, i32, i32)
35
+ s->irq_ctrl = 0;
27
+DEF_HELPER_FLAGS_1(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32)
36
+ s->gerror = 0;
28
DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32)
37
+ s->gerrorn = 0;
29
38
+ s->statusr = 0;
30
DEF_HELPER_3(shl_cc, i32, env, i32, i32)
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-a64.c
34
+++ b/target/arm/translate-a64.c
35
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode,
36
37
switch (opcode) {
38
case 0x3c: /* URECPE */
39
- gen_helper_recpe_u32(tcg_res, tcg_op, fpst);
40
+ gen_helper_recpe_u32(tcg_res, tcg_op);
41
break;
42
case 0x3d: /* FRECPE */
43
gen_helper_recpe_f32(tcg_res, tcg_op, fpst);
44
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
45
unallocated_encoding(s);
46
return;
47
}
48
- need_fpstatus = true;
49
break;
50
case 0x1e: /* FRINT32Z */
51
case 0x1f: /* FRINT64Z */
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
53
gen_helper_rints_exact(tcg_res, tcg_op, tcg_fpstatus);
54
break;
55
case 0x7c: /* URSQRTE */
56
- gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
57
+ gen_helper_rsqrte_u32(tcg_res, tcg_op);
58
break;
59
case 0x1e: /* FRINT32Z */
60
case 0x5e: /* FRINT32X */
61
diff --git a/target/arm/translate.c b/target/arm/translate.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/translate.c
64
+++ b/target/arm/translate.c
65
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
66
break;
67
}
68
case NEON_2RM_VRECPE:
69
- {
70
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
71
- gen_helper_recpe_u32(tmp, tmp, fpstatus);
72
- tcg_temp_free_ptr(fpstatus);
73
+ gen_helper_recpe_u32(tmp, tmp);
74
break;
75
- }
76
case NEON_2RM_VRSQRTE:
77
- {
78
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
79
- gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
80
- tcg_temp_free_ptr(fpstatus);
81
+ gen_helper_rsqrte_u32(tmp, tmp);
82
break;
83
- }
84
case NEON_2RM_VRECPE_F:
85
{
86
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
87
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/vfp_helper.c
90
+++ b/target/arm/vfp_helper.c
91
@@ -XXX,XX +XXX,XX @@ float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
92
return make_float64(val);
93
}
39
}
94
40
95
-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
41
static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
96
+uint32_t HELPER(recpe_u32)(uint32_t a)
97
{
98
- /* float_status *s = fpstp; */
99
int input, estimate;
100
101
if ((a & 0x80000000) == 0) {
102
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
103
return deposit32(0, (32 - 9), 9, estimate);
104
}
105
106
-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
107
+uint32_t HELPER(rsqrte_u32)(uint32_t a)
108
{
109
int estimate;
110
111
--
42
--
112
2.20.1
43
2.25.1
113
44
114
45
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Currently the ITS accesses each 8-byte doubleword in a 4-doubleword
2
2
command packet with a separate address_space_ldq_le() call. This is
3
Pass a pointer directly to env->vfp.qc[0], rather than env.
3
awkward because the individual command processing functions have
4
This will allow SVE2, which does not modify QC, to pass a
4
ended up with code to handle "load more doublewords out of the
5
pointer to dummy storage.
5
packet", which is both unwieldy and also a potential source of bugs
6
6
because it's not obvious when looking at a line that pulls a field
7
Change the return type of inl_qrdml.h_s16 to match the
7
out of the 'value' variable which of the 4 doublewords that variable
8
sense of the operation: signed.
8
currently holds.
9
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Switch to using address_space_map() to map the whole command packet
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
at once and fish the four doublewords out of it. Then each process_*
12
Message-id: 20200513163245.17915-14-richard.henderson@linaro.org
12
function can start with a few lines of code that extract the fields
13
it cares about.
14
15
This requires us to split out the guts of process_its_cmd() into a
16
new do_process_its_cmd(), because we were previously overloading the
17
value and offset arguments as a backdoor way to directly pass the
18
devid and eventid from a write to GITS_TRANSLATER. The new
19
do_process_its_cmd() takes those arguments directly, and
20
process_its_cmd() is just a wrapper that does the "read fields from
21
command packet" part.
22
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20220201193207.2771604-2-peter.maydell@linaro.org
14
---
26
---
15
target/arm/translate.c | 18 ++++++++---
27
hw/intc/gicv3_internal.h | 4 +-
16
target/arm/vec_helper.c | 70 +++++++++++++++++++++++------------------
28
hw/intc/arm_gicv3_its.c | 208 +++++++++++----------------------------
17
2 files changed, 54 insertions(+), 34 deletions(-)
29
2 files changed, 62 insertions(+), 150 deletions(-)
18
30
19
diff --git a/target/arm/translate.c b/target/arm/translate.c
31
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
20
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate.c
33
--- a/hw/intc/gicv3_internal.h
22
+++ b/target/arm/translate.c
34
+++ b/hw/intc/gicv3_internal.h
23
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
35
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
24
[NEON_2RM_VCVT_UF] = 0x4,
36
#define LPI_CTE_ENABLED TABLE_ENTRY_VALID_MASK
25
};
37
#define LPI_PRIORITY_MASK 0xfc
26
38
27
+static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
39
-#define GITS_CMDQ_ENTRY_SIZE 32
28
+ uint32_t opr_sz, uint32_t max_sz,
40
-#define NUM_BYTES_IN_DW 8
29
+ gen_helper_gvec_3_ptr *fn)
41
+#define GITS_CMDQ_ENTRY_WORDS 4
42
+#define GITS_CMDQ_ENTRY_SIZE (GITS_CMDQ_ENTRY_WORDS * sizeof(uint64_t))
43
44
#define CMD_MASK 0xff
45
46
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/intc/arm_gicv3_its.c
49
+++ b/hw/intc/arm_gicv3_its.c
50
@@ -XXX,XX +XXX,XX @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
51
* 3. handling of ITS CLEAR command
52
* 4. handling of ITS DISCARD command
53
*/
54
-static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
55
- uint32_t offset, ItsCmdType cmd)
56
+static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
57
+ uint32_t eventid, ItsCmdType cmd)
58
{
59
- AddressSpace *as = &s->gicv3->dma_as;
60
- uint32_t devid, eventid;
61
MemTxResult res = MEMTX_OK;
62
bool dte_valid;
63
uint64_t dte = 0;
64
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
65
bool cte_valid = false;
66
uint64_t rdbase;
67
68
- if (cmd == NONE) {
69
- devid = offset;
70
- } else {
71
- devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
72
-
73
- offset += NUM_BYTES_IN_DW;
74
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
75
- MEMTXATTRS_UNSPECIFIED, &res);
76
- }
77
-
78
- if (res != MEMTX_OK) {
79
- return CMD_STALL;
80
- }
81
-
82
- eventid = (value & EVENTID_MASK);
83
-
84
if (devid >= s->dt.num_entries) {
85
qemu_log_mask(LOG_GUEST_ERROR,
86
"%s: invalid command attributes: devid %d>=%d",
87
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
88
}
89
return CMD_CONTINUE;
90
}
91
-
92
-static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
93
- uint32_t offset, bool ignore_pInt)
94
+static ItsCmdResult process_its_cmd(GICv3ITSState *s, const uint64_t *cmdpkt,
95
+ ItsCmdType cmd)
30
+{
96
+{
31
+ TCGv_ptr qc_ptr = tcg_temp_new_ptr();
97
+ uint32_t devid, eventid;
32
+
98
+
33
+ tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc));
99
+ devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
34
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr,
100
+ eventid = cmdpkt[1] & EVENTID_MASK;
35
+ opr_sz, max_sz, 0, fn);
101
+ return do_process_its_cmd(s, devid, eventid, cmd);
36
+ tcg_temp_free_ptr(qc_ptr);
37
+}
102
+}
38
+
103
+
39
void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
104
+static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
40
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
105
+ bool ignore_pInt)
41
{
106
{
42
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
107
- AddressSpace *as = &s->gicv3->dma_as;
43
gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
108
uint32_t devid, eventid;
44
};
109
uint32_t pIntid = 0;
45
tcg_debug_assert(vece >= 1 && vece <= 2);
110
uint64_t num_eventids;
46
- tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
111
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
47
- opr_sz, max_sz, 0, fns[vece - 1]);
112
uint64_t dte = 0;
48
+ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
113
IteEntry ite = {};
114
115
- devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
116
- offset += NUM_BYTES_IN_DW;
117
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
118
- MEMTXATTRS_UNSPECIFIED, &res);
119
-
120
- if (res != MEMTX_OK) {
121
- return CMD_STALL;
122
- }
123
-
124
- eventid = (value & EVENTID_MASK);
125
+ devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
126
+ eventid = cmdpkt[1] & EVENTID_MASK;
127
128
if (ignore_pInt) {
129
pIntid = eventid;
130
} else {
131
- pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
132
+ pIntid = (cmdpkt[1] & pINTID_MASK) >> pINTID_SHIFT;
133
}
134
135
- offset += NUM_BYTES_IN_DW;
136
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
137
- MEMTXATTRS_UNSPECIFIED, &res);
138
-
139
- if (res != MEMTX_OK) {
140
- return CMD_STALL;
141
- }
142
-
143
- icid = value & ICID_MASK;
144
+ icid = cmdpkt[2] & ICID_MASK;
145
146
if (devid >= s->dt.num_entries) {
147
qemu_log_mask(LOG_GUEST_ERROR,
148
@@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
149
return res == MEMTX_OK;
49
}
150
}
50
151
51
void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
152
-static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset)
52
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
153
+static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
53
gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
154
{
54
};
155
- AddressSpace *as = &s->gicv3->dma_as;
55
tcg_debug_assert(vece >= 1 && vece <= 2);
156
uint16_t icid;
56
- tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
157
uint64_t rdbase;
57
- opr_sz, max_sz, 0, fns[vece - 1]);
158
bool valid;
58
+ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
159
- MemTxResult res = MEMTX_OK;
160
- uint64_t value;
161
162
- offset += NUM_BYTES_IN_DW;
163
- offset += NUM_BYTES_IN_DW;
164
+ icid = cmdpkt[2] & ICID_MASK;
165
166
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
167
- MEMTXATTRS_UNSPECIFIED, &res);
168
-
169
- if (res != MEMTX_OK) {
170
- return CMD_STALL;
171
- }
172
-
173
- icid = value & ICID_MASK;
174
-
175
- rdbase = (value & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
176
+ rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
177
rdbase &= RDBASE_PROCNUM_MASK;
178
179
- valid = (value & CMD_FIELD_VALID_MASK);
180
+ valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
181
182
if ((icid >= s->ct.num_entries) || (rdbase >= s->gicv3->num_cpu)) {
183
qemu_log_mask(LOG_GUEST_ERROR,
184
@@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
185
return res == MEMTX_OK;
59
}
186
}
60
187
61
#define GEN_CMP0(NAME, COND) \
188
-static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
62
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
189
- uint32_t offset)
63
index XXXXXXX..XXXXXXX 100644
190
+static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
64
--- a/target/arm/vec_helper.c
191
{
65
+++ b/target/arm/vec_helper.c
192
- AddressSpace *as = &s->gicv3->dma_as;
66
@@ -XXX,XX +XXX,XX @@
193
uint32_t devid;
67
#define H4(x) (x)
194
uint8_t size;
68
#endif
195
uint64_t itt_addr;
69
196
bool valid;
70
-#define SET_QC() env->vfp.qc[0] = 1
197
- MemTxResult res = MEMTX_OK;
71
-
198
72
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
199
- devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
73
{
200
-
74
uint64_t *d = vd + opr_sz;
201
- offset += NUM_BYTES_IN_DW;
75
@@ -XXX,XX +XXX,XX @@ static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
202
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
203
- MEMTXATTRS_UNSPECIFIED, &res);
204
-
205
- if (res != MEMTX_OK) {
206
- return CMD_STALL;
207
- }
208
-
209
- size = (value & SIZE_MASK);
210
-
211
- offset += NUM_BYTES_IN_DW;
212
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
213
- MEMTXATTRS_UNSPECIFIED, &res);
214
-
215
- if (res != MEMTX_OK) {
216
- return CMD_STALL;
217
- }
218
-
219
- itt_addr = (value & ITTADDR_MASK) >> ITTADDR_SHIFT;
220
-
221
- valid = (value & CMD_FIELD_VALID_MASK);
222
+ devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
223
+ size = cmdpkt[1] & SIZE_MASK;
224
+ itt_addr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
225
+ valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
226
227
if ((devid >= s->dt.num_entries) ||
228
(size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
229
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
230
return update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL;
76
}
231
}
77
232
78
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
233
-static ItsCmdResult process_movall(GICv3ITSState *s, uint64_t value,
79
-static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
234
- uint32_t offset)
80
- int16_t src2, int16_t src3)
235
+static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
81
+static int16_t inl_qrdmlah_s16(int16_t src1, int16_t src2,
236
{
82
+ int16_t src3, uint32_t *sat)
237
- AddressSpace *as = &s->gicv3->dma_as;
83
{
238
- MemTxResult res = MEMTX_OK;
84
/* Simplify:
239
uint64_t rd1, rd2;
85
* = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
240
86
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
241
- /* No fields in dwords 0 or 1 */
87
ret = ((int32_t)src3 << 15) + ret + (1 << 14);
242
- offset += NUM_BYTES_IN_DW;
88
ret >>= 15;
243
- offset += NUM_BYTES_IN_DW;
89
if (ret != (int16_t)ret) {
244
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
90
- SET_QC();
245
- MEMTXATTRS_UNSPECIFIED, &res);
91
+ *sat = 1;
246
- if (res != MEMTX_OK) {
92
ret = (ret < 0 ? -0x8000 : 0x7fff);
247
- return CMD_STALL;
248
- }
249
+ rd1 = FIELD_EX64(cmdpkt[2], MOVALL_2, RDBASE1);
250
+ rd2 = FIELD_EX64(cmdpkt[3], MOVALL_3, RDBASE2);
251
252
- rd1 = FIELD_EX64(value, MOVALL_2, RDBASE1);
253
if (rd1 >= s->gicv3->num_cpu) {
254
qemu_log_mask(LOG_GUEST_ERROR,
255
"%s: RDBASE1 %" PRId64
256
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movall(GICv3ITSState *s, uint64_t value,
257
__func__, rd1, s->gicv3->num_cpu);
258
return CMD_CONTINUE;
93
}
259
}
94
return ret;
260
-
95
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
261
- offset += NUM_BYTES_IN_DW;
96
uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
262
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
97
uint32_t src2, uint32_t src3)
263
- MEMTXATTRS_UNSPECIFIED, &res);
98
{
264
- if (res != MEMTX_OK) {
99
- uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
265
- return CMD_STALL;
100
- uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
266
- }
101
+ uint32_t *sat = &env->vfp.qc[0];
267
-
102
+ uint16_t e1 = inl_qrdmlah_s16(src1, src2, src3, sat);
268
- rd2 = FIELD_EX64(value, MOVALL_3, RDBASE2);
103
+ uint16_t e2 = inl_qrdmlah_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat);
269
if (rd2 >= s->gicv3->num_cpu) {
104
return deposit32(e1, 16, 16, e2);
270
qemu_log_mask(LOG_GUEST_ERROR,
271
"%s: RDBASE2 %" PRId64
272
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movall(GICv3ITSState *s, uint64_t value,
273
return CMD_CONTINUE;
105
}
274
}
106
275
107
void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
276
-static ItsCmdResult process_movi(GICv3ITSState *s, uint64_t value,
108
- void *ve, uint32_t desc)
277
- uint32_t offset)
109
+ void *vq, uint32_t desc)
278
+static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
110
{
279
{
111
uintptr_t opr_sz = simd_oprsz(desc);
280
- AddressSpace *as = &s->gicv3->dma_as;
112
int16_t *d = vd;
281
MemTxResult res = MEMTX_OK;
113
int16_t *n = vn;
282
uint32_t devid, eventid, intid;
114
int16_t *m = vm;
283
uint16_t old_icid, new_icid;
115
- CPUARMState *env = ve;
284
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, uint64_t value,
116
uintptr_t i;
285
uint64_t num_eventids;
117
286
IteEntry ite = {};
118
for (i = 0; i < opr_sz / 2; ++i) {
287
119
- d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
288
- devid = FIELD_EX64(value, MOVI_0, DEVICEID);
120
+ d[i] = inl_qrdmlah_s16(n[i], m[i], d[i], vq);
289
-
121
}
290
- offset += NUM_BYTES_IN_DW;
122
clear_tail(d, opr_sz, simd_maxsz(desc));
291
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
123
}
292
- MEMTXATTRS_UNSPECIFIED, &res);
124
293
- if (res != MEMTX_OK) {
125
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
294
- return CMD_STALL;
126
-static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
295
- }
127
- int16_t src2, int16_t src3)
296
- eventid = FIELD_EX64(value, MOVI_1, EVENTID);
128
+static int16_t inl_qrdmlsh_s16(int16_t src1, int16_t src2,
297
-
129
+ int16_t src3, uint32_t *sat)
298
- offset += NUM_BYTES_IN_DW;
130
{
299
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
131
/* Similarly, using subtraction:
300
- MEMTXATTRS_UNSPECIFIED, &res);
132
* = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
301
- if (res != MEMTX_OK) {
133
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
302
- return CMD_STALL;
134
ret = ((int32_t)src3 << 15) - ret + (1 << 14);
303
- }
135
ret >>= 15;
304
- new_icid = FIELD_EX64(value, MOVI_2, ICID);
136
if (ret != (int16_t)ret) {
305
+ devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
137
- SET_QC();
306
+ eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
138
+ *sat = 1;
307
+ new_icid = FIELD_EX64(cmdpkt[2], MOVI_2, ICID);
139
ret = (ret < 0 ? -0x8000 : 0x7fff);
308
140
}
309
if (devid >= s->dt.num_entries) {
141
return ret;
310
qemu_log_mask(LOG_GUEST_ERROR,
142
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
311
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
143
uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
312
uint32_t wr_offset = 0;
144
uint32_t src2, uint32_t src3)
313
uint32_t rd_offset = 0;
145
{
314
uint32_t cq_offset = 0;
146
- uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
315
- uint64_t data;
147
- uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
316
AddressSpace *as = &s->gicv3->dma_as;
148
+ uint32_t *sat = &env->vfp.qc[0];
317
- MemTxResult res = MEMTX_OK;
149
+ uint16_t e1 = inl_qrdmlsh_s16(src1, src2, src3, sat);
318
uint8_t cmd;
150
+ uint16_t e2 = inl_qrdmlsh_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat);
319
int i;
151
return deposit32(e1, 16, 16, e2);
320
152
}
321
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
153
322
154
void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
323
while (wr_offset != rd_offset) {
155
- void *ve, uint32_t desc)
324
ItsCmdResult result = CMD_CONTINUE;
156
+ void *vq, uint32_t desc)
325
+ void *hostmem;
157
{
326
+ hwaddr buflen;
158
uintptr_t opr_sz = simd_oprsz(desc);
327
+ uint64_t cmdpkt[GITS_CMDQ_ENTRY_WORDS];
159
int16_t *d = vd;
328
160
int16_t *n = vn;
329
cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
161
int16_t *m = vm;
330
- data = address_space_ldq_le(as, s->cq.base_addr + cq_offset,
162
- CPUARMState *env = ve;
331
- MEMTXATTRS_UNSPECIFIED, &res);
163
uintptr_t i;
332
- if (res != MEMTX_OK) {
164
165
for (i = 0; i < opr_sz / 2; ++i) {
166
- d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
167
+ d[i] = inl_qrdmlsh_s16(n[i], m[i], d[i], vq);
168
}
169
clear_tail(d, opr_sz, simd_maxsz(desc));
170
}
171
172
/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
173
-uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
174
- int32_t src2, int32_t src3)
175
+static int32_t inl_qrdmlah_s32(int32_t src1, int32_t src2,
176
+ int32_t src3, uint32_t *sat)
177
{
178
/* Simplify similarly to int_qrdmlah_s16 above. */
179
int64_t ret = (int64_t)src1 * src2;
180
ret = ((int64_t)src3 << 31) + ret + (1 << 30);
181
ret >>= 31;
182
if (ret != (int32_t)ret) {
183
- SET_QC();
184
+ *sat = 1;
185
ret = (ret < 0 ? INT32_MIN : INT32_MAX);
186
}
187
return ret;
188
}
189
190
+uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
191
+ int32_t src2, int32_t src3)
192
+{
193
+ uint32_t *sat = &env->vfp.qc[0];
194
+ return inl_qrdmlah_s32(src1, src2, src3, sat);
195
+}
196
+
333
+
197
void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
334
+ buflen = GITS_CMDQ_ENTRY_SIZE;
198
- void *ve, uint32_t desc)
335
+ hostmem = address_space_map(as, s->cq.base_addr + cq_offset,
199
+ void *vq, uint32_t desc)
336
+ &buflen, false, MEMTXATTRS_UNSPECIFIED);
200
{
337
+ if (!hostmem || buflen != GITS_CMDQ_ENTRY_SIZE) {
201
uintptr_t opr_sz = simd_oprsz(desc);
338
+ if (hostmem) {
202
int32_t *d = vd;
339
+ address_space_unmap(as, hostmem, buflen, false, 0);
203
int32_t *n = vn;
340
+ }
204
int32_t *m = vm;
341
s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
205
- CPUARMState *env = ve;
342
qemu_log_mask(LOG_GUEST_ERROR,
206
uintptr_t i;
343
"%s: could not read command at 0x%" PRIx64 "\n",
207
344
__func__, s->cq.base_addr + cq_offset);
208
for (i = 0; i < opr_sz / 4; ++i) {
345
break;
209
- d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
346
}
210
+ d[i] = inl_qrdmlah_s32(n[i], m[i], d[i], vq);
347
+ for (i = 0; i < ARRAY_SIZE(cmdpkt); i++) {
211
}
348
+ cmdpkt[i] = ldq_le_p(hostmem + i * sizeof(uint64_t));
212
clear_tail(d, opr_sz, simd_maxsz(desc));
349
+ }
213
}
350
+ address_space_unmap(as, hostmem, buflen, false, 0);
214
351
215
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
352
- cmd = (data & CMD_MASK);
216
-uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
353
+ cmd = cmdpkt[0] & CMD_MASK;
217
- int32_t src2, int32_t src3)
354
218
+static int32_t inl_qrdmlsh_s32(int32_t src1, int32_t src2,
355
trace_gicv3_its_process_command(rd_offset, cmd);
219
+ int32_t src3, uint32_t *sat)
356
220
{
357
switch (cmd) {
221
/* Simplify similarly to int_qrdmlsh_s16 above. */
358
case GITS_CMD_INT:
222
int64_t ret = (int64_t)src1 * src2;
359
- result = process_its_cmd(s, data, cq_offset, INTERRUPT);
223
ret = ((int64_t)src3 << 31) - ret + (1 << 30);
360
+ result = process_its_cmd(s, cmdpkt, INTERRUPT);
224
ret >>= 31;
361
break;
225
if (ret != (int32_t)ret) {
362
case GITS_CMD_CLEAR:
226
- SET_QC();
363
- result = process_its_cmd(s, data, cq_offset, CLEAR);
227
+ *sat = 1;
364
+ result = process_its_cmd(s, cmdpkt, CLEAR);
228
ret = (ret < 0 ? INT32_MIN : INT32_MAX);
365
break;
229
}
366
case GITS_CMD_SYNC:
230
return ret;
367
/*
231
}
368
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
232
369
*/
233
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
370
break;
234
+ int32_t src2, int32_t src3)
371
case GITS_CMD_MAPD:
235
+{
372
- result = process_mapd(s, data, cq_offset);
236
+ uint32_t *sat = &env->vfp.qc[0];
373
+ result = process_mapd(s, cmdpkt);
237
+ return inl_qrdmlsh_s32(src1, src2, src3, sat);
374
break;
238
+}
375
case GITS_CMD_MAPC:
239
+
376
- result = process_mapc(s, cq_offset);
240
void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
377
+ result = process_mapc(s, cmdpkt);
241
- void *ve, uint32_t desc)
378
break;
242
+ void *vq, uint32_t desc)
379
case GITS_CMD_MAPTI:
243
{
380
- result = process_mapti(s, data, cq_offset, false);
244
uintptr_t opr_sz = simd_oprsz(desc);
381
+ result = process_mapti(s, cmdpkt, false);
245
int32_t *d = vd;
382
break;
246
int32_t *n = vn;
383
case GITS_CMD_MAPI:
247
int32_t *m = vm;
384
- result = process_mapti(s, data, cq_offset, true);
248
- CPUARMState *env = ve;
385
+ result = process_mapti(s, cmdpkt, true);
249
uintptr_t i;
386
break;
250
387
case GITS_CMD_DISCARD:
251
for (i = 0; i < opr_sz / 4; ++i) {
388
- result = process_its_cmd(s, data, cq_offset, DISCARD);
252
- d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
389
+ result = process_its_cmd(s, cmdpkt, DISCARD);
253
+ d[i] = inl_qrdmlsh_s32(n[i], m[i], d[i], vq);
390
break;
254
}
391
case GITS_CMD_INV:
255
clear_tail(d, opr_sz, simd_maxsz(desc));
392
case GITS_CMD_INVALL:
256
}
393
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
394
}
395
break;
396
case GITS_CMD_MOVI:
397
- result = process_movi(s, data, cq_offset);
398
+ result = process_movi(s, cmdpkt);
399
break;
400
case GITS_CMD_MOVALL:
401
- result = process_movall(s, data, cq_offset);
402
+ result = process_movall(s, cmdpkt);
403
break;
404
default:
405
break;
406
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
407
{
408
GICv3ITSState *s = (GICv3ITSState *)opaque;
409
bool result = true;
410
- uint32_t devid = 0;
411
412
trace_gicv3_its_translation_write(offset, data, size, attrs.requester_id);
413
414
switch (offset) {
415
case GITS_TRANSLATER:
416
if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
417
- devid = attrs.requester_id;
418
- result = process_its_cmd(s, data, devid, NONE);
419
+ result = do_process_its_cmd(s, attrs.requester_id, data, NONE);
420
}
421
break;
422
default:
257
--
423
--
258
2.20.1
424
2.25.1
259
425
260
426
diff view generated by jsdifflib
1
Convert the Neon integer VMUL, VMLA, and VMLS 3-reg-same inssn to
1
In the ITS, a DTE is an entry in the device table, which contains
2
decodetree.
2
multiple fields. Currently the function get_dte() which reads one
3
3
entry from the device table returns it as a raw 64-bit integer,
4
We don't have a gvec helper for multiply-accumulate, so VMLA and VMLS
4
which we then pass around in that form, only extracting fields
5
need a loop function do_3same_fp(). This takes a reads_vd parameter
5
from it as we need them.
6
to do_3same_fp() which tells it to load the old value into vd before
6
7
calling the callback function, in the same way that the do_vfp_3op_sp()
7
Create a real C struct with the same fields as the DTE, and
8
and do_vfp_3op_dp() functions in translate-vfp.inc.c work. (The
8
populate it in get_dte(), so that that function and update_dte()
9
only uses in this patch pass reads_vd == true, but later commits
9
are the only ones that need to care about the in-guest-memory
10
will use reads_vd == false.)
10
format of the DTE.
11
12
This conversion fixes in passing an underdecoding for VMUL
13
(originally reported by Fredrik Strupe <fredrik@strupe.net>): bit 1
14
of the 'size' field must be 0. The old decoder didn't enforce this,
15
but the decodetree pattern does.
16
17
The gen_VMLA_fp_reg() function performs the addition operation
18
with the operands in the opposite order to the old decoder:
19
since Neon sets 'default NaN mode' float32_add operations are
20
commutative so there is no behaviour difference, but putting
21
them this way around matches the Arm ARM pseudocode and the
22
required operation order for the subtraction in gen_VMLS_fp_reg().
23
11
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-id: 20200512163904.10918-14-peter.maydell@linaro.org
14
Message-id: 20220201193207.2771604-3-peter.maydell@linaro.org
27
---
15
---
28
target/arm/neon-dp.decode | 3 ++
16
hw/intc/arm_gicv3_its.c | 111 ++++++++++++++++++++--------------------
29
target/arm/translate-neon.inc.c | 81 +++++++++++++++++++++++++++++++++
17
1 file changed, 56 insertions(+), 55 deletions(-)
30
target/arm/translate.c | 17 +------
18
31
3 files changed, 85 insertions(+), 16 deletions(-)
19
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
32
33
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
34
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/neon-dp.decode
21
--- a/hw/intc/arm_gicv3_its.c
36
+++ b/target/arm/neon-dp.decode
22
+++ b/hw/intc/arm_gicv3_its.c
37
@@ -XXX,XX +XXX,XX @@ VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
38
VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
24
uint64_t itel;
39
VPADD_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 0 .... @3same_fp_q0
25
} IteEntry;
40
VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
26
41
+VMLA_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
27
+typedef struct DTEntry {
42
+VMLS_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 1 .... @3same_fp
28
+ bool valid;
43
+VMUL_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
29
+ unsigned size;
44
VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
30
+ uint64_t ittaddr;
45
VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
31
+} DTEntry;
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-neon.inc.c
49
+++ b/target/arm/translate-neon.inc.c
50
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPADD, padd_u)
51
DO_3SAME_VQDMULH(VQDMULH, qdmulh)
52
DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
53
54
+static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
55
+ bool reads_vd)
56
+{
57
+ /*
58
+ * FP operations handled elementwise 32 bits at a time.
59
+ * If reads_vd is true then the old value of Vd will be
60
+ * loaded before calling the callback function. This is
61
+ * used for multiply-accumulate type operations.
62
+ */
63
+ TCGv_i32 tmp, tmp2;
64
+ int pass;
65
+
66
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
67
+ return false;
68
+ }
69
+
70
+ /* UNDEF accesses to D16-D31 if they don't exist. */
71
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
72
+ ((a->vd | a->vn | a->vm) & 0x10)) {
73
+ return false;
74
+ }
75
+
76
+ if ((a->vn | a->vm | a->vd) & a->q) {
77
+ return false;
78
+ }
79
+
80
+ if (!vfp_access_check(s)) {
81
+ return true;
82
+ }
83
+
84
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
85
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
86
+ tmp = neon_load_reg(a->vn, pass);
87
+ tmp2 = neon_load_reg(a->vm, pass);
88
+ if (reads_vd) {
89
+ TCGv_i32 tmp_rd = neon_load_reg(a->vd, pass);
90
+ fn(tmp_rd, tmp, tmp2, fpstatus);
91
+ neon_store_reg(a->vd, pass, tmp_rd);
92
+ tcg_temp_free_i32(tmp);
93
+ } else {
94
+ fn(tmp, tmp, tmp2, fpstatus);
95
+ neon_store_reg(a->vd, pass, tmp);
96
+ }
97
+ tcg_temp_free_i32(tmp2);
98
+ }
99
+ tcg_temp_free_ptr(fpstatus);
100
+ return true;
101
+}
102
+
32
+
103
/*
33
/*
104
* For all the functions using this macro, size == 1 means fp16,
34
* The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
105
* which is an architecture extension we don't implement yet.
35
* if a command parameter is not correct. These include both "stall
106
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
36
@@ -XXX,XX +XXX,XX @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
107
DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
37
return FIELD_EX64(*cte, CTE, VALID);
108
DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
38
}
109
DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
39
110
+DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s)
40
-static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
111
+
41
+static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
42
IteEntry ite)
43
{
44
AddressSpace *as = &s->gicv3->dma_as;
45
- uint64_t itt_addr;
46
MemTxResult res = MEMTX_OK;
47
48
- itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
49
- itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
50
-
51
- address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
52
+ address_space_stq_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
53
sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
54
&res);
55
56
if (res == MEMTX_OK) {
57
- address_space_stl_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
58
+ address_space_stl_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
59
sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
60
MEMTXATTRS_UNSPECIFIED, &res);
61
}
62
@@ -XXX,XX +XXX,XX @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
63
}
64
}
65
66
-static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
67
+static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
68
uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
69
{
70
AddressSpace *as = &s->gicv3->dma_as;
71
- uint64_t itt_addr;
72
bool status = false;
73
IteEntry ite = {};
74
75
- itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
76
- itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
77
-
78
- ite.itel = address_space_ldq_le(as, itt_addr +
79
+ ite.itel = address_space_ldq_le(as, dte->ittaddr +
80
(eventid * (sizeof(uint64_t) +
81
sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
82
res);
83
84
if (*res == MEMTX_OK) {
85
- ite.iteh = address_space_ldl_le(as, itt_addr +
86
+ ite.iteh = address_space_ldl_le(as, dte->ittaddr +
87
(eventid * (sizeof(uint64_t) +
88
sizeof(uint32_t))) + sizeof(uint32_t),
89
MEMTXATTRS_UNSPECIFIED, res);
90
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
91
return status;
92
}
93
94
-static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
112
+/*
95
+/*
113
+ * For all the functions using this macro, size == 1 means fp16,
96
+ * Read the Device Table entry at index @devid. On success (including
114
+ * which is an architecture extension we don't implement yet.
97
+ * successfully determining that there is no valid DTE for this index),
98
+ * we return MEMTX_OK and populate the DTEntry struct accordingly.
99
+ * If there is an error reading memory then we return the error code.
115
+ */
100
+ */
116
+#define DO_3S_FP(INSN,FUNC,READS_VD) \
101
+static MemTxResult get_dte(GICv3ITSState *s, uint32_t devid, DTEntry *dte)
117
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
102
{
118
+ { \
103
+ MemTxResult res = MEMTX_OK;
119
+ if (a->size != 0) { \
104
AddressSpace *as = &s->gicv3->dma_as;
120
+ /* TODO fp16 support */ \
105
- uint64_t entry_addr = table_entry_addr(s, &s->dt, devid, res);
121
+ return false; \
106
+ uint64_t entry_addr = table_entry_addr(s, &s->dt, devid, &res);
122
+ } \
107
+ uint64_t dteval;
123
+ return do_3same_fp(s, a, FUNC, READS_VD); \
108
109
if (entry_addr == -1) {
110
- return 0; /* a DTE entry with the Valid bit clear */
111
+ /* No L2 table entry, i.e. no valid DTE, or a memory error */
112
+ dte->valid = false;
113
+ return res;
114
}
115
- return address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res);
116
+ dteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
117
+ if (res != MEMTX_OK) {
118
+ return res;
124
+ }
119
+ }
125
+
120
+ dte->valid = FIELD_EX64(dteval, DTE, VALID);
126
+static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
121
+ dte->size = FIELD_EX64(dteval, DTE, SIZE);
127
+ TCGv_ptr fpstatus)
122
+ /* DTE word field stores bits [51:8] of the ITT address */
128
+{
123
+ dte->ittaddr = FIELD_EX64(dteval, DTE, ITTADDR) << ITTADDR_SHIFT;
129
+ gen_helper_vfp_muls(vn, vn, vm, fpstatus);
124
+ return MEMTX_OK;
130
+ gen_helper_vfp_adds(vd, vd, vn, fpstatus);
125
}
131
+}
126
132
+
127
/*
133
+static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
128
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
134
+ TCGv_ptr fpstatus)
129
uint32_t eventid, ItsCmdType cmd)
135
+{
136
+ gen_helper_vfp_muls(vn, vn, vm, fpstatus);
137
+ gen_helper_vfp_subs(vd, vd, vn, fpstatus);
138
+}
139
+
140
+DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
141
+DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
142
143
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
144
{
130
{
145
diff --git a/target/arm/translate.c b/target/arm/translate.c
131
MemTxResult res = MEMTX_OK;
146
index XXXXXXX..XXXXXXX 100644
132
- bool dte_valid;
147
--- a/target/arm/translate.c
133
- uint64_t dte = 0;
148
+++ b/target/arm/translate.c
134
uint64_t num_eventids;
149
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
135
uint16_t icid = 0;
150
case NEON_3R_VPADD_VQRDMLAH:
136
uint32_t pIntid = 0;
151
case NEON_3R_VQDMULH_VQRDMULH:
137
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
152
case NEON_3R_FLOAT_ARITH:
138
uint64_t cte = 0;
153
+ case NEON_3R_FLOAT_MULTIPLY:
139
bool cte_valid = false;
154
/* Already handled by decodetree */
140
uint64_t rdbase;
155
return 1;
141
+ DTEntry dte;
156
}
142
157
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
143
if (devid >= s->dt.num_entries) {
158
tmp = neon_load_reg(rn, pass);
144
qemu_log_mask(LOG_GUEST_ERROR,
159
tmp2 = neon_load_reg(rm, pass);
145
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
160
switch (op) {
146
return CMD_CONTINUE;
161
- case NEON_3R_FLOAT_MULTIPLY:
147
}
162
- {
148
163
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
149
- dte = get_dte(s, devid, &res);
164
- gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
150
-
165
- if (!u) {
151
- if (res != MEMTX_OK) {
166
- tcg_temp_free_i32(tmp2);
152
+ if (get_dte(s, devid, &dte) != MEMTX_OK) {
167
- tmp2 = neon_load_reg(rd, pass);
153
return CMD_STALL;
168
- if (size == 0) {
154
}
169
- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
155
- dte_valid = FIELD_EX64(dte, DTE, VALID);
170
- } else {
156
-
171
- gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
157
- if (!dte_valid) {
172
- }
158
+ if (!dte.valid) {
173
- }
159
qemu_log_mask(LOG_GUEST_ERROR,
174
- tcg_temp_free_ptr(fpstatus);
160
"%s: invalid command attributes: "
175
- break;
161
- "invalid dte: %"PRIx64" for %d\n",
176
- }
162
- __func__, dte, devid);
177
case NEON_3R_FLOAT_CMP:
163
+ "invalid dte for %d\n", __func__, devid);
178
{
164
return CMD_CONTINUE;
179
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
165
}
166
167
- num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
168
-
169
+ num_eventids = 1ULL << (dte.size + 1);
170
if (eventid >= num_eventids) {
171
qemu_log_mask(LOG_GUEST_ERROR,
172
"%s: invalid command attributes: eventid %d >= %"
173
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
174
return CMD_CONTINUE;
175
}
176
177
- ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
178
+ ite_valid = get_ite(s, eventid, &dte, &icid, &pIntid, &res);
179
if (res != MEMTX_OK) {
180
return CMD_STALL;
181
}
182
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
183
if (cmd == DISCARD) {
184
IteEntry ite = {};
185
/* remove mapping from interrupt translation table */
186
- return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
187
+ return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
188
}
189
return CMD_CONTINUE;
190
}
191
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
192
uint32_t pIntid = 0;
193
uint64_t num_eventids;
194
uint32_t num_intids;
195
- bool dte_valid;
196
- MemTxResult res = MEMTX_OK;
197
uint16_t icid = 0;
198
- uint64_t dte = 0;
199
IteEntry ite = {};
200
+ DTEntry dte;
201
202
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
203
eventid = cmdpkt[1] & EVENTID_MASK;
204
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
205
return CMD_CONTINUE;
206
}
207
208
- dte = get_dte(s, devid, &res);
209
-
210
- if (res != MEMTX_OK) {
211
+ if (get_dte(s, devid, &dte) != MEMTX_OK) {
212
return CMD_STALL;
213
}
214
- dte_valid = FIELD_EX64(dte, DTE, VALID);
215
- num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
216
+ num_eventids = 1ULL << (dte.size + 1);
217
num_intids = 1ULL << (GICD_TYPER_IDBITS + 1);
218
219
if ((icid >= s->ct.num_entries)
220
- || !dte_valid || (eventid >= num_eventids) ||
221
+ || !dte.valid || (eventid >= num_eventids) ||
222
(((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) &&
223
(pIntid != INTID_SPURIOUS))) {
224
qemu_log_mask(LOG_GUEST_ERROR,
225
"%s: invalid command attributes "
226
"icid %d or eventid %d or pIntid %d or"
227
"unmapped dte %d\n", __func__, icid, eventid,
228
- pIntid, dte_valid);
229
+ pIntid, dte.valid);
230
/*
231
* in this implementation, in case of error
232
* we ignore this command and move onto the next
233
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
234
}
235
236
/* add ite entry to interrupt translation table */
237
- ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
238
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, true);
239
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
240
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
241
ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
242
ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
243
244
- return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
245
+ return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
246
}
247
248
static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
249
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
250
uint16_t old_icid, new_icid;
251
uint64_t old_cte, new_cte;
252
uint64_t old_rdbase, new_rdbase;
253
- uint64_t dte;
254
- bool dte_valid, ite_valid, cte_valid;
255
+ bool ite_valid, cte_valid;
256
uint64_t num_eventids;
257
IteEntry ite = {};
258
+ DTEntry dte;
259
260
devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
261
eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
262
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
263
__func__, devid, s->dt.num_entries);
264
return CMD_CONTINUE;
265
}
266
- dte = get_dte(s, devid, &res);
267
- if (res != MEMTX_OK) {
268
+ if (get_dte(s, devid, &dte) != MEMTX_OK) {
269
return CMD_STALL;
270
}
271
272
- dte_valid = FIELD_EX64(dte, DTE, VALID);
273
- if (!dte_valid) {
274
+ if (!dte.valid) {
275
qemu_log_mask(LOG_GUEST_ERROR,
276
"%s: invalid command attributes: "
277
- "invalid dte: %"PRIx64" for %d\n",
278
- __func__, dte, devid);
279
+ "invalid dte for %d\n", __func__, devid);
280
return CMD_CONTINUE;
281
}
282
283
- num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
284
+ num_eventids = 1ULL << (dte.size + 1);
285
if (eventid >= num_eventids) {
286
qemu_log_mask(LOG_GUEST_ERROR,
287
"%s: invalid command attributes: eventid %d >= %"
288
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
289
return CMD_CONTINUE;
290
}
291
292
- ite_valid = get_ite(s, eventid, dte, &old_icid, &intid, &res);
293
+ ite_valid = get_ite(s, eventid, &dte, &old_icid, &intid, &res);
294
if (res != MEMTX_OK) {
295
return CMD_STALL;
296
}
297
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
298
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, intid);
299
ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
300
ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, new_icid);
301
- return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
302
+ return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
303
}
304
305
/*
180
--
306
--
181
2.20.1
307
2.25.1
182
308
183
309
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Make update_dte() take a DTEntry struct rather than all the fields of
2
the new DTE as separate arguments.
2
3
3
The functions eliminate duplication of the special cases for
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
this operation. They match up with the GVecGen2iFn typedef.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220201193207.2771604-4-peter.maydell@linaro.org
7
---
8
hw/intc/arm_gicv3_its.c | 35 ++++++++++++++++++-----------------
9
1 file changed, 18 insertions(+), 17 deletions(-)
5
10
6
Add out-of-line helpers. We got away with only having inline
11
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
7
expanders because the neon vector size is only 16 bytes, and
8
we know that the inline expansion will always succeed.
9
When we reuse this for SVE, tcg-gvec-op may decide to use an
10
out-of-line helper due to longer vector lengths.
11
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200513163245.17915-4-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/helper.h | 10 ++
18
target/arm/translate.h | 7 +-
19
target/arm/translate-a64.c | 20 +---
20
target/arm/translate.c | 186 +++++++++++++++++++++----------------
21
target/arm/vec_helper.c | 38 ++++++++
22
5 files changed, 160 insertions(+), 101 deletions(-)
23
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
25
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
13
--- a/hw/intc/arm_gicv3_its.c
27
+++ b/target/arm/helper.h
14
+++ b/hw/intc/arm_gicv3_its.c
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(gvec_ursra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
15
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
29
DEF_HELPER_FLAGS_3(gvec_ursra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
16
return update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL;
30
DEF_HELPER_FLAGS_3(gvec_ursra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
31
32
+DEF_HELPER_FLAGS_3(gvec_sri_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_3(gvec_sri_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_3(gvec_sri_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_3(gvec_sri_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
36
+
37
+DEF_HELPER_FLAGS_3(gvec_sli_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_3(gvec_sli_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_3(gvec_sli_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_3(gvec_sli_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
41
+
42
#ifdef TARGET_AARCH64
43
#include "helper-a64.h"
44
#include "helper-sve.h"
45
diff --git a/target/arm/translate.h b/target/arm/translate.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate.h
48
+++ b/target/arm/translate.h
49
@@ -XXX,XX +XXX,XX @@ extern const GVecGen3 mls_op[4];
50
extern const GVecGen3 cmtst_op[4];
51
extern const GVecGen3 sshl_op[4];
52
extern const GVecGen3 ushl_op[4];
53
-extern const GVecGen2i sri_op[4];
54
-extern const GVecGen2i sli_op[4];
55
extern const GVecGen4 uqadd_op[4];
56
extern const GVecGen4 sqadd_op[4];
57
extern const GVecGen4 uqsub_op[4];
58
@@ -XXX,XX +XXX,XX @@ void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
59
void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
60
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
61
62
+void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
63
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
64
+void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
65
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
66
+
67
/*
68
* Forward to the isar_feature_* tests given a DisasContext pointer.
69
*/
70
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/translate-a64.c
73
+++ b/target/arm/translate-a64.c
74
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op2(DisasContext *s, bool is_q, int rd,
75
is_q ? 16 : 8, vec_full_reg_size(s), gvec_op);
76
}
17
}
77
18
78
-/* Expand a 2-operand + immediate AdvSIMD vector operation using
19
-static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
79
- * an op descriptor.
20
- uint8_t size, uint64_t itt_addr)
80
- */
21
+/*
81
-static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd,
22
+ * Update the Device Table entry for @devid to @dte. Returns true
82
- int rn, int64_t imm, const GVecGen2i *gvec_op)
23
+ * on success, false if there was a memory access error.
83
-{
24
+ */
84
- tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
25
+static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
85
- is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op);
26
{
86
-}
27
AddressSpace *as = &s->gicv3->dma_as;
87
-
28
uint64_t entry_addr;
88
/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
29
- uint64_t dte = 0;
89
static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
30
+ uint64_t dteval = 0;
90
int rn, int rm, const GVecGen3 *gvec_op)
31
MemTxResult res = MEMTX_OK;
91
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
32
92
gen_gvec_fn2i(s, is_q, rd, rn, shift,
33
if (s->dt.valid) {
93
is_u ? gen_gvec_usra : gen_gvec_ssra, size);
34
- if (valid) {
94
return;
35
+ if (dte->valid) {
95
+
36
/* add mapping entry to device table */
96
case 0x08: /* SRI */
37
- dte = FIELD_DP64(dte, DTE, VALID, 1);
97
- /* Shift count same as element size is valid but does nothing. */
38
- dte = FIELD_DP64(dte, DTE, SIZE, size);
98
- if (shift == 8 << size) {
39
- dte = FIELD_DP64(dte, DTE, ITTADDR, itt_addr);
99
- goto done;
40
+ dteval = FIELD_DP64(dteval, DTE, VALID, 1);
100
- }
41
+ dteval = FIELD_DP64(dteval, DTE, SIZE, dte->size);
101
- gen_gvec_op2i(s, is_q, rd, rn, shift, &sri_op[size]);
42
+ dteval = FIELD_DP64(dteval, DTE, ITTADDR, dte->ittaddr);
102
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sri, size);
43
}
103
return;
44
} else {
104
45
return true;
105
case 0x00: /* SSHR / USHR */
46
@@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
106
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
47
/* No L2 table for this index: discard write and continue */
48
return true;
107
}
49
}
108
tcg_temp_free_i64(tcg_round);
50
- address_space_stq_le(as, entry_addr, dte, MEMTXATTRS_UNSPECIFIED, &res);
109
51
+ address_space_stq_le(as, entry_addr, dteval, MEMTXATTRS_UNSPECIFIED, &res);
110
- done:
52
return res == MEMTX_OK;
111
clear_vec_high(s, is_q, rd);
112
}
53
}
113
54
114
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
55
static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
56
{
57
uint32_t devid;
58
- uint8_t size;
59
- uint64_t itt_addr;
60
- bool valid;
61
+ DTEntry dte;
62
63
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
64
- size = cmdpkt[1] & SIZE_MASK;
65
- itt_addr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
66
- valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
67
+ dte.size = cmdpkt[1] & SIZE_MASK;
68
+ dte.ittaddr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
69
+ dte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
70
71
if ((devid >= s->dt.num_entries) ||
72
- (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
73
+ (dte.size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
74
qemu_log_mask(LOG_GUEST_ERROR,
75
"ITS MAPD: invalid device table attributes "
76
- "devid %d or size %d\n", devid, size);
77
+ "devid %d or size %d\n", devid, dte.size);
78
/*
79
* in this implementation, in case of error
80
* we ignore this command and move onto the next
81
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
82
return CMD_CONTINUE;
115
}
83
}
116
84
117
if (insert) {
85
- return update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL;
118
- gen_gvec_op2i(s, is_q, rd, rn, shift, &sli_op[size]);
86
+ return update_dte(s, devid, &dte) ? CMD_CONTINUE : CMD_STALL;
119
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sli, size);
120
} else {
121
gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shli, size);
122
}
123
diff --git a/target/arm/translate.c b/target/arm/translate.c
124
index XXXXXXX..XXXXXXX 100644
125
--- a/target/arm/translate.c
126
+++ b/target/arm/translate.c
127
@@ -XXX,XX +XXX,XX @@ static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
128
129
static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
130
{
131
- if (sh == 0) {
132
- tcg_gen_mov_vec(d, a);
133
- } else {
134
- TCGv_vec t = tcg_temp_new_vec_matching(d);
135
- TCGv_vec m = tcg_temp_new_vec_matching(d);
136
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
137
+ TCGv_vec m = tcg_temp_new_vec_matching(d);
138
139
- tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
140
- tcg_gen_shri_vec(vece, t, a, sh);
141
- tcg_gen_and_vec(vece, d, d, m);
142
- tcg_gen_or_vec(vece, d, d, t);
143
+ tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
144
+ tcg_gen_shri_vec(vece, t, a, sh);
145
+ tcg_gen_and_vec(vece, d, d, m);
146
+ tcg_gen_or_vec(vece, d, d, t);
147
148
- tcg_temp_free_vec(t);
149
- tcg_temp_free_vec(m);
150
- }
151
+ tcg_temp_free_vec(t);
152
+ tcg_temp_free_vec(m);
153
}
87
}
154
88
155
-static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
89
static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
156
+void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
157
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
158
+{
159
+ static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
160
+ const GVecGen2i ops[4] = {
161
+ { .fni8 = gen_shr8_ins_i64,
162
+ .fniv = gen_shr_ins_vec,
163
+ .fno = gen_helper_gvec_sri_b,
164
+ .load_dest = true,
165
+ .opt_opc = vecop_list,
166
+ .vece = MO_8 },
167
+ { .fni8 = gen_shr16_ins_i64,
168
+ .fniv = gen_shr_ins_vec,
169
+ .fno = gen_helper_gvec_sri_h,
170
+ .load_dest = true,
171
+ .opt_opc = vecop_list,
172
+ .vece = MO_16 },
173
+ { .fni4 = gen_shr32_ins_i32,
174
+ .fniv = gen_shr_ins_vec,
175
+ .fno = gen_helper_gvec_sri_s,
176
+ .load_dest = true,
177
+ .opt_opc = vecop_list,
178
+ .vece = MO_32 },
179
+ { .fni8 = gen_shr64_ins_i64,
180
+ .fniv = gen_shr_ins_vec,
181
+ .fno = gen_helper_gvec_sri_d,
182
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
183
+ .load_dest = true,
184
+ .opt_opc = vecop_list,
185
+ .vece = MO_64 },
186
+ };
187
188
-const GVecGen2i sri_op[4] = {
189
- { .fni8 = gen_shr8_ins_i64,
190
- .fniv = gen_shr_ins_vec,
191
- .load_dest = true,
192
- .opt_opc = vecop_list_sri,
193
- .vece = MO_8 },
194
- { .fni8 = gen_shr16_ins_i64,
195
- .fniv = gen_shr_ins_vec,
196
- .load_dest = true,
197
- .opt_opc = vecop_list_sri,
198
- .vece = MO_16 },
199
- { .fni4 = gen_shr32_ins_i32,
200
- .fniv = gen_shr_ins_vec,
201
- .load_dest = true,
202
- .opt_opc = vecop_list_sri,
203
- .vece = MO_32 },
204
- { .fni8 = gen_shr64_ins_i64,
205
- .fniv = gen_shr_ins_vec,
206
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
207
- .load_dest = true,
208
- .opt_opc = vecop_list_sri,
209
- .vece = MO_64 },
210
-};
211
+ /* tszimm encoding produces immediates in the range [1..esize]. */
212
+ tcg_debug_assert(shift > 0);
213
+ tcg_debug_assert(shift <= (8 << vece));
214
+
215
+ /* Shift of esize leaves destination unchanged. */
216
+ if (shift < (8 << vece)) {
217
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
218
+ } else {
219
+ /* Nop, but we do need to clear the tail. */
220
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
221
+ }
222
+}
223
224
static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
225
{
226
@@ -XXX,XX +XXX,XX @@ static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
227
228
static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
229
{
230
- if (sh == 0) {
231
- tcg_gen_mov_vec(d, a);
232
- } else {
233
- TCGv_vec t = tcg_temp_new_vec_matching(d);
234
- TCGv_vec m = tcg_temp_new_vec_matching(d);
235
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
236
+ TCGv_vec m = tcg_temp_new_vec_matching(d);
237
238
- tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
239
- tcg_gen_shli_vec(vece, t, a, sh);
240
- tcg_gen_and_vec(vece, d, d, m);
241
- tcg_gen_or_vec(vece, d, d, t);
242
+ tcg_gen_shli_vec(vece, t, a, sh);
243
+ tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
244
+ tcg_gen_and_vec(vece, d, d, m);
245
+ tcg_gen_or_vec(vece, d, d, t);
246
247
- tcg_temp_free_vec(t);
248
- tcg_temp_free_vec(m);
249
- }
250
+ tcg_temp_free_vec(t);
251
+ tcg_temp_free_vec(m);
252
}
253
254
-static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
255
+void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
256
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
257
+{
258
+ static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
259
+ const GVecGen2i ops[4] = {
260
+ { .fni8 = gen_shl8_ins_i64,
261
+ .fniv = gen_shl_ins_vec,
262
+ .fno = gen_helper_gvec_sli_b,
263
+ .load_dest = true,
264
+ .opt_opc = vecop_list,
265
+ .vece = MO_8 },
266
+ { .fni8 = gen_shl16_ins_i64,
267
+ .fniv = gen_shl_ins_vec,
268
+ .fno = gen_helper_gvec_sli_h,
269
+ .load_dest = true,
270
+ .opt_opc = vecop_list,
271
+ .vece = MO_16 },
272
+ { .fni4 = gen_shl32_ins_i32,
273
+ .fniv = gen_shl_ins_vec,
274
+ .fno = gen_helper_gvec_sli_s,
275
+ .load_dest = true,
276
+ .opt_opc = vecop_list,
277
+ .vece = MO_32 },
278
+ { .fni8 = gen_shl64_ins_i64,
279
+ .fniv = gen_shl_ins_vec,
280
+ .fno = gen_helper_gvec_sli_d,
281
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
282
+ .load_dest = true,
283
+ .opt_opc = vecop_list,
284
+ .vece = MO_64 },
285
+ };
286
287
-const GVecGen2i sli_op[4] = {
288
- { .fni8 = gen_shl8_ins_i64,
289
- .fniv = gen_shl_ins_vec,
290
- .load_dest = true,
291
- .opt_opc = vecop_list_sli,
292
- .vece = MO_8 },
293
- { .fni8 = gen_shl16_ins_i64,
294
- .fniv = gen_shl_ins_vec,
295
- .load_dest = true,
296
- .opt_opc = vecop_list_sli,
297
- .vece = MO_16 },
298
- { .fni4 = gen_shl32_ins_i32,
299
- .fniv = gen_shl_ins_vec,
300
- .load_dest = true,
301
- .opt_opc = vecop_list_sli,
302
- .vece = MO_32 },
303
- { .fni8 = gen_shl64_ins_i64,
304
- .fniv = gen_shl_ins_vec,
305
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
306
- .load_dest = true,
307
- .opt_opc = vecop_list_sli,
308
- .vece = MO_64 },
309
-};
310
+ /* tszimm encoding produces immediates in the range [0..esize-1]. */
311
+ tcg_debug_assert(shift >= 0);
312
+ tcg_debug_assert(shift < (8 << vece));
313
+
314
+ if (shift == 0) {
315
+ tcg_gen_gvec_mov(vece, rd_ofs, rm_ofs, opr_sz, max_sz);
316
+ } else {
317
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
318
+ }
319
+}
320
321
static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
322
{
323
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
324
}
325
/* Right shift comes here negative. */
326
shift = -shift;
327
- /* Shift out of range leaves destination unchanged. */
328
- if (shift < 8 << size) {
329
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
330
- shift, &sri_op[size]);
331
- }
332
+ gen_gvec_sri(size, rd_ofs, rm_ofs, shift,
333
+ vec_size, vec_size);
334
return 0;
335
336
case 5: /* VSHL, VSLI */
337
if (u) { /* VSLI */
338
- /* Shift out of range leaves destination unchanged. */
339
- if (shift < 8 << size) {
340
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
341
- vec_size, shift, &sli_op[size]);
342
- }
343
+ gen_gvec_sli(size, rd_ofs, rm_ofs, shift,
344
+ vec_size, vec_size);
345
} else { /* VSHL */
346
/* Shifts larger than the element size are
347
* architecturally valid and results in zero.
348
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
349
index XXXXXXX..XXXXXXX 100644
350
--- a/target/arm/vec_helper.c
351
+++ b/target/arm/vec_helper.c
352
@@ -XXX,XX +XXX,XX @@ DO_RSRA(gvec_ursra_d, uint64_t)
353
354
#undef DO_RSRA
355
356
+#define DO_SRI(NAME, TYPE) \
357
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
358
+{ \
359
+ intptr_t i, oprsz = simd_oprsz(desc); \
360
+ int shift = simd_data(desc); \
361
+ TYPE *d = vd, *n = vn; \
362
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
363
+ d[i] = deposit64(d[i], 0, sizeof(TYPE) * 8 - shift, n[i] >> shift); \
364
+ } \
365
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
366
+}
367
+
368
+DO_SRI(gvec_sri_b, uint8_t)
369
+DO_SRI(gvec_sri_h, uint16_t)
370
+DO_SRI(gvec_sri_s, uint32_t)
371
+DO_SRI(gvec_sri_d, uint64_t)
372
+
373
+#undef DO_SRI
374
+
375
+#define DO_SLI(NAME, TYPE) \
376
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
377
+{ \
378
+ intptr_t i, oprsz = simd_oprsz(desc); \
379
+ int shift = simd_data(desc); \
380
+ TYPE *d = vd, *n = vn; \
381
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
382
+ d[i] = deposit64(d[i], shift, sizeof(TYPE) * 8 - shift, n[i]); \
383
+ } \
384
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
385
+}
386
+
387
+DO_SLI(gvec_sli_b, uint8_t)
388
+DO_SLI(gvec_sli_h, uint16_t)
389
+DO_SLI(gvec_sli_s, uint32_t)
390
+DO_SLI(gvec_sli_d, uint64_t)
391
+
392
+#undef DO_SLI
393
+
394
/*
395
* Convert float16 to float32, raising no exceptions and
396
* preserving exceptional values, including SNaN.
397
--
90
--
398
2.20.1
91
2.25.1
399
92
400
93
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In the ITS, a CTE is an entry in the collection table, which contains
2
2
multiple fields. Currently the function get_cte() which reads one
3
The functions eliminate duplication of the special cases for
3
entry from the device table returns a success/failure boolean and
4
this operation. They match up with the GVecGen2iFn typedef.
4
passes back the raw 64-bit integer CTE value via a pointer argument.
5
5
We then extract fields from the CTE as we need them.
6
Add out-of-line helpers. We got away with only having inline
6
7
expanders because the neon vector size is only 16 bytes, and
7
Create a real C struct with the same fields as the CTE, and
8
we know that the inline expansion will always succeed.
8
populate it in get_cte(), so that that function and update_cte()
9
When we reuse this for SVE, tcg-gvec-op may decide to use an
9
are the only ones which need to care about the in-guest-memory
10
out-of-line helper due to longer vector lengths.
10
format of the CTE.
11
11
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
This brings get_cte()'s API into line with get_dte().
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
14
Message-id: 20200513163245.17915-2-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20220201193207.2771604-5-peter.maydell@linaro.org
16
---
17
---
17
target/arm/helper.h | 10 +++
18
hw/intc/arm_gicv3_its.c | 96 ++++++++++++++++++++++-------------------
18
target/arm/translate.h | 7 +-
19
1 file changed, 52 insertions(+), 44 deletions(-)
19
target/arm/translate-a64.c | 15 +---
20
20
target/arm/translate.c | 161 ++++++++++++++++++++++---------------
21
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
21
target/arm/vec_helper.c | 25 ++++++
22
5 files changed, 139 insertions(+), 79 deletions(-)
23
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
23
--- a/hw/intc/arm_gicv3_its.c
27
+++ b/target/arm/helper.h
24
+++ b/hw/intc/arm_gicv3_its.c
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_pmull_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
@@ -XXX,XX +XXX,XX @@ typedef struct DTEntry {
29
26
uint64_t ittaddr;
30
DEF_HELPER_FLAGS_4(neon_pmull_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
} DTEntry;
31
28
32
+DEF_HELPER_FLAGS_3(gvec_ssra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
29
+typedef struct CTEntry {
33
+DEF_HELPER_FLAGS_3(gvec_ssra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
30
+ bool valid;
34
+DEF_HELPER_FLAGS_3(gvec_ssra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
31
+ uint32_t rdbase;
35
+DEF_HELPER_FLAGS_3(gvec_ssra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
32
+} CTEntry;
36
+
37
+DEF_HELPER_FLAGS_3(gvec_usra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_3(gvec_usra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_3(gvec_usra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_3(gvec_usra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
41
+
42
#ifdef TARGET_AARCH64
43
#include "helper-a64.h"
44
#include "helper-sve.h"
45
diff --git a/target/arm/translate.h b/target/arm/translate.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate.h
48
+++ b/target/arm/translate.h
49
@@ -XXX,XX +XXX,XX @@ extern const GVecGen3 mls_op[4];
50
extern const GVecGen3 cmtst_op[4];
51
extern const GVecGen3 sshl_op[4];
52
extern const GVecGen3 ushl_op[4];
53
-extern const GVecGen2i ssra_op[4];
54
-extern const GVecGen2i usra_op[4];
55
extern const GVecGen2i sri_op[4];
56
extern const GVecGen2i sli_op[4];
57
extern const GVecGen4 uqadd_op[4];
58
@@ -XXX,XX +XXX,XX @@ void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
59
void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
60
void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
61
62
+void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
63
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
64
+void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
65
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
66
+
33
+
67
/*
34
/*
68
* Forward to the isar_feature_* tests given a DisasContext pointer.
35
* The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
69
*/
36
* if a command parameter is not correct. These include both "stall
70
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ static uint64_t table_entry_addr(GICv3ITSState *s, TableDesc *td,
71
index XXXXXXX..XXXXXXX 100644
38
return (l2 & ((1ULL << 51) - 1)) + (idx % num_l2_entries) * td->entry_sz;
72
--- a/target/arm/translate-a64.c
73
+++ b/target/arm/translate-a64.c
74
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
75
76
switch (opcode) {
77
case 0x02: /* SSRA / USRA (accumulate) */
78
- if (is_u) {
79
- /* Shift count same as element size produces zero to add. */
80
- if (shift == 8 << size) {
81
- goto done;
82
- }
83
- gen_gvec_op2i(s, is_q, rd, rn, shift, &usra_op[size]);
84
- } else {
85
- /* Shift count same as element size produces all sign to add. */
86
- if (shift == 8 << size) {
87
- shift -= 1;
88
- }
89
- gen_gvec_op2i(s, is_q, rd, rn, shift, &ssra_op[size]);
90
- }
91
+ gen_gvec_fn2i(s, is_q, rd, rn, shift,
92
+ is_u ? gen_gvec_usra : gen_gvec_ssra, size);
93
return;
94
case 0x08: /* SRI */
95
/* Shift count same as element size is valid but does nothing. */
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate.c
99
+++ b/target/arm/translate.c
100
@@ -XXX,XX +XXX,XX @@ static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
101
tcg_gen_add_vec(vece, d, d, a);
102
}
39
}
103
40
104
-static const TCGOpcode vecop_list_ssra[] = {
41
-static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
105
- INDEX_op_sari_vec, INDEX_op_add_vec, 0
42
- MemTxResult *res)
106
-};
43
+/*
107
+void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
44
+ * Read the Collection Table entry at index @icid. On success (including
108
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
45
+ * successfully determining that there is no valid CTE for this index),
109
+{
46
+ * we return MEMTX_OK and populate the CTEntry struct @cte accordingly.
110
+ static const TCGOpcode vecop_list[] = {
47
+ * If there is an error reading memory then we return the error code.
111
+ INDEX_op_sari_vec, INDEX_op_add_vec, 0
48
+ */
112
+ };
49
+static MemTxResult get_cte(GICv3ITSState *s, uint16_t icid, CTEntry *cte)
113
+ static const GVecGen2i ops[4] = {
114
+ { .fni8 = gen_ssra8_i64,
115
+ .fniv = gen_ssra_vec,
116
+ .fno = gen_helper_gvec_ssra_b,
117
+ .load_dest = true,
118
+ .opt_opc = vecop_list,
119
+ .vece = MO_8 },
120
+ { .fni8 = gen_ssra16_i64,
121
+ .fniv = gen_ssra_vec,
122
+ .fno = gen_helper_gvec_ssra_h,
123
+ .load_dest = true,
124
+ .opt_opc = vecop_list,
125
+ .vece = MO_16 },
126
+ { .fni4 = gen_ssra32_i32,
127
+ .fniv = gen_ssra_vec,
128
+ .fno = gen_helper_gvec_ssra_s,
129
+ .load_dest = true,
130
+ .opt_opc = vecop_list,
131
+ .vece = MO_32 },
132
+ { .fni8 = gen_ssra64_i64,
133
+ .fniv = gen_ssra_vec,
134
+ .fno = gen_helper_gvec_ssra_b,
135
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
136
+ .opt_opc = vecop_list,
137
+ .load_dest = true,
138
+ .vece = MO_64 },
139
+ };
140
141
-const GVecGen2i ssra_op[4] = {
142
- { .fni8 = gen_ssra8_i64,
143
- .fniv = gen_ssra_vec,
144
- .load_dest = true,
145
- .opt_opc = vecop_list_ssra,
146
- .vece = MO_8 },
147
- { .fni8 = gen_ssra16_i64,
148
- .fniv = gen_ssra_vec,
149
- .load_dest = true,
150
- .opt_opc = vecop_list_ssra,
151
- .vece = MO_16 },
152
- { .fni4 = gen_ssra32_i32,
153
- .fniv = gen_ssra_vec,
154
- .load_dest = true,
155
- .opt_opc = vecop_list_ssra,
156
- .vece = MO_32 },
157
- { .fni8 = gen_ssra64_i64,
158
- .fniv = gen_ssra_vec,
159
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
160
- .opt_opc = vecop_list_ssra,
161
- .load_dest = true,
162
- .vece = MO_64 },
163
-};
164
+ /* tszimm encoding produces immediates in the range [1..esize]. */
165
+ tcg_debug_assert(shift > 0);
166
+ tcg_debug_assert(shift <= (8 << vece));
167
+
168
+ /*
169
+ * Shifts larger than the element size are architecturally valid.
170
+ * Signed results in all sign bits.
171
+ */
172
+ shift = MIN(shift, (8 << vece) - 1);
173
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
174
+}
175
176
static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
177
{
50
{
178
@@ -XXX,XX +XXX,XX @@ static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
51
AddressSpace *as = &s->gicv3->dma_as;
179
tcg_gen_add_vec(vece, d, d, a);
52
- uint64_t entry_addr = table_entry_addr(s, &s->ct, icid, res);
53
+ MemTxResult res = MEMTX_OK;
54
+ uint64_t entry_addr = table_entry_addr(s, &s->ct, icid, &res);
55
+ uint64_t cteval;
56
57
if (entry_addr == -1) {
58
- return false; /* not valid */
59
+ /* No L2 table entry, i.e. no valid CTE, or a memory error */
60
+ cte->valid = false;
61
+ return res;
62
}
63
64
- *cte = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res);
65
- return FIELD_EX64(*cte, CTE, VALID);
66
+ cteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
67
+ if (res != MEMTX_OK) {
68
+ return res;
69
+ }
70
+ cte->valid = FIELD_EX64(cteval, CTE, VALID);
71
+ cte->rdbase = FIELD_EX64(cteval, CTE, RDBASE);
72
+ return MEMTX_OK;
180
}
73
}
181
74
182
-static const TCGOpcode vecop_list_usra[] = {
75
static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
183
- INDEX_op_shri_vec, INDEX_op_add_vec, 0
76
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
184
-};
77
uint16_t icid = 0;
185
+void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
78
uint32_t pIntid = 0;
186
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
79
bool ite_valid = false;
187
+{
80
- uint64_t cte = 0;
188
+ static const TCGOpcode vecop_list[] = {
81
- bool cte_valid = false;
189
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
82
- uint64_t rdbase;
190
+ };
83
DTEntry dte;
191
+ static const GVecGen2i ops[4] = {
84
+ CTEntry cte;
192
+ { .fni8 = gen_usra8_i64,
85
193
+ .fniv = gen_usra_vec,
86
if (devid >= s->dt.num_entries) {
194
+ .fno = gen_helper_gvec_usra_b,
87
qemu_log_mask(LOG_GUEST_ERROR,
195
+ .load_dest = true,
88
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
196
+ .opt_opc = vecop_list,
89
return CMD_CONTINUE;
197
+ .vece = MO_8, },
90
}
198
+ { .fni8 = gen_usra16_i64,
91
199
+ .fniv = gen_usra_vec,
92
- cte_valid = get_cte(s, icid, &cte, &res);
200
+ .fno = gen_helper_gvec_usra_h,
93
- if (res != MEMTX_OK) {
201
+ .load_dest = true,
94
+ if (get_cte(s, icid, &cte) != MEMTX_OK) {
202
+ .opt_opc = vecop_list,
95
return CMD_STALL;
203
+ .vece = MO_16, },
96
}
204
+ { .fni4 = gen_usra32_i32,
97
- if (!cte_valid) {
205
+ .fniv = gen_usra_vec,
98
+ if (!cte.valid) {
206
+ .fno = gen_helper_gvec_usra_s,
99
qemu_log_mask(LOG_GUEST_ERROR,
207
+ .load_dest = true,
100
- "%s: invalid command attributes: "
208
+ .opt_opc = vecop_list,
101
- "invalid cte: %"PRIx64"\n",
209
+ .vece = MO_32, },
102
- __func__, cte);
210
+ { .fni8 = gen_usra64_i64,
103
+ "%s: invalid command attributes: invalid CTE\n",
211
+ .fniv = gen_usra_vec,
104
+ __func__);
212
+ .fno = gen_helper_gvec_usra_d,
105
return CMD_CONTINUE;
213
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
106
}
214
+ .load_dest = true,
107
215
+ .opt_opc = vecop_list,
108
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
216
+ .vece = MO_64, },
109
* Current implementation only supports rdbase == procnum
217
+ };
110
* Hence rdbase physical address is ignored
218
111
*/
219
-const GVecGen2i usra_op[4] = {
112
- rdbase = FIELD_EX64(cte, CTE, RDBASE);
220
- { .fni8 = gen_usra8_i64,
113
-
221
- .fniv = gen_usra_vec,
114
- if (rdbase >= s->gicv3->num_cpu) {
222
- .load_dest = true,
115
+ if (cte.rdbase >= s->gicv3->num_cpu) {
223
- .opt_opc = vecop_list_usra,
116
return CMD_CONTINUE;
224
- .vece = MO_8, },
117
}
225
- { .fni8 = gen_usra16_i64,
118
226
- .fniv = gen_usra_vec,
119
if ((cmd == CLEAR) || (cmd == DISCARD)) {
227
- .load_dest = true,
120
- gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
228
- .opt_opc = vecop_list_usra,
121
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], pIntid, 0);
229
- .vece = MO_16, },
122
} else {
230
- { .fni4 = gen_usra32_i32,
123
- gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
231
- .fniv = gen_usra_vec,
124
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], pIntid, 1);
232
- .load_dest = true,
125
}
233
- .opt_opc = vecop_list_usra,
126
234
- .vece = MO_32, },
127
if (cmd == DISCARD) {
235
- { .fni8 = gen_usra64_i64,
128
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
236
- .fniv = gen_usra_vec,
129
MemTxResult res = MEMTX_OK;
237
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
130
uint32_t devid, eventid, intid;
238
- .load_dest = true,
131
uint16_t old_icid, new_icid;
239
- .opt_opc = vecop_list_usra,
132
- uint64_t old_cte, new_cte;
240
- .vece = MO_64, },
133
- uint64_t old_rdbase, new_rdbase;
241
-};
134
- bool ite_valid, cte_valid;
242
+ /* tszimm encoding produces immediates in the range [1..esize]. */
135
+ bool ite_valid;
243
+ tcg_debug_assert(shift > 0);
136
uint64_t num_eventids;
244
+ tcg_debug_assert(shift <= (8 << vece));
137
IteEntry ite = {};
245
+
138
DTEntry dte;
246
+ /*
139
+ CTEntry old_cte, new_cte;
247
+ * Shifts larger than the element size are architecturally valid.
140
248
+ * Unsigned results in all zeros as input to accumulate: nop.
141
devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
249
+ */
142
eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
250
+ if (shift < (8 << vece)) {
143
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
251
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
144
return CMD_CONTINUE;
252
+ } else {
145
}
253
+ /* Nop, but we do need to clear the tail. */
146
254
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
147
- cte_valid = get_cte(s, old_icid, &old_cte, &res);
255
+ }
148
- if (res != MEMTX_OK) {
256
+}
149
+ if (get_cte(s, old_icid, &old_cte) != MEMTX_OK) {
257
150
return CMD_STALL;
258
static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
151
}
259
{
152
- if (!cte_valid) {
260
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
153
+ if (!old_cte.valid) {
261
case 1: /* VSRA */
154
qemu_log_mask(LOG_GUEST_ERROR,
262
/* Right shift comes here negative. */
155
"%s: invalid command attributes: "
263
shift = -shift;
156
- "invalid cte: %"PRIx64"\n",
264
- /* Shifts larger than the element size are architecturally
157
- __func__, old_cte);
265
- * valid. Unsigned results in all zeros; signed results
158
+ "invalid CTE for old ICID 0x%x\n",
266
- * in all sign bits.
159
+ __func__, old_icid);
267
- */
160
return CMD_CONTINUE;
268
- if (!u) {
161
}
269
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
162
270
- MIN(shift, (8 << size) - 1),
163
- cte_valid = get_cte(s, new_icid, &new_cte, &res);
271
- &ssra_op[size]);
164
- if (res != MEMTX_OK) {
272
- } else if (shift >= 8 << size) {
165
+ if (get_cte(s, new_icid, &new_cte) != MEMTX_OK) {
273
- /* rd += 0 */
166
return CMD_STALL;
274
+ if (u) {
167
}
275
+ gen_gvec_usra(size, rd_ofs, rm_ofs, shift,
168
- if (!cte_valid) {
276
+ vec_size, vec_size);
169
+ if (!new_cte.valid) {
277
} else {
170
qemu_log_mask(LOG_GUEST_ERROR,
278
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
171
"%s: invalid command attributes: "
279
- shift, &usra_op[size]);
172
- "invalid cte: %"PRIx64"\n",
280
+ gen_gvec_ssra(size, rd_ofs, rm_ofs, shift,
173
- __func__, new_cte);
281
+ vec_size, vec_size);
174
+ "invalid CTE for new ICID 0x%x\n",
282
}
175
+ __func__, new_icid);
283
return 0;
176
return CMD_CONTINUE;
284
177
}
285
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
178
286
index XXXXXXX..XXXXXXX 100644
179
- old_rdbase = FIELD_EX64(old_cte, CTE, RDBASE);
287
--- a/target/arm/vec_helper.c
180
- if (old_rdbase >= s->gicv3->num_cpu) {
288
+++ b/target/arm/vec_helper.c
181
+ if (old_cte.rdbase >= s->gicv3->num_cpu) {
289
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_sqsub_d)(void *vd, void *vq, void *vn,
182
qemu_log_mask(LOG_GUEST_ERROR,
290
clear_tail(d, oprsz, simd_maxsz(desc));
183
- "%s: CTE has invalid rdbase 0x%"PRIx64"\n",
291
}
184
- __func__, old_rdbase);
292
185
+ "%s: CTE has invalid rdbase 0x%x\n",
293
+
186
+ __func__, old_cte.rdbase);
294
+#define DO_SRA(NAME, TYPE) \
187
return CMD_CONTINUE;
295
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
188
}
296
+{ \
189
297
+ intptr_t i, oprsz = simd_oprsz(desc); \
190
- new_rdbase = FIELD_EX64(new_cte, CTE, RDBASE);
298
+ int shift = simd_data(desc); \
191
- if (new_rdbase >= s->gicv3->num_cpu) {
299
+ TYPE *d = vd, *n = vn; \
192
+ if (new_cte.rdbase >= s->gicv3->num_cpu) {
300
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
193
qemu_log_mask(LOG_GUEST_ERROR,
301
+ d[i] += n[i] >> shift; \
194
- "%s: CTE has invalid rdbase 0x%"PRIx64"\n",
302
+ } \
195
- __func__, new_rdbase);
303
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
196
+ "%s: CTE has invalid rdbase 0x%x\n",
304
+}
197
+ __func__, new_cte.rdbase);
305
+
198
return CMD_CONTINUE;
306
+DO_SRA(gvec_ssra_b, int8_t)
199
}
307
+DO_SRA(gvec_ssra_h, int16_t)
200
308
+DO_SRA(gvec_ssra_s, int32_t)
201
- if (old_rdbase != new_rdbase) {
309
+DO_SRA(gvec_ssra_d, int64_t)
202
+ if (old_cte.rdbase != new_cte.rdbase) {
310
+
203
/* Move the LPI from the old redistributor to the new one */
311
+DO_SRA(gvec_usra_b, uint8_t)
204
- gicv3_redist_mov_lpi(&s->gicv3->cpu[old_rdbase],
312
+DO_SRA(gvec_usra_h, uint16_t)
205
- &s->gicv3->cpu[new_rdbase],
313
+DO_SRA(gvec_usra_s, uint32_t)
206
+ gicv3_redist_mov_lpi(&s->gicv3->cpu[old_cte.rdbase],
314
+DO_SRA(gvec_usra_d, uint64_t)
207
+ &s->gicv3->cpu[new_cte.rdbase],
315
+
208
intid);
316
+#undef DO_SRA
209
}
317
+
210
318
/*
319
* Convert float16 to float32, raising no exceptions and
320
* preserving exceptional values, including SNaN.
321
--
211
--
322
2.20.1
212
2.25.1
323
213
324
214
diff view generated by jsdifflib
1
Convert the Neon VADD, VSUB, VABD 3-reg-same insns to decodetree.
1
Make update_cte() take a CTEntry struct rather than all the fields
2
We already have gvec helpers for addition and subtraction, but must
2
of the new CTE as separate arguments.
3
add one for fabd.
3
4
This brings it into line with the update_dte() API.
4
5
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
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-12-peter.maydell@linaro.org
8
Message-id: 20220201193207.2771604-6-peter.maydell@linaro.org
8
---
9
---
9
target/arm/helper.h | 3 ++-
10
hw/intc/arm_gicv3_its.c | 32 +++++++++++++++++---------------
10
target/arm/neon-dp.decode | 8 ++++++++
11
1 file changed, 17 insertions(+), 15 deletions(-)
11
target/arm/neon_helper.c | 7 -------
12
target/arm/translate-neon.inc.c | 28 ++++++++++++++++++++++++++++
13
target/arm/translate.c | 10 +++-------
14
target/arm/vec_helper.c | 7 +++++++
15
6 files changed, 48 insertions(+), 15 deletions(-)
16
12
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
15
--- a/hw/intc/arm_gicv3_its.c
20
+++ b/target/arm/helper.h
16
+++ b/hw/intc/arm_gicv3_its.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(neon_qneg_s16, TCG_CALL_NO_RWG, i32, env, i32)
17
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
22
DEF_HELPER_FLAGS_2(neon_qneg_s32, TCG_CALL_NO_RWG, i32, env, i32)
18
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
23
DEF_HELPER_FLAGS_2(neon_qneg_s64, TCG_CALL_NO_RWG, i64, env, i64)
24
25
-DEF_HELPER_3(neon_abd_f32, i32, i32, i32, ptr)
26
DEF_HELPER_3(neon_ceq_f32, i32, i32, i32, ptr)
27
DEF_HELPER_3(neon_cge_f32, i32, i32, i32, ptr)
28
DEF_HELPER_3(neon_cgt_f32, i32, i32, i32, ptr)
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmul_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
30
DEF_HELPER_FLAGS_5(gvec_fmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
32
33
+DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
34
+
35
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
36
void, ptr, ptr, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
38
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/neon-dp.decode
41
+++ b/target/arm/neon-dp.decode
42
@@ -XXX,XX +XXX,XX @@
43
@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
44
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
45
46
+# For FP insns the high bit of 'size' is used as part of opcode decode
47
+@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
48
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
49
+
50
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
51
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
52
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
53
@@ -XXX,XX +XXX,XX @@ SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
54
vm=%vm_dp vn=%vn_dp vd=%vd_dp
55
56
VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
57
+
58
+VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
59
+VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
60
+VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
61
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/neon_helper.c
64
+++ b/target/arm/neon_helper.c
65
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_qneg_s64)(CPUARMState *env, uint64_t x)
66
}
19
}
67
20
68
/* NEON Float helpers. */
21
-static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
69
-uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b, void *fpstp)
22
- uint64_t rdbase)
70
-{
71
- float_status *fpst = fpstp;
72
- float32 f0 = make_float32(a);
73
- float32 f1 = make_float32(b);
74
- return float32_val(float32_abs(float32_sub(f0, f1, fpst)));
75
-}
76
77
/* Floating point comparisons produce an integer result.
78
* Note that EQ doesn't signal InvalidOp for QNaNs but GE and GT do.
79
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/translate-neon.inc.c
82
+++ b/target/arm/translate-neon.inc.c
83
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPADD, padd_u)
84
85
DO_3SAME_VQDMULH(VQDMULH, qdmulh)
86
DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
87
+
88
+/*
23
+/*
89
+ * For all the functions using this macro, size == 1 means fp16,
24
+ * Update the Collection Table entry for @icid to @cte. Returns true
90
+ * which is an architecture extension we don't implement yet.
25
+ * on success, false if there was a memory access error.
91
+ */
26
+ */
92
+#define DO_3S_FP_GVEC(INSN,FUNC) \
27
+static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
93
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
28
{
94
+ uint32_t rn_ofs, uint32_t rm_ofs, \
29
AddressSpace *as = &s->gicv3->dma_as;
95
+ uint32_t oprsz, uint32_t maxsz) \
30
uint64_t entry_addr;
96
+ { \
31
- uint64_t cte = 0;
97
+ TCGv_ptr fpst = get_fpstatus_ptr(1); \
32
+ uint64_t cteval = 0;
98
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \
33
MemTxResult res = MEMTX_OK;
99
+ oprsz, maxsz, 0, FUNC); \
34
100
+ tcg_temp_free_ptr(fpst); \
35
if (!s->ct.valid) {
101
+ } \
36
return true;
102
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
37
}
103
+ { \
38
104
+ if (a->size != 0) { \
39
- if (valid) {
105
+ /* TODO fp16 support */ \
40
+ if (cte->valid) {
106
+ return false; \
41
/* add mapping entry to collection table */
107
+ } \
42
- cte = FIELD_DP64(cte, CTE, VALID, 1);
108
+ return do_3same(s, a, gen_##INSN##_3s); \
43
- cte = FIELD_DP64(cte, CTE, RDBASE, rdbase);
109
+ }
44
+ cteval = FIELD_DP64(cteval, CTE, VALID, 1);
110
+
45
+ cteval = FIELD_DP64(cteval, CTE, RDBASE, cte->rdbase);
111
+
46
}
112
+DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
47
113
+DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
48
entry_addr = table_entry_addr(s, &s->ct, icid, &res);
114
+DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
49
@@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
115
diff --git a/target/arm/translate.c b/target/arm/translate.c
50
return true;
116
index XXXXXXX..XXXXXXX 100644
51
}
117
--- a/target/arm/translate.c
52
118
+++ b/target/arm/translate.c
53
- address_space_stq_le(as, entry_addr, cte, MEMTXATTRS_UNSPECIFIED, &res);
119
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
54
+ address_space_stq_le(as, entry_addr, cteval, MEMTXATTRS_UNSPECIFIED, &res);
120
switch (op) {
55
return res == MEMTX_OK;
121
case NEON_3R_FLOAT_ARITH:
122
pairwise = (u && size < 2); /* if VPADD (float) */
123
+ if (!pairwise) {
124
+ return 1; /* handled by decodetree */
125
+ }
126
break;
127
case NEON_3R_FLOAT_MINMAX:
128
pairwise = u; /* if VPMIN/VPMAX (float) */
129
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
130
{
131
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
132
switch ((u << 2) | size) {
133
- case 0: /* VADD */
134
case 4: /* VPADD */
135
gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
136
break;
137
- case 2: /* VSUB */
138
- gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
139
- break;
140
- case 6: /* VABD */
141
- gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
142
- break;
143
default:
144
abort();
145
}
146
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/target/arm/vec_helper.c
149
+++ b/target/arm/vec_helper.c
150
@@ -XXX,XX +XXX,XX @@ static float64 float64_ftsmul(float64 op1, uint64_t op2, float_status *stat)
151
return result;
152
}
56
}
153
57
154
+static float32 float32_abd(float32 op1, float32 op2, float_status *stat)
58
static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
155
+{
59
{
156
+ return float32_abs(float32_sub(op1, op2, stat));
60
uint16_t icid;
157
+}
61
- uint64_t rdbase;
158
+
62
- bool valid;
159
#define DO_3OP(NAME, FUNC, TYPE) \
63
+ CTEntry cte;
160
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
64
161
{ \
65
icid = cmdpkt[2] & ICID_MASK;
162
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_ftsmul_h, float16_ftsmul, float16)
66
163
DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32)
67
- rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
164
DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64)
68
- rdbase &= RDBASE_PROCNUM_MASK;
165
69
+ cte.rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
166
+DO_3OP(gvec_fabd_s, float32_abd, float32)
70
+ cte.rdbase &= RDBASE_PROCNUM_MASK;
167
+
71
168
#ifdef TARGET_AARCH64
72
- valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
169
73
+ cte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
170
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
74
75
- if ((icid >= s->ct.num_entries) || (rdbase >= s->gicv3->num_cpu)) {
76
+ if ((icid >= s->ct.num_entries) || (cte.rdbase >= s->gicv3->num_cpu)) {
77
qemu_log_mask(LOG_GUEST_ERROR,
78
"ITS MAPC: invalid collection table attributes "
79
- "icid %d rdbase %" PRIu64 "\n", icid, rdbase);
80
+ "icid %d rdbase %u\n", icid, cte.rdbase);
81
/*
82
* in this implementation, in case of error
83
* we ignore this command and move onto the next
84
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
85
return CMD_CONTINUE;
86
}
87
88
- return update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL;
89
+ return update_cte(s, icid, &cte) ? CMD_CONTINUE : CMD_STALL;
90
}
91
92
/*
171
--
93
--
172
2.20.1
94
2.25.1
173
95
174
96
diff view generated by jsdifflib
1
Convert the Neon integer VPADD 3-reg-same insns to decodetree. These
1
In get_ite() and update_ite() we work with a 12-byte in-guest-memory
2
are 'pairwise' operations. (Note that VQRDMLAH, which shares the
2
table entry, which we intend to handle as an 8-byte value followed by
3
same primary opcode but has U=1, has already been converted.)
3
a 4-byte value. Unfortunately the calculation of the address of the
4
4-byte value is wrong, because we write it as:
5
6
table_base_address + (index * entrysize) + 4
7
(obfuscated by the way the expression has been written)
8
9
when it should be + 8. This bug meant that we overwrote the top
10
bytes of the 8-byte value with the 4-byte value. There are no
11
guest-visible effects because the top half of the 8-byte value
12
contains only the doorbell interrupt field, which is used only in
13
GICv4, and the two bugs in the "write ITE" and "read ITE" codepaths
14
cancel each other out.
15
16
We can't simply change the calculation, because this would break
17
migration of a (TCG) guest from the old version of QEMU which had
18
in-guest-memory interrupt tables written using the buggy version of
19
update_ite(). We must also at the same time change the layout of the
20
fields within the ITE_L and ITE_H values so that the in-memory
21
locations of the fields we care about (VALID, INTTYPE, INTID and
22
ICID) stay the same.
4
23
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-10-peter.maydell@linaro.org
26
Message-id: 20220201193207.2771604-7-peter.maydell@linaro.org
8
---
27
---
9
target/arm/neon-dp.decode | 2 ++
28
hw/intc/gicv3_internal.h | 19 ++++++++++---------
10
target/arm/translate-neon.inc.c | 2 ++
29
hw/intc/arm_gicv3_its.c | 28 +++++++++++-----------------
11
target/arm/translate.c | 19 +------------------
30
2 files changed, 21 insertions(+), 26 deletions(-)
12
3 files changed, 5 insertions(+), 18 deletions(-)
13
31
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
32
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
15
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
34
--- a/hw/intc/gicv3_internal.h
17
+++ b/target/arm/neon-dp.decode
35
+++ b/hw/intc/gicv3_internal.h
18
@@ -XXX,XX +XXX,XX @@ VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
36
@@ -XXX,XX +XXX,XX @@ FIELD(MOVI_2, ICID, 0, 16)
19
VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
37
* 12 bytes Interrupt translation Table Entry size
20
VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
38
* as per Table 5.3 in GICv3 spec
21
39
* ITE Lower 8 Bytes
22
+VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0
40
- * Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 |
23
+
41
- * Values: | Doorbell | IntNum | IntType | Valid |
24
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
42
+ * Bits: | 63 ... 48 | 47 ... 32 | 31 ... 26 | 25 ... 2 | 1 | 0 |
25
43
+ * Values: | vPEID | ICID | unused | IntNum | IntType | Valid |
26
SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
44
* ITE Higher 4 Bytes
27
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
45
- * Bits: | 31 ... 16 | 15 ...0 |
46
- * Values: | vPEID | ICID |
47
- * (When Doorbell is unused, as it always is in GICv3, it is 1023)
48
+ * Bits: | 31 ... 25 | 24 ... 0 |
49
+ * Values: | unused | Doorbell |
50
+ * (When Doorbell is unused, as it always is for INTYPE_PHYSICAL,
51
+ * the value of that field in memory cannot be relied upon -- older
52
+ * versions of QEMU did not correctly write to that memory.)
53
*/
54
#define ITS_ITT_ENTRY_SIZE 0xC
55
56
FIELD(ITE_L, VALID, 0, 1)
57
FIELD(ITE_L, INTTYPE, 1, 1)
58
FIELD(ITE_L, INTID, 2, 24)
59
-FIELD(ITE_L, DOORBELL, 26, 24)
60
-
61
-FIELD(ITE_H, ICID, 0, 16)
62
-FIELD(ITE_H, VPEID, 16, 16)
63
+FIELD(ITE_L, ICID, 32, 16)
64
+FIELD(ITE_L, VPEID, 48, 16)
65
+FIELD(ITE_H, DOORBELL, 0, 24)
66
67
/* Possible values for ITE_L INTTYPE */
68
#define ITE_INTTYPE_VIRTUAL 0
69
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
28
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-neon.inc.c
71
--- a/hw/intc/arm_gicv3_its.c
30
+++ b/target/arm/translate-neon.inc.c
72
+++ b/hw/intc/arm_gicv3_its.c
31
@@ -XXX,XX +XXX,XX @@ static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn)
73
@@ -XXX,XX +XXX,XX @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
32
#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
74
{
33
#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
75
AddressSpace *as = &s->gicv3->dma_as;
34
#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
76
MemTxResult res = MEMTX_OK;
35
+#define gen_helper_neon_padd_u32 tcg_gen_add_i32
77
+ hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
36
78
37
DO_3SAME_PAIR(VPMAX_S, pmax_s)
79
- address_space_stq_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
38
DO_3SAME_PAIR(VPMIN_S, pmin_s)
80
- sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
39
DO_3SAME_PAIR(VPMAX_U, pmax_u)
81
- &res);
40
DO_3SAME_PAIR(VPMIN_U, pmin_u)
82
+ address_space_stq_le(as, iteaddr, ite.itel, MEMTXATTRS_UNSPECIFIED, &res);
41
+DO_3SAME_PAIR(VPADD, padd_u)
83
42
diff --git a/target/arm/translate.c b/target/arm/translate.c
84
if (res == MEMTX_OK) {
43
index XXXXXXX..XXXXXXX 100644
85
- address_space_stl_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
44
--- a/target/arm/translate.c
86
- sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
45
+++ b/target/arm/translate.c
87
+ address_space_stl_le(as, iteaddr + 8, ite.iteh,
46
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
88
MEMTXATTRS_UNSPECIFIED, &res);
47
return 1;
89
}
48
}
90
if (res != MEMTX_OK) {
49
switch (op) {
91
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
50
- case NEON_3R_VPADD_VQRDMLAH:
92
AddressSpace *as = &s->gicv3->dma_as;
51
- if (!u) {
93
bool status = false;
52
- break; /* VPADD */
94
IteEntry ite = {};
53
- }
95
+ hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
54
- /* VQRDMLAH : handled by decodetree */
96
55
- return 1;
97
- ite.itel = address_space_ldq_le(as, dte->ittaddr +
56
-
98
- (eventid * (sizeof(uint64_t) +
57
case NEON_3R_VFM_VQRDMLSH:
99
- sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
58
if (!u) {
100
- res);
59
/* VFM, VFMS */
101
+ ite.itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, res);
60
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
102
61
case NEON_3R_VQRSHL:
103
if (*res == MEMTX_OK) {
62
case NEON_3R_VPMAX:
104
- ite.iteh = address_space_ldl_le(as, dte->ittaddr +
63
case NEON_3R_VPMIN:
105
- (eventid * (sizeof(uint64_t) +
64
+ case NEON_3R_VPADD_VQRDMLAH:
106
- sizeof(uint32_t))) + sizeof(uint32_t),
65
/* Already handled by decodetree */
107
+ ite.iteh = address_space_ldl_le(as, iteaddr + 8,
66
return 1;
108
MEMTXATTRS_UNSPECIFIED, res);
67
}
109
68
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
110
if (*res == MEMTX_OK) {
69
}
111
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
70
pairwise = 0;
112
int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
71
switch (op) {
113
if (inttype == ITE_INTTYPE_PHYSICAL) {
72
- case NEON_3R_VPADD_VQRDMLAH:
114
*pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
73
- pairwise = 1;
115
- *icid = FIELD_EX32(ite.iteh, ITE_H, ICID);
74
- break;
116
+ *icid = FIELD_EX64(ite.itel, ITE_L, ICID);
75
case NEON_3R_FLOAT_ARITH:
117
status = true;
76
pairwise = (u && size < 2); /* if VPADD (float) */
77
break;
78
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
79
}
118
}
80
}
119
}
81
break;
120
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
82
- case NEON_3R_VPADD_VQRDMLAH:
121
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, true);
83
- switch (size) {
122
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
84
- case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
123
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
85
- case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
124
- ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
86
- case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
125
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
87
- default: abort();
126
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, icid);
88
- }
127
+ ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
89
- break;
128
90
case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
129
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
91
{
130
}
92
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
131
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
132
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, 1);
133
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
134
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, intid);
135
- ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
136
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, new_icid);
137
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, new_icid);
138
+ ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
139
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
140
}
141
93
--
142
--
94
2.20.1
143
2.25.1
95
144
96
145
diff view generated by jsdifflib
1
Convert the Neon SHA instructions in the 3-reg-same group
1
The get_ite() code has some awkward nested if statements; clean
2
to decodetree.
2
them up by returning early if the memory accesses fail.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200512163904.10918-3-peter.maydell@linaro.org
6
Message-id: 20220201193207.2771604-8-peter.maydell@linaro.org
7
---
7
---
8
target/arm/neon-dp.decode | 10 +++
8
hw/intc/arm_gicv3_its.c | 26 ++++++++++++++------------
9
target/arm/translate-neon.inc.c | 139 ++++++++++++++++++++++++++++++++
9
1 file changed, 14 insertions(+), 12 deletions(-)
10
target/arm/translate.c | 46 +----------
11
3 files changed, 151 insertions(+), 44 deletions(-)
12
10
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
11
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
13
--- a/hw/intc/arm_gicv3_its.c
16
+++ b/target/arm/neon-dp.decode
14
+++ b/hw/intc/arm_gicv3_its.c
17
@@ -XXX,XX +XXX,XX @@ VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
15
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
18
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
16
hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
19
17
20
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
18
ite.itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, res);
21
+
19
+ if (*res != MEMTX_OK) {
22
+SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
23
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
24
+SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... \
25
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
26
+SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \
27
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
28
+SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
29
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
30
+
31
VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
32
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate-neon.inc.c
35
+++ b/target/arm/translate-neon.inc.c
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
37
38
DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
39
DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)
40
+
41
+static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a)
42
+{
43
+ TCGv_ptr ptr1, ptr2, ptr3;
44
+ TCGv_i32 tmp;
45
+
46
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
47
+ !dc_isar_feature(aa32_sha1, s)) {
48
+ return false;
20
+ return false;
49
+ }
21
+ }
50
+
22
51
+ /* UNDEF accesses to D16-D31 if they don't exist. */
23
- if (*res == MEMTX_OK) {
52
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
24
- ite.iteh = address_space_ldl_le(as, iteaddr + 8,
53
+ ((a->vd | a->vn | a->vm) & 0x10)) {
25
- MEMTXATTRS_UNSPECIFIED, res);
26
+ ite.iteh = address_space_ldl_le(as, iteaddr + 8,
27
+ MEMTXATTRS_UNSPECIFIED, res);
28
+ if (*res != MEMTX_OK) {
54
+ return false;
29
+ return false;
55
+ }
30
+ }
56
+
31
57
+ if ((a->vn | a->vm | a->vd) & 1) {
32
- if (*res == MEMTX_OK) {
58
+ return false;
33
- if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
59
+ }
34
- int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
60
+
35
- if (inttype == ITE_INTTYPE_PHYSICAL) {
61
+ if (!vfp_access_check(s)) {
36
- *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
62
+ return true;
37
- *icid = FIELD_EX64(ite.itel, ITE_L, ICID);
63
+ }
38
- status = true;
64
+
65
+ ptr1 = vfp_reg_ptr(true, a->vd);
66
+ ptr2 = vfp_reg_ptr(true, a->vn);
67
+ ptr3 = vfp_reg_ptr(true, a->vm);
68
+ tmp = tcg_const_i32(a->optype);
69
+ gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp);
70
+ tcg_temp_free_i32(tmp);
71
+ tcg_temp_free_ptr(ptr1);
72
+ tcg_temp_free_ptr(ptr2);
73
+ tcg_temp_free_ptr(ptr3);
74
+
75
+ return true;
76
+}
77
+
78
+static bool trans_SHA256H_3s(DisasContext *s, arg_SHA256H_3s *a)
79
+{
80
+ TCGv_ptr ptr1, ptr2, ptr3;
81
+
82
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
83
+ !dc_isar_feature(aa32_sha2, s)) {
84
+ return false;
85
+ }
86
+
87
+ /* UNDEF accesses to D16-D31 if they don't exist. */
88
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
89
+ ((a->vd | a->vn | a->vm) & 0x10)) {
90
+ return false;
91
+ }
92
+
93
+ if ((a->vn | a->vm | a->vd) & 1) {
94
+ return false;
95
+ }
96
+
97
+ if (!vfp_access_check(s)) {
98
+ return true;
99
+ }
100
+
101
+ ptr1 = vfp_reg_ptr(true, a->vd);
102
+ ptr2 = vfp_reg_ptr(true, a->vn);
103
+ ptr3 = vfp_reg_ptr(true, a->vm);
104
+ gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
105
+ tcg_temp_free_ptr(ptr1);
106
+ tcg_temp_free_ptr(ptr2);
107
+ tcg_temp_free_ptr(ptr3);
108
+
109
+ return true;
110
+}
111
+
112
+static bool trans_SHA256H2_3s(DisasContext *s, arg_SHA256H2_3s *a)
113
+{
114
+ TCGv_ptr ptr1, ptr2, ptr3;
115
+
116
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
117
+ !dc_isar_feature(aa32_sha2, s)) {
118
+ return false;
119
+ }
120
+
121
+ /* UNDEF accesses to D16-D31 if they don't exist. */
122
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
123
+ ((a->vd | a->vn | a->vm) & 0x10)) {
124
+ return false;
125
+ }
126
+
127
+ if ((a->vn | a->vm | a->vd) & 1) {
128
+ return false;
129
+ }
130
+
131
+ if (!vfp_access_check(s)) {
132
+ return true;
133
+ }
134
+
135
+ ptr1 = vfp_reg_ptr(true, a->vd);
136
+ ptr2 = vfp_reg_ptr(true, a->vn);
137
+ ptr3 = vfp_reg_ptr(true, a->vm);
138
+ gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
139
+ tcg_temp_free_ptr(ptr1);
140
+ tcg_temp_free_ptr(ptr2);
141
+ tcg_temp_free_ptr(ptr3);
142
+
143
+ return true;
144
+}
145
+
146
+static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a)
147
+{
148
+ TCGv_ptr ptr1, ptr2, ptr3;
149
+
150
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
151
+ !dc_isar_feature(aa32_sha2, s)) {
152
+ return false;
153
+ }
154
+
155
+ /* UNDEF accesses to D16-D31 if they don't exist. */
156
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
157
+ ((a->vd | a->vn | a->vm) & 0x10)) {
158
+ return false;
159
+ }
160
+
161
+ if ((a->vn | a->vm | a->vd) & 1) {
162
+ return false;
163
+ }
164
+
165
+ if (!vfp_access_check(s)) {
166
+ return true;
167
+ }
168
+
169
+ ptr1 = vfp_reg_ptr(true, a->vd);
170
+ ptr2 = vfp_reg_ptr(true, a->vn);
171
+ ptr3 = vfp_reg_ptr(true, a->vm);
172
+ gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
173
+ tcg_temp_free_ptr(ptr1);
174
+ tcg_temp_free_ptr(ptr2);
175
+ tcg_temp_free_ptr(ptr3);
176
+
177
+ return true;
178
+}
179
diff --git a/target/arm/translate.c b/target/arm/translate.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/target/arm/translate.c
182
+++ b/target/arm/translate.c
183
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
184
int vec_size;
185
uint32_t imm;
186
TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
187
- TCGv_ptr ptr1, ptr2, ptr3;
188
+ TCGv_ptr ptr1, ptr2;
189
TCGv_i64 tmp64;
190
191
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
192
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
193
return 1;
194
}
195
switch (op) {
196
- case NEON_3R_SHA:
197
- /* The SHA-1/SHA-256 3-register instructions require special
198
- * treatment here, as their size field is overloaded as an
199
- * op type selector, and they all consume their input in a
200
- * single pass.
201
- */
202
- if (!q) {
203
- return 1;
204
- }
205
- if (!u) { /* SHA-1 */
206
- if (!dc_isar_feature(aa32_sha1, s)) {
207
- return 1;
208
- }
209
- ptr1 = vfp_reg_ptr(true, rd);
210
- ptr2 = vfp_reg_ptr(true, rn);
211
- ptr3 = vfp_reg_ptr(true, rm);
212
- tmp4 = tcg_const_i32(size);
213
- gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
214
- tcg_temp_free_i32(tmp4);
215
- } else { /* SHA-256 */
216
- if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
217
- return 1;
218
- }
219
- ptr1 = vfp_reg_ptr(true, rd);
220
- ptr2 = vfp_reg_ptr(true, rn);
221
- ptr3 = vfp_reg_ptr(true, rm);
222
- switch (size) {
223
- case 0:
224
- gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
225
- break;
226
- case 1:
227
- gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
228
- break;
229
- case 2:
230
- gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
231
- break;
232
- }
39
- }
233
- }
40
- }
234
- tcg_temp_free_ptr(ptr1);
41
+ if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
235
- tcg_temp_free_ptr(ptr2);
42
+ int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
236
- tcg_temp_free_ptr(ptr3);
43
+ if (inttype == ITE_INTTYPE_PHYSICAL) {
237
- return 0;
44
+ *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
238
-
45
+ *icid = FIELD_EX64(ite.itel, ITE_L, ICID);
239
case NEON_3R_VPADD_VQRDMLAH:
46
+ status = true;
240
if (!u) {
241
break; /* VPADD */
242
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
243
case NEON_3R_VMUL:
244
case NEON_3R_VML:
245
case NEON_3R_VSHL:
246
+ case NEON_3R_SHA:
247
/* Already handled by decodetree */
248
return 1;
249
}
47
}
48
}
49
return status;
250
--
50
--
251
2.20.1
51
2.25.1
252
52
253
53
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In get_ite() we currently return the caller some of the fields of an
2
2
Interrupt Table Entry via a set of pointer arguments, and validate
3
Create vectorized versions of handle_shri_with_rndacc
3
some of them internally (interrupt type and valid bit) to return a
4
for shift+round and shift+round+accumulate. Add out-of-line
4
simple true/false 'valid' indication. Define a new ITEntry struct
5
helpers in preparation for longer vector lengths from SVE.
5
which has all the fields that the in-memory ITE has, and bring the
6
6
get_ite() function in to line with get_dte() and get_cte().
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
This paves the way for handling virtual interrupts, which will want
9
Message-id: 20200513163245.17915-3-richard.henderson@linaro.org
9
a different subset of the fields in the ITE. Handling them under
10
the old "lots of pointer arguments" scheme would have meant a
11
confusingly large set of arguments for this function.
12
13
The new struct ITEntry is obviously confusably similar to the
14
existing IteEntry struct, whose fields are the raw 12 bytes
15
of the in-memory ITE. In the next commit we will make update_ite()
16
use ITEntry instead of IteEntry, which will allow us to delete
17
the IteEntry struct and remove the confusion.
18
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20220201193207.2771604-9-peter.maydell@linaro.org
11
---
22
---
12
target/arm/helper.h | 20 ++
23
hw/intc/arm_gicv3_its.c | 102 ++++++++++++++++++++++------------------
13
target/arm/translate.h | 9 +
24
1 file changed, 55 insertions(+), 47 deletions(-)
14
target/arm/translate-a64.c | 11 +-
25
15
target/arm/translate.c | 463 +++++++++++++++++++++++++++++++++++--
26
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
16
target/arm/vec_helper.c | 50 ++++
17
5 files changed, 527 insertions(+), 26 deletions(-)
18
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
20
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.h
28
--- a/hw/intc/arm_gicv3_its.c
22
+++ b/target/arm/helper.h
29
+++ b/hw/intc/arm_gicv3_its.c
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(gvec_usra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
30
@@ -XXX,XX +XXX,XX @@ typedef struct CTEntry {
24
DEF_HELPER_FLAGS_3(gvec_usra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
31
uint32_t rdbase;
25
DEF_HELPER_FLAGS_3(gvec_usra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
32
} CTEntry;
26
33
27
+DEF_HELPER_FLAGS_3(gvec_srshr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
34
+typedef struct ITEntry {
28
+DEF_HELPER_FLAGS_3(gvec_srshr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
35
+ bool valid;
29
+DEF_HELPER_FLAGS_3(gvec_srshr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
36
+ int inttype;
30
+DEF_HELPER_FLAGS_3(gvec_srshr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
37
+ uint32_t intid;
38
+ uint32_t doorbell;
39
+ uint32_t icid;
40
+ uint32_t vpeid;
41
+} ITEntry;
31
+
42
+
32
+DEF_HELPER_FLAGS_3(gvec_urshr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_3(gvec_urshr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_3(gvec_urshr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_3(gvec_urshr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
36
+
37
+DEF_HELPER_FLAGS_3(gvec_srsra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_3(gvec_srsra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_3(gvec_srsra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_3(gvec_srsra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
41
+
42
+DEF_HELPER_FLAGS_3(gvec_ursra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
43
+DEF_HELPER_FLAGS_3(gvec_ursra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
44
+DEF_HELPER_FLAGS_3(gvec_ursra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_3(gvec_ursra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
46
+
47
#ifdef TARGET_AARCH64
48
#include "helper-a64.h"
49
#include "helper-sve.h"
50
diff --git a/target/arm/translate.h b/target/arm/translate.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate.h
53
+++ b/target/arm/translate.h
54
@@ -XXX,XX +XXX,XX @@ void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
55
void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
56
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
57
58
+void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
59
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
60
+void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
61
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
62
+void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
63
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
64
+void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
65
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
66
+
43
+
67
/*
44
/*
68
* Forward to the isar_feature_* tests given a DisasContext pointer.
45
* The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
69
*/
46
* if a command parameter is not correct. These include both "stall
70
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
47
@@ -XXX,XX +XXX,XX @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/translate-a64.c
73
+++ b/target/arm/translate-a64.c
74
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
75
return;
76
77
case 0x04: /* SRSHR / URSHR (rounding) */
78
- break;
79
+ gen_gvec_fn2i(s, is_q, rd, rn, shift,
80
+ is_u ? gen_gvec_urshr : gen_gvec_srshr, size);
81
+ return;
82
+
83
case 0x06: /* SRSRA / URSRA (accum + rounding) */
84
- accumulate = true;
85
- break;
86
+ gen_gvec_fn2i(s, is_q, rd, rn, shift,
87
+ is_u ? gen_gvec_ursra : gen_gvec_srsra, size);
88
+ return;
89
+
90
default:
91
g_assert_not_reached();
92
}
93
diff --git a/target/arm/translate.c b/target/arm/translate.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/translate.c
96
+++ b/target/arm/translate.c
97
@@ -XXX,XX +XXX,XX @@ void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
98
}
48
}
99
}
49
}
100
50
51
-static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
52
- uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
101
+/*
53
+/*
102
+ * Shift one less than the requested amount, and the low bit is
54
+ * Read the Interrupt Table entry at index @eventid from the table specified
103
+ * the rounding bit. For the 8 and 16-bit operations, because we
55
+ * by the DTE @dte. On success, we return MEMTX_OK and populate the ITEntry
104
+ * mask the low bit, we can perform a normal integer shift instead
56
+ * struct @ite accordingly. If there is an error reading memory then we return
105
+ * of a vector shift.
57
+ * the error code.
106
+ */
58
+ */
107
+static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
59
+static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid,
108
+{
60
+ const DTEntry *dte, ITEntry *ite)
109
+ TCGv_i64 t = tcg_temp_new_i64();
110
+
111
+ tcg_gen_shri_i64(t, a, sh - 1);
112
+ tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
113
+ tcg_gen_vec_sar8i_i64(d, a, sh);
114
+ tcg_gen_vec_add8_i64(d, d, t);
115
+ tcg_temp_free_i64(t);
116
+}
117
+
118
+static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
119
+{
120
+ TCGv_i64 t = tcg_temp_new_i64();
121
+
122
+ tcg_gen_shri_i64(t, a, sh - 1);
123
+ tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
124
+ tcg_gen_vec_sar16i_i64(d, a, sh);
125
+ tcg_gen_vec_add16_i64(d, d, t);
126
+ tcg_temp_free_i64(t);
127
+}
128
+
129
+static void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
130
+{
131
+ TCGv_i32 t = tcg_temp_new_i32();
132
+
133
+ tcg_gen_extract_i32(t, a, sh - 1, 1);
134
+ tcg_gen_sari_i32(d, a, sh);
135
+ tcg_gen_add_i32(d, d, t);
136
+ tcg_temp_free_i32(t);
137
+}
138
+
139
+static void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
140
+{
141
+ TCGv_i64 t = tcg_temp_new_i64();
142
+
143
+ tcg_gen_extract_i64(t, a, sh - 1, 1);
144
+ tcg_gen_sari_i64(d, a, sh);
145
+ tcg_gen_add_i64(d, d, t);
146
+ tcg_temp_free_i64(t);
147
+}
148
+
149
+static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
150
+{
151
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
152
+ TCGv_vec ones = tcg_temp_new_vec_matching(d);
153
+
154
+ tcg_gen_shri_vec(vece, t, a, sh - 1);
155
+ tcg_gen_dupi_vec(vece, ones, 1);
156
+ tcg_gen_and_vec(vece, t, t, ones);
157
+ tcg_gen_sari_vec(vece, d, a, sh);
158
+ tcg_gen_add_vec(vece, d, d, t);
159
+
160
+ tcg_temp_free_vec(t);
161
+ tcg_temp_free_vec(ones);
162
+}
163
+
164
+void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
165
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
166
+{
167
+ static const TCGOpcode vecop_list[] = {
168
+ INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
169
+ };
170
+ static const GVecGen2i ops[4] = {
171
+ { .fni8 = gen_srshr8_i64,
172
+ .fniv = gen_srshr_vec,
173
+ .fno = gen_helper_gvec_srshr_b,
174
+ .opt_opc = vecop_list,
175
+ .vece = MO_8 },
176
+ { .fni8 = gen_srshr16_i64,
177
+ .fniv = gen_srshr_vec,
178
+ .fno = gen_helper_gvec_srshr_h,
179
+ .opt_opc = vecop_list,
180
+ .vece = MO_16 },
181
+ { .fni4 = gen_srshr32_i32,
182
+ .fniv = gen_srshr_vec,
183
+ .fno = gen_helper_gvec_srshr_s,
184
+ .opt_opc = vecop_list,
185
+ .vece = MO_32 },
186
+ { .fni8 = gen_srshr64_i64,
187
+ .fniv = gen_srshr_vec,
188
+ .fno = gen_helper_gvec_srshr_d,
189
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
190
+ .opt_opc = vecop_list,
191
+ .vece = MO_64 },
192
+ };
193
+
194
+ /* tszimm encoding produces immediates in the range [1..esize] */
195
+ tcg_debug_assert(shift > 0);
196
+ tcg_debug_assert(shift <= (8 << vece));
197
+
198
+ if (shift == (8 << vece)) {
199
+ /*
200
+ * Shifts larger than the element size are architecturally valid.
201
+ * Signed results in all sign bits. With rounding, this produces
202
+ * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
203
+ * I.e. always zero.
204
+ */
205
+ tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0);
206
+ } else {
207
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
208
+ }
209
+}
210
+
211
+static void gen_srsra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
212
+{
213
+ TCGv_i64 t = tcg_temp_new_i64();
214
+
215
+ gen_srshr8_i64(t, a, sh);
216
+ tcg_gen_vec_add8_i64(d, d, t);
217
+ tcg_temp_free_i64(t);
218
+}
219
+
220
+static void gen_srsra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
221
+{
222
+ TCGv_i64 t = tcg_temp_new_i64();
223
+
224
+ gen_srshr16_i64(t, a, sh);
225
+ tcg_gen_vec_add16_i64(d, d, t);
226
+ tcg_temp_free_i64(t);
227
+}
228
+
229
+static void gen_srsra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
230
+{
231
+ TCGv_i32 t = tcg_temp_new_i32();
232
+
233
+ gen_srshr32_i32(t, a, sh);
234
+ tcg_gen_add_i32(d, d, t);
235
+ tcg_temp_free_i32(t);
236
+}
237
+
238
+static void gen_srsra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
239
+{
240
+ TCGv_i64 t = tcg_temp_new_i64();
241
+
242
+ gen_srshr64_i64(t, a, sh);
243
+ tcg_gen_add_i64(d, d, t);
244
+ tcg_temp_free_i64(t);
245
+}
246
+
247
+static void gen_srsra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
248
+{
249
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
250
+
251
+ gen_srshr_vec(vece, t, a, sh);
252
+ tcg_gen_add_vec(vece, d, d, t);
253
+ tcg_temp_free_vec(t);
254
+}
255
+
256
+void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
257
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
258
+{
259
+ static const TCGOpcode vecop_list[] = {
260
+ INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
261
+ };
262
+ static const GVecGen2i ops[4] = {
263
+ { .fni8 = gen_srsra8_i64,
264
+ .fniv = gen_srsra_vec,
265
+ .fno = gen_helper_gvec_srsra_b,
266
+ .opt_opc = vecop_list,
267
+ .load_dest = true,
268
+ .vece = MO_8 },
269
+ { .fni8 = gen_srsra16_i64,
270
+ .fniv = gen_srsra_vec,
271
+ .fno = gen_helper_gvec_srsra_h,
272
+ .opt_opc = vecop_list,
273
+ .load_dest = true,
274
+ .vece = MO_16 },
275
+ { .fni4 = gen_srsra32_i32,
276
+ .fniv = gen_srsra_vec,
277
+ .fno = gen_helper_gvec_srsra_s,
278
+ .opt_opc = vecop_list,
279
+ .load_dest = true,
280
+ .vece = MO_32 },
281
+ { .fni8 = gen_srsra64_i64,
282
+ .fniv = gen_srsra_vec,
283
+ .fno = gen_helper_gvec_srsra_d,
284
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
285
+ .opt_opc = vecop_list,
286
+ .load_dest = true,
287
+ .vece = MO_64 },
288
+ };
289
+
290
+ /* tszimm encoding produces immediates in the range [1..esize] */
291
+ tcg_debug_assert(shift > 0);
292
+ tcg_debug_assert(shift <= (8 << vece));
293
+
294
+ /*
295
+ * Shifts larger than the element size are architecturally valid.
296
+ * Signed results in all sign bits. With rounding, this produces
297
+ * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
298
+ * I.e. always zero. With accumulation, this leaves D unchanged.
299
+ */
300
+ if (shift == (8 << vece)) {
301
+ /* Nop, but we do need to clear the tail. */
302
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
303
+ } else {
304
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
305
+ }
306
+}
307
+
308
+static void gen_urshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
309
+{
310
+ TCGv_i64 t = tcg_temp_new_i64();
311
+
312
+ tcg_gen_shri_i64(t, a, sh - 1);
313
+ tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
314
+ tcg_gen_vec_shr8i_i64(d, a, sh);
315
+ tcg_gen_vec_add8_i64(d, d, t);
316
+ tcg_temp_free_i64(t);
317
+}
318
+
319
+static void gen_urshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
320
+{
321
+ TCGv_i64 t = tcg_temp_new_i64();
322
+
323
+ tcg_gen_shri_i64(t, a, sh - 1);
324
+ tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
325
+ tcg_gen_vec_shr16i_i64(d, a, sh);
326
+ tcg_gen_vec_add16_i64(d, d, t);
327
+ tcg_temp_free_i64(t);
328
+}
329
+
330
+static void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
331
+{
332
+ TCGv_i32 t = tcg_temp_new_i32();
333
+
334
+ tcg_gen_extract_i32(t, a, sh - 1, 1);
335
+ tcg_gen_shri_i32(d, a, sh);
336
+ tcg_gen_add_i32(d, d, t);
337
+ tcg_temp_free_i32(t);
338
+}
339
+
340
+static void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
341
+{
342
+ TCGv_i64 t = tcg_temp_new_i64();
343
+
344
+ tcg_gen_extract_i64(t, a, sh - 1, 1);
345
+ tcg_gen_shri_i64(d, a, sh);
346
+ tcg_gen_add_i64(d, d, t);
347
+ tcg_temp_free_i64(t);
348
+}
349
+
350
+static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift)
351
+{
352
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
353
+ TCGv_vec ones = tcg_temp_new_vec_matching(d);
354
+
355
+ tcg_gen_shri_vec(vece, t, a, shift - 1);
356
+ tcg_gen_dupi_vec(vece, ones, 1);
357
+ tcg_gen_and_vec(vece, t, t, ones);
358
+ tcg_gen_shri_vec(vece, d, a, shift);
359
+ tcg_gen_add_vec(vece, d, d, t);
360
+
361
+ tcg_temp_free_vec(t);
362
+ tcg_temp_free_vec(ones);
363
+}
364
+
365
+void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
366
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
367
+{
368
+ static const TCGOpcode vecop_list[] = {
369
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
370
+ };
371
+ static const GVecGen2i ops[4] = {
372
+ { .fni8 = gen_urshr8_i64,
373
+ .fniv = gen_urshr_vec,
374
+ .fno = gen_helper_gvec_urshr_b,
375
+ .opt_opc = vecop_list,
376
+ .vece = MO_8 },
377
+ { .fni8 = gen_urshr16_i64,
378
+ .fniv = gen_urshr_vec,
379
+ .fno = gen_helper_gvec_urshr_h,
380
+ .opt_opc = vecop_list,
381
+ .vece = MO_16 },
382
+ { .fni4 = gen_urshr32_i32,
383
+ .fniv = gen_urshr_vec,
384
+ .fno = gen_helper_gvec_urshr_s,
385
+ .opt_opc = vecop_list,
386
+ .vece = MO_32 },
387
+ { .fni8 = gen_urshr64_i64,
388
+ .fniv = gen_urshr_vec,
389
+ .fno = gen_helper_gvec_urshr_d,
390
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
391
+ .opt_opc = vecop_list,
392
+ .vece = MO_64 },
393
+ };
394
+
395
+ /* tszimm encoding produces immediates in the range [1..esize] */
396
+ tcg_debug_assert(shift > 0);
397
+ tcg_debug_assert(shift <= (8 << vece));
398
+
399
+ if (shift == (8 << vece)) {
400
+ /*
401
+ * Shifts larger than the element size are architecturally valid.
402
+ * Unsigned results in zero. With rounding, this produces a
403
+ * copy of the most significant bit.
404
+ */
405
+ tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift - 1, opr_sz, max_sz);
406
+ } else {
407
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
408
+ }
409
+}
410
+
411
+static void gen_ursra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
412
+{
413
+ TCGv_i64 t = tcg_temp_new_i64();
414
+
415
+ if (sh == 8) {
416
+ tcg_gen_vec_shr8i_i64(t, a, 7);
417
+ } else {
418
+ gen_urshr8_i64(t, a, sh);
419
+ }
420
+ tcg_gen_vec_add8_i64(d, d, t);
421
+ tcg_temp_free_i64(t);
422
+}
423
+
424
+static void gen_ursra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
425
+{
426
+ TCGv_i64 t = tcg_temp_new_i64();
427
+
428
+ if (sh == 16) {
429
+ tcg_gen_vec_shr16i_i64(t, a, 15);
430
+ } else {
431
+ gen_urshr16_i64(t, a, sh);
432
+ }
433
+ tcg_gen_vec_add16_i64(d, d, t);
434
+ tcg_temp_free_i64(t);
435
+}
436
+
437
+static void gen_ursra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
438
+{
439
+ TCGv_i32 t = tcg_temp_new_i32();
440
+
441
+ if (sh == 32) {
442
+ tcg_gen_shri_i32(t, a, 31);
443
+ } else {
444
+ gen_urshr32_i32(t, a, sh);
445
+ }
446
+ tcg_gen_add_i32(d, d, t);
447
+ tcg_temp_free_i32(t);
448
+}
449
+
450
+static void gen_ursra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
451
+{
452
+ TCGv_i64 t = tcg_temp_new_i64();
453
+
454
+ if (sh == 64) {
455
+ tcg_gen_shri_i64(t, a, 63);
456
+ } else {
457
+ gen_urshr64_i64(t, a, sh);
458
+ }
459
+ tcg_gen_add_i64(d, d, t);
460
+ tcg_temp_free_i64(t);
461
+}
462
+
463
+static void gen_ursra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
464
+{
465
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
466
+
467
+ if (sh == (8 << vece)) {
468
+ tcg_gen_shri_vec(vece, t, a, sh - 1);
469
+ } else {
470
+ gen_urshr_vec(vece, t, a, sh);
471
+ }
472
+ tcg_gen_add_vec(vece, d, d, t);
473
+ tcg_temp_free_vec(t);
474
+}
475
+
476
+void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
477
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
478
+{
479
+ static const TCGOpcode vecop_list[] = {
480
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
481
+ };
482
+ static const GVecGen2i ops[4] = {
483
+ { .fni8 = gen_ursra8_i64,
484
+ .fniv = gen_ursra_vec,
485
+ .fno = gen_helper_gvec_ursra_b,
486
+ .opt_opc = vecop_list,
487
+ .load_dest = true,
488
+ .vece = MO_8 },
489
+ { .fni8 = gen_ursra16_i64,
490
+ .fniv = gen_ursra_vec,
491
+ .fno = gen_helper_gvec_ursra_h,
492
+ .opt_opc = vecop_list,
493
+ .load_dest = true,
494
+ .vece = MO_16 },
495
+ { .fni4 = gen_ursra32_i32,
496
+ .fniv = gen_ursra_vec,
497
+ .fno = gen_helper_gvec_ursra_s,
498
+ .opt_opc = vecop_list,
499
+ .load_dest = true,
500
+ .vece = MO_32 },
501
+ { .fni8 = gen_ursra64_i64,
502
+ .fniv = gen_ursra_vec,
503
+ .fno = gen_helper_gvec_ursra_d,
504
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
505
+ .opt_opc = vecop_list,
506
+ .load_dest = true,
507
+ .vece = MO_64 },
508
+ };
509
+
510
+ /* tszimm encoding produces immediates in the range [1..esize] */
511
+ tcg_debug_assert(shift > 0);
512
+ tcg_debug_assert(shift <= (8 << vece));
513
+
514
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
515
+}
516
+
517
static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
518
{
61
{
519
uint64_t mask = dup_const(MO_8, 0xff >> shift);
62
AddressSpace *as = &s->gicv3->dma_as;
520
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
63
- bool status = false;
521
}
64
- IteEntry ite = {};
522
return 0;
65
+ MemTxResult res = MEMTX_OK;
523
66
+ uint64_t itel;
524
+ case 2: /* VRSHR */
67
+ uint32_t iteh;
525
+ /* Right shift comes here negative. */
68
hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
526
+ shift = -shift;
69
527
+ if (u) {
70
- ite.itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, res);
528
+ gen_gvec_urshr(size, rd_ofs, rm_ofs, shift,
71
- if (*res != MEMTX_OK) {
529
+ vec_size, vec_size);
72
- return false;
530
+ } else {
73
+ itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, &res);
531
+ gen_gvec_srshr(size, rd_ofs, rm_ofs, shift,
74
+ if (res != MEMTX_OK) {
532
+ vec_size, vec_size);
75
+ return res;
533
+ }
76
}
534
+ return 0;
77
535
+
78
- ite.iteh = address_space_ldl_le(as, iteaddr + 8,
536
+ case 3: /* VRSRA */
79
- MEMTXATTRS_UNSPECIFIED, res);
537
+ /* Right shift comes here negative. */
80
- if (*res != MEMTX_OK) {
538
+ shift = -shift;
81
- return false;
539
+ if (u) {
82
+ iteh = address_space_ldl_le(as, iteaddr + 8, MEMTXATTRS_UNSPECIFIED, &res);
540
+ gen_gvec_ursra(size, rd_ofs, rm_ofs, shift,
83
+ if (res != MEMTX_OK) {
541
+ vec_size, vec_size);
84
+ return res;
542
+ } else {
85
}
543
+ gen_gvec_srsra(size, rd_ofs, rm_ofs, shift,
86
544
+ vec_size, vec_size);
87
- if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
545
+ }
88
- int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
546
+ return 0;
89
- if (inttype == ITE_INTTYPE_PHYSICAL) {
547
+
90
- *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
548
case 4: /* VSRI */
91
- *icid = FIELD_EX64(ite.itel, ITE_L, ICID);
549
if (!u) {
92
- status = true;
550
return 1;
93
- }
551
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
94
- }
552
neon_load_reg64(cpu_V0, rm + pass);
95
- return status;
553
tcg_gen_movi_i64(cpu_V1, imm);
96
+ ite->valid = FIELD_EX64(itel, ITE_L, VALID);
554
switch (op) {
97
+ ite->inttype = FIELD_EX64(itel, ITE_L, INTTYPE);
555
- case 2: /* VRSHR */
98
+ ite->intid = FIELD_EX64(itel, ITE_L, INTID);
556
- case 3: /* VRSRA */
99
+ ite->icid = FIELD_EX64(itel, ITE_L, ICID);
557
- if (u)
100
+ ite->vpeid = FIELD_EX64(itel, ITE_L, VPEID);
558
- gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
101
+ ite->doorbell = FIELD_EX64(iteh, ITE_H, DOORBELL);
559
- else
102
+ return MEMTX_OK;
560
- gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
103
}
561
- break;
104
562
case 6: /* VQSHLU */
563
gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
564
cpu_V0, cpu_V1);
565
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
566
default:
567
g_assert_not_reached();
568
}
569
- if (op == 3) {
570
- /* Accumulate. */
571
- neon_load_reg64(cpu_V1, rd + pass);
572
- tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
573
- }
574
neon_store_reg64(cpu_V0, rd + pass);
575
} else { /* size < 3 */
576
/* Operands in T0 and T1. */
577
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
578
tmp2 = tcg_temp_new_i32();
579
tcg_gen_movi_i32(tmp2, imm);
580
switch (op) {
581
- case 2: /* VRSHR */
582
- case 3: /* VRSRA */
583
- GEN_NEON_INTEGER_OP(rshl);
584
- break;
585
case 6: /* VQSHLU */
586
switch (size) {
587
case 0:
588
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
589
g_assert_not_reached();
590
}
591
tcg_temp_free_i32(tmp2);
592
-
593
- if (op == 3) {
594
- /* Accumulate. */
595
- tmp2 = neon_load_reg(rd, pass);
596
- gen_neon_add(size, tmp, tmp2);
597
- tcg_temp_free_i32(tmp2);
598
- }
599
neon_store_reg(rd, pass, tmp);
600
}
601
} /* for pass */
602
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
603
index XXXXXXX..XXXXXXX 100644
604
--- a/target/arm/vec_helper.c
605
+++ b/target/arm/vec_helper.c
606
@@ -XXX,XX +XXX,XX @@ DO_SRA(gvec_usra_d, uint64_t)
607
608
#undef DO_SRA
609
610
+#define DO_RSHR(NAME, TYPE) \
611
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
612
+{ \
613
+ intptr_t i, oprsz = simd_oprsz(desc); \
614
+ int shift = simd_data(desc); \
615
+ TYPE *d = vd, *n = vn; \
616
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
617
+ TYPE tmp = n[i] >> (shift - 1); \
618
+ d[i] = (tmp >> 1) + (tmp & 1); \
619
+ } \
620
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
621
+}
622
+
623
+DO_RSHR(gvec_srshr_b, int8_t)
624
+DO_RSHR(gvec_srshr_h, int16_t)
625
+DO_RSHR(gvec_srshr_s, int32_t)
626
+DO_RSHR(gvec_srshr_d, int64_t)
627
+
628
+DO_RSHR(gvec_urshr_b, uint8_t)
629
+DO_RSHR(gvec_urshr_h, uint16_t)
630
+DO_RSHR(gvec_urshr_s, uint32_t)
631
+DO_RSHR(gvec_urshr_d, uint64_t)
632
+
633
+#undef DO_RSHR
634
+
635
+#define DO_RSRA(NAME, TYPE) \
636
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
637
+{ \
638
+ intptr_t i, oprsz = simd_oprsz(desc); \
639
+ int shift = simd_data(desc); \
640
+ TYPE *d = vd, *n = vn; \
641
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
642
+ TYPE tmp = n[i] >> (shift - 1); \
643
+ d[i] += (tmp >> 1) + (tmp & 1); \
644
+ } \
645
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
646
+}
647
+
648
+DO_RSRA(gvec_srsra_b, int8_t)
649
+DO_RSRA(gvec_srsra_h, int16_t)
650
+DO_RSRA(gvec_srsra_s, int32_t)
651
+DO_RSRA(gvec_srsra_d, int64_t)
652
+
653
+DO_RSRA(gvec_ursra_b, uint8_t)
654
+DO_RSRA(gvec_ursra_h, uint16_t)
655
+DO_RSRA(gvec_ursra_s, uint32_t)
656
+DO_RSRA(gvec_ursra_d, uint64_t)
657
+
658
+#undef DO_RSRA
659
+
660
/*
105
/*
661
* Convert float16 to float32, raising no exceptions and
106
@@ -XXX,XX +XXX,XX @@ static MemTxResult get_dte(GICv3ITSState *s, uint32_t devid, DTEntry *dte)
662
* preserving exceptional values, including SNaN.
107
static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
108
uint32_t eventid, ItsCmdType cmd)
109
{
110
- MemTxResult res = MEMTX_OK;
111
uint64_t num_eventids;
112
- uint16_t icid = 0;
113
- uint32_t pIntid = 0;
114
- bool ite_valid = false;
115
DTEntry dte;
116
CTEntry cte;
117
+ ITEntry ite;
118
119
if (devid >= s->dt.num_entries) {
120
qemu_log_mask(LOG_GUEST_ERROR,
121
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
122
return CMD_CONTINUE;
123
}
124
125
- ite_valid = get_ite(s, eventid, &dte, &icid, &pIntid, &res);
126
- if (res != MEMTX_OK) {
127
+ if (get_ite(s, eventid, &dte, &ite) != MEMTX_OK) {
128
return CMD_STALL;
129
}
130
131
- if (!ite_valid) {
132
+ if (!ite.valid || ite.inttype != ITE_INTTYPE_PHYSICAL) {
133
qemu_log_mask(LOG_GUEST_ERROR,
134
"%s: invalid command attributes: invalid ITE\n",
135
__func__);
136
return CMD_CONTINUE;
137
}
138
139
- if (icid >= s->ct.num_entries) {
140
+ if (ite.icid >= s->ct.num_entries) {
141
qemu_log_mask(LOG_GUEST_ERROR,
142
"%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
143
- __func__, icid);
144
+ __func__, ite.icid);
145
return CMD_CONTINUE;
146
}
147
148
- if (get_cte(s, icid, &cte) != MEMTX_OK) {
149
+ if (get_cte(s, ite.icid, &cte) != MEMTX_OK) {
150
return CMD_STALL;
151
}
152
if (!cte.valid) {
153
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
154
}
155
156
if ((cmd == CLEAR) || (cmd == DISCARD)) {
157
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], pIntid, 0);
158
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 0);
159
} else {
160
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], pIntid, 1);
161
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 1);
162
}
163
164
if (cmd == DISCARD) {
165
- IteEntry ite = {};
166
+ IteEntry itee = {};
167
/* remove mapping from interrupt translation table */
168
- return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
169
+ return update_ite(s, eventid, &dte, itee) ? CMD_CONTINUE : CMD_STALL;
170
}
171
return CMD_CONTINUE;
172
}
173
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
174
175
static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
176
{
177
- MemTxResult res = MEMTX_OK;
178
- uint32_t devid, eventid, intid;
179
- uint16_t old_icid, new_icid;
180
- bool ite_valid;
181
+ uint32_t devid, eventid;
182
+ uint16_t new_icid;
183
uint64_t num_eventids;
184
IteEntry ite = {};
185
DTEntry dte;
186
CTEntry old_cte, new_cte;
187
+ ITEntry old_ite;
188
189
devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
190
eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
191
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
192
return CMD_CONTINUE;
193
}
194
195
- ite_valid = get_ite(s, eventid, &dte, &old_icid, &intid, &res);
196
- if (res != MEMTX_OK) {
197
+ if (get_ite(s, eventid, &dte, &old_ite) != MEMTX_OK) {
198
return CMD_STALL;
199
}
200
201
- if (!ite_valid) {
202
+ if (!old_ite.valid || old_ite.inttype != ITE_INTTYPE_PHYSICAL) {
203
qemu_log_mask(LOG_GUEST_ERROR,
204
"%s: invalid command attributes: invalid ITE\n",
205
__func__);
206
return CMD_CONTINUE;
207
}
208
209
- if (old_icid >= s->ct.num_entries) {
210
+ if (old_ite.icid >= s->ct.num_entries) {
211
qemu_log_mask(LOG_GUEST_ERROR,
212
"%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
213
- __func__, old_icid);
214
+ __func__, old_ite.icid);
215
return CMD_CONTINUE;
216
}
217
218
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
219
return CMD_CONTINUE;
220
}
221
222
- if (get_cte(s, old_icid, &old_cte) != MEMTX_OK) {
223
+ if (get_cte(s, old_ite.icid, &old_cte) != MEMTX_OK) {
224
return CMD_STALL;
225
}
226
if (!old_cte.valid) {
227
qemu_log_mask(LOG_GUEST_ERROR,
228
"%s: invalid command attributes: "
229
"invalid CTE for old ICID 0x%x\n",
230
- __func__, old_icid);
231
+ __func__, old_ite.icid);
232
return CMD_CONTINUE;
233
}
234
235
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
236
/* Move the LPI from the old redistributor to the new one */
237
gicv3_redist_mov_lpi(&s->gicv3->cpu[old_cte.rdbase],
238
&s->gicv3->cpu[new_cte.rdbase],
239
- intid);
240
+ old_ite.intid);
241
}
242
243
/* Update the ICID field in the interrupt translation table entry */
244
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, 1);
245
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
246
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, intid);
247
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, old_ite.intid);
248
ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, new_icid);
249
ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
250
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
663
--
251
--
664
2.20.1
252
2.25.1
665
253
666
254
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
In 1dc8425e551, while converting to gvec, I added an extra range check
4
against the shift count. This was unnecessary because the encoding of
5
the shift count produces 0 to the element size - 1.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-5-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate.c | 12 ++----------
13
1 file changed, 2 insertions(+), 10 deletions(-)
14
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.c
18
+++ b/target/arm/translate.c
19
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
20
gen_gvec_sli(size, rd_ofs, rm_ofs, shift,
21
vec_size, vec_size);
22
} else { /* VSHL */
23
- /* Shifts larger than the element size are
24
- * architecturally valid and results in zero.
25
- */
26
- if (shift >= 8 << size) {
27
- tcg_gen_gvec_dup_imm(size, rd_ofs,
28
- vec_size, vec_size, 0);
29
- } else {
30
- tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
31
- vec_size, vec_size);
32
- }
33
+ tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
34
+ vec_size, vec_size);
35
}
36
return 0;
37
}
38
--
39
2.20.1
40
41
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Provide a functional interface for the vector expansion.
4
This fits better with the existing set of helpers that
5
we provide for other operations.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-8-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate.h | 7 +-
13
target/arm/translate-a64.c | 4 +-
14
target/arm/translate-neon.inc.c | 16 +----
15
target/arm/translate.c | 117 +++++++++++++++++---------------
16
4 files changed, 71 insertions(+), 73 deletions(-)
17
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate.h
21
+++ b/target/arm/translate.h
22
@@ -XXX,XX +XXX,XX @@ void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
23
void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
24
uint32_t opr_sz, uint32_t max_sz);
25
26
-extern const GVecGen3 mla_op[4];
27
-extern const GVecGen3 mls_op[4];
28
+void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
29
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
30
+void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
31
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
32
+
33
extern const GVecGen3 cmtst_op[4];
34
extern const GVecGen3 sshl_op[4];
35
extern const GVecGen3 ushl_op[4];
36
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-a64.c
39
+++ b/target/arm/translate-a64.c
40
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
41
return;
42
case 0x12: /* MLA, MLS */
43
if (u) {
44
- gen_gvec_op3(s, is_q, rd, rn, rm, &mls_op[size]);
45
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_mls, size);
46
} else {
47
- gen_gvec_op3(s, is_q, rd, rn, rm, &mla_op[size]);
48
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_mla, size);
49
}
50
return;
51
case 0x11:
52
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/translate-neon.inc.c
55
+++ b/target/arm/translate-neon.inc.c
56
@@ -XXX,XX +XXX,XX @@ DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax)
57
DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin)
58
DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin)
59
DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
60
+DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla)
61
+DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls)
62
63
#define DO_3SAME_CMP(INSN, COND) \
64
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
65
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
66
return do_3same(s, a, gen_VMUL_p_3s);
67
}
68
69
-#define DO_3SAME_GVEC3_NO_SZ_3(INSN, OPARRAY) \
70
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
71
- uint32_t rn_ofs, uint32_t rm_ofs, \
72
- uint32_t oprsz, uint32_t maxsz) \
73
- { \
74
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
75
- oprsz, maxsz, &OPARRAY[vece]); \
76
- } \
77
- DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s)
78
-
79
-
80
-DO_3SAME_GVEC3_NO_SZ_3(VMLA, mla_op)
81
-DO_3SAME_GVEC3_NO_SZ_3(VMLS, mls_op)
82
-
83
#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \
84
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
85
uint32_t rn_ofs, uint32_t rm_ofs, \
86
diff --git a/target/arm/translate.c b/target/arm/translate.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/translate.c
89
+++ b/target/arm/translate.c
90
@@ -XXX,XX +XXX,XX @@ static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
91
/* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
92
* these tables are shared with AArch64 which does support them.
93
*/
94
+void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
95
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
96
+{
97
+ static const TCGOpcode vecop_list[] = {
98
+ INDEX_op_mul_vec, INDEX_op_add_vec, 0
99
+ };
100
+ static const GVecGen3 ops[4] = {
101
+ { .fni4 = gen_mla8_i32,
102
+ .fniv = gen_mla_vec,
103
+ .load_dest = true,
104
+ .opt_opc = vecop_list,
105
+ .vece = MO_8 },
106
+ { .fni4 = gen_mla16_i32,
107
+ .fniv = gen_mla_vec,
108
+ .load_dest = true,
109
+ .opt_opc = vecop_list,
110
+ .vece = MO_16 },
111
+ { .fni4 = gen_mla32_i32,
112
+ .fniv = gen_mla_vec,
113
+ .load_dest = true,
114
+ .opt_opc = vecop_list,
115
+ .vece = MO_32 },
116
+ { .fni8 = gen_mla64_i64,
117
+ .fniv = gen_mla_vec,
118
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
119
+ .load_dest = true,
120
+ .opt_opc = vecop_list,
121
+ .vece = MO_64 },
122
+ };
123
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
124
+}
125
126
-static const TCGOpcode vecop_list_mla[] = {
127
- INDEX_op_mul_vec, INDEX_op_add_vec, 0
128
-};
129
-
130
-static const TCGOpcode vecop_list_mls[] = {
131
- INDEX_op_mul_vec, INDEX_op_sub_vec, 0
132
-};
133
-
134
-const GVecGen3 mla_op[4] = {
135
- { .fni4 = gen_mla8_i32,
136
- .fniv = gen_mla_vec,
137
- .load_dest = true,
138
- .opt_opc = vecop_list_mla,
139
- .vece = MO_8 },
140
- { .fni4 = gen_mla16_i32,
141
- .fniv = gen_mla_vec,
142
- .load_dest = true,
143
- .opt_opc = vecop_list_mla,
144
- .vece = MO_16 },
145
- { .fni4 = gen_mla32_i32,
146
- .fniv = gen_mla_vec,
147
- .load_dest = true,
148
- .opt_opc = vecop_list_mla,
149
- .vece = MO_32 },
150
- { .fni8 = gen_mla64_i64,
151
- .fniv = gen_mla_vec,
152
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
153
- .load_dest = true,
154
- .opt_opc = vecop_list_mla,
155
- .vece = MO_64 },
156
-};
157
-
158
-const GVecGen3 mls_op[4] = {
159
- { .fni4 = gen_mls8_i32,
160
- .fniv = gen_mls_vec,
161
- .load_dest = true,
162
- .opt_opc = vecop_list_mls,
163
- .vece = MO_8 },
164
- { .fni4 = gen_mls16_i32,
165
- .fniv = gen_mls_vec,
166
- .load_dest = true,
167
- .opt_opc = vecop_list_mls,
168
- .vece = MO_16 },
169
- { .fni4 = gen_mls32_i32,
170
- .fniv = gen_mls_vec,
171
- .load_dest = true,
172
- .opt_opc = vecop_list_mls,
173
- .vece = MO_32 },
174
- { .fni8 = gen_mls64_i64,
175
- .fniv = gen_mls_vec,
176
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
177
- .load_dest = true,
178
- .opt_opc = vecop_list_mls,
179
- .vece = MO_64 },
180
-};
181
+void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
182
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
183
+{
184
+ static const TCGOpcode vecop_list[] = {
185
+ INDEX_op_mul_vec, INDEX_op_sub_vec, 0
186
+ };
187
+ static const GVecGen3 ops[4] = {
188
+ { .fni4 = gen_mls8_i32,
189
+ .fniv = gen_mls_vec,
190
+ .load_dest = true,
191
+ .opt_opc = vecop_list,
192
+ .vece = MO_8 },
193
+ { .fni4 = gen_mls16_i32,
194
+ .fniv = gen_mls_vec,
195
+ .load_dest = true,
196
+ .opt_opc = vecop_list,
197
+ .vece = MO_16 },
198
+ { .fni4 = gen_mls32_i32,
199
+ .fniv = gen_mls_vec,
200
+ .load_dest = true,
201
+ .opt_opc = vecop_list,
202
+ .vece = MO_32 },
203
+ { .fni8 = gen_mls64_i64,
204
+ .fniv = gen_mls_vec,
205
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
206
+ .load_dest = true,
207
+ .opt_opc = vecop_list,
208
+ .vece = MO_64 },
209
+ };
210
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
211
+}
212
213
/* CMTST : test is "if (X & Y != 0)". */
214
static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
215
--
216
2.20.1
217
218
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Rather than perform the argument swap during code generation,
4
perform it during decode. This means it doesn't have to be
5
special cased later, and we can share code with aarch64 code
6
generation. Hopefully the decode comment addresses any confusion
7
that might arise in between.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200513163245.17915-9-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/neon-dp.decode | 17 +++++++++++++++--
15
target/arm/translate-neon.inc.c | 3 +--
16
2 files changed, 16 insertions(+), 4 deletions(-)
17
18
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/neon-dp.decode
21
+++ b/target/arm/neon-dp.decode
22
@@ -XXX,XX +XXX,XX @@ VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same
23
VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same
24
VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same
25
26
-VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same
27
-VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same
28
+# The _rev suffix indicates that Vn and Vm are reversed. This is
29
+# the case for shifts. In the Arm ARM these insns are documented
30
+# with the Vm and Vn fields in their usual places, but in the
31
+# assembly the operands are listed "backwards", ie in the order
32
+# Dd, Dm, Dn where other insns use Dd, Dn, Dm. For QEMU we choose
33
+# to consider Vm and Vn as being in different fields in the insn,
34
+# which allows us to avoid special-casing shifts in the trans_
35
+# function code. We would otherwise need to manually swap the operands
36
+# over to call Neon helper functions that are shared with AArch64,
37
+# which does not have this odd reversed-operand situation.
38
+@3same_rev .... ... . . . size:2 .... .... .... . q:1 . . .... \
39
+ &3same vn=%vm_dp vm=%vn_dp vd=%vd_dp
40
+
41
+VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same_rev
42
+VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
43
44
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
45
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-neon.inc.c
49
+++ b/target/arm/translate-neon.inc.c
50
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
51
uint32_t rn_ofs, uint32_t rm_ofs, \
52
uint32_t oprsz, uint32_t maxsz) \
53
{ \
54
- /* Note the operation is vshl vd,vm,vn */ \
55
- tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, \
56
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
57
oprsz, maxsz, &OPARRAY[vece]); \
58
} \
59
DO_3SAME(INSN, gen_##INSN##_3s)
60
--
61
2.20.1
62
63
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Provide a functional interface for the vector expansion.
4
This fits better with the existing set of helpers that
5
we provide for other operations.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-10-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate.h | 10 ++-
13
target/arm/translate-a64.c | 18 ++--
14
target/arm/translate-neon.inc.c | 23 +----
15
target/arm/translate.c | 146 +++++++++++++++++---------------
16
4 files changed, 95 insertions(+), 102 deletions(-)
17
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate.h
21
+++ b/target/arm/translate.h
22
@@ -XXX,XX +XXX,XX @@ void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
23
void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
24
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
25
26
-extern const GVecGen3 cmtst_op[4];
27
-extern const GVecGen3 sshl_op[4];
28
-extern const GVecGen3 ushl_op[4];
29
+void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
30
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
31
+void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
32
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
33
+void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
34
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
35
+
36
extern const GVecGen4 uqadd_op[4];
37
extern const GVecGen4 sqadd_op[4];
38
extern const GVecGen4 uqsub_op[4];
39
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate-a64.c
42
+++ b/target/arm/translate-a64.c
43
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
44
is_q ? 16 : 8, vec_full_reg_size(s));
45
}
46
47
-/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
48
-static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
49
- int rn, int rm, const GVecGen3 *gvec_op)
50
-{
51
- tcg_gen_gvec_3(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
52
- vec_full_reg_offset(s, rm), is_q ? 16 : 8,
53
- vec_full_reg_size(s), gvec_op);
54
-}
55
-
56
/* Expand a 3-operand operation using an out-of-line helper. */
57
static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
58
int rn, int rm, int data, gen_helper_gvec_3 *fn)
59
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
60
(u ? uqsub_op : sqsub_op) + size);
61
return;
62
case 0x08: /* SSHL, USHL */
63
- gen_gvec_op3(s, is_q, rd, rn, rm,
64
- u ? &ushl_op[size] : &sshl_op[size]);
65
+ if (u) {
66
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_ushl, size);
67
+ } else {
68
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sshl, size);
69
+ }
70
return;
71
case 0x0c: /* SMAX, UMAX */
72
if (u) {
73
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
74
return;
75
case 0x11:
76
if (!u) { /* CMTST */
77
- gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]);
78
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_cmtst, size);
79
return;
80
}
81
/* else CMEQ */
82
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/translate-neon.inc.c
85
+++ b/target/arm/translate-neon.inc.c
86
@@ -XXX,XX +XXX,XX @@ DO_3SAME(VBIC, tcg_gen_gvec_andc)
87
DO_3SAME(VORR, tcg_gen_gvec_or)
88
DO_3SAME(VORN, tcg_gen_gvec_orc)
89
DO_3SAME(VEOR, tcg_gen_gvec_xor)
90
+DO_3SAME(VSHL_S, gen_gvec_sshl)
91
+DO_3SAME(VSHL_U, gen_gvec_ushl)
92
93
/* These insns are all gvec_bitsel but with the inputs in various orders. */
94
#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \
95
@@ -XXX,XX +XXX,XX @@ DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin)
96
DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
97
DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla)
98
DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls)
99
+DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst)
100
101
#define DO_3SAME_CMP(INSN, COND) \
102
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
103
@@ -XXX,XX +XXX,XX @@ DO_3SAME_CMP(VCGE_S, TCG_COND_GE)
104
DO_3SAME_CMP(VCGE_U, TCG_COND_GEU)
105
DO_3SAME_CMP(VCEQ, TCG_COND_EQ)
106
107
-static void gen_VTST_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
108
- uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
109
-{
110
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &cmtst_op[vece]);
111
-}
112
-DO_3SAME_NO_SZ_3(VTST, gen_VTST_3s)
113
-
114
#define DO_3SAME_GVEC4(INSN, OPARRAY) \
115
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
116
uint32_t rn_ofs, uint32_t rm_ofs, \
117
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
118
}
119
return do_3same(s, a, gen_VMUL_p_3s);
120
}
121
-
122
-#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \
123
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
124
- uint32_t rn_ofs, uint32_t rm_ofs, \
125
- uint32_t oprsz, uint32_t maxsz) \
126
- { \
127
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
128
- oprsz, maxsz, &OPARRAY[vece]); \
129
- } \
130
- DO_3SAME(INSN, gen_##INSN##_3s)
131
-
132
-DO_3SAME_GVEC3_SHIFT(VSHL_S, sshl_op)
133
-DO_3SAME_GVEC3_SHIFT(VSHL_U, ushl_op)
134
diff --git a/target/arm/translate.c b/target/arm/translate.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/target/arm/translate.c
137
+++ b/target/arm/translate.c
138
@@ -XXX,XX +XXX,XX @@ static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
139
tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
140
}
141
142
-static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
143
-
144
-const GVecGen3 cmtst_op[4] = {
145
- { .fni4 = gen_helper_neon_tst_u8,
146
- .fniv = gen_cmtst_vec,
147
- .opt_opc = vecop_list_cmtst,
148
- .vece = MO_8 },
149
- { .fni4 = gen_helper_neon_tst_u16,
150
- .fniv = gen_cmtst_vec,
151
- .opt_opc = vecop_list_cmtst,
152
- .vece = MO_16 },
153
- { .fni4 = gen_cmtst_i32,
154
- .fniv = gen_cmtst_vec,
155
- .opt_opc = vecop_list_cmtst,
156
- .vece = MO_32 },
157
- { .fni8 = gen_cmtst_i64,
158
- .fniv = gen_cmtst_vec,
159
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
160
- .opt_opc = vecop_list_cmtst,
161
- .vece = MO_64 },
162
-};
163
+void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
164
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
165
+{
166
+ static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 };
167
+ static const GVecGen3 ops[4] = {
168
+ { .fni4 = gen_helper_neon_tst_u8,
169
+ .fniv = gen_cmtst_vec,
170
+ .opt_opc = vecop_list,
171
+ .vece = MO_8 },
172
+ { .fni4 = gen_helper_neon_tst_u16,
173
+ .fniv = gen_cmtst_vec,
174
+ .opt_opc = vecop_list,
175
+ .vece = MO_16 },
176
+ { .fni4 = gen_cmtst_i32,
177
+ .fniv = gen_cmtst_vec,
178
+ .opt_opc = vecop_list,
179
+ .vece = MO_32 },
180
+ { .fni8 = gen_cmtst_i64,
181
+ .fniv = gen_cmtst_vec,
182
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
183
+ .opt_opc = vecop_list,
184
+ .vece = MO_64 },
185
+ };
186
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
187
+}
188
189
void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
190
{
191
@@ -XXX,XX +XXX,XX @@ static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
192
tcg_temp_free_vec(rsh);
193
}
194
195
-static const TCGOpcode ushl_list[] = {
196
- INDEX_op_neg_vec, INDEX_op_shlv_vec,
197
- INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
198
-};
199
-
200
-const GVecGen3 ushl_op[4] = {
201
- { .fniv = gen_ushl_vec,
202
- .fno = gen_helper_gvec_ushl_b,
203
- .opt_opc = ushl_list,
204
- .vece = MO_8 },
205
- { .fniv = gen_ushl_vec,
206
- .fno = gen_helper_gvec_ushl_h,
207
- .opt_opc = ushl_list,
208
- .vece = MO_16 },
209
- { .fni4 = gen_ushl_i32,
210
- .fniv = gen_ushl_vec,
211
- .opt_opc = ushl_list,
212
- .vece = MO_32 },
213
- { .fni8 = gen_ushl_i64,
214
- .fniv = gen_ushl_vec,
215
- .opt_opc = ushl_list,
216
- .vece = MO_64 },
217
-};
218
+void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
219
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
220
+{
221
+ static const TCGOpcode vecop_list[] = {
222
+ INDEX_op_neg_vec, INDEX_op_shlv_vec,
223
+ INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
224
+ };
225
+ static const GVecGen3 ops[4] = {
226
+ { .fniv = gen_ushl_vec,
227
+ .fno = gen_helper_gvec_ushl_b,
228
+ .opt_opc = vecop_list,
229
+ .vece = MO_8 },
230
+ { .fniv = gen_ushl_vec,
231
+ .fno = gen_helper_gvec_ushl_h,
232
+ .opt_opc = vecop_list,
233
+ .vece = MO_16 },
234
+ { .fni4 = gen_ushl_i32,
235
+ .fniv = gen_ushl_vec,
236
+ .opt_opc = vecop_list,
237
+ .vece = MO_32 },
238
+ { .fni8 = gen_ushl_i64,
239
+ .fniv = gen_ushl_vec,
240
+ .opt_opc = vecop_list,
241
+ .vece = MO_64 },
242
+ };
243
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
244
+}
245
246
void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
247
{
248
@@ -XXX,XX +XXX,XX @@ static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
249
tcg_temp_free_vec(tmp);
250
}
251
252
-static const TCGOpcode sshl_list[] = {
253
- INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
254
- INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
255
-};
256
-
257
-const GVecGen3 sshl_op[4] = {
258
- { .fniv = gen_sshl_vec,
259
- .fno = gen_helper_gvec_sshl_b,
260
- .opt_opc = sshl_list,
261
- .vece = MO_8 },
262
- { .fniv = gen_sshl_vec,
263
- .fno = gen_helper_gvec_sshl_h,
264
- .opt_opc = sshl_list,
265
- .vece = MO_16 },
266
- { .fni4 = gen_sshl_i32,
267
- .fniv = gen_sshl_vec,
268
- .opt_opc = sshl_list,
269
- .vece = MO_32 },
270
- { .fni8 = gen_sshl_i64,
271
- .fniv = gen_sshl_vec,
272
- .opt_opc = sshl_list,
273
- .vece = MO_64 },
274
-};
275
+void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
276
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
277
+{
278
+ static const TCGOpcode vecop_list[] = {
279
+ INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
280
+ INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
281
+ };
282
+ static const GVecGen3 ops[4] = {
283
+ { .fniv = gen_sshl_vec,
284
+ .fno = gen_helper_gvec_sshl_b,
285
+ .opt_opc = vecop_list,
286
+ .vece = MO_8 },
287
+ { .fniv = gen_sshl_vec,
288
+ .fno = gen_helper_gvec_sshl_h,
289
+ .opt_opc = vecop_list,
290
+ .vece = MO_16 },
291
+ { .fni4 = gen_sshl_i32,
292
+ .fniv = gen_sshl_vec,
293
+ .opt_opc = vecop_list,
294
+ .vece = MO_32 },
295
+ { .fni8 = gen_sshl_i64,
296
+ .fniv = gen_sshl_vec,
297
+ .opt_opc = vecop_list,
298
+ .vece = MO_64 },
299
+ };
300
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
301
+}
302
303
static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
304
TCGv_vec a, TCGv_vec b)
305
--
306
2.20.1
307
308
diff view generated by jsdifflib
Deleted patch
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
1
3
Add APEI/GHES detailed design document
4
5
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
6
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
7
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
8
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
9
Message-id: 20200512030609.19593-4-gengdongjiu@huawei.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/specs/acpi_hest_ghes.rst | 110 ++++++++++++++++++++++++++++++++++
13
docs/specs/index.rst | 1 +
14
2 files changed, 111 insertions(+)
15
create mode 100644 docs/specs/acpi_hest_ghes.rst
16
17
diff --git a/docs/specs/acpi_hest_ghes.rst b/docs/specs/acpi_hest_ghes.rst
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/docs/specs/acpi_hest_ghes.rst
22
@@ -XXX,XX +XXX,XX @@
23
+APEI tables generating and CPER record
24
+======================================
25
+
26
+..
27
+ Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
28
+
29
+ This work is licensed under the terms of the GNU GPL, version 2 or later.
30
+ See the COPYING file in the top-level directory.
31
+
32
+Design Details
33
+--------------
34
+
35
+::
36
+
37
+ etc/acpi/tables etc/hardware_errors
38
+ ==================== ===============================
39
+ + +--------------------------+ +----------------------------+
40
+ | | HEST | +--------->| error_block_address1 |------+
41
+ | +--------------------------+ | +----------------------------+ |
42
+ | | GHES1 | | +------->| error_block_address2 |------+-+
43
+ | +--------------------------+ | | +----------------------------+ | |
44
+ | | ................. | | | | .............. | | |
45
+ | | error_status_address-----+-+ | -----------------------------+ | |
46
+ | | ................. | | +--->| error_block_addressN |------+-+---+
47
+ | | read_ack_register--------+-+ | | +----------------------------+ | | |
48
+ | | read_ack_preserve | +-+---+--->| read_ack_register1 | | | |
49
+ | | read_ack_write | | | +----------------------------+ | | |
50
+ + +--------------------------+ | +-+--->| read_ack_register2 | | | |
51
+ | | GHES2 | | | | +----------------------------+ | | |
52
+ + +--------------------------+ | | | | ............. | | | |
53
+ | | ................. | | | | +----------------------------+ | | |
54
+ | | error_status_address-----+---+ | | +->| read_ack_registerN | | | |
55
+ | | ................. | | | | +----------------------------+ | | |
56
+ | | read_ack_register--------+-----+ | | |Generic Error Status Block 1|<-----+ | |
57
+ | | read_ack_preserve | | | |-+------------------------+-+ | |
58
+ | | read_ack_write | | | | | CPER | | | |
59
+ + +--------------------------| | | | | CPER | | | |
60
+ | | ............... | | | | | .... | | | |
61
+ + +--------------------------+ | | | | CPER | | | |
62
+ | | GHESN | | | |-+------------------------+-| | |
63
+ + +--------------------------+ | | |Generic Error Status Block 2|<-------+ |
64
+ | | ................. | | | |-+------------------------+-+ |
65
+ | | error_status_address-----+-------+ | | | CPER | | |
66
+ | | ................. | | | | CPER | | |
67
+ | | read_ack_register--------+---------+ | | .... | | |
68
+ | | read_ack_preserve | | | CPER | | |
69
+ | | read_ack_write | +-+------------------------+-+ |
70
+ + +--------------------------+ | .......... | |
71
+ |----------------------------+ |
72
+ |Generic Error Status Block N |<----------+
73
+ |-+-------------------------+-+
74
+ | | CPER | |
75
+ | | CPER | |
76
+ | | .... | |
77
+ | | CPER | |
78
+ +-+-------------------------+-+
79
+
80
+
81
+(1) QEMU generates the ACPI HEST table. This table goes in the current
82
+ "etc/acpi/tables" fw_cfg blob. Each error source has different
83
+ notification types.
84
+
85
+(2) A new fw_cfg blob called "etc/hardware_errors" is introduced. QEMU
86
+ also needs to populate this blob. The "etc/hardware_errors" fw_cfg blob
87
+ contains an address registers table and an Error Status Data Block table.
88
+
89
+(3) The address registers table contains N Error Block Address entries
90
+ and N Read Ack Register entries. The size for each entry is 8-byte.
91
+ The Error Status Data Block table contains N Error Status Data Block
92
+ entries. The size for each entry is 4096(0x1000) bytes. The total size
93
+ for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
94
+ N is the number of the kinds of hardware error sources.
95
+
96
+(4) QEMU generates the ACPI linker/loader script for the firmware. The
97
+ firmware pre-allocates memory for "etc/acpi/tables", "etc/hardware_errors"
98
+ and copies blob contents there.
99
+
100
+(5) QEMU generates N ADD_POINTER commands, which patch addresses in the
101
+ "error_status_address" fields of the HEST table with a pointer to the
102
+ corresponding "address registers" in the "etc/hardware_errors" blob.
103
+
104
+(6) QEMU generates N ADD_POINTER commands, which patch addresses in the
105
+ "read_ack_register" fields of the HEST table with a pointer to the
106
+ corresponding "read_ack_register" within the "etc/hardware_errors" blob.
107
+
108
+(7) QEMU generates N ADD_POINTER commands for the firmware, which patch
109
+ addresses in the "error_block_address" fields with a pointer to the
110
+ respective "Error Status Data Block" in the "etc/hardware_errors" blob.
111
+
112
+(8) QEMU defines a third and write-only fw_cfg blob which is called
113
+ "etc/hardware_errors_addr". Through that blob, the firmware can send back
114
+ the guest-side allocation addresses to QEMU. The "etc/hardware_errors_addr"
115
+ blob contains a 8-byte entry. QEMU generates a single WRITE_POINTER command
116
+ for the firmware. The firmware will write back the start address of
117
+ "etc/hardware_errors" blob to the fw_cfg file "etc/hardware_errors_addr".
118
+
119
+(9) When QEMU gets a SIGBUS from the kernel, QEMU writes CPER into corresponding
120
+ "Error Status Data Block", guest memory, and then injects platform specific
121
+ interrupt (in case of arm/virt machine it's Synchronous External Abort) as a
122
+ notification which is necessary for notifying the guest.
123
+
124
+(10) This notification (in virtual hardware) will be handled by the guest
125
+ kernel, on receiving notification, guest APEI driver could read the CPER error
126
+ and take appropriate action.
127
+
128
+(11) kvm_arch_on_sigbus_vcpu() uses source_id as index in "etc/hardware_errors" to
129
+ find out "Error Status Data Block" entry corresponding to error source. So supported
130
+ source_id values should be assigned here and not be changed afterwards to make sure
131
+ that guest will write error into expected "Error Status Data Block" even if guest was
132
+ migrated to a newer QEMU.
133
diff --git a/docs/specs/index.rst b/docs/specs/index.rst
134
index XXXXXXX..XXXXXXX 100644
135
--- a/docs/specs/index.rst
136
+++ b/docs/specs/index.rst
137
@@ -XXX,XX +XXX,XX @@ Contents:
138
ppc-spapr-xive
139
acpi_hw_reduced_hotplug
140
tpm
141
+ acpi_hest_ghes
142
--
143
2.20.1
144
145
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
Make the update_ite() struct use the new ITEntry struct, so that
2
callers don't need to assemble the in-memory ITE data themselves, and
3
only get_ite() and update_ite() need to care about that in-memory
4
layout. We can then drop the no-longer-used IteEntry struct
5
definition.
2
6
3
kvm_hwpoison_page_add() and kvm_unpoison_all() will both
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
be used by X86 and ARM platforms, so moving them into
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
"accel/kvm/kvm-all.c" to avoid duplicate code.
9
Message-id: 20220201193207.2771604-10-peter.maydell@linaro.org
10
---
11
hw/intc/arm_gicv3_its.c | 62 +++++++++++++++++++++--------------------
12
1 file changed, 32 insertions(+), 30 deletions(-)
6
13
7
For architectures that don't use the poison-list functionality
14
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
8
the reset handler will harmlessly do nothing, so let's register
9
the kvm_unpoison_all() function in the generic kvm_init() function.
10
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
13
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
14
Acked-by: Xiang Zheng <zhengxiang9@huawei.com>
15
Message-id: 20200512030609.19593-8-gengdongjiu@huawei.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/sysemu/kvm_int.h | 12 ++++++++++++
19
accel/kvm/kvm-all.c | 36 ++++++++++++++++++++++++++++++++++++
20
target/i386/kvm.c | 36 ------------------------------------
21
3 files changed, 48 insertions(+), 36 deletions(-)
22
23
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
24
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
25
--- a/include/sysemu/kvm_int.h
16
--- a/hw/intc/arm_gicv3_its.c
26
+++ b/include/sysemu/kvm_int.h
17
+++ b/hw/intc/arm_gicv3_its.c
27
@@ -XXX,XX +XXX,XX @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
18
@@ -XXX,XX +XXX,XX @@ typedef enum ItsCmdType {
28
AddressSpace *as, int as_id);
19
INTERRUPT = 3,
29
20
} ItsCmdType;
30
void kvm_set_max_memslot_size(hwaddr max_slot_size);
21
22
-typedef struct {
23
- uint32_t iteh;
24
- uint64_t itel;
25
-} IteEntry;
26
-
27
typedef struct DTEntry {
28
bool valid;
29
unsigned size;
30
@@ -XXX,XX +XXX,XX @@ static MemTxResult get_cte(GICv3ITSState *s, uint16_t icid, CTEntry *cte)
31
return MEMTX_OK;
32
}
33
34
+/*
35
+ * Update the Interrupt Table entry at index @evinted in the table specified
36
+ * by the dte @dte. Returns true on success, false if there was a memory
37
+ * access error.
38
+ */
39
static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
40
- IteEntry ite)
41
+ const ITEntry *ite)
42
{
43
AddressSpace *as = &s->gicv3->dma_as;
44
MemTxResult res = MEMTX_OK;
45
hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
46
+ uint64_t itel = 0;
47
+ uint32_t iteh = 0;
48
49
- address_space_stq_le(as, iteaddr, ite.itel, MEMTXATTRS_UNSPECIFIED, &res);
50
-
51
- if (res == MEMTX_OK) {
52
- address_space_stl_le(as, iteaddr + 8, ite.iteh,
53
- MEMTXATTRS_UNSPECIFIED, &res);
54
+ if (ite->valid) {
55
+ itel = FIELD_DP64(itel, ITE_L, VALID, 1);
56
+ itel = FIELD_DP64(itel, ITE_L, INTTYPE, ite->inttype);
57
+ itel = FIELD_DP64(itel, ITE_L, INTID, ite->intid);
58
+ itel = FIELD_DP64(itel, ITE_L, ICID, ite->icid);
59
+ itel = FIELD_DP64(itel, ITE_L, VPEID, ite->vpeid);
60
+ iteh = FIELD_DP32(iteh, ITE_H, DOORBELL, ite->doorbell);
61
}
31
+
62
+
32
+/**
63
+ address_space_stq_le(as, iteaddr, itel, MEMTXATTRS_UNSPECIFIED, &res);
33
+ * kvm_hwpoison_page_add:
64
if (res != MEMTX_OK) {
34
+ *
65
return false;
35
+ * Parameters:
66
- } else {
36
+ * @ram_addr: the address in the RAM for the poisoned page
67
- return true;
37
+ *
68
}
38
+ * Add a poisoned page to the list
69
+ address_space_stl_le(as, iteaddr + 8, iteh, MEMTXATTRS_UNSPECIFIED, &res);
39
+ *
70
+ return res == MEMTX_OK;
40
+ * Return: None.
41
+ */
42
+void kvm_hwpoison_page_add(ram_addr_t ram_addr);
43
#endif
44
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/accel/kvm/kvm-all.c
47
+++ b/accel/kvm/kvm-all.c
48
@@ -XXX,XX +XXX,XX @@
49
#include "qapi/visitor.h"
50
#include "qapi/qapi-types-common.h"
51
#include "qapi/qapi-visit-common.h"
52
+#include "sysemu/reset.h"
53
54
#include "hw/boards.h"
55
56
@@ -XXX,XX +XXX,XX @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension)
57
return ret;
58
}
71
}
59
72
60
+typedef struct HWPoisonPage {
73
/*
61
+ ram_addr_t ram_addr;
74
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
62
+ QLIST_ENTRY(HWPoisonPage) list;
63
+} HWPoisonPage;
64
+
65
+static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
66
+ QLIST_HEAD_INITIALIZER(hwpoison_page_list);
67
+
68
+static void kvm_unpoison_all(void *param)
69
+{
70
+ HWPoisonPage *page, *next_page;
71
+
72
+ QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
73
+ QLIST_REMOVE(page, list);
74
+ qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
75
+ g_free(page);
76
+ }
77
+}
78
+
79
+void kvm_hwpoison_page_add(ram_addr_t ram_addr)
80
+{
81
+ HWPoisonPage *page;
82
+
83
+ QLIST_FOREACH(page, &hwpoison_page_list, list) {
84
+ if (page->ram_addr == ram_addr) {
85
+ return;
86
+ }
87
+ }
88
+ page = g_new(HWPoisonPage, 1);
89
+ page->ram_addr = ram_addr;
90
+ QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
91
+}
92
+
93
static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
94
{
95
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
96
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
97
s->kernel_irqchip_split = mc->default_kernel_irqchip_split ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
98
}
75
}
99
76
100
+ qemu_register_reset(kvm_unpoison_all, NULL);
77
if (cmd == DISCARD) {
101
+
78
- IteEntry itee = {};
102
if (s->kernel_irqchip_allowed) {
79
+ ITEntry ite = {};
103
kvm_irqchip_create(s);
80
/* remove mapping from interrupt translation table */
81
- return update_ite(s, eventid, &dte, itee) ? CMD_CONTINUE : CMD_STALL;
82
+ ite.valid = false;
83
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
104
}
84
}
105
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
85
return CMD_CONTINUE;
106
index XXXXXXX..XXXXXXX 100644
86
}
107
--- a/target/i386/kvm.c
87
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
108
+++ b/target/i386/kvm.c
88
uint64_t num_eventids;
109
@@ -XXX,XX +XXX,XX @@
89
uint32_t num_intids;
110
#include "sysemu/sysemu.h"
90
uint16_t icid = 0;
111
#include "sysemu/hw_accel.h"
91
- IteEntry ite = {};
112
#include "sysemu/kvm_int.h"
92
DTEntry dte;
113
-#include "sysemu/reset.h"
93
+ ITEntry ite;
114
#include "sysemu/runstate.h"
94
115
#include "kvm_i386.h"
95
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
116
#include "hyperv.h"
96
eventid = cmdpkt[1] & EVENTID_MASK;
117
@@ -XXX,XX +XXX,XX @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index)
97
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
118
}
98
}
99
100
/* add ite entry to interrupt translation table */
101
- ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, true);
102
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
103
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
104
- ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, icid);
105
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
106
-
107
- return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
108
+ ite.valid = true;
109
+ ite.inttype = ITE_INTTYPE_PHYSICAL;
110
+ ite.intid = pIntid;
111
+ ite.icid = icid;
112
+ ite.doorbell = INTID_SPURIOUS;
113
+ ite.vpeid = 0;
114
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
119
}
115
}
120
116
121
-
117
/*
122
-typedef struct HWPoisonPage {
118
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
123
- ram_addr_t ram_addr;
119
uint32_t devid, eventid;
124
- QLIST_ENTRY(HWPoisonPage) list;
120
uint16_t new_icid;
125
-} HWPoisonPage;
121
uint64_t num_eventids;
126
-
122
- IteEntry ite = {};
127
-static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
123
DTEntry dte;
128
- QLIST_HEAD_INITIALIZER(hwpoison_page_list);
124
CTEntry old_cte, new_cte;
129
-
125
ITEntry old_ite;
130
-static void kvm_unpoison_all(void *param)
126
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
131
-{
132
- HWPoisonPage *page, *next_page;
133
-
134
- QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
135
- QLIST_REMOVE(page, list);
136
- qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
137
- g_free(page);
138
- }
139
-}
140
-
141
-static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
142
-{
143
- HWPoisonPage *page;
144
-
145
- QLIST_FOREACH(page, &hwpoison_page_list, list) {
146
- if (page->ram_addr == ram_addr) {
147
- return;
148
- }
149
- }
150
- page = g_new(HWPoisonPage, 1);
151
- page->ram_addr = ram_addr;
152
- QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
153
-}
154
-
155
static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
156
int *max_banks)
157
{
158
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init(MachineState *ms, KVMState *s)
159
fprintf(stderr, "e820_add_entry() table is full\n");
160
return ret;
161
}
127
}
162
- qemu_register_reset(kvm_unpoison_all, NULL);
128
163
129
/* Update the ICID field in the interrupt translation table entry */
164
shadow_mem = object_property_get_int(OBJECT(s), "kvm-shadow-mem", &error_abort);
130
- ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, 1);
165
if (shadow_mem != -1) {
131
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
132
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, old_ite.intid);
133
- ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, new_icid);
134
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
135
- return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
136
+ old_ite.icid = new_icid;
137
+ return update_ite(s, eventid, &dte, &old_ite) ? CMD_CONTINUE : CMD_STALL;
138
}
139
140
/*
166
--
141
--
167
2.20.1
142
2.25.1
168
143
169
144
diff view generated by jsdifflib
1
Convert the 64-bit element insns in the 3-reg-same group
1
Currently we track in the TableDesc and CmdQDesc structs the state of
2
to decodetree. This covers VQSHL, VRSHL and VQRSHL where
2
the GITS_BASER<n> and GITS_CBASER Valid bits. However we aren't very
3
size==0b11.
3
consistent abut checking the valid field: we test it in update_cte()
4
and update_dte(), but not anywhere else we look things up in tables.
5
6
The GIC specification says that it is UNPREDICTABLE if a guest fails
7
to set any of these Valid bits before enabling the ITS via
8
GITS_CTLR.Enabled. So we can choose to handle Valid == 0 as
9
equivalent to a zero-length table. This is in fact how we're already
10
catching this case in most of the table-access paths: when Valid is 0
11
we leave the num_entries fields in TableDesc or CmdQDesc set to zero,
12
and then the out-of-bounds check "index >= num_entries" that we have
13
to do anyway before doing any of these table lookups will always be
14
true, catching the no-valid-table case without any extra code.
15
16
So we can remove the checks on the valid field from update_cte()
17
and update_dte(): since these happen after the bounds check there
18
was never any case when the test could fail. That means the valid
19
fields would be entirely unused, so just remove them.
4
20
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-4-peter.maydell@linaro.org
23
Message-id: 20220201193207.2771604-11-peter.maydell@linaro.org
8
---
24
---
9
target/arm/neon-dp.decode | 13 +++++++++++
25
include/hw/intc/arm_gicv3_its_common.h | 2 --
10
target/arm/translate-neon.inc.c | 24 +++++++++++++++++++++
26
hw/intc/arm_gicv3_its.c | 31 ++++++++++++--------------
11
target/arm/translate.c | 38 ++-------------------------------
27
2 files changed, 14 insertions(+), 19 deletions(-)
12
3 files changed, 39 insertions(+), 36 deletions(-)
13
28
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
29
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
15
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
31
--- a/include/hw/intc/arm_gicv3_its_common.h
17
+++ b/target/arm/neon-dp.decode
32
+++ b/include/hw/intc/arm_gicv3_its_common.h
18
@@ -XXX,XX +XXX,XX @@ VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same
33
@@ -XXX,XX +XXX,XX @@
19
VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same_rev
34
#define GITS_TRANSLATER 0x0040
20
VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
35
21
36
typedef struct {
22
+# Insns operating on 64-bit elements (size!=0b11 handled elsewhere)
37
- bool valid;
23
+# The _rev suffix indicates that Vn and Vm are reversed (as explained
38
bool indirect;
24
+# by the comment for the @3same_rev format).
39
uint16_t entry_sz;
25
+@3same_64_rev .... ... . . . 11 .... .... .... . q:1 . . .... \
40
uint32_t page_sz;
26
+ &3same vm=%vn_dp vn=%vm_dp vd=%vd_dp size=3
41
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
+
42
} TableDesc;
28
+VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
43
29
+VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
44
typedef struct {
30
+VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
45
- bool valid;
31
+VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
46
uint32_t num_entries;
32
+VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
47
uint64_t base_addr;
33
+VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
48
} CmdQDesc;
34
+
49
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
35
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
36
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
37
VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
38
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
39
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/translate-neon.inc.c
51
--- a/hw/intc/arm_gicv3_its.c
41
+++ b/target/arm/translate-neon.inc.c
52
+++ b/hw/intc/arm_gicv3_its.c
42
@@ -XXX,XX +XXX,XX @@ static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a)
53
@@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
43
54
uint64_t cteval = 0;
44
return true;
55
MemTxResult res = MEMTX_OK;
45
}
56
46
+
57
- if (!s->ct.valid) {
47
+#define DO_3SAME_64(INSN, FUNC) \
58
- return true;
48
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
59
- }
49
+ uint32_t rn_ofs, uint32_t rm_ofs, \
60
-
50
+ uint32_t oprsz, uint32_t maxsz) \
61
if (cte->valid) {
51
+ { \
62
/* add mapping entry to collection table */
52
+ static const GVecGen3 op = { .fni8 = FUNC }; \
63
cteval = FIELD_DP64(cteval, CTE, VALID, 1);
53
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &op); \
64
@@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
54
+ } \
65
uint64_t dteval = 0;
55
+ DO_3SAME(INSN, gen_##INSN##_3s)
66
MemTxResult res = MEMTX_OK;
56
+
67
57
+#define DO_3SAME_64_ENV(INSN, FUNC) \
68
- if (s->dt.valid) {
58
+ static void gen_##INSN##_elt(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m) \
69
- if (dte->valid) {
59
+ { \
70
- /* add mapping entry to device table */
60
+ FUNC(d, cpu_env, n, m); \
71
- dteval = FIELD_DP64(dteval, DTE, VALID, 1);
61
+ } \
72
- dteval = FIELD_DP64(dteval, DTE, SIZE, dte->size);
62
+ DO_3SAME_64(INSN, gen_##INSN##_elt)
73
- dteval = FIELD_DP64(dteval, DTE, ITTADDR, dte->ittaddr);
63
+
74
- }
64
+DO_3SAME_64(VRSHL_S64, gen_helper_neon_rshl_s64)
75
- } else {
65
+DO_3SAME_64(VRSHL_U64, gen_helper_neon_rshl_u64)
76
- return true;
66
+DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64)
77
+ if (dte->valid) {
67
+DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64)
78
+ /* add mapping entry to device table */
68
+DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64)
79
+ dteval = FIELD_DP64(dteval, DTE, VALID, 1);
69
+DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
80
+ dteval = FIELD_DP64(dteval, DTE, SIZE, dte->size);
70
diff --git a/target/arm/translate.c b/target/arm/translate.c
81
+ dteval = FIELD_DP64(dteval, DTE, ITTADDR, dte->ittaddr);
71
index XXXXXXX..XXXXXXX 100644
82
}
72
--- a/target/arm/translate.c
83
73
+++ b/target/arm/translate.c
84
entry_addr = table_entry_addr(s, &s->dt, devid, &res);
74
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
85
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
75
}
86
}
76
87
77
if (size == 3) {
88
memset(td, 0, sizeof(*td));
78
- /* 64-bit element instructions. */
89
- td->valid = FIELD_EX64(value, GITS_BASER, VALID);
79
- for (pass = 0; pass < (q ? 2 : 1); pass++) {
90
/*
80
- neon_load_reg64(cpu_V0, rn + pass);
91
* If GITS_BASER<n>.Valid is 0 for any <n> then we will not process
81
- neon_load_reg64(cpu_V1, rm + pass);
92
* interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we
82
- switch (op) {
93
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
83
- case NEON_3R_VQSHL:
94
* for the register corresponding to the Collection table but we
84
- if (u) {
95
* still have to process interrupts using non-memory-backed
85
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
96
* Collection table entries.)
86
- cpu_V1, cpu_V0);
97
+ * The specification makes it UNPREDICTABLE to enable the ITS without
87
- } else {
98
+ * marking each BASER<n> as valid. We choose to handle these as if
88
- gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
99
+ * the table was zero-sized, so commands using the table will fail
89
- cpu_V1, cpu_V0);
100
+ * and interrupts requested via GITS_TRANSLATER writes will be ignored.
90
- }
101
+ * This happens automatically by leaving the num_entries field at
91
- break;
102
+ * zero, which will be caught by the bounds checks we have before
92
- case NEON_3R_VRSHL:
103
+ * every table lookup anyway.
93
- if (u) {
104
*/
94
- gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
105
- if (!td->valid) {
95
- } else {
106
+ if (!FIELD_EX64(value, GITS_BASER, VALID)) {
96
- gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
107
continue;
97
- }
98
- break;
99
- case NEON_3R_VQRSHL:
100
- if (u) {
101
- gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
102
- cpu_V1, cpu_V0);
103
- } else {
104
- gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
105
- cpu_V1, cpu_V0);
106
- }
107
- break;
108
- default:
109
- abort();
110
- }
111
- neon_store_reg64(cpu_V0, rd + pass);
112
- }
113
- return 0;
114
+ /* 64-bit element instructions: handled by decodetree */
115
+ return 1;
116
}
108
}
117
pairwise = 0;
109
td->page_sz = page_sz;
118
switch (op) {
110
@@ -XXX,XX +XXX,XX @@ static void extract_cmdq_params(GICv3ITSState *s)
111
num_pages = FIELD_EX64(value, GITS_CBASER, SIZE) + 1;
112
113
memset(&s->cq, 0 , sizeof(s->cq));
114
- s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
115
116
- if (s->cq.valid) {
117
+ if (FIELD_EX64(value, GITS_CBASER, VALID)) {
118
s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) /
119
GITS_CMDQ_ENTRY_SIZE;
120
s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
119
--
121
--
120
2.20.1
122
2.25.1
121
123
122
124
diff view generated by jsdifflib
1
Convert the Neon integer 3-reg-same compare insns VCGE, VCGT,
1
In the MAPC command, if V=0 this is a request to delete a collection
2
VCEQ, VACGE and VACGT to decodetree.
2
table entry and the rdbase field of the command packet will not be
3
used. In particular, the specification says that the "UNPREDICTABLE
4
if rdbase is not valid" only applies for V=1.
5
6
We were doing a check-and-log-guest-error on rdbase regardless of
7
whether the V bit was set, and also (harmlessly but confusingly)
8
storing the contents of the rdbase field into the updated collection
9
table entry. Update the code so that if V=0 we don't check or use
10
the rdbase field value.
3
11
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200512163904.10918-15-peter.maydell@linaro.org
14
Message-id: 20220201193207.2771604-12-peter.maydell@linaro.org
7
---
15
---
8
target/arm/neon-dp.decode | 5 +++++
16
hw/intc/arm_gicv3_its.c | 24 ++++++++++++------------
9
target/arm/translate-neon.inc.c | 6 +++++
17
1 file changed, 12 insertions(+), 12 deletions(-)
10
target/arm/translate.c | 39 ++-------------------------------
11
3 files changed, 13 insertions(+), 37 deletions(-)
12
18
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
19
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
21
--- a/hw/intc/arm_gicv3_its.c
16
+++ b/target/arm/neon-dp.decode
22
+++ b/hw/intc/arm_gicv3_its.c
17
@@ -XXX,XX +XXX,XX @@ VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
23
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
18
VMLA_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
24
CTEntry cte;
19
VMLS_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 1 .... @3same_fp
25
20
VMUL_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
26
icid = cmdpkt[2] & ICID_MASK;
21
+VCEQ_fp_3s 1111 001 0 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
27
-
22
+VCGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
28
- cte.rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
23
+VACGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 1 .... @3same_fp
29
- cte.rdbase &= RDBASE_PROCNUM_MASK;
24
+VCGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 0 .... @3same_fp
30
-
25
+VACGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 1 .... @3same_fp
31
cte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
26
VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
32
+ if (cte.valid) {
27
VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
33
+ cte.rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
34
+ cte.rdbase &= RDBASE_PROCNUM_MASK;
29
index XXXXXXX..XXXXXXX 100644
35
+ } else {
30
--- a/target/arm/translate-neon.inc.c
36
+ cte.rdbase = 0;
31
+++ b/target/arm/translate-neon.inc.c
37
+ }
32
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s)
38
33
return do_3same_fp(s, a, FUNC, READS_VD); \
39
- if ((icid >= s->ct.num_entries) || (cte.rdbase >= s->gicv3->num_cpu)) {
40
+ if (icid >= s->ct.num_entries) {
41
+ qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPC: invalid ICID 0x%d", icid);
42
+ return CMD_CONTINUE;
43
+ }
44
+ if (cte.valid && cte.rdbase >= s->gicv3->num_cpu) {
45
qemu_log_mask(LOG_GUEST_ERROR,
46
- "ITS MAPC: invalid collection table attributes "
47
- "icid %d rdbase %u\n", icid, cte.rdbase);
48
- /*
49
- * in this implementation, in case of error
50
- * we ignore this command and move onto the next
51
- * command in the queue
52
- */
53
+ "ITS MAPC: invalid RDBASE %u ", cte.rdbase);
54
return CMD_CONTINUE;
34
}
55
}
35
56
36
+DO_3S_FP(VCEQ, gen_helper_neon_ceq_f32, false)
37
+DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false)
38
+DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false)
39
+DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
40
+DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
41
+
42
static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
43
TCGv_ptr fpstatus)
44
{
45
diff --git a/target/arm/translate.c b/target/arm/translate.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate.c
48
+++ b/target/arm/translate.c
49
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
50
case NEON_3R_VQDMULH_VQRDMULH:
51
case NEON_3R_FLOAT_ARITH:
52
case NEON_3R_FLOAT_MULTIPLY:
53
+ case NEON_3R_FLOAT_CMP:
54
+ case NEON_3R_FLOAT_ACMP:
55
/* Already handled by decodetree */
56
return 1;
57
}
58
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
59
return 1; /* VPMIN/VPMAX handled by decodetree */
60
}
61
break;
62
- case NEON_3R_FLOAT_CMP:
63
- if (!u && size) {
64
- /* no encoding for U=0 C=1x */
65
- return 1;
66
- }
67
- break;
68
- case NEON_3R_FLOAT_ACMP:
69
- if (!u) {
70
- return 1;
71
- }
72
- break;
73
case NEON_3R_FLOAT_MISC:
74
/* VMAXNM/VMINNM in ARMv8 */
75
if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
76
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
77
tmp = neon_load_reg(rn, pass);
78
tmp2 = neon_load_reg(rm, pass);
79
switch (op) {
80
- case NEON_3R_FLOAT_CMP:
81
- {
82
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
83
- if (!u) {
84
- gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
85
- } else {
86
- if (size == 0) {
87
- gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
88
- } else {
89
- gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
90
- }
91
- }
92
- tcg_temp_free_ptr(fpstatus);
93
- break;
94
- }
95
- case NEON_3R_FLOAT_ACMP:
96
- {
97
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
98
- if (size == 0) {
99
- gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
100
- } else {
101
- gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
102
- }
103
- tcg_temp_free_ptr(fpstatus);
104
- break;
105
- }
106
case NEON_3R_FLOAT_MINMAX:
107
{
108
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
109
--
57
--
110
2.20.1
58
2.25.1
111
59
112
60
diff view generated by jsdifflib
1
Convert the Neon VQRDMLAH and VQRDMLSH insns in the 3-reg-same group
1
When handling MAPI/MAPTI, we allow the supplied interrupt ID to be
2
to decodetree. These don't use do_3same() because they want to
2
either 1023 or something in the valid LPI range. This is a mistake:
3
operate on VFP double registers, whose offsets are different from the
3
only a real valid LPI is allowed. (The general behaviour of the ITS
4
neon_reg_offset() calculations do_3same does.
4
is that most interrupt ID fields require a value in the LPI range;
5
the exception is that fields specifying a doorbell value, which are
6
all in GICv4 commands, allow also 1023 to mean "no doorbell".)
7
Remove the condition that incorrectly allows 1023 here.
5
8
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>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200512163904.10918-2-peter.maydell@linaro.org
11
Message-id: 20220201193207.2771604-13-peter.maydell@linaro.org
9
---
12
---
10
target/arm/neon-dp.decode | 3 +++
13
hw/intc/arm_gicv3_its.c | 3 +--
11
target/arm/translate-neon.inc.c | 15 +++++++++++++++
14
1 file changed, 1 insertion(+), 2 deletions(-)
12
target/arm/translate.c | 14 ++------------
13
3 files changed, 20 insertions(+), 12 deletions(-)
14
15
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
16
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
18
--- a/hw/intc/arm_gicv3_its.c
18
+++ b/target/arm/neon-dp.decode
19
+++ b/hw/intc/arm_gicv3_its.c
19
@@ -XXX,XX +XXX,XX @@ VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same
20
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
20
21
21
VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
22
if ((icid >= s->ct.num_entries)
22
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
23
|| !dte.valid || (eventid >= num_eventids) ||
23
+
24
- (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) &&
24
+VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
25
- (pIntid != INTID_SPURIOUS))) {
25
+VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
26
+ (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)))) {
26
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
27
qemu_log_mask(LOG_GUEST_ERROR,
27
index XXXXXXX..XXXXXXX 100644
28
"%s: invalid command attributes "
28
--- a/target/arm/translate-neon.inc.c
29
"icid %d or eventid %d or pIntid %d or"
29
+++ b/target/arm/translate-neon.inc.c
30
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
31
}
32
return do_3same(s, a, gen_VMUL_p_3s);
33
}
34
+
35
+#define DO_VQRDMLAH(INSN, FUNC) \
36
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
37
+ { \
38
+ if (!dc_isar_feature(aa32_rdm, s)) { \
39
+ return false; \
40
+ } \
41
+ if (a->size != 1 && a->size != 2) { \
42
+ return false; \
43
+ } \
44
+ return do_3same(s, a, FUNC); \
45
+ }
46
+
47
+DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
48
+DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)
49
diff --git a/target/arm/translate.c b/target/arm/translate.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/translate.c
52
+++ b/target/arm/translate.c
53
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
54
if (!u) {
55
break; /* VPADD */
56
}
57
- /* VQRDMLAH */
58
- if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) {
59
- gen_gvec_sqrdmlah_qc(size, rd_ofs, rn_ofs, rm_ofs,
60
- vec_size, vec_size);
61
- return 0;
62
- }
63
+ /* VQRDMLAH : handled by decodetree */
64
return 1;
65
66
case NEON_3R_VFM_VQRDMLSH:
67
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
68
}
69
break;
70
}
71
- /* VQRDMLSH */
72
- if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) {
73
- gen_gvec_sqrdmlsh_qc(size, rd_ofs, rn_ofs, rm_ofs,
74
- vec_size, vec_size);
75
- return 0;
76
- }
77
+ /* VQRDMLSH : handled by decodetree */
78
return 1;
79
80
case NEON_3R_VABD:
81
--
30
--
82
2.20.1
31
2.25.1
83
32
84
33
diff view generated by jsdifflib
1
Convert the Neon fp VMAX/VMIN/VMAXNM/VMINNM/VRECPS/VRSQRTS 3-reg-same
1
In most of the ITS command processing, we check different error
2
insns to decodetree. (These are all the remaining non-accumulation
2
possibilities one at a time and log them appropriately. In
3
instructions in this group.)
3
process_mapti() and process_mapd() we have code which checks
4
multiple error cases at once, which means the logging is less
5
specific than it could be. Split those cases up.
4
6
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-17-peter.maydell@linaro.org
9
Message-id: 20220201193207.2771604-14-peter.maydell@linaro.org
8
---
10
---
9
target/arm/neon-dp.decode | 6 +++
11
hw/intc/arm_gicv3_its.c | 52 ++++++++++++++++++++++++-----------------
10
target/arm/translate-neon.inc.c | 70 +++++++++++++++++++++++++++++++++
12
1 file changed, 31 insertions(+), 21 deletions(-)
11
target/arm/translate.c | 42 +-------------------
12
3 files changed, 78 insertions(+), 40 deletions(-)
13
13
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
16
--- a/hw/intc/arm_gicv3_its.c
17
+++ b/target/arm/neon-dp.decode
17
+++ b/hw/intc/arm_gicv3_its.c
18
@@ -XXX,XX +XXX,XX @@ VCGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
18
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
19
VACGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 1 .... @3same_fp
19
num_eventids = 1ULL << (dte.size + 1);
20
VCGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 0 .... @3same_fp
20
num_intids = 1ULL << (GICD_TYPER_IDBITS + 1);
21
VACGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 1 .... @3same_fp
21
22
+VMAX_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 0 .... @3same_fp
22
- if ((icid >= s->ct.num_entries)
23
+VMIN_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 0 .... @3same_fp
23
- || !dte.valid || (eventid >= num_eventids) ||
24
VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
24
- (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)))) {
25
VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
25
+ if (icid >= s->ct.num_entries) {
26
+VRECPS_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
26
qemu_log_mask(LOG_GUEST_ERROR,
27
+VRSQRTS_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
27
- "%s: invalid command attributes "
28
+VMAXNM_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
28
- "icid %d or eventid %d or pIntid %d or"
29
+VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
29
- "unmapped dte %d\n", __func__, icid, eventid,
30
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
30
- pIntid, dte.valid);
31
index XXXXXXX..XXXXXXX 100644
31
- /*
32
--- a/target/arm/translate-neon.inc.c
32
- * in this implementation, in case of error
33
+++ b/target/arm/translate-neon.inc.c
33
- * we ignore this command and move onto the next
34
@@ -XXX,XX +XXX,XX @@ DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false)
34
- * command in the queue
35
DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false)
35
- */
36
DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
36
+ "%s: invalid ICID 0x%x >= 0x%x\n",
37
DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
37
+ __func__, icid, s->ct.num_entries);
38
+DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
38
+ return CMD_CONTINUE;
39
+DO_3S_FP(VMIN, gen_helper_vfp_mins, false)
40
41
static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
42
TCGv_ptr fpstatus)
43
@@ -XXX,XX +XXX,XX @@ static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
44
DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
45
DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
46
47
+static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
48
+{
49
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
50
+ return false;
51
+ }
39
+ }
52
+
40
+
53
+ if (a->size != 0) {
41
+ if (!dte.valid) {
54
+ /* TODO fp16 support */
42
+ qemu_log_mask(LOG_GUEST_ERROR,
55
+ return false;
43
+ "%s: no valid DTE for devid 0x%x\n", __func__, devid);
44
+ return CMD_CONTINUE;
56
+ }
45
+ }
57
+
46
+
58
+ return do_3same_fp(s, a, gen_helper_vfp_maxnums, false);
47
+ if (eventid >= num_eventids) {
59
+}
48
+ qemu_log_mask(LOG_GUEST_ERROR,
60
+
49
+ "%s: invalid event ID 0x%x >= 0x%" PRIx64 "\n",
61
+static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
50
+ __func__, eventid, num_eventids);
62
+{
51
+ return CMD_CONTINUE;
63
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
64
+ return false;
65
+ }
52
+ }
66
+
53
+
67
+ if (a->size != 0) {
54
+ if (pIntid < GICV3_LPI_INTID_START || pIntid >= num_intids) {
68
+ /* TODO fp16 support */
55
+ qemu_log_mask(LOG_GUEST_ERROR,
69
+ return false;
56
+ "%s: invalid interrupt ID 0x%x\n", __func__, pIntid);
57
return CMD_CONTINUE;
58
}
59
60
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
61
dte.ittaddr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
62
dte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
63
64
- if ((devid >= s->dt.num_entries) ||
65
- (dte.size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
66
+ if (devid >= s->dt.num_entries) {
67
qemu_log_mask(LOG_GUEST_ERROR,
68
- "ITS MAPD: invalid device table attributes "
69
- "devid %d or size %d\n", devid, dte.size);
70
- /*
71
- * in this implementation, in case of error
72
- * we ignore this command and move onto the next
73
- * command in the queue
74
- */
75
+ "ITS MAPD: invalid device ID field 0x%x >= 0x%x\n",
76
+ devid, s->dt.num_entries);
77
+ return CMD_CONTINUE;
70
+ }
78
+ }
71
+
79
+
72
+ return do_3same_fp(s, a, gen_helper_vfp_minnums, false);
80
+ if (dte.size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS)) {
73
+}
81
+ qemu_log_mask(LOG_GUEST_ERROR,
74
+
82
+ "ITS MAPD: invalid size %d\n", dte.size);
75
+WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32)
83
return CMD_CONTINUE;
76
+
84
}
77
+static void gen_VRECPS_fp_3s(unsigned vece, uint32_t rd_ofs,
85
78
+ uint32_t rn_ofs, uint32_t rm_ofs,
79
+ uint32_t oprsz, uint32_t maxsz)
80
+{
81
+ static const GVecGen3 ops = { .fni4 = gen_VRECPS_tramp };
82
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
83
+}
84
+
85
+static bool trans_VRECPS_fp_3s(DisasContext *s, arg_3same *a)
86
+{
87
+ if (a->size != 0) {
88
+ /* TODO fp16 support */
89
+ return false;
90
+ }
91
+
92
+ return do_3same(s, a, gen_VRECPS_fp_3s);
93
+}
94
+
95
+WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32)
96
+
97
+static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs,
98
+ uint32_t rn_ofs, uint32_t rm_ofs,
99
+ uint32_t oprsz, uint32_t maxsz)
100
+{
101
+ static const GVecGen3 ops = { .fni4 = gen_VRSQRTS_tramp };
102
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
103
+}
104
+
105
+static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
106
+{
107
+ if (a->size != 0) {
108
+ /* TODO fp16 support */
109
+ return false;
110
+ }
111
+
112
+ return do_3same(s, a, gen_VRSQRTS_fp_3s);
113
+}
114
+
115
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
116
{
117
/* FP operations handled pairwise 32 bits at a time */
118
diff --git a/target/arm/translate.c b/target/arm/translate.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/target/arm/translate.c
121
+++ b/target/arm/translate.c
122
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
123
case NEON_3R_FLOAT_MULTIPLY:
124
case NEON_3R_FLOAT_CMP:
125
case NEON_3R_FLOAT_ACMP:
126
+ case NEON_3R_FLOAT_MINMAX:
127
+ case NEON_3R_FLOAT_MISC:
128
/* Already handled by decodetree */
129
return 1;
130
}
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
132
return 1;
133
}
134
switch (op) {
135
- case NEON_3R_FLOAT_MINMAX:
136
- if (u) {
137
- return 1; /* VPMIN/VPMAX handled by decodetree */
138
- }
139
- break;
140
- case NEON_3R_FLOAT_MISC:
141
- /* VMAXNM/VMINNM in ARMv8 */
142
- if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
143
- return 1;
144
- }
145
- break;
146
case NEON_3R_VFM_VQRDMLSH:
147
if (!dc_isar_feature(aa32_simdfmac, s)) {
148
return 1;
149
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
150
tmp = neon_load_reg(rn, pass);
151
tmp2 = neon_load_reg(rm, pass);
152
switch (op) {
153
- case NEON_3R_FLOAT_MINMAX:
154
- {
155
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
156
- if (size == 0) {
157
- gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
158
- } else {
159
- gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
160
- }
161
- tcg_temp_free_ptr(fpstatus);
162
- break;
163
- }
164
- case NEON_3R_FLOAT_MISC:
165
- if (u) {
166
- /* VMAXNM/VMINNM */
167
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
168
- if (size == 0) {
169
- gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
170
- } else {
171
- gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
172
- }
173
- tcg_temp_free_ptr(fpstatus);
174
- } else {
175
- if (size == 0) {
176
- gen_helper_recps_f32(tmp, cpu_env, tmp, tmp2);
177
- } else {
178
- gen_helper_rsqrts_f32(tmp, cpu_env, tmp, tmp2);
179
- }
180
- }
181
- break;
182
case NEON_3R_VFM_VQRDMLSH:
183
{
184
/* VFMA, VFMS: fused multiply-add */
185
--
86
--
186
2.20.1
87
2.25.1
187
88
188
89
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Kevin Townsend <kevin.townsend@linaro.org>
2
2
3
This patch builds error_block_address and read_ack_register fields
3
This commit adds emulation of the magnetometer on the LSM303DLHC.
4
in hardware errors table , the error_block_address points to Generic
4
It allows the magnetometer's X, Y and Z outputs to be set via the
5
Error Status Block(GESB) via bios_linker. The max size for one GESB
5
mag-x, mag-y and mag-z properties, as well as the 12-bit
6
is 1kb, For more detailed information, please refer to
6
temperature output via the temperature property. Sensor can be
7
document: docs/specs/acpi_hest_ghes.rst
7
enabled with 'CONFIG_LSM303DLHC_MAG=y'.
8
8
9
Now we only support one Error source, if necessary, we can extend to
9
Signed-off-by: Kevin Townsend <kevin.townsend@linaro.org>
10
support more.
10
Message-id: 20220130095032.35392-1-kevin.townsend@linaro.org
11
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Suggested-by: Laszlo Ersek <lersek@redhat.com>
13
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
14
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
17
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
18
Message-id: 20200512030609.19593-5-gengdongjiu@huawei.com
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
13
---
21
default-configs/arm-softmmu.mak | 1 +
14
hw/sensor/lsm303dlhc_mag.c | 556 ++++++++++++++++++++++++++++++
22
include/hw/acpi/aml-build.h | 1 +
15
tests/qtest/lsm303dlhc-mag-test.c | 148 ++++++++
23
include/hw/acpi/ghes.h | 28 +++++++++++
16
hw/sensor/Kconfig | 4 +
24
hw/acpi/aml-build.c | 2 +
17
hw/sensor/meson.build | 1 +
25
hw/acpi/ghes.c | 89 +++++++++++++++++++++++++++++++++
18
tests/qtest/meson.build | 1 +
26
hw/arm/virt-acpi-build.c | 5 ++
19
5 files changed, 710 insertions(+)
27
hw/acpi/Kconfig | 4 ++
20
create mode 100644 hw/sensor/lsm303dlhc_mag.c
28
hw/acpi/Makefile.objs | 1 +
21
create mode 100644 tests/qtest/lsm303dlhc-mag-test.c
29
8 files changed, 131 insertions(+)
30
create mode 100644 include/hw/acpi/ghes.h
31
create mode 100644 hw/acpi/ghes.c
32
22
33
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
23
diff --git a/hw/sensor/lsm303dlhc_mag.c b/hw/sensor/lsm303dlhc_mag.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/default-configs/arm-softmmu.mak
36
+++ b/default-configs/arm-softmmu.mak
37
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX7=y
38
CONFIG_FSL_IMX6UL=y
39
CONFIG_SEMIHOSTING=y
40
CONFIG_ALLWINNER_H3=y
41
+CONFIG_ACPI_APEI=y
42
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/include/hw/acpi/aml-build.h
45
+++ b/include/hw/acpi/aml-build.h
46
@@ -XXX,XX +XXX,XX @@ struct AcpiBuildTables {
47
GArray *rsdp;
48
GArray *tcpalog;
49
GArray *vmgenid;
50
+ GArray *hardware_errors;
51
BIOSLinker *linker;
52
} AcpiBuildTables;
53
54
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
55
new file mode 100644
24
new file mode 100644
56
index XXXXXXX..XXXXXXX
25
index XXXXXXX..XXXXXXX
57
--- /dev/null
26
--- /dev/null
58
+++ b/include/hw/acpi/ghes.h
27
+++ b/hw/sensor/lsm303dlhc_mag.c
59
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
60
+/*
29
+/*
61
+ * Support for generating APEI tables and recording CPER for Guests
30
+ * LSM303DLHC I2C magnetometer.
62
+ *
31
+ *
63
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
32
+ * Copyright (C) 2021 Linaro Ltd.
33
+ * Written by Kevin Townsend <kevin.townsend@linaro.org>
64
+ *
34
+ *
65
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
35
+ * Based on: https://www.st.com/resource/en/datasheet/lsm303dlhc.pdf
66
+ *
36
+ *
67
+ * This program is free software; you can redistribute it and/or modify
37
+ * SPDX-License-Identifier: GPL-2.0-or-later
68
+ * it under the terms of the GNU General Public License as published by
38
+ */
69
+ * the Free Software Foundation; either version 2 of the License, or
39
+
70
+ * (at your option) any later version.
40
+/*
71
+
41
+ * The I2C address associated with this device is set on the command-line when
72
+ * This program is distributed in the hope that it will be useful,
42
+ * initialising the machine, but the following address is standard: 0x1E.
73
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
43
+ *
74
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44
+ * Get and set functions for 'mag-x', 'mag-y' and 'mag-z' assume that
75
+ * GNU General Public License for more details.
45
+ * 1 = 0.001 uT. (NOTE the 1 gauss = 100 uT, so setting a value of 100,000
76
+
46
+ * would be equal to 1 gauss or 100 uT.)
77
+ * You should have received a copy of the GNU General Public License along
47
+ *
78
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
48
+ * Get and set functions for 'temperature' assume that 1 = 0.001 C, so 23.6 C
79
+ */
49
+ * would be equal to 23600.
80
+
50
+ */
81
+#ifndef ACPI_GHES_H
51
+
82
+#define ACPI_GHES_H
52
+#include "qemu/osdep.h"
83
+
53
+#include "hw/i2c/i2c.h"
84
+#include "hw/acpi/bios-linker-loader.h"
54
+#include "migration/vmstate.h"
85
+
55
+#include "qapi/error.h"
86
+void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
56
+#include "qapi/visitor.h"
87
+#endif
57
+#include "qemu/module.h"
88
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
58
+#include "qemu/log.h"
89
index XXXXXXX..XXXXXXX 100644
59
+#include "qemu/bswap.h"
90
--- a/hw/acpi/aml-build.c
60
+
91
+++ b/hw/acpi/aml-build.c
61
+enum LSM303DLHCMagReg {
92
@@ -XXX,XX +XXX,XX @@ void acpi_build_tables_init(AcpiBuildTables *tables)
62
+ LSM303DLHC_MAG_REG_CRA = 0x00,
93
tables->table_data = g_array_new(false, true /* clear */, 1);
63
+ LSM303DLHC_MAG_REG_CRB = 0x01,
94
tables->tcpalog = g_array_new(false, true /* clear */, 1);
64
+ LSM303DLHC_MAG_REG_MR = 0x02,
95
tables->vmgenid = g_array_new(false, true /* clear */, 1);
65
+ LSM303DLHC_MAG_REG_OUT_X_H = 0x03,
96
+ tables->hardware_errors = g_array_new(false, true /* clear */, 1);
66
+ LSM303DLHC_MAG_REG_OUT_X_L = 0x04,
97
tables->linker = bios_linker_loader_init();
67
+ LSM303DLHC_MAG_REG_OUT_Z_H = 0x05,
98
}
68
+ LSM303DLHC_MAG_REG_OUT_Z_L = 0x06,
99
69
+ LSM303DLHC_MAG_REG_OUT_Y_H = 0x07,
100
@@ -XXX,XX +XXX,XX @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
70
+ LSM303DLHC_MAG_REG_OUT_Y_L = 0x08,
101
g_array_free(tables->table_data, true);
71
+ LSM303DLHC_MAG_REG_SR = 0x09,
102
g_array_free(tables->tcpalog, mfre);
72
+ LSM303DLHC_MAG_REG_IRA = 0x0A,
103
g_array_free(tables->vmgenid, mfre);
73
+ LSM303DLHC_MAG_REG_IRB = 0x0B,
104
+ g_array_free(tables->hardware_errors, mfre);
74
+ LSM303DLHC_MAG_REG_IRC = 0x0C,
105
}
75
+ LSM303DLHC_MAG_REG_TEMP_OUT_H = 0x31,
106
76
+ LSM303DLHC_MAG_REG_TEMP_OUT_L = 0x32
107
/*
77
+};
108
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
78
+
79
+typedef struct LSM303DLHCMagState {
80
+ I2CSlave parent_obj;
81
+ uint8_t cra;
82
+ uint8_t crb;
83
+ uint8_t mr;
84
+ int16_t x;
85
+ int16_t z;
86
+ int16_t y;
87
+ int16_t x_lock;
88
+ int16_t z_lock;
89
+ int16_t y_lock;
90
+ uint8_t sr;
91
+ uint8_t ira;
92
+ uint8_t irb;
93
+ uint8_t irc;
94
+ int16_t temperature;
95
+ int16_t temperature_lock;
96
+ uint8_t len;
97
+ uint8_t buf;
98
+ uint8_t pointer;
99
+} LSM303DLHCMagState;
100
+
101
+#define TYPE_LSM303DLHC_MAG "lsm303dlhc_mag"
102
+OBJECT_DECLARE_SIMPLE_TYPE(LSM303DLHCMagState, LSM303DLHC_MAG)
103
+
104
+/*
105
+ * Conversion factor from Gauss to sensor values for each GN gain setting,
106
+ * in units "lsb per Gauss" (see data sheet table 3). There is no documented
107
+ * behaviour if the GN setting in CRB is incorrectly set to 0b000;
108
+ * we arbitrarily make it the same as 0b001.
109
+ */
110
+uint32_t xy_gain[] = { 1100, 1100, 855, 670, 450, 400, 330, 230 };
111
+uint32_t z_gain[] = { 980, 980, 760, 600, 400, 355, 295, 205 };
112
+
113
+static void lsm303dlhc_mag_get_x(Object *obj, Visitor *v, const char *name,
114
+ void *opaque, Error **errp)
115
+{
116
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
117
+ int gm = extract32(s->crb, 5, 3);
118
+
119
+ /* Convert to uT where 1000 = 1 uT. Conversion factor depends on gain. */
120
+ int64_t value = muldiv64(s->x, 100000, xy_gain[gm]);
121
+ visit_type_int(v, name, &value, errp);
122
+}
123
+
124
+static void lsm303dlhc_mag_get_y(Object *obj, Visitor *v, const char *name,
125
+ void *opaque, Error **errp)
126
+{
127
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
128
+ int gm = extract32(s->crb, 5, 3);
129
+
130
+ /* Convert to uT where 1000 = 1 uT. Conversion factor depends on gain. */
131
+ int64_t value = muldiv64(s->y, 100000, xy_gain[gm]);
132
+ visit_type_int(v, name, &value, errp);
133
+}
134
+
135
+static void lsm303dlhc_mag_get_z(Object *obj, Visitor *v, const char *name,
136
+ void *opaque, Error **errp)
137
+{
138
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
139
+ int gm = extract32(s->crb, 5, 3);
140
+
141
+ /* Convert to uT where 1000 = 1 uT. Conversion factor depends on gain. */
142
+ int64_t value = muldiv64(s->z, 100000, z_gain[gm]);
143
+ visit_type_int(v, name, &value, errp);
144
+}
145
+
146
+static void lsm303dlhc_mag_set_x(Object *obj, Visitor *v, const char *name,
147
+ void *opaque, Error **errp)
148
+{
149
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
150
+ int64_t value;
151
+ int64_t reg;
152
+ int gm = extract32(s->crb, 5, 3);
153
+
154
+ if (!visit_type_int(v, name, &value, errp)) {
155
+ return;
156
+ }
157
+
158
+ reg = muldiv64(value, xy_gain[gm], 100000);
159
+
160
+ /* Make sure we are within a 12-bit limit. */
161
+ if (reg > 2047 || reg < -2048) {
162
+ error_setg(errp, "value %" PRId64 " out of register's range", value);
163
+ return;
164
+ }
165
+
166
+ s->x = (int16_t)reg;
167
+}
168
+
169
+static void lsm303dlhc_mag_set_y(Object *obj, Visitor *v, const char *name,
170
+ void *opaque, Error **errp)
171
+{
172
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
173
+ int64_t value;
174
+ int64_t reg;
175
+ int gm = extract32(s->crb, 5, 3);
176
+
177
+ if (!visit_type_int(v, name, &value, errp)) {
178
+ return;
179
+ }
180
+
181
+ reg = muldiv64(value, xy_gain[gm], 100000);
182
+
183
+ /* Make sure we are within a 12-bit limit. */
184
+ if (reg > 2047 || reg < -2048) {
185
+ error_setg(errp, "value %" PRId64 " out of register's range", value);
186
+ return;
187
+ }
188
+
189
+ s->y = (int16_t)reg;
190
+}
191
+
192
+static void lsm303dlhc_mag_set_z(Object *obj, Visitor *v, const char *name,
193
+ void *opaque, Error **errp)
194
+{
195
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
196
+ int64_t value;
197
+ int64_t reg;
198
+ int gm = extract32(s->crb, 5, 3);
199
+
200
+ if (!visit_type_int(v, name, &value, errp)) {
201
+ return;
202
+ }
203
+
204
+ reg = muldiv64(value, z_gain[gm], 100000);
205
+
206
+ /* Make sure we are within a 12-bit limit. */
207
+ if (reg > 2047 || reg < -2048) {
208
+ error_setg(errp, "value %" PRId64 " out of register's range", value);
209
+ return;
210
+ }
211
+
212
+ s->z = (int16_t)reg;
213
+}
214
+
215
+/*
216
+ * Get handler for the temperature property.
217
+ */
218
+static void lsm303dlhc_mag_get_temperature(Object *obj, Visitor *v,
219
+ const char *name, void *opaque,
220
+ Error **errp)
221
+{
222
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
223
+ int64_t value;
224
+
225
+ /* Convert to 1 lsb = 0.125 C to 1 = 0.001 C for 'temperature' property. */
226
+ value = s->temperature * 125;
227
+
228
+ visit_type_int(v, name, &value, errp);
229
+}
230
+
231
+/*
232
+ * Set handler for the temperature property.
233
+ */
234
+static void lsm303dlhc_mag_set_temperature(Object *obj, Visitor *v,
235
+ const char *name, void *opaque,
236
+ Error **errp)
237
+{
238
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
239
+ int64_t value;
240
+
241
+ if (!visit_type_int(v, name, &value, errp)) {
242
+ return;
243
+ }
244
+
245
+ /* Input temperature is in 0.001 C units. Convert to 1 lsb = 0.125 C. */
246
+ value /= 125;
247
+
248
+ if (value > 2047 || value < -2048) {
249
+ error_setg(errp, "value %" PRId64 " lsb is out of range", value);
250
+ return;
251
+ }
252
+
253
+ s->temperature = (int16_t)value;
254
+}
255
+
256
+/*
257
+ * Callback handler whenever a 'I2C_START_RECV' (read) event is received.
258
+ */
259
+static void lsm303dlhc_mag_read(LSM303DLHCMagState *s)
260
+{
261
+ /*
262
+ * Set the LOCK bit whenever a new read attempt is made. This will be
263
+ * cleared in I2C_FINISH. Note that DRDY is always set to 1 in this driver.
264
+ */
265
+ s->sr = 0x3;
266
+
267
+ /*
268
+ * Copy the current X/Y/Z and temp. values into the locked registers so
269
+ * that 'mag-x', 'mag-y', 'mag-z' and 'temperature' can continue to be
270
+ * updated via QOM, etc., without corrupting the current read event.
271
+ */
272
+ s->x_lock = s->x;
273
+ s->z_lock = s->z;
274
+ s->y_lock = s->y;
275
+ s->temperature_lock = s->temperature;
276
+}
277
+
278
+/*
279
+ * Callback handler whenever a 'I2C_FINISH' event is received.
280
+ */
281
+static void lsm303dlhc_mag_finish(LSM303DLHCMagState *s)
282
+{
283
+ /*
284
+ * Clear the LOCK bit when the read attempt terminates.
285
+ * This bit is initially set in the I2C_START_RECV handler.
286
+ */
287
+ s->sr = 0x1;
288
+}
289
+
290
+/*
291
+ * Callback handler when a device attempts to write to a register.
292
+ */
293
+static void lsm303dlhc_mag_write(LSM303DLHCMagState *s)
294
+{
295
+ switch (s->pointer) {
296
+ case LSM303DLHC_MAG_REG_CRA:
297
+ s->cra = s->buf;
298
+ break;
299
+ case LSM303DLHC_MAG_REG_CRB:
300
+ /* Make sure gain is at least 1, falling back to 1 on an error. */
301
+ if (s->buf >> 5 == 0) {
302
+ s->buf = 1 << 5;
303
+ }
304
+ s->crb = s->buf;
305
+ break;
306
+ case LSM303DLHC_MAG_REG_MR:
307
+ s->mr = s->buf;
308
+ break;
309
+ case LSM303DLHC_MAG_REG_SR:
310
+ s->sr = s->buf;
311
+ break;
312
+ case LSM303DLHC_MAG_REG_IRA:
313
+ s->ira = s->buf;
314
+ break;
315
+ case LSM303DLHC_MAG_REG_IRB:
316
+ s->irb = s->buf;
317
+ break;
318
+ case LSM303DLHC_MAG_REG_IRC:
319
+ s->irc = s->buf;
320
+ break;
321
+ default:
322
+ qemu_log_mask(LOG_GUEST_ERROR, "reg is read-only: 0x%02X", s->buf);
323
+ break;
324
+ }
325
+}
326
+
327
+/*
328
+ * Low-level master-to-slave transaction handler.
329
+ */
330
+static int lsm303dlhc_mag_send(I2CSlave *i2c, uint8_t data)
331
+{
332
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(i2c);
333
+
334
+ if (s->len == 0) {
335
+ /* First byte is the reg pointer */
336
+ s->pointer = data;
337
+ s->len++;
338
+ } else if (s->len == 1) {
339
+ /* Second byte is the new register value. */
340
+ s->buf = data;
341
+ lsm303dlhc_mag_write(s);
342
+ } else {
343
+ g_assert_not_reached();
344
+ }
345
+
346
+ return 0;
347
+}
348
+
349
+/*
350
+ * Low-level slave-to-master transaction handler (read attempts).
351
+ */
352
+static uint8_t lsm303dlhc_mag_recv(I2CSlave *i2c)
353
+{
354
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(i2c);
355
+ uint8_t resp;
356
+
357
+ switch (s->pointer) {
358
+ case LSM303DLHC_MAG_REG_CRA:
359
+ resp = s->cra;
360
+ break;
361
+ case LSM303DLHC_MAG_REG_CRB:
362
+ resp = s->crb;
363
+ break;
364
+ case LSM303DLHC_MAG_REG_MR:
365
+ resp = s->mr;
366
+ break;
367
+ case LSM303DLHC_MAG_REG_OUT_X_H:
368
+ resp = (uint8_t)(s->x_lock >> 8);
369
+ break;
370
+ case LSM303DLHC_MAG_REG_OUT_X_L:
371
+ resp = (uint8_t)(s->x_lock);
372
+ break;
373
+ case LSM303DLHC_MAG_REG_OUT_Z_H:
374
+ resp = (uint8_t)(s->z_lock >> 8);
375
+ break;
376
+ case LSM303DLHC_MAG_REG_OUT_Z_L:
377
+ resp = (uint8_t)(s->z_lock);
378
+ break;
379
+ case LSM303DLHC_MAG_REG_OUT_Y_H:
380
+ resp = (uint8_t)(s->y_lock >> 8);
381
+ break;
382
+ case LSM303DLHC_MAG_REG_OUT_Y_L:
383
+ resp = (uint8_t)(s->y_lock);
384
+ break;
385
+ case LSM303DLHC_MAG_REG_SR:
386
+ resp = s->sr;
387
+ break;
388
+ case LSM303DLHC_MAG_REG_IRA:
389
+ resp = s->ira;
390
+ break;
391
+ case LSM303DLHC_MAG_REG_IRB:
392
+ resp = s->irb;
393
+ break;
394
+ case LSM303DLHC_MAG_REG_IRC:
395
+ resp = s->irc;
396
+ break;
397
+ case LSM303DLHC_MAG_REG_TEMP_OUT_H:
398
+ /* Check if the temperature sensor is enabled or not (CRA & 0x80). */
399
+ if (s->cra & 0x80) {
400
+ resp = (uint8_t)(s->temperature_lock >> 8);
401
+ } else {
402
+ resp = 0;
403
+ }
404
+ break;
405
+ case LSM303DLHC_MAG_REG_TEMP_OUT_L:
406
+ if (s->cra & 0x80) {
407
+ resp = (uint8_t)(s->temperature_lock & 0xff);
408
+ } else {
409
+ resp = 0;
410
+ }
411
+ break;
412
+ default:
413
+ resp = 0;
414
+ break;
415
+ }
416
+
417
+ /*
418
+ * The address pointer on the LSM303DLHC auto-increments whenever a byte
419
+ * is read, without the master device having to request the next address.
420
+ *
421
+ * The auto-increment process has the following logic:
422
+ *
423
+ * - if (s->pointer == 8) then s->pointer = 3
424
+ * - else: if (s->pointer == 12) then s->pointer = 0
425
+ * - else: s->pointer += 1
426
+ *
427
+ * Reading an invalid address return 0.
428
+ */
429
+ if (s->pointer == LSM303DLHC_MAG_REG_OUT_Y_L) {
430
+ s->pointer = LSM303DLHC_MAG_REG_OUT_X_H;
431
+ } else if (s->pointer == LSM303DLHC_MAG_REG_IRC) {
432
+ s->pointer = LSM303DLHC_MAG_REG_CRA;
433
+ } else {
434
+ s->pointer++;
435
+ }
436
+
437
+ return resp;
438
+}
439
+
440
+/*
441
+ * Bus state change handler.
442
+ */
443
+static int lsm303dlhc_mag_event(I2CSlave *i2c, enum i2c_event event)
444
+{
445
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(i2c);
446
+
447
+ switch (event) {
448
+ case I2C_START_SEND:
449
+ break;
450
+ case I2C_START_RECV:
451
+ lsm303dlhc_mag_read(s);
452
+ break;
453
+ case I2C_FINISH:
454
+ lsm303dlhc_mag_finish(s);
455
+ break;
456
+ case I2C_NACK:
457
+ break;
458
+ }
459
+
460
+ s->len = 0;
461
+ return 0;
462
+}
463
+
464
+/*
465
+ * Device data description using VMSTATE macros.
466
+ */
467
+static const VMStateDescription vmstate_lsm303dlhc_mag = {
468
+ .name = "LSM303DLHC_MAG",
469
+ .version_id = 0,
470
+ .minimum_version_id = 0,
471
+ .fields = (VMStateField[]) {
472
+
473
+ VMSTATE_I2C_SLAVE(parent_obj, LSM303DLHCMagState),
474
+ VMSTATE_UINT8(len, LSM303DLHCMagState),
475
+ VMSTATE_UINT8(buf, LSM303DLHCMagState),
476
+ VMSTATE_UINT8(pointer, LSM303DLHCMagState),
477
+ VMSTATE_UINT8(cra, LSM303DLHCMagState),
478
+ VMSTATE_UINT8(crb, LSM303DLHCMagState),
479
+ VMSTATE_UINT8(mr, LSM303DLHCMagState),
480
+ VMSTATE_INT16(x, LSM303DLHCMagState),
481
+ VMSTATE_INT16(z, LSM303DLHCMagState),
482
+ VMSTATE_INT16(y, LSM303DLHCMagState),
483
+ VMSTATE_INT16(x_lock, LSM303DLHCMagState),
484
+ VMSTATE_INT16(z_lock, LSM303DLHCMagState),
485
+ VMSTATE_INT16(y_lock, LSM303DLHCMagState),
486
+ VMSTATE_UINT8(sr, LSM303DLHCMagState),
487
+ VMSTATE_UINT8(ira, LSM303DLHCMagState),
488
+ VMSTATE_UINT8(irb, LSM303DLHCMagState),
489
+ VMSTATE_UINT8(irc, LSM303DLHCMagState),
490
+ VMSTATE_INT16(temperature, LSM303DLHCMagState),
491
+ VMSTATE_INT16(temperature_lock, LSM303DLHCMagState),
492
+ VMSTATE_END_OF_LIST()
493
+ }
494
+};
495
+
496
+/*
497
+ * Put the device into post-reset default state.
498
+ */
499
+static void lsm303dlhc_mag_default_cfg(LSM303DLHCMagState *s)
500
+{
501
+ /* Set the device into is default reset state. */
502
+ s->len = 0;
503
+ s->pointer = 0; /* Current register. */
504
+ s->buf = 0; /* Shared buffer. */
505
+ s->cra = 0x10; /* Temp Enabled = 0, Data Rate = 15.0 Hz. */
506
+ s->crb = 0x20; /* Gain = +/- 1.3 Gauss. */
507
+ s->mr = 0x3; /* Operating Mode = Sleep. */
508
+ s->x = 0;
509
+ s->z = 0;
510
+ s->y = 0;
511
+ s->x_lock = 0;
512
+ s->z_lock = 0;
513
+ s->y_lock = 0;
514
+ s->sr = 0x1; /* DRDY = 1. */
515
+ s->ira = 0x48;
516
+ s->irb = 0x34;
517
+ s->irc = 0x33;
518
+ s->temperature = 0; /* Default to 0 degrees C (0/8 lsb = 0 C). */
519
+ s->temperature_lock = 0;
520
+}
521
+
522
+/*
523
+ * Callback handler when DeviceState 'reset' is set to true.
524
+ */
525
+static void lsm303dlhc_mag_reset(DeviceState *dev)
526
+{
527
+ I2CSlave *i2c = I2C_SLAVE(dev);
528
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(i2c);
529
+
530
+ /* Set the device into its default reset state. */
531
+ lsm303dlhc_mag_default_cfg(s);
532
+}
533
+
534
+/*
535
+ * Initialisation of any public properties.
536
+ */
537
+static void lsm303dlhc_mag_initfn(Object *obj)
538
+{
539
+ object_property_add(obj, "mag-x", "int",
540
+ lsm303dlhc_mag_get_x,
541
+ lsm303dlhc_mag_set_x, NULL, NULL);
542
+
543
+ object_property_add(obj, "mag-y", "int",
544
+ lsm303dlhc_mag_get_y,
545
+ lsm303dlhc_mag_set_y, NULL, NULL);
546
+
547
+ object_property_add(obj, "mag-z", "int",
548
+ lsm303dlhc_mag_get_z,
549
+ lsm303dlhc_mag_set_z, NULL, NULL);
550
+
551
+ object_property_add(obj, "temperature", "int",
552
+ lsm303dlhc_mag_get_temperature,
553
+ lsm303dlhc_mag_set_temperature, NULL, NULL);
554
+}
555
+
556
+/*
557
+ * Set the virtual method pointers (bus state change, tx/rx, etc.).
558
+ */
559
+static void lsm303dlhc_mag_class_init(ObjectClass *klass, void *data)
560
+{
561
+ DeviceClass *dc = DEVICE_CLASS(klass);
562
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
563
+
564
+ dc->reset = lsm303dlhc_mag_reset;
565
+ dc->vmsd = &vmstate_lsm303dlhc_mag;
566
+ k->event = lsm303dlhc_mag_event;
567
+ k->recv = lsm303dlhc_mag_recv;
568
+ k->send = lsm303dlhc_mag_send;
569
+}
570
+
571
+static const TypeInfo lsm303dlhc_mag_info = {
572
+ .name = TYPE_LSM303DLHC_MAG,
573
+ .parent = TYPE_I2C_SLAVE,
574
+ .instance_size = sizeof(LSM303DLHCMagState),
575
+ .instance_init = lsm303dlhc_mag_initfn,
576
+ .class_init = lsm303dlhc_mag_class_init,
577
+};
578
+
579
+static void lsm303dlhc_mag_register_types(void)
580
+{
581
+ type_register_static(&lsm303dlhc_mag_info);
582
+}
583
+
584
+type_init(lsm303dlhc_mag_register_types)
585
diff --git a/tests/qtest/lsm303dlhc-mag-test.c b/tests/qtest/lsm303dlhc-mag-test.c
109
new file mode 100644
586
new file mode 100644
110
index XXXXXXX..XXXXXXX
587
index XXXXXXX..XXXXXXX
111
--- /dev/null
588
--- /dev/null
112
+++ b/hw/acpi/ghes.c
589
+++ b/tests/qtest/lsm303dlhc-mag-test.c
113
@@ -XXX,XX +XXX,XX @@
590
@@ -XXX,XX +XXX,XX @@
114
+/*
591
+/*
115
+ * Support for generating APEI tables and recording CPER for Guests
592
+ * QTest testcase for the LSM303DLHC I2C magnetometer
116
+ *
593
+ *
117
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
594
+ * Copyright (C) 2021 Linaro Ltd.
595
+ * Written by Kevin Townsend <kevin.townsend@linaro.org>
118
+ *
596
+ *
119
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
597
+ * Based on: https://www.st.com/resource/en/datasheet/lsm303dlhc.pdf
120
+ *
598
+ *
121
+ * This program is free software; you can redistribute it and/or modify
599
+ * SPDX-License-Identifier: GPL-2.0-or-later
122
+ * it under the terms of the GNU General Public License as published by
123
+ * the Free Software Foundation; either version 2 of the License, or
124
+ * (at your option) any later version.
125
+
126
+ * This program is distributed in the hope that it will be useful,
127
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
128
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
129
+ * GNU General Public License for more details.
130
+
131
+ * You should have received a copy of the GNU General Public License along
132
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
133
+ */
600
+ */
134
+
601
+
135
+#include "qemu/osdep.h"
602
+#include "qemu/osdep.h"
136
+#include "qemu/units.h"
603
+#include "libqtest-single.h"
137
+#include "hw/acpi/ghes.h"
604
+#include "libqos/qgraph.h"
138
+#include "hw/acpi/aml-build.h"
605
+#include "libqos/i2c.h"
139
+
606
+#include "qapi/qmp/qdict.h"
140
+#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
607
+
141
+#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
608
+#define LSM303DLHC_MAG_TEST_ID "lsm303dlhc_mag-test"
142
+
609
+#define LSM303DLHC_MAG_REG_CRA 0x00
143
+/* The max size in bytes for one error block */
610
+#define LSM303DLHC_MAG_REG_CRB 0x01
144
+#define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB)
611
+#define LSM303DLHC_MAG_REG_OUT_X_H 0x03
145
+
612
+#define LSM303DLHC_MAG_REG_OUT_Z_H 0x05
146
+/* Now only support ARMv8 SEA notification type error source */
613
+#define LSM303DLHC_MAG_REG_OUT_Y_H 0x07
147
+#define ACPI_GHES_ERROR_SOURCE_COUNT 1
614
+#define LSM303DLHC_MAG_REG_IRC 0x0C
148
+
615
+#define LSM303DLHC_MAG_REG_TEMP_OUT_H 0x31
149
+/*
616
+
150
+ * Build table for the hardware error fw_cfg blob.
617
+static int qmp_lsm303dlhc_mag_get_property(const char *id, const char *prop)
151
+ * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
618
+{
152
+ * See docs/specs/acpi_hest_ghes.rst for blobs format.
619
+ QDict *response;
153
+ */
620
+ int ret;
154
+void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
621
+
155
+{
622
+ response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, "
156
+ int i, error_status_block_offset;
623
+ "'property': %s } }", id, prop);
157
+
624
+ g_assert(qdict_haskey(response, "return"));
158
+ /* Build error_block_address */
625
+ ret = qdict_get_int(response, "return");
159
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
626
+ qobject_unref(response);
160
+ build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t));
627
+ return ret;
161
+ }
628
+}
162
+
629
+
163
+ /* Build read_ack_register */
630
+static void qmp_lsm303dlhc_mag_set_property(const char *id, const char *prop,
164
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
631
+ int value)
165
+ /*
632
+{
166
+ * Initialize the value of read_ack_register to 1, so GHES can be
633
+ QDict *response;
167
+ * writeable after (re)boot.
634
+
168
+ * ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2
635
+ response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, "
169
+ * (GHESv2 - Type 10)
636
+ "'property': %s, 'value': %d } }", id, prop, value);
170
+ */
637
+ g_assert(qdict_haskey(response, "return"));
171
+ build_append_int_noprefix(hardware_errors, 1, sizeof(uint64_t));
638
+ qobject_unref(response);
172
+ }
639
+}
173
+
640
+
174
+ /* Generic Error Status Block offset in the hardware error fw_cfg blob */
641
+static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc)
175
+ error_status_block_offset = hardware_errors->len;
642
+{
176
+
643
+ int64_t value;
177
+ /* Reserve space for Error Status Data Block */
644
+ QI2CDevice *i2cdev = (QI2CDevice *)obj;
178
+ acpi_data_push(hardware_errors,
645
+
179
+ ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT);
646
+ /* Check default value for CRB */
180
+
647
+ g_assert_cmphex(i2c_get8(i2cdev, LSM303DLHC_MAG_REG_CRB), ==, 0x20);
181
+ /* Tell guest firmware to place hardware_errors blob into RAM */
648
+
182
+ bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE,
649
+ /* Set x to 1.0 gauss and verify the value */
183
+ hardware_errors, sizeof(uint64_t), false);
650
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-x", 100000);
184
+
651
+ value = qmp_lsm303dlhc_mag_get_property(
185
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
652
+ LSM303DLHC_MAG_TEST_ID, "mag-x");
186
+ /*
653
+ g_assert_cmpint(value, ==, 100000);
187
+ * Tell firmware to patch error_block_address entries to point to
654
+
188
+ * corresponding "Generic Error Status Block"
655
+ /* Set y to 1.5 gauss and verify the value */
189
+ */
656
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-y", 150000);
190
+ bios_linker_loader_add_pointer(linker,
657
+ value = qmp_lsm303dlhc_mag_get_property(
191
+ ACPI_GHES_ERRORS_FW_CFG_FILE, sizeof(uint64_t) * i,
658
+ LSM303DLHC_MAG_TEST_ID, "mag-y");
192
+ sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
659
+ g_assert_cmpint(value, ==, 150000);
193
+ error_status_block_offset + i * ACPI_GHES_MAX_RAW_DATA_LENGTH);
660
+
194
+ }
661
+ /* Set z to 0.5 gauss and verify the value */
195
+
662
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-z", 50000);
196
+ /*
663
+ value = qmp_lsm303dlhc_mag_get_property(
197
+ * tell firmware to write hardware_errors GPA into
664
+ LSM303DLHC_MAG_TEST_ID, "mag-z");
198
+ * hardware_errors_addr fw_cfg, once the former has been initialized.
665
+ g_assert_cmpint(value, ==, 50000);
199
+ */
666
+
200
+ bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE,
667
+ /* Set temperature to 23.6 C and verify the value */
201
+ 0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0);
668
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID,
202
+}
669
+ "temperature", 23600);
203
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
670
+ value = qmp_lsm303dlhc_mag_get_property(
671
+ LSM303DLHC_MAG_TEST_ID, "temperature");
672
+ /* Should return 23.5 C due to 0.125°C steps. */
673
+ g_assert_cmpint(value, ==, 23500);
674
+
675
+ /* Read raw x axis registers (1 gauss = 1100 at +/-1.3 g gain) */
676
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_OUT_X_H);
677
+ g_assert_cmphex(value, ==, 1100);
678
+
679
+ /* Read raw y axis registers (1.5 gauss = 1650 at +/- 1.3 g gain = ) */
680
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_OUT_Y_H);
681
+ g_assert_cmphex(value, ==, 1650);
682
+
683
+ /* Read raw z axis registers (0.5 gauss = 490 at +/- 1.3 g gain = ) */
684
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_OUT_Z_H);
685
+ g_assert_cmphex(value, ==, 490);
686
+
687
+ /* Read raw temperature registers with temp disabled (CRA = 0x10) */
688
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_TEMP_OUT_H);
689
+ g_assert_cmphex(value, ==, 0);
690
+
691
+ /* Enable temperature reads (CRA = 0x90) */
692
+ i2c_set8(i2cdev, LSM303DLHC_MAG_REG_CRA, 0x90);
693
+
694
+ /* Read raw temp registers (23.5 C = 188 at 1 lsb = 0.125 C) */
695
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_TEMP_OUT_H);
696
+ g_assert_cmphex(value, ==, 188);
697
+}
698
+
699
+static void reg_wraparound(void *obj, void *data, QGuestAllocator *alloc)
700
+{
701
+ uint8_t value[4];
702
+ QI2CDevice *i2cdev = (QI2CDevice *)obj;
703
+
704
+ /* Set x to 1.0 gauss, and y to 1.5 gauss for known test values */
705
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-x", 100000);
706
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-y", 150000);
707
+
708
+ /* Check that requesting 4 bytes starting at Y_H wraps around to X_L */
709
+ i2c_read_block(i2cdev, LSM303DLHC_MAG_REG_OUT_Y_H, value, 4);
710
+ /* 1.5 gauss = 1650 lsb = 0x672 */
711
+ g_assert_cmphex(value[0], ==, 0x06);
712
+ g_assert_cmphex(value[1], ==, 0x72);
713
+ /* 1.0 gauss = 1100 lsb = 0x44C */
714
+ g_assert_cmphex(value[2], ==, 0x04);
715
+ g_assert_cmphex(value[3], ==, 0x4C);
716
+
717
+ /* Check that requesting LSM303DLHC_MAG_REG_IRC wraps around to CRA */
718
+ i2c_read_block(i2cdev, LSM303DLHC_MAG_REG_IRC, value, 2);
719
+ /* Default value for IRC = 0x33 */
720
+ g_assert_cmphex(value[0], ==, 0x33);
721
+ /* Default value for CRA = 0x10 */
722
+ g_assert_cmphex(value[1], ==, 0x10);
723
+}
724
+
725
+static void lsm303dlhc_mag_register_nodes(void)
726
+{
727
+ QOSGraphEdgeOptions opts = {
728
+ .extra_device_opts = "id=" LSM303DLHC_MAG_TEST_ID ",address=0x1e"
729
+ };
730
+ add_qi2c_address(&opts, &(QI2CAddress) { 0x1E });
731
+
732
+ qos_node_create_driver("lsm303dlhc_mag", i2c_device_create);
733
+ qos_node_consumes("lsm303dlhc_mag", "i2c-bus", &opts);
734
+
735
+ qos_add_test("tx-rx", "lsm303dlhc_mag", send_and_receive, NULL);
736
+ qos_add_test("regwrap", "lsm303dlhc_mag", reg_wraparound, NULL);
737
+}
738
+libqos_init(lsm303dlhc_mag_register_nodes);
739
diff --git a/hw/sensor/Kconfig b/hw/sensor/Kconfig
204
index XXXXXXX..XXXXXXX 100644
740
index XXXXXXX..XXXXXXX 100644
205
--- a/hw/arm/virt-acpi-build.c
741
--- a/hw/sensor/Kconfig
206
+++ b/hw/arm/virt-acpi-build.c
742
+++ b/hw/sensor/Kconfig
207
@@ -XXX,XX +XXX,XX @@
743
@@ -XXX,XX +XXX,XX @@ config ADM1272
208
#include "sysemu/reset.h"
744
config MAX34451
209
#include "kvm_arm.h"
745
bool
210
#include "migration/vmstate.h"
746
depends on I2C
211
+#include "hw/acpi/ghes.h"
747
+
212
748
+config LSM303DLHC_MAG
213
#define ARM_SPI_BASE 32
749
+ bool
214
750
+ depends on I2C
215
@@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
751
diff --git a/hw/sensor/meson.build b/hw/sensor/meson.build
216
acpi_add_table(table_offsets, tables_blob);
217
build_spcr(tables_blob, tables->linker, vms);
218
219
+ if (vms->ras) {
220
+ build_ghes_error_table(tables->hardware_errors, tables->linker);
221
+ }
222
+
223
if (ms->numa_state->num_nodes > 0) {
224
acpi_add_table(table_offsets, tables_blob);
225
build_srat(tables_blob, tables->linker, vms);
226
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
227
index XXXXXXX..XXXXXXX 100644
752
index XXXXXXX..XXXXXXX 100644
228
--- a/hw/acpi/Kconfig
753
--- a/hw/sensor/meson.build
229
+++ b/hw/acpi/Kconfig
754
+++ b/hw/sensor/meson.build
230
@@ -XXX,XX +XXX,XX @@ config ACPI_HMAT
755
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_DPS310', if_true: files('dps310.c'))
231
bool
756
softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c'))
232
depends on ACPI
757
softmmu_ss.add(when: 'CONFIG_ADM1272', if_true: files('adm1272.c'))
233
758
softmmu_ss.add(when: 'CONFIG_MAX34451', if_true: files('max34451.c'))
234
+config ACPI_APEI
759
+softmmu_ss.add(when: 'CONFIG_LSM303DLHC_MAG', if_true: files('lsm303dlhc_mag.c'))
235
+ bool
760
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
236
+ depends on ACPI
237
+
238
config ACPI_PCI
239
bool
240
depends on ACPI && PCI
241
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
242
index XXXXXXX..XXXXXXX 100644
761
index XXXXXXX..XXXXXXX 100644
243
--- a/hw/acpi/Makefile.objs
762
--- a/tests/qtest/meson.build
244
+++ b/hw/acpi/Makefile.objs
763
+++ b/tests/qtest/meson.build
245
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
764
@@ -XXX,XX +XXX,XX @@ qos_test_ss.add(
246
common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
765
'eepro100-test.c',
247
common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o
766
'es1370-test.c',
248
common-obj-$(CONFIG_ACPI_HMAT) += hmat.o
767
'ipoctal232-test.c',
249
+common-obj-$(CONFIG_ACPI_APEI) += ghes.o
768
+ 'lsm303dlhc-mag-test.c',
250
common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
769
'max34451-test.c',
251
common-obj-$(call lnot,$(CONFIG_PC)) += acpi-x86-stub.o
770
'megasas-test.c',
252
771
'ne2000-test.c',
253
--
772
--
254
2.20.1
773
2.25.1
255
774
256
775
diff view generated by jsdifflib
Deleted patch
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
1
3
I and Xiang are willing to review the APEI-related patches and
4
volunteer as the reviewers for the HEST/GHES part.
5
6
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
7
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Acked-by: Michael S. Tsirkin <mst@redhat.com>
10
Message-id: 20200512030609.19593-11-gengdongjiu@huawei.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
MAINTAINERS | 9 +++++++++
14
1 file changed, 9 insertions(+)
15
16
diff --git a/MAINTAINERS b/MAINTAINERS
17
index XXXXXXX..XXXXXXX 100644
18
--- a/MAINTAINERS
19
+++ b/MAINTAINERS
20
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/bios-tables-test.c
21
F: tests/qtest/acpi-utils.[hc]
22
F: tests/data/acpi/
23
24
+ACPI/HEST/GHES
25
+R: Dongjiu Geng <gengdongjiu@huawei.com>
26
+R: Xiang Zheng <zhengxiang9@huawei.com>
27
+L: qemu-arm@nongnu.org
28
+S: Maintained
29
+F: hw/acpi/ghes.c
30
+F: include/hw/acpi/ghes.h
31
+F: docs/specs/acpi_hest_ghes.rst
32
+
33
ppc4xx
34
M: David Gibson <david@gibson.dropbear.id.au>
35
L: qemu-ppc@nongnu.org
36
--
37
2.20.1
38
39
diff view generated by jsdifflib