1
Mostly this is patches from me and RTH cleaning up and doing
1
target-arm queue: I have a lot more still in my to-review
2
more decodetree conversion for AArch32 Neon. The major new feature
2
queue, but my rule of thumb is when I get to 50 patches or
3
is Dongjiu Geng's patchset to report host memory errors to KVM guests;
3
so to send out what I have.
4
also a new aspeed board from Patrick Williams.
5
4
6
thanks
5
thanks
7
-- PMM
6
-- PMM
8
7
9
The following changes since commit 035b448b84f3557206abc44d786c5d3db2638f7d:
8
The following changes since commit 9a7beaad3dbba982f7a461d676b55a5c3851d312:
10
9
11
Merge remote-tracking branch 'remotes/gkurz/tags/9p-next-2020-05-14' into staging (2020-05-14 10:58:30 +0100)
10
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210304' into staging (2021-03-05 10:47:46 +0000)
12
11
13
are available in the Git repository at:
12
are available in the Git repository at:
14
13
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200514
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210305
16
15
17
for you to fetch changes up to e95485f85657be21135c17a9226e297c21e73360:
16
for you to fetch changes up to 2c669ff88ec6733420a000103a2b8b9e93df4945:
18
17
19
target/arm: Convert NEON VFMA, VFMS 3-reg-same insns to decodetree (2020-05-14 15:03:09 +0100)
18
hw/arm/mps2: Update old infocenter.arm.com URLs (2021-03-05 15:17:38 +0000)
20
19
21
----------------------------------------------------------------
20
----------------------------------------------------------------
22
target-arm queue:
21
* sbsa-ref: remove cortex-a53 from list of supported cpus
23
* target/arm: Use correct GDB XML for M-profile cores
22
* sbsa-ref: add 'max' to list of allowed cpus
24
* target/arm: Code cleanup to use gvec APIs better
23
* target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
25
* aspeed: Add support for the sonorapass-bmc board
24
* npcm7xx: add EMC model
26
* target/arm: Support reporting KVM host memory errors
25
* xlnx-zynqmp: Remove obsolete 'has_rpu' property
27
to the guest via ACPI notifications
26
* target/arm: Speed up aarch64 TBL/TBX
28
* target/arm: Finish conversion of Neon 3-reg-same insns to decodetree
27
* virtio-mmio: improve virtio-mmio get_dev_path alog
28
* target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
29
* target/arm: Restrict v8M IDAU to TCG
30
* target/arm/cpu: Update coding style to make checkpatch.pl happy
31
* musicpal, tc6393xb, omap_lcdc, tcx: drop dead code for non-32-bit-RGB surfaces
32
* Add new board: mps3-an524
29
33
30
----------------------------------------------------------------
34
----------------------------------------------------------------
31
Dongjiu Geng (10):
35
Doug Evans (3):
32
acpi: nvdimm: change NVDIMM_UUID_LE to a common macro
36
hw/net: Add npcm7xx emc model
33
hw/arm/virt: Introduce a RAS machine option
37
hw/arm: Add npcm7xx emc model
34
docs: APEI GHES generation and CPER record description
38
tests/qtests: Add npcm7xx emc model test
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
39
43
Patrick Williams (1):
40
Marcin Juszkiewicz (2):
44
aspeed: Add support for the sonorapass-bmc board
41
sbsa-ref: remove cortex-a53 from list of supported cpus
42
sbsa-ref: add 'max' to list of allowed cpus
45
43
46
Peter Maydell (18):
44
Peter Collingbourne (1):
47
target/arm: Use correct GDB XML for M-profile cores
45
target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
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
46
66
Richard Henderson (16):
47
Peter Maydell (34):
67
target/arm: Create gen_gvec_[us]sra
48
hw/arm/musicpal: Remove dead code for non-32-bit-RGB surfaces
68
target/arm: Create gen_gvec_{u,s}{rshr,rsra}
49
hw/display/tc6393xb: Remove dead code for handling non-32bpp surfaces
69
target/arm: Create gen_gvec_{sri,sli}
50
hw/display/tc6393xb: Expand out macros in template header
70
target/arm: Remove unnecessary range check for VSHL
51
hw/display/tc6393xb: Inline tc6393xb_draw_graphic32() at its callsite
71
target/arm: Tidy handle_vec_simd_shri
52
hw/display/omap_lcdc: Expand out macros in template header
72
target/arm: Create gen_gvec_{ceq,clt,cle,cgt,cge}0
53
hw/display/omap_lcdc: Drop broken bigendian ifdef
73
target/arm: Create gen_gvec_{mla,mls}
54
hw/display/omap_lcdc: Fix coding style issues in template header
74
target/arm: Swap argument order for VSHL during decode
55
hw/display/omap_lcdc: Inline template header into C file
75
target/arm: Create gen_gvec_{cmtst,ushl,sshl}
56
hw/display/omap_lcdc: Delete unnecessary macro
76
target/arm: Create gen_gvec_{uqadd, sqadd, uqsub, sqsub}
57
hw/display/tcx: Drop unnecessary code for handling BGR format outputs
77
target/arm: Remove fp_status from helper_{recpe, rsqrte}_u32
58
hw/arm/mps2-tz: Make SYSCLK frequency board-specific
78
target/arm: Create gen_gvec_{qrdmla,qrdmls}
59
hw/misc/mps2-scc: Support configurable number of OSCCLK values
79
target/arm: Pass pointer to qc to qrdmla/qrdmls
60
hw/arm/mps2-tz: Correct the OSCCLK settings for mps2-an505 and mps2-an511
80
target/arm: Clear tail in gvec_fmul_idx_*, gvec_fmla_idx_*
61
hw/arm/mps2-tz: Make the OSCCLK settings be configurable per-board
81
target/arm: Vectorize SABD/UABD
62
hw/misc/mps2-fpgaio: Make number of LEDs configurable by board
82
target/arm: Vectorize SABA/UABA
63
hw/misc/mps2-fpgaio: Support SWITCH register
64
hw/arm/mps2-tz: Make FPGAIO switch and LED config per-board
65
hw/arm/mps2-tz: Condition IRQ splitting on number of CPUs, not board type
66
hw/arm/mps2-tz: Make number of IRQs board-specific
67
hw/misc/mps2-scc: Implement CFG_REG5 and CFG_REG6 for MPS3 AN524
68
hw/arm/mps2-tz: Correct wrong interrupt numbers for DMA and SPI
69
hw/arm/mps2-tz: Allow PPCPortInfo structures to specify device interrupts
70
hw/arm/mps2-tz: Move device IRQ info to data structures
71
hw/arm/mps2-tz: Size the uart-irq-orgate based on the number of UARTs
72
hw/arm/mps2-tz: Allow boards to have different PPCInfo data
73
hw/arm/mps2-tz: Make RAM arrangement board-specific
74
hw/arm/mps2-tz: Set MachineClass default_ram info from RAMInfo data
75
hw/arm/mps2-tz: Support ROMs as well as RAMs
76
hw/arm/mps2-tz: Get armv7m_load_kernel() size argument from RAMInfo
77
hw/arm/mps2-tz: Add new mps3-an524 board
78
hw/arm/mps2-tz: Stub out USB controller for mps3-an524
79
hw/arm/mps2-tz: Provide PL031 RTC on mps3-an524
80
docs/system/arm/mps2.rst: Document the new mps3-an524 board
81
hw/arm/mps2: Update old infocenter.arm.com URLs
83
82
84
docs/specs/acpi_hest_ghes.rst | 110 ++
83
Philippe Mathieu-Daudé (4):
85
docs/specs/index.rst | 1 +
84
hw/arm/xlnx-zynqmp: Remove obsolete 'has_rpu' property
86
configure | 4 +-
85
hw/i2c/npcm7xx_smbus: Simplify npcm7xx_smbus_init()
87
default-configs/arm-softmmu.mak | 1 +
86
target/arm: Restrict v8M IDAU to TCG
88
include/hw/acpi/aml-build.h | 1 +
87
target/arm/cpu: Update coding style to make checkpatch.pl happy
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
88
89
Rebecca Cran (3):
90
target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
91
target/arm: Enable FEAT_SSBS for "max" AARCH64 CPU
92
target/arm: Set ID_PFR2.SSBS to 1 for "max" 32-bit CPU
93
94
Richard Henderson (1):
95
target/arm: Speed up aarch64 TBL/TBX
96
97
schspa (1):
98
virtio-mmio: improve virtio-mmio get_dev_path alog
99
100
docs/system/arm/mps2.rst | 24 +-
101
docs/system/arm/nuvoton.rst | 3 +-
102
hw/display/omap_lcd_template.h | 169 --------
103
hw/display/tc6393xb_template.h | 72 ----
104
include/hw/arm/armsse.h | 4 +-
105
include/hw/arm/npcm7xx.h | 2 +
106
include/hw/arm/xlnx-zynqmp.h | 2 -
107
include/hw/misc/armsse-cpuid.h | 2 +-
108
include/hw/misc/armsse-mhu.h | 2 +-
109
include/hw/misc/iotkit-secctl.h | 2 +-
110
include/hw/misc/iotkit-sysctl.h | 2 +-
111
include/hw/misc/iotkit-sysinfo.h | 2 +-
112
include/hw/misc/mps2-fpgaio.h | 8 +-
113
include/hw/misc/mps2-scc.h | 10 +-
114
include/hw/net/npcm7xx_emc.h | 286 +++++++++++++
115
include/ui/console.h | 10 -
116
target/arm/cpu.h | 15 +-
117
target/arm/helper-a64.h | 2 +-
118
target/arm/internals.h | 6 +
119
hw/arm/mps2-tz.c | 632 +++++++++++++++++++++++-----
120
hw/arm/mps2.c | 5 +
121
hw/arm/musicpal.c | 64 ++-
122
hw/arm/npcm7xx.c | 50 ++-
123
hw/arm/sbsa-ref.c | 2 +-
124
hw/arm/xlnx-zynqmp.c | 6 -
125
hw/display/omap_lcdc.c | 129 +++++-
126
hw/display/tc6393xb.c | 48 +--
127
hw/display/tcx.c | 31 +-
128
hw/i2c/npcm7xx_smbus.c | 1 -
129
hw/misc/armsse-cpuid.c | 2 +-
130
hw/misc/armsse-mhu.c | 2 +-
131
hw/misc/iotkit-sysctl.c | 2 +-
132
hw/misc/iotkit-sysinfo.c | 2 +-
133
hw/misc/mps2-fpgaio.c | 43 +-
134
hw/misc/mps2-scc.c | 93 ++++-
135
hw/net/npcm7xx_emc.c | 857 ++++++++++++++++++++++++++++++++++++++
136
hw/virtio/virtio-mmio.c | 13 +-
137
target/arm/cpu.c | 23 +-
138
target/arm/cpu64.c | 5 +
139
target/arm/cpu_tcg.c | 8 +
140
target/arm/helper-a64.c | 32 --
141
target/arm/helper.c | 39 +-
142
target/arm/mte_helper.c | 13 +-
143
target/arm/translate-a64.c | 70 +---
144
target/arm/vec_helper.c | 48 +++
145
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++++++++
146
hw/net/meson.build | 1 +
147
hw/net/trace-events | 17 +
148
tests/qtest/meson.build | 3 +-
149
49 files changed, 3098 insertions(+), 628 deletions(-)
150
delete mode 100644 hw/display/omap_lcd_template.h
151
delete mode 100644 hw/display/tc6393xb_template.h
152
create mode 100644 include/hw/net/npcm7xx_emc.h
153
create mode 100644 hw/net/npcm7xx_emc.c
154
create mode 100644 tests/qtest/npcm7xx_emc-test.c
155
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
Include 64-bit element size in preparation for SVE2.
3
Cortex-A53 supports 40bits of address space. sbsa-ref's memory starts
4
above this limit.
4
5
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20200513163245.17915-17-richard.henderson@linaro.org
8
Acked-by: Leif Lindholm <leif@nuviainc.com>
9
Message-id: 20210216150122.3830863-2-marcin.juszkiewicz@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
hw/arm/sbsa-ref.c | 1 -
11
target/arm/translate.h | 5 ++
13
1 file changed, 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/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
17
--- a/hw/arm/sbsa-ref.c
21
+++ b/target/arm/helper.h
18
+++ b/hw/arm/sbsa-ref.c
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(neon_pmax_s8, i32, i32, i32)
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
23
DEF_HELPER_2(neon_pmax_u16, i32, i32, i32)
20
};
24
DEF_HELPER_2(neon_pmax_s16, i32, i32, i32)
21
25
22
static const char * const valid_cpus[] = {
26
-DEF_HELPER_2(neon_abd_u8, i32, i32, i32)
23
- ARM_CPU_TYPE_NAME("cortex-a53"),
27
-DEF_HELPER_2(neon_abd_s8, i32, i32, i32)
24
ARM_CPU_TYPE_NAME("cortex-a57"),
28
-DEF_HELPER_2(neon_abd_u16, i32, i32, i32)
25
ARM_CPU_TYPE_NAME("cortex-a72"),
29
-DEF_HELPER_2(neon_abd_s16, i32, i32, i32)
26
};
30
-DEF_HELPER_2(neon_abd_u32, i32, i32, i32)
31
-DEF_HELPER_2(neon_abd_s32, i32, i32, i32)
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
--
27
--
317
2.20.1
28
2.20.1
318
29
319
30
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
I and Xiang are willing to review the APEI-related patches and
3
Let add 'max' cpu while work goes on adding newer CPU types than
4
volunteer as the reviewers for the HEST/GHES part.
4
Cortex-A72. This allows us to check SVE etc support.
5
5
6
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
7
Acked-by: Leif Lindholm <leif@nuviainc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Acked-by: Michael S. Tsirkin <mst@redhat.com>
9
Message-id: 20210216150122.3830863-3-marcin.juszkiewicz@linaro.org
10
Message-id: 20200512030609.19593-11-gengdongjiu@huawei.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
MAINTAINERS | 9 +++++++++
12
hw/arm/sbsa-ref.c | 1 +
14
1 file changed, 9 insertions(+)
13
1 file changed, 1 insertion(+)
15
14
16
diff --git a/MAINTAINERS b/MAINTAINERS
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/MAINTAINERS
17
--- a/hw/arm/sbsa-ref.c
19
+++ b/MAINTAINERS
18
+++ b/hw/arm/sbsa-ref.c
20
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/bios-tables-test.c
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
21
F: tests/qtest/acpi-utils.[hc]
20
static const char * const valid_cpus[] = {
22
F: tests/data/acpi/
21
ARM_CPU_TYPE_NAME("cortex-a57"),
23
22
ARM_CPU_TYPE_NAME("cortex-a72"),
24
+ACPI/HEST/GHES
23
+ ARM_CPU_TYPE_NAME("max"),
25
+R: Dongjiu Geng <gengdongjiu@huawei.com>
24
};
26
+R: Xiang Zheng <zhengxiang9@huawei.com>
25
27
+L: qemu-arm@nongnu.org
26
static bool cpu_type_valid(const char *cpu)
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
--
27
--
37
2.20.1
28
2.20.1
38
29
39
30
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Rebecca Cran <rebecca@nuviainc.com>
2
2
3
Add a SIGBUS signal handler. In this handler, it checks the SIGBUS type,
3
Add support for FEAT_SSBS. SSBS (Speculative Store Bypass Safe) is an
4
translates the host VA delivered by host to guest PA, then fills this PA
4
optional feature in ARMv8.0, and mandatory in ARMv8.5.
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: Rebecca Cran <rebecca@nuviainc.com>
9
External Abort(SEA). Then host kernel gets an APEI notification and calls
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
memory_failure() to unmapped the affected page in stage 2, finally
8
Message-id: 20210216224543.16142-2-rebecca@nuviainc.com
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>
33
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
34
Message-id: 20200512030609.19593-10-gengdongjiu@huawei.com
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
---
10
---
37
include/sysemu/kvm.h | 3 +-
11
target/arm/cpu.h | 15 ++++++++++++++-
38
target/arm/cpu.h | 4 +++
12
target/arm/internals.h | 6 ++++++
39
target/arm/internals.h | 5 +--
13
target/arm/helper.c | 37 +++++++++++++++++++++++++++++++++++++
40
target/i386/cpu.h | 2 ++
14
target/arm/translate-a64.c | 12 ++++++++++++
41
target/arm/helper.c | 2 +-
15
4 files changed, 69 insertions(+), 1 deletion(-)
42
target/arm/kvm64.c | 77 +++++++++++++++++++++++++++++++++++++++++
43
target/arm/tlb_helper.c | 2 +-
44
7 files changed, 89 insertions(+), 6 deletions(-)
45
16
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
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
61
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
63
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
64
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
65
/* ARM processors have a weak memory model */
22
#define SCTLR_TE (1U << 30) /* AArch32 only */
66
#define TCG_GUEST_DEFAULT_MO (0)
23
#define SCTLR_EnIB (1U << 30) /* v8.3, AArch64 only */
67
24
#define SCTLR_EnIA (1U << 31) /* v8.3, AArch64 only */
68
+#ifdef TARGET_AARCH64
25
+#define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */
69
+#define KVM_HAVE_MCE_INJECTION 1
26
#define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */
70
+#endif
27
#define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */
28
#define SCTLR_ITFSB (1ULL << 37) /* v8.5-MemTag */
29
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
30
#define SCTLR_TCF (3ULL << 40) /* v8.5-MemTag */
31
#define SCTLR_ATA0 (1ULL << 42) /* v8.5-MemTag */
32
#define SCTLR_ATA (1ULL << 43) /* v8.5-MemTag */
33
-#define SCTLR_DSSBS (1ULL << 44) /* v8.5 */
34
+#define SCTLR_DSSBS_64 (1ULL << 44) /* v8.5, AArch64 only */
35
36
#define CPTR_TCPAC (1U << 31)
37
#define CPTR_TTA (1U << 20)
38
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
39
#define CPSR_IL (1U << 20)
40
#define CPSR_DIT (1U << 21)
41
#define CPSR_PAN (1U << 22)
42
+#define CPSR_SSBS (1U << 23)
43
#define CPSR_J (1U << 24)
44
#define CPSR_IT_0_1 (3U << 25)
45
#define CPSR_Q (1U << 27)
46
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
47
#define PSTATE_A (1U << 8)
48
#define PSTATE_D (1U << 9)
49
#define PSTATE_BTYPE (3U << 10)
50
+#define PSTATE_SSBS (1U << 12)
51
#define PSTATE_IL (1U << 20)
52
#define PSTATE_SS (1U << 21)
53
#define PSTATE_PAN (1U << 22)
54
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
55
return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0;
56
}
57
58
+static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
59
+{
60
+ return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
61
+}
71
+
62
+
72
#define EXCP_UDEF 1 /* undefined instruction */
63
/*
73
#define EXCP_SWI 2 /* software interrupt */
64
* 64-bit feature tests via id registers.
74
#define EXCP_PREFETCH_ABORT 3
65
*/
66
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
67
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
68
}
69
70
+static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
71
+{
72
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
73
+}
74
+
75
/*
76
* Feature tests for "does this exist in either 32-bit or 64-bit?"
77
*/
75
diff --git a/target/arm/internals.h b/target/arm/internals.h
78
diff --git a/target/arm/internals.h b/target/arm/internals.h
76
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/internals.h
80
--- a/target/arm/internals.h
78
+++ b/target/arm/internals.h
81
+++ 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)
82
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch32_cpsr_valid_mask(uint64_t features,
80
| ARM_EL_IL | (ea << 9) | (s1ptw << 7) | fsc;
83
if (isar_feature_aa32_dit(id)) {
84
valid |= CPSR_DIT;
85
}
86
+ if (isar_feature_aa32_ssbs(id)) {
87
+ valid |= CPSR_SSBS;
88
+ }
89
90
return valid;
81
}
91
}
82
92
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
83
-static inline uint32_t syn_data_abort_no_iss(int same_el,
93
if (isar_feature_aa64_dit(id)) {
84
+static inline uint32_t syn_data_abort_no_iss(int same_el, int fnv,
94
valid |= PSTATE_DIT;
85
int ea, int cm, int s1ptw,
95
}
86
int wnr, int fsc)
96
+ if (isar_feature_aa64_ssbs(id)) {
87
{
97
+ valid |= PSTATE_SSBS;
88
return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
98
+ }
89
| ARM_EL_IL
99
if (isar_feature_aa64_mte(id)) {
90
- | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
100
valid |= PSTATE_TCO;
91
+ | (fnv << 10) | (ea << 9) | (cm << 8) | (s1ptw << 7)
101
}
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
102
diff --git a/target/arm/helper.c b/target/arm/helper.c
110
index XXXXXXX..XXXXXXX 100644
103
index XXXXXXX..XXXXXXX 100644
111
--- a/target/arm/helper.c
104
--- a/target/arm/helper.c
112
+++ b/target/arm/helper.c
105
+++ b/target/arm/helper.c
113
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
106
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dit_reginfo = {
114
* Report exception with ESR indicating a fault due to a
107
.readfn = aa64_dit_read, .writefn = aa64_dit_write
115
* translation table walk for a cache maintenance instruction.
108
};
116
*/
109
117
- syn = syn_data_abort_no_iss(current_el == target_el,
110
+static uint64_t aa64_ssbs_read(CPUARMState *env, const ARMCPRegInfo *ri)
118
+ syn = syn_data_abort_no_iss(current_el == target_el, 0,
119
fi.ea, 1, fi.s1ptw, 1, fsc);
120
env->exception.vaddress = value;
121
env->exception.fsr = fsr;
122
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/target/arm/kvm64.c
125
+++ b/target/arm/kvm64.c
126
@@ -XXX,XX +XXX,XX @@
127
#include "sysemu/kvm_int.h"
128
#include "kvm_arm.h"
129
#include "internals.h"
130
+#include "hw/acpi/acpi.h"
131
+#include "hw/acpi/ghes.h"
132
+#include "hw/arm/virt.h"
133
134
static bool have_guest_debug;
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
+{
111
+{
143
+ ARMCPU *cpu = ARM_CPU(c);
112
+ return env->pstate & PSTATE_SSBS;
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
+}
113
+}
163
+
114
+
164
#define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
115
+static void aa64_ssbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
165
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
116
+ uint64_t value)
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
+{
117
+{
173
+ ram_addr_t ram_addr;
118
+ env->pstate = (env->pstate & ~PSTATE_SSBS) | (value & PSTATE_SSBS);
174
+ hwaddr paddr;
119
+}
175
+ Object *obj = qdev_get_machine();
176
+ VirtMachineState *vms = VIRT_MACHINE(obj);
177
+ bool acpi_enabled = virt_is_acpi_enabled(vms);
178
+
120
+
179
+ assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
121
+static const ARMCPRegInfo ssbs_reginfo = {
122
+ .name = "SSBS", .state = ARM_CP_STATE_AA64,
123
+ .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 6,
124
+ .type = ARM_CP_NO_RAW, .access = PL0_RW,
125
+ .readfn = aa64_ssbs_read, .writefn = aa64_ssbs_write
126
+};
180
+
127
+
181
+ if (acpi_enabled && addr &&
128
static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env,
182
+ object_property_get_bool(obj, "ras", NULL)) {
129
const ARMCPRegInfo *ri,
183
+ ram_addr = qemu_ram_addr_from_host(addr);
130
bool isread)
184
+ if (ram_addr != RAM_ADDR_INVALID &&
131
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
185
+ kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
132
if (cpu_isar_feature(aa64_dit, cpu)) {
186
+ kvm_hwpoison_page_add(ram_addr);
133
define_one_arm_cp_reg(cpu, &dit_reginfo);
187
+ /*
134
}
188
+ * If this is a BUS_MCEERR_AR, we know we have been called
135
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
189
+ * synchronously from the vCPU thread, so we can easily
136
+ define_one_arm_cp_reg(cpu, &ssbs_reginfo);
190
+ * synchronize the state and inject an error.
137
+ }
191
+ *
138
192
+ * TODO: we currently don't tell the guest at all about
139
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
193
+ * BUS_MCEERR_AO. In that case we might either be being
140
define_arm_cp_regs(cpu, vhe_reginfo);
194
+ * called synchronously from the vCPU thread, or a bit
141
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
195
+ * later from the main thread, so doing the injection of
142
env->uncached_cpsr &= ~(CPSR_IL | CPSR_J);
196
+ * the error would be more complicated.
143
env->daif |= mask;
197
+ */
144
198
+ if (code == BUS_MCEERR_AR) {
145
+ if (cpu_isar_feature(aa32_ssbs, env_archcpu(env))) {
199
+ kvm_cpu_synchronize_state(c);
146
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_32) {
200
+ if (!acpi_ghes_record_errors(ACPI_HEST_SRC_ID_SEA, paddr)) {
147
+ env->uncached_cpsr |= CPSR_SSBS;
201
+ kvm_inject_arm_sea(c);
148
+ } else {
202
+ } else {
149
+ env->uncached_cpsr &= ~CPSR_SSBS;
203
+ error_report("failed to record the error");
204
+ abort();
205
+ }
206
+ }
207
+ return;
208
+ }
209
+ if (code == BUS_MCEERR_AO) {
210
+ error_report("Hardware memory error at addr %p for memory used by "
211
+ "QEMU itself instead of guest system!", addr);
212
+ }
150
+ }
213
+ }
151
+ }
214
+
152
+
215
+ if (code == BUS_MCEERR_AR) {
153
if (new_mode == ARM_CPU_MODE_HYP) {
216
+ error_report("Hardware memory error!");
154
env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
217
+ exit(1);
155
env->elr_el[2] = env->regs[15];
156
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
157
new_mode |= PSTATE_TCO;
158
}
159
160
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
161
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_64) {
162
+ new_mode |= PSTATE_SSBS;
163
+ } else {
164
+ new_mode &= ~PSTATE_SSBS;
165
+ }
218
+ }
166
+ }
219
+}
220
+
167
+
221
/* C6.6.29 BRK instruction */
168
pstate_write(env, PSTATE_DAIF | new_mode);
222
static const uint32_t brk_insn = 0xd4200000;
169
env->aarch64 = 1;
223
170
aarch64_restore_sp(env, new_el);
224
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
171
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
225
index XXXXXXX..XXXXXXX 100644
172
index XXXXXXX..XXXXXXX 100644
226
--- a/target/arm/tlb_helper.c
173
--- a/target/arm/translate-a64.c
227
+++ b/target/arm/tlb_helper.c
174
+++ b/target/arm/translate-a64.c
228
@@ -XXX,XX +XXX,XX @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
175
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
229
* ISV field.
176
tcg_temp_free_i32(t1);
230
*/
177
break;
231
if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
178
232
- syn = syn_data_abort_no_iss(same_el,
179
+ case 0x19: /* SSBS */
233
+ syn = syn_data_abort_no_iss(same_el, 0,
180
+ if (!dc_isar_feature(aa64_ssbs, s)) {
234
ea, 0, s1ptw, is_write, fsc);
181
+ goto do_unallocated;
235
} else {
182
+ }
236
/*
183
+ if (crm & 1) {
184
+ set_pstate_bits(PSTATE_SSBS);
185
+ } else {
186
+ clear_pstate_bits(PSTATE_SSBS);
187
+ }
188
+ /* Don't need to rebuild hflags since SSBS is a nop */
189
+ break;
190
+
191
case 0x1a: /* DIT */
192
if (!dc_isar_feature(aa64_dit, s)) {
193
goto do_unallocated;
237
--
194
--
238
2.20.1
195
2.20.1
239
196
240
197
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Rebecca Cran <rebecca@nuviainc.com>
2
2
3
Rather than perform the argument swap during code generation,
3
Set ID_AA64PFR1_EL1.SSBS to 2 and ID_PFR2.SSBS to 1.
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
4
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200513163245.17915-9-richard.henderson@linaro.org
7
Message-id: 20210216224543.16142-3-rebecca@nuviainc.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
9
---
14
target/arm/neon-dp.decode | 17 +++++++++++++++--
10
target/arm/cpu64.c | 5 +++++
15
target/arm/translate-neon.inc.c | 3 +--
11
1 file changed, 5 insertions(+)
16
2 files changed, 16 insertions(+), 4 deletions(-)
17
12
18
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/neon-dp.decode
15
--- a/target/arm/cpu64.c
21
+++ b/target/arm/neon-dp.decode
16
+++ b/target/arm/cpu64.c
22
@@ -XXX,XX +XXX,XX @@ VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same
17
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
23
VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same
18
24
VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same
19
t = cpu->isar.id_aa64pfr1;
25
20
t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
26
-VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same
21
+ t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2);
27
-VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same
22
/*
28
+# The _rev suffix indicates that Vn and Vm are reversed. This is
23
* Begin with full support for MTE. This will be downgraded to MTE=0
29
+# the case for shifts. In the Arm ARM these insns are documented
24
* during realize if the board provides no tag memory, much like
30
+# with the Vm and Vn fields in their usual places, but in the
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
31
+# assembly the operands are listed "backwards", ie in the order
26
u = FIELD_DP32(u, ID_PFR0, DIT, 1);
32
+# Dd, Dm, Dn where other insns use Dd, Dn, Dm. For QEMU we choose
27
cpu->isar.id_pfr0 = u;
33
+# to consider Vm and Vn as being in different fields in the insn,
28
34
+# which allows us to avoid special-casing shifts in the trans_
29
+ u = cpu->isar.id_pfr2;
35
+# function code. We would otherwise need to manually swap the operands
30
+ u = FIELD_DP32(u, ID_PFR2, SSBS, 1);
36
+# over to call Neon helper functions that are shared with AArch64,
31
+ cpu->isar.id_pfr2 = u;
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
+
32
+
41
+VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same_rev
33
u = cpu->isar.id_mmfr3;
42
+VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
34
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
43
35
cpu->isar.id_mmfr3 = u;
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
--
36
--
61
2.20.1
37
2.20.1
62
38
63
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Rebecca Cran <rebecca@nuviainc.com>
2
2
3
In 1dc8425e551, while converting to gvec, I added an extra range check
3
Enable FEAT_SSBS for the "max" 32-bit CPU.
4
against the shift count. This was unnecessary because the encoding of
5
the shift count produces 0 to the element size - 1.
6
4
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-5-richard.henderson@linaro.org
7
Message-id: 20210216224543.16142-4-rebecca@nuviainc.com
8
[PMM: fix typo causing compilation failure]
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.c | 12 ++----------
11
target/arm/cpu.c | 4 ++++
13
1 file changed, 2 insertions(+), 10 deletions(-)
12
1 file changed, 4 insertions(+)
14
13
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.c
16
--- a/target/arm/cpu.c
18
+++ b/target/arm/translate.c
17
+++ b/target/arm/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
20
gen_gvec_sli(size, rd_ofs, rm_ofs, shift,
19
t = cpu->isar.id_pfr0;
21
vec_size, vec_size);
20
t = FIELD_DP32(t, ID_PFR0, DIT, 1);
22
} else { /* VSHL */
21
cpu->isar.id_pfr0 = t;
23
- /* Shifts larger than the element size are
22
+
24
- * architecturally valid and results in zero.
23
+ t = cpu->isar.id_pfr2;
25
- */
24
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
26
- if (shift >= 8 << size) {
25
+ cpu->isar.id_pfr2 = t;
27
- tcg_gen_gvec_dup_imm(size, rd_ofs,
26
}
28
- vec_size, vec_size, 0);
27
#endif
29
- } else {
28
}
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
--
29
--
39
2.20.1
30
2.20.1
40
31
41
32
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Doug Evans <dje@google.com>
2
2
3
This patch builds error_block_address and read_ack_register fields
3
This is a 10/100 ethernet device that has several features.
4
in hardware errors table , the error_block_address points to Generic
4
Only the ones needed by the Linux driver have been implemented.
5
Error Status Block(GESB) via bios_linker. The max size for one GESB
5
See npcm7xx_emc.c for a list of unimplemented features.
6
is 1kb, For more detailed information, please refer to
7
document: docs/specs/acpi_hest_ghes.rst
8
6
9
Now we only support one Error source, if necessary, we can extend to
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
10
support more.
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
11
9
Signed-off-by: Doug Evans <dje@google.com>
12
Suggested-by: Laszlo Ersek <lersek@redhat.com>
10
Message-id: 20210218212453.831406-2-dje@google.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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
12
---
21
default-configs/arm-softmmu.mak | 1 +
13
include/hw/net/npcm7xx_emc.h | 286 ++++++++++++
22
include/hw/acpi/aml-build.h | 1 +
14
hw/net/npcm7xx_emc.c | 857 +++++++++++++++++++++++++++++++++++
23
include/hw/acpi/ghes.h | 28 +++++++++++
15
hw/net/meson.build | 1 +
24
hw/acpi/aml-build.c | 2 +
16
hw/net/trace-events | 17 +
25
hw/acpi/ghes.c | 89 +++++++++++++++++++++++++++++++++
17
4 files changed, 1161 insertions(+)
26
hw/arm/virt-acpi-build.c | 5 ++
18
create mode 100644 include/hw/net/npcm7xx_emc.h
27
hw/acpi/Kconfig | 4 ++
19
create mode 100644 hw/net/npcm7xx_emc.c
28
hw/acpi/Makefile.objs | 1 +
29
8 files changed, 131 insertions(+)
30
create mode 100644 include/hw/acpi/ghes.h
31
create mode 100644 hw/acpi/ghes.c
32
20
33
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
21
diff --git a/include/hw/net/npcm7xx_emc.h b/include/hw/net/npcm7xx_emc.h
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
22
new file mode 100644
56
index XXXXXXX..XXXXXXX
23
index XXXXXXX..XXXXXXX
57
--- /dev/null
24
--- /dev/null
58
+++ b/include/hw/acpi/ghes.h
25
+++ b/include/hw/net/npcm7xx_emc.h
59
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
60
+/*
27
+/*
61
+ * Support for generating APEI tables and recording CPER for Guests
28
+ * Nuvoton NPCM7xx EMC Module
62
+ *
29
+ *
63
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
30
+ * Copyright 2020 Google LLC
64
+ *
31
+ *
65
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
32
+ * This program is free software; you can redistribute it and/or modify it
33
+ * under the terms of the GNU General Public License as published by the
34
+ * Free Software Foundation; either version 2 of the License, or
35
+ * (at your option) any later version.
66
+ *
36
+ *
67
+ * This program is free software; you can redistribute it and/or modify
37
+ * This program is distributed in the hope that it will be useful, but WITHOUT
68
+ * it under the terms of the GNU General Public License as published by
38
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
69
+ * the Free Software Foundation; either version 2 of the License, or
39
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
70
+ * (at your option) any later version.
40
+ * for more details.
71
+
72
+ * This program is distributed in the hope that it will be useful,
73
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
74
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75
+ * GNU General Public License for more details.
76
+
77
+ * You should have received a copy of the GNU General Public License along
78
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
79
+ */
41
+ */
80
+
42
+
81
+#ifndef ACPI_GHES_H
43
+#ifndef NPCM7XX_EMC_H
82
+#define ACPI_GHES_H
44
+#define NPCM7XX_EMC_H
83
+
45
+
84
+#include "hw/acpi/bios-linker-loader.h"
46
+#include "hw/irq.h"
85
+
47
+#include "hw/sysbus.h"
86
+void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
48
+#include "net/net.h"
87
+#endif
49
+
88
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
50
+/* 32-bit register indices. */
89
index XXXXXXX..XXXXXXX 100644
51
+enum NPCM7xxPWMRegister {
90
--- a/hw/acpi/aml-build.c
52
+ /* Control registers. */
91
+++ b/hw/acpi/aml-build.c
53
+ REG_CAMCMR,
92
@@ -XXX,XX +XXX,XX @@ void acpi_build_tables_init(AcpiBuildTables *tables)
54
+ REG_CAMEN,
93
tables->table_data = g_array_new(false, true /* clear */, 1);
55
+
94
tables->tcpalog = g_array_new(false, true /* clear */, 1);
56
+ /* There are 16 CAMn[ML] registers. */
95
tables->vmgenid = g_array_new(false, true /* clear */, 1);
57
+ REG_CAMM_BASE,
96
+ tables->hardware_errors = g_array_new(false, true /* clear */, 1);
58
+ REG_CAML_BASE,
97
tables->linker = bios_linker_loader_init();
59
+ REG_CAMML_LAST = 0x21,
98
}
60
+
99
61
+ REG_TXDLSA = 0x22,
100
@@ -XXX,XX +XXX,XX @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
62
+ REG_RXDLSA,
101
g_array_free(tables->table_data, true);
63
+ REG_MCMDR,
102
g_array_free(tables->tcpalog, mfre);
64
+ REG_MIID,
103
g_array_free(tables->vmgenid, mfre);
65
+ REG_MIIDA,
104
+ g_array_free(tables->hardware_errors, mfre);
66
+ REG_FFTCR,
105
}
67
+ REG_TSDR,
106
68
+ REG_RSDR,
107
/*
69
+ REG_DMARFC,
108
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
70
+ REG_MIEN,
71
+
72
+ /* Status registers. */
73
+ REG_MISTA,
74
+ REG_MGSTA,
75
+ REG_MPCNT,
76
+ REG_MRPC,
77
+ REG_MRPCC,
78
+ REG_MREPC,
79
+ REG_DMARFS,
80
+ REG_CTXDSA,
81
+ REG_CTXBSA,
82
+ REG_CRXDSA,
83
+ REG_CRXBSA,
84
+
85
+ NPCM7XX_NUM_EMC_REGS,
86
+};
87
+
88
+/* REG_CAMCMR fields */
89
+/* Enable CAM Compare */
90
+#define REG_CAMCMR_ECMP (1 << 4)
91
+/* Complement CAM Compare */
92
+#define REG_CAMCMR_CCAM (1 << 3)
93
+/* Accept Broadcast Packet */
94
+#define REG_CAMCMR_ABP (1 << 2)
95
+/* Accept Multicast Packet */
96
+#define REG_CAMCMR_AMP (1 << 1)
97
+/* Accept Unicast Packet */
98
+#define REG_CAMCMR_AUP (1 << 0)
99
+
100
+/* REG_MCMDR fields */
101
+/* Software Reset */
102
+#define REG_MCMDR_SWR (1 << 24)
103
+/* Internal Loopback Select */
104
+#define REG_MCMDR_LBK (1 << 21)
105
+/* Operation Mode Select */
106
+#define REG_MCMDR_OPMOD (1 << 20)
107
+/* Enable MDC Clock Generation */
108
+#define REG_MCMDR_ENMDC (1 << 19)
109
+/* Full-Duplex Mode Select */
110
+#define REG_MCMDR_FDUP (1 << 18)
111
+/* Enable SQE Checking */
112
+#define REG_MCMDR_ENSEQ (1 << 17)
113
+/* Send PAUSE Frame */
114
+#define REG_MCMDR_SDPZ (1 << 16)
115
+/* No Defer */
116
+#define REG_MCMDR_NDEF (1 << 9)
117
+/* Frame Transmission On */
118
+#define REG_MCMDR_TXON (1 << 8)
119
+/* Strip CRC Checksum */
120
+#define REG_MCMDR_SPCRC (1 << 5)
121
+/* Accept CRC Error Packet */
122
+#define REG_MCMDR_AEP (1 << 4)
123
+/* Accept Control Packet */
124
+#define REG_MCMDR_ACP (1 << 3)
125
+/* Accept Runt Packet */
126
+#define REG_MCMDR_ARP (1 << 2)
127
+/* Accept Long Packet */
128
+#define REG_MCMDR_ALP (1 << 1)
129
+/* Frame Reception On */
130
+#define REG_MCMDR_RXON (1 << 0)
131
+
132
+/* REG_MIEN fields */
133
+/* Enable Transmit Descriptor Unavailable Interrupt */
134
+#define REG_MIEN_ENTDU (1 << 23)
135
+/* Enable Transmit Completion Interrupt */
136
+#define REG_MIEN_ENTXCP (1 << 18)
137
+/* Enable Transmit Interrupt */
138
+#define REG_MIEN_ENTXINTR (1 << 16)
139
+/* Enable Receive Descriptor Unavailable Interrupt */
140
+#define REG_MIEN_ENRDU (1 << 10)
141
+/* Enable Receive Good Interrupt */
142
+#define REG_MIEN_ENRXGD (1 << 4)
143
+/* Enable Receive Interrupt */
144
+#define REG_MIEN_ENRXINTR (1 << 0)
145
+
146
+/* REG_MISTA fields */
147
+/* TODO: Add error fields and support simulated errors? */
148
+/* Transmit Bus Error Interrupt */
149
+#define REG_MISTA_TXBERR (1 << 24)
150
+/* Transmit Descriptor Unavailable Interrupt */
151
+#define REG_MISTA_TDU (1 << 23)
152
+/* Transmit Completion Interrupt */
153
+#define REG_MISTA_TXCP (1 << 18)
154
+/* Transmit Interrupt */
155
+#define REG_MISTA_TXINTR (1 << 16)
156
+/* Receive Bus Error Interrupt */
157
+#define REG_MISTA_RXBERR (1 << 11)
158
+/* Receive Descriptor Unavailable Interrupt */
159
+#define REG_MISTA_RDU (1 << 10)
160
+/* DMA Early Notification Interrupt */
161
+#define REG_MISTA_DENI (1 << 9)
162
+/* Maximum Frame Length Interrupt */
163
+#define REG_MISTA_DFOI (1 << 8)
164
+/* Receive Good Interrupt */
165
+#define REG_MISTA_RXGD (1 << 4)
166
+/* Packet Too Long Interrupt */
167
+#define REG_MISTA_PTLE (1 << 3)
168
+/* Receive Interrupt */
169
+#define REG_MISTA_RXINTR (1 << 0)
170
+
171
+/* REG_MGSTA fields */
172
+/* Transmission Halted */
173
+#define REG_MGSTA_TXHA (1 << 11)
174
+/* Receive Halted */
175
+#define REG_MGSTA_RXHA (1 << 11)
176
+
177
+/* REG_DMARFC fields */
178
+/* Maximum Receive Frame Length */
179
+#define REG_DMARFC_RXMS(word) extract32((word), 0, 16)
180
+
181
+/* REG MIIDA fields */
182
+/* Busy Bit */
183
+#define REG_MIIDA_BUSY (1 << 17)
184
+
185
+/* Transmit and receive descriptors */
186
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
187
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
188
+
189
+struct NPCM7xxEMCTxDesc {
190
+ uint32_t flags;
191
+ uint32_t txbsa;
192
+ uint32_t status_and_length;
193
+ uint32_t ntxdsa;
194
+};
195
+
196
+struct NPCM7xxEMCRxDesc {
197
+ uint32_t status_and_length;
198
+ uint32_t rxbsa;
199
+ uint32_t reserved;
200
+ uint32_t nrxdsa;
201
+};
202
+
203
+/* NPCM7xxEMCTxDesc.flags values */
204
+/* Owner: 0 = cpu, 1 = emc */
205
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
206
+/* Transmit interrupt enable */
207
+#define TX_DESC_FLAG_INTEN (1 << 2)
208
+/* CRC append */
209
+#define TX_DESC_FLAG_CRCAPP (1 << 1)
210
+/* Padding enable */
211
+#define TX_DESC_FLAG_PADEN (1 << 0)
212
+
213
+/* NPCM7xxEMCTxDesc.status_and_length values */
214
+/* Collision count */
215
+#define TX_DESC_STATUS_CCNT_SHIFT 28
216
+#define TX_DESC_STATUS_CCNT_BITSIZE 4
217
+/* SQE error */
218
+#define TX_DESC_STATUS_SQE (1 << 26)
219
+/* Transmission paused */
220
+#define TX_DESC_STATUS_PAU (1 << 25)
221
+/* P transmission halted */
222
+#define TX_DESC_STATUS_TXHA (1 << 24)
223
+/* Late collision */
224
+#define TX_DESC_STATUS_LC (1 << 23)
225
+/* Transmission abort */
226
+#define TX_DESC_STATUS_TXABT (1 << 22)
227
+/* No carrier sense */
228
+#define TX_DESC_STATUS_NCS (1 << 21)
229
+/* Defer exceed */
230
+#define TX_DESC_STATUS_EXDEF (1 << 20)
231
+/* Transmission complete */
232
+#define TX_DESC_STATUS_TXCP (1 << 19)
233
+/* Transmission deferred */
234
+#define TX_DESC_STATUS_DEF (1 << 17)
235
+/* Transmit interrupt */
236
+#define TX_DESC_STATUS_TXINTR (1 << 16)
237
+
238
+#define TX_DESC_PKT_LEN(word) extract32((word), 0, 16)
239
+
240
+/* Transmit buffer start address */
241
+#define TX_DESC_TXBSA(word) ((uint32_t) (word) & ~3u)
242
+
243
+/* Next transmit descriptor start address */
244
+#define TX_DESC_NTXDSA(word) ((uint32_t) (word) & ~3u)
245
+
246
+/* NPCM7xxEMCRxDesc.status_and_length values */
247
+/* Owner: 0b00 = cpu, 0b01 = undefined, 0b10 = emc, 0b11 = undefined */
248
+#define RX_DESC_STATUS_OWNER_SHIFT 30
249
+#define RX_DESC_STATUS_OWNER_BITSIZE 2
250
+#define RX_DESC_STATUS_OWNER_MASK (3 << RX_DESC_STATUS_OWNER_SHIFT)
251
+/* Runt packet */
252
+#define RX_DESC_STATUS_RP (1 << 22)
253
+/* Alignment error */
254
+#define RX_DESC_STATUS_ALIE (1 << 21)
255
+/* Frame reception complete */
256
+#define RX_DESC_STATUS_RXGD (1 << 20)
257
+/* Packet too long */
258
+#define RX_DESC_STATUS_PTLE (1 << 19)
259
+/* CRC error */
260
+#define RX_DESC_STATUS_CRCE (1 << 17)
261
+/* Receive interrupt */
262
+#define RX_DESC_STATUS_RXINTR (1 << 16)
263
+
264
+#define RX_DESC_PKT_LEN(word) extract32((word), 0, 16)
265
+
266
+/* Receive buffer start address */
267
+#define RX_DESC_RXBSA(word) ((uint32_t) (word) & ~3u)
268
+
269
+/* Next receive descriptor start address */
270
+#define RX_DESC_NRXDSA(word) ((uint32_t) (word) & ~3u)
271
+
272
+/* Minimum packet length, when TX_DESC_FLAG_PADEN is set. */
273
+#define MIN_PACKET_LENGTH 64
274
+
275
+struct NPCM7xxEMCState {
276
+ /*< private >*/
277
+ SysBusDevice parent;
278
+ /*< public >*/
279
+
280
+ MemoryRegion iomem;
281
+
282
+ qemu_irq tx_irq;
283
+ qemu_irq rx_irq;
284
+
285
+ NICState *nic;
286
+ NICConf conf;
287
+
288
+ /* 0 or 1, for log messages */
289
+ uint8_t emc_num;
290
+
291
+ uint32_t regs[NPCM7XX_NUM_EMC_REGS];
292
+
293
+ /*
294
+ * tx is active. Set to true by TSDR and then switches off when out of
295
+ * descriptors. If the TXON bit in REG_MCMDR is off then this is off.
296
+ */
297
+ bool tx_active;
298
+
299
+ /*
300
+ * rx is active. Set to true by RSDR and then switches off when out of
301
+ * descriptors. If the RXON bit in REG_MCMDR is off then this is off.
302
+ */
303
+ bool rx_active;
304
+};
305
+
306
+typedef struct NPCM7xxEMCState NPCM7xxEMCState;
307
+
308
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
309
+#define NPCM7XX_EMC(obj) \
310
+ OBJECT_CHECK(NPCM7xxEMCState, (obj), TYPE_NPCM7XX_EMC)
311
+
312
+#endif /* NPCM7XX_EMC_H */
313
diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c
109
new file mode 100644
314
new file mode 100644
110
index XXXXXXX..XXXXXXX
315
index XXXXXXX..XXXXXXX
111
--- /dev/null
316
--- /dev/null
112
+++ b/hw/acpi/ghes.c
317
+++ b/hw/net/npcm7xx_emc.c
113
@@ -XXX,XX +XXX,XX @@
318
@@ -XXX,XX +XXX,XX @@
114
+/*
319
+/*
115
+ * Support for generating APEI tables and recording CPER for Guests
320
+ * Nuvoton NPCM7xx EMC Module
116
+ *
321
+ *
117
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
322
+ * Copyright 2020 Google LLC
118
+ *
323
+ *
119
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
324
+ * This program is free software; you can redistribute it and/or modify it
325
+ * under the terms of the GNU General Public License as published by the
326
+ * Free Software Foundation; either version 2 of the License, or
327
+ * (at your option) any later version.
120
+ *
328
+ *
121
+ * This program is free software; you can redistribute it and/or modify
329
+ * This program is distributed in the hope that it will be useful, but WITHOUT
122
+ * it under the terms of the GNU General Public License as published by
330
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
123
+ * the Free Software Foundation; either version 2 of the License, or
331
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
124
+ * (at your option) any later version.
332
+ * for more details.
125
+
333
+ *
126
+ * This program is distributed in the hope that it will be useful,
334
+ * Unsupported/unimplemented features:
127
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
335
+ * - MCMDR.FDUP (full duplex) is ignored, half duplex is not supported
128
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
336
+ * - Only CAM0 is supported, CAM[1-15] are not
129
+ * GNU General Public License for more details.
337
+ * - writes to CAMEN.[1-15] are ignored, these bits always read as zeroes
130
+
338
+ * - MII is not implemented, MIIDA.BUSY and MIID always return zero
131
+ * You should have received a copy of the GNU General Public License along
339
+ * - MCMDR.LBK is not implemented
132
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
340
+ * - MCMDR.{OPMOD,ENSQE,AEP,ARP} are not supported
341
+ * - H/W FIFOs are not supported, MCMDR.FFTCR is ignored
342
+ * - MGSTA.SQE is not supported
343
+ * - pause and control frames are not implemented
344
+ * - MGSTA.CCNT is not supported
345
+ * - MPCNT, DMARFS are not implemented
133
+ */
346
+ */
134
+
347
+
135
+#include "qemu/osdep.h"
348
+#include "qemu/osdep.h"
349
+
350
+/* For crc32 */
351
+#include <zlib.h>
352
+
353
+#include "qemu-common.h"
354
+#include "hw/irq.h"
355
+#include "hw/qdev-clock.h"
356
+#include "hw/qdev-properties.h"
357
+#include "hw/net/npcm7xx_emc.h"
358
+#include "net/eth.h"
359
+#include "migration/vmstate.h"
360
+#include "qemu/bitops.h"
361
+#include "qemu/error-report.h"
362
+#include "qemu/log.h"
363
+#include "qemu/module.h"
136
+#include "qemu/units.h"
364
+#include "qemu/units.h"
137
+#include "hw/acpi/ghes.h"
365
+#include "sysemu/dma.h"
138
+#include "hw/acpi/aml-build.h"
366
+#include "trace.h"
139
+
367
+
140
+#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
368
+#define CRC_LENGTH 4
141
+#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
142
+
143
+/* The max size in bytes for one error block */
144
+#define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB)
145
+
146
+/* Now only support ARMv8 SEA notification type error source */
147
+#define ACPI_GHES_ERROR_SOURCE_COUNT 1
148
+
369
+
149
+/*
370
+/*
150
+ * Build table for the hardware error fw_cfg blob.
371
+ * The maximum size of a (layer 2) ethernet frame as defined by 802.3.
151
+ * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
372
+ * 1518 = 6(dest macaddr) + 6(src macaddr) + 2(proto) + 4(crc) + 1500(payload)
152
+ * See docs/specs/acpi_hest_ghes.rst for blobs format.
373
+ * This does not include an additional 4 for the vlan field (802.1q).
153
+ */
374
+ */
154
+void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
375
+#define MAX_ETH_FRAME_SIZE 1518
155
+{
376
+
156
+ int i, error_status_block_offset;
377
+static const char *emc_reg_name(int regno)
157
+
378
+{
158
+ /* Build error_block_address */
379
+#define REG(name) case REG_ ## name: return #name;
159
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
380
+ switch (regno) {
160
+ build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t));
381
+ REG(CAMCMR)
161
+ }
382
+ REG(CAMEN)
162
+
383
+ REG(TXDLSA)
163
+ /* Build read_ack_register */
384
+ REG(RXDLSA)
164
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
385
+ REG(MCMDR)
386
+ REG(MIID)
387
+ REG(MIIDA)
388
+ REG(FFTCR)
389
+ REG(TSDR)
390
+ REG(RSDR)
391
+ REG(DMARFC)
392
+ REG(MIEN)
393
+ REG(MISTA)
394
+ REG(MGSTA)
395
+ REG(MPCNT)
396
+ REG(MRPC)
397
+ REG(MRPCC)
398
+ REG(MREPC)
399
+ REG(DMARFS)
400
+ REG(CTXDSA)
401
+ REG(CTXBSA)
402
+ REG(CRXDSA)
403
+ REG(CRXBSA)
404
+ case REG_CAMM_BASE + 0: return "CAM0M";
405
+ case REG_CAML_BASE + 0: return "CAM0L";
406
+ case REG_CAMM_BASE + 2 ... REG_CAMML_LAST:
407
+ /* Only CAM0 is supported, fold the others into something simple. */
408
+ if (regno & 1) {
409
+ return "CAM<n>L";
410
+ } else {
411
+ return "CAM<n>M";
412
+ }
413
+ default: return "UNKNOWN";
414
+ }
415
+#undef REG
416
+}
417
+
418
+static void emc_reset(NPCM7xxEMCState *emc)
419
+{
420
+ trace_npcm7xx_emc_reset(emc->emc_num);
421
+
422
+ memset(&emc->regs[0], 0, sizeof(emc->regs));
423
+
424
+ /* These regs have non-zero reset values. */
425
+ emc->regs[REG_TXDLSA] = 0xfffffffc;
426
+ emc->regs[REG_RXDLSA] = 0xfffffffc;
427
+ emc->regs[REG_MIIDA] = 0x00900000;
428
+ emc->regs[REG_FFTCR] = 0x0101;
429
+ emc->regs[REG_DMARFC] = 0x0800;
430
+ emc->regs[REG_MPCNT] = 0x7fff;
431
+
432
+ emc->tx_active = false;
433
+ emc->rx_active = false;
434
+}
435
+
436
+static void npcm7xx_emc_reset(DeviceState *dev)
437
+{
438
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
439
+ emc_reset(emc);
440
+}
441
+
442
+static void emc_soft_reset(NPCM7xxEMCState *emc)
443
+{
444
+ /*
445
+ * The docs say at least MCMDR.{LBK,OPMOD} bits are not changed during a
446
+ * soft reset, but does not go into further detail. For now, KISS.
447
+ */
448
+ uint32_t mcmdr = emc->regs[REG_MCMDR];
449
+ emc_reset(emc);
450
+ emc->regs[REG_MCMDR] = mcmdr & (REG_MCMDR_LBK | REG_MCMDR_OPMOD);
451
+
452
+ qemu_set_irq(emc->tx_irq, 0);
453
+ qemu_set_irq(emc->rx_irq, 0);
454
+}
455
+
456
+static void emc_set_link(NetClientState *nc)
457
+{
458
+ /* Nothing to do yet. */
459
+}
460
+
461
+/* MISTA.TXINTR is the union of the individual bits with their enables. */
462
+static void emc_update_mista_txintr(NPCM7xxEMCState *emc)
463
+{
464
+ /* Only look at the bits we support. */
465
+ uint32_t mask = (REG_MISTA_TXBERR |
466
+ REG_MISTA_TDU |
467
+ REG_MISTA_TXCP);
468
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
469
+ emc->regs[REG_MISTA] |= REG_MISTA_TXINTR;
470
+ } else {
471
+ emc->regs[REG_MISTA] &= ~REG_MISTA_TXINTR;
472
+ }
473
+}
474
+
475
+/* MISTA.RXINTR is the union of the individual bits with their enables. */
476
+static void emc_update_mista_rxintr(NPCM7xxEMCState *emc)
477
+{
478
+ /* Only look at the bits we support. */
479
+ uint32_t mask = (REG_MISTA_RXBERR |
480
+ REG_MISTA_RDU |
481
+ REG_MISTA_RXGD);
482
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
483
+ emc->regs[REG_MISTA] |= REG_MISTA_RXINTR;
484
+ } else {
485
+ emc->regs[REG_MISTA] &= ~REG_MISTA_RXINTR;
486
+ }
487
+}
488
+
489
+/* N.B. emc_update_mista_txintr must have already been called. */
490
+static void emc_update_tx_irq(NPCM7xxEMCState *emc)
491
+{
492
+ int level = !!(emc->regs[REG_MISTA] &
493
+ emc->regs[REG_MIEN] &
494
+ REG_MISTA_TXINTR);
495
+ trace_npcm7xx_emc_update_tx_irq(level);
496
+ qemu_set_irq(emc->tx_irq, level);
497
+}
498
+
499
+/* N.B. emc_update_mista_rxintr must have already been called. */
500
+static void emc_update_rx_irq(NPCM7xxEMCState *emc)
501
+{
502
+ int level = !!(emc->regs[REG_MISTA] &
503
+ emc->regs[REG_MIEN] &
504
+ REG_MISTA_RXINTR);
505
+ trace_npcm7xx_emc_update_rx_irq(level);
506
+ qemu_set_irq(emc->rx_irq, level);
507
+}
508
+
509
+/* Update IRQ states due to changes in MIEN,MISTA. */
510
+static void emc_update_irq_from_reg_change(NPCM7xxEMCState *emc)
511
+{
512
+ emc_update_mista_txintr(emc);
513
+ emc_update_tx_irq(emc);
514
+
515
+ emc_update_mista_rxintr(emc);
516
+ emc_update_rx_irq(emc);
517
+}
518
+
519
+static int emc_read_tx_desc(dma_addr_t addr, NPCM7xxEMCTxDesc *desc)
520
+{
521
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
522
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
523
+ HWADDR_PRIx "\n", __func__, addr);
524
+ return -1;
525
+ }
526
+ desc->flags = le32_to_cpu(desc->flags);
527
+ desc->txbsa = le32_to_cpu(desc->txbsa);
528
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
529
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
530
+ return 0;
531
+}
532
+
533
+static int emc_write_tx_desc(const NPCM7xxEMCTxDesc *desc, dma_addr_t addr)
534
+{
535
+ NPCM7xxEMCTxDesc le_desc;
536
+
537
+ le_desc.flags = cpu_to_le32(desc->flags);
538
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
539
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
540
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
541
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
542
+ sizeof(le_desc))) {
543
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
544
+ HWADDR_PRIx "\n", __func__, addr);
545
+ return -1;
546
+ }
547
+ return 0;
548
+}
549
+
550
+static int emc_read_rx_desc(dma_addr_t addr, NPCM7xxEMCRxDesc *desc)
551
+{
552
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
553
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
554
+ HWADDR_PRIx "\n", __func__, addr);
555
+ return -1;
556
+ }
557
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
558
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
559
+ desc->reserved = le32_to_cpu(desc->reserved);
560
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
561
+ return 0;
562
+}
563
+
564
+static int emc_write_rx_desc(const NPCM7xxEMCRxDesc *desc, dma_addr_t addr)
565
+{
566
+ NPCM7xxEMCRxDesc le_desc;
567
+
568
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
569
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
570
+ le_desc.reserved = cpu_to_le32(desc->reserved);
571
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
572
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
573
+ sizeof(le_desc))) {
574
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
575
+ HWADDR_PRIx "\n", __func__, addr);
576
+ return -1;
577
+ }
578
+ return 0;
579
+}
580
+
581
+static void emc_set_mista(NPCM7xxEMCState *emc, uint32_t flags)
582
+{
583
+ trace_npcm7xx_emc_set_mista(flags);
584
+ emc->regs[REG_MISTA] |= flags;
585
+ if (extract32(flags, 16, 16)) {
586
+ emc_update_mista_txintr(emc);
587
+ }
588
+ if (extract32(flags, 0, 16)) {
589
+ emc_update_mista_rxintr(emc);
590
+ }
591
+}
592
+
593
+static void emc_halt_tx(NPCM7xxEMCState *emc, uint32_t mista_flag)
594
+{
595
+ emc->tx_active = false;
596
+ emc_set_mista(emc, mista_flag);
597
+}
598
+
599
+static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag)
600
+{
601
+ emc->rx_active = false;
602
+ emc_set_mista(emc, mista_flag);
603
+}
604
+
605
+static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc,
606
+ const NPCM7xxEMCTxDesc *tx_desc,
607
+ uint32_t desc_addr)
608
+{
609
+ /* Update the current descriptor, if only to reset the owner flag. */
610
+ if (emc_write_tx_desc(tx_desc, desc_addr)) {
165
+ /*
611
+ /*
166
+ * Initialize the value of read_ack_register to 1, so GHES can be
612
+ * We just read it so this shouldn't generally happen.
167
+ * writeable after (re)boot.
613
+ * Error already reported.
168
+ * ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2
169
+ * (GHESv2 - Type 10)
170
+ */
614
+ */
171
+ build_append_int_noprefix(hardware_errors, 1, sizeof(uint64_t));
615
+ emc_set_mista(emc, REG_MISTA_TXBERR);
172
+ }
616
+ }
173
+
617
+ emc->regs[REG_CTXDSA] = TX_DESC_NTXDSA(tx_desc->ntxdsa);
174
+ /* Generic Error Status Block offset in the hardware error fw_cfg blob */
618
+}
175
+ error_status_block_offset = hardware_errors->len;
619
+
176
+
620
+static void emc_set_next_rx_descriptor(NPCM7xxEMCState *emc,
177
+ /* Reserve space for Error Status Data Block */
621
+ const NPCM7xxEMCRxDesc *rx_desc,
178
+ acpi_data_push(hardware_errors,
622
+ uint32_t desc_addr)
179
+ ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT);
623
+{
180
+
624
+ /* Update the current descriptor, if only to reset the owner flag. */
181
+ /* Tell guest firmware to place hardware_errors blob into RAM */
625
+ if (emc_write_rx_desc(rx_desc, desc_addr)) {
182
+ bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE,
183
+ hardware_errors, sizeof(uint64_t), false);
184
+
185
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
186
+ /*
626
+ /*
187
+ * Tell firmware to patch error_block_address entries to point to
627
+ * We just read it so this shouldn't generally happen.
188
+ * corresponding "Generic Error Status Block"
628
+ * Error already reported.
189
+ */
629
+ */
190
+ bios_linker_loader_add_pointer(linker,
630
+ emc_set_mista(emc, REG_MISTA_RXBERR);
191
+ ACPI_GHES_ERRORS_FW_CFG_FILE, sizeof(uint64_t) * i,
631
+ }
192
+ sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
632
+ emc->regs[REG_CRXDSA] = RX_DESC_NRXDSA(rx_desc->nrxdsa);
193
+ error_status_block_offset + i * ACPI_GHES_MAX_RAW_DATA_LENGTH);
633
+}
194
+ }
634
+
635
+static void emc_try_send_next_packet(NPCM7xxEMCState *emc)
636
+{
637
+ /* Working buffer for sending out packets. Most packets fit in this. */
638
+#define TX_BUFFER_SIZE 2048
639
+ uint8_t tx_send_buffer[TX_BUFFER_SIZE];
640
+ uint32_t desc_addr = TX_DESC_NTXDSA(emc->regs[REG_CTXDSA]);
641
+ NPCM7xxEMCTxDesc tx_desc;
642
+ uint32_t next_buf_addr, length;
643
+ uint8_t *buf;
644
+ g_autofree uint8_t *malloced_buf = NULL;
645
+
646
+ if (emc_read_tx_desc(desc_addr, &tx_desc)) {
647
+ /* Error reading descriptor, already reported. */
648
+ emc_halt_tx(emc, REG_MISTA_TXBERR);
649
+ emc_update_tx_irq(emc);
650
+ return;
651
+ }
652
+
653
+ /* Nothing we can do if we don't own the descriptor. */
654
+ if (!(tx_desc.flags & TX_DESC_FLAG_OWNER_MASK)) {
655
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
656
+ emc_halt_tx(emc, REG_MISTA_TDU);
657
+ emc_update_tx_irq(emc);
658
+ return;
659
+ }
660
+
661
+ /* Give the descriptor back regardless of what happens. */
662
+ tx_desc.flags &= ~TX_DESC_FLAG_OWNER_MASK;
663
+ tx_desc.status_and_length &= 0xffff;
195
+
664
+
196
+ /*
665
+ /*
197
+ * tell firmware to write hardware_errors GPA into
666
+ * Despite the h/w documentation saying the tx buffer is word aligned,
198
+ * hardware_errors_addr fw_cfg, once the former has been initialized.
667
+ * the linux driver does not word align the buffer. There is value in not
668
+ * aligning the buffer: See the description of NET_IP_ALIGN in linux
669
+ * kernel sources.
199
+ */
670
+ */
200
+ bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE,
671
+ next_buf_addr = tx_desc.txbsa;
201
+ 0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0);
672
+ emc->regs[REG_CTXBSA] = next_buf_addr;
202
+}
673
+ length = TX_DESC_PKT_LEN(tx_desc.status_and_length);
203
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
674
+ buf = &tx_send_buffer[0];
675
+
676
+ if (length > sizeof(tx_send_buffer)) {
677
+ malloced_buf = g_malloc(length);
678
+ buf = malloced_buf;
679
+ }
680
+
681
+ if (dma_memory_read(&address_space_memory, next_buf_addr, buf, length)) {
682
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n",
683
+ __func__, next_buf_addr);
684
+ emc_set_mista(emc, REG_MISTA_TXBERR);
685
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
686
+ emc_update_tx_irq(emc);
687
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
688
+ return;
689
+ }
690
+
691
+ if ((tx_desc.flags & TX_DESC_FLAG_PADEN) && (length < MIN_PACKET_LENGTH)) {
692
+ memset(buf + length, 0, MIN_PACKET_LENGTH - length);
693
+ length = MIN_PACKET_LENGTH;
694
+ }
695
+
696
+ /* N.B. emc_receive can get called here. */
697
+ qemu_send_packet(qemu_get_queue(emc->nic), buf, length);
698
+ trace_npcm7xx_emc_sent_packet(length);
699
+
700
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXCP;
701
+ if (tx_desc.flags & TX_DESC_FLAG_INTEN) {
702
+ emc_set_mista(emc, REG_MISTA_TXCP);
703
+ }
704
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_TXINTR) {
705
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXINTR;
706
+ }
707
+
708
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
709
+ emc_update_tx_irq(emc);
710
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
711
+}
712
+
713
+static bool emc_can_receive(NetClientState *nc)
714
+{
715
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
716
+
717
+ bool can_receive = emc->rx_active;
718
+ trace_npcm7xx_emc_can_receive(can_receive);
719
+ return can_receive;
720
+}
721
+
722
+/* If result is false then *fail_reason contains the reason. */
723
+static bool emc_receive_filter1(NPCM7xxEMCState *emc, const uint8_t *buf,
724
+ size_t len, const char **fail_reason)
725
+{
726
+ eth_pkt_types_e pkt_type = get_eth_packet_type(PKT_GET_ETH_HDR(buf));
727
+
728
+ switch (pkt_type) {
729
+ case ETH_PKT_BCAST:
730
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
731
+ return true;
732
+ } else {
733
+ *fail_reason = "Broadcast packet disabled";
734
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_ABP);
735
+ }
736
+ case ETH_PKT_MCAST:
737
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
738
+ return true;
739
+ } else {
740
+ *fail_reason = "Multicast packet disabled";
741
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_AMP);
742
+ }
743
+ case ETH_PKT_UCAST: {
744
+ bool matches;
745
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_AUP) {
746
+ return true;
747
+ }
748
+ matches = ((emc->regs[REG_CAMCMR] & REG_CAMCMR_ECMP) &&
749
+ /* We only support one CAM register, CAM0. */
750
+ (emc->regs[REG_CAMEN] & (1 << 0)) &&
751
+ memcmp(buf, emc->conf.macaddr.a, ETH_ALEN) == 0);
752
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
753
+ *fail_reason = "MACADDR matched, comparison complemented";
754
+ return !matches;
755
+ } else {
756
+ *fail_reason = "MACADDR didn't match";
757
+ return matches;
758
+ }
759
+ }
760
+ default:
761
+ g_assert_not_reached();
762
+ }
763
+}
764
+
765
+static bool emc_receive_filter(NPCM7xxEMCState *emc, const uint8_t *buf,
766
+ size_t len)
767
+{
768
+ const char *fail_reason = NULL;
769
+ bool ok = emc_receive_filter1(emc, buf, len, &fail_reason);
770
+ if (!ok) {
771
+ trace_npcm7xx_emc_packet_filtered_out(fail_reason);
772
+ }
773
+ return ok;
774
+}
775
+
776
+static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1)
777
+{
778
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
779
+ const uint32_t len = len1;
780
+ size_t max_frame_len;
781
+ bool long_frame;
782
+ uint32_t desc_addr;
783
+ NPCM7xxEMCRxDesc rx_desc;
784
+ uint32_t crc;
785
+ uint8_t *crc_ptr;
786
+ uint32_t buf_addr;
787
+
788
+ trace_npcm7xx_emc_receiving_packet(len);
789
+
790
+ if (!emc_can_receive(nc)) {
791
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__);
792
+ return -1;
793
+ }
794
+
795
+ if (len < ETH_HLEN ||
796
+ /* Defensive programming: drop unsupportable large packets. */
797
+ len > 0xffff - CRC_LENGTH) {
798
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Dropped frame of %u bytes\n",
799
+ __func__, len);
800
+ return len;
801
+ }
802
+
803
+ /*
804
+ * DENI is set if EMC received the Length/Type field of the incoming
805
+ * packet, so it will be set regardless of what happens next.
806
+ */
807
+ emc_set_mista(emc, REG_MISTA_DENI);
808
+
809
+ if (!emc_receive_filter(emc, buf, len)) {
810
+ emc_update_rx_irq(emc);
811
+ return len;
812
+ }
813
+
814
+ /* Huge frames (> DMARFC) are dropped. */
815
+ max_frame_len = REG_DMARFC_RXMS(emc->regs[REG_DMARFC]);
816
+ if (len + CRC_LENGTH > max_frame_len) {
817
+ trace_npcm7xx_emc_packet_dropped(len);
818
+ emc_set_mista(emc, REG_MISTA_DFOI);
819
+ emc_update_rx_irq(emc);
820
+ return len;
821
+ }
822
+
823
+ /*
824
+ * Long Frames (> MAX_ETH_FRAME_SIZE) are also dropped, unless MCMDR.ALP
825
+ * is set.
826
+ */
827
+ long_frame = false;
828
+ if (len + CRC_LENGTH > MAX_ETH_FRAME_SIZE) {
829
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_ALP) {
830
+ long_frame = true;
831
+ } else {
832
+ trace_npcm7xx_emc_packet_dropped(len);
833
+ emc_set_mista(emc, REG_MISTA_PTLE);
834
+ emc_update_rx_irq(emc);
835
+ return len;
836
+ }
837
+ }
838
+
839
+ desc_addr = RX_DESC_NRXDSA(emc->regs[REG_CRXDSA]);
840
+ if (emc_read_rx_desc(desc_addr, &rx_desc)) {
841
+ /* Error reading descriptor, already reported. */
842
+ emc_halt_rx(emc, REG_MISTA_RXBERR);
843
+ emc_update_rx_irq(emc);
844
+ return len;
845
+ }
846
+
847
+ /* Nothing we can do if we don't own the descriptor. */
848
+ if (!(rx_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK)) {
849
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
850
+ emc_halt_rx(emc, REG_MISTA_RDU);
851
+ emc_update_rx_irq(emc);
852
+ return len;
853
+ }
854
+
855
+ crc = 0;
856
+ crc_ptr = (uint8_t *) &crc;
857
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
858
+ crc = cpu_to_be32(crc32(~0, buf, len));
859
+ }
860
+
861
+ /* Give the descriptor back regardless of what happens. */
862
+ rx_desc.status_and_length &= ~RX_DESC_STATUS_OWNER_MASK;
863
+
864
+ buf_addr = rx_desc.rxbsa;
865
+ emc->regs[REG_CRXBSA] = buf_addr;
866
+ if (dma_memory_write(&address_space_memory, buf_addr, buf, len) ||
867
+ (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC) &&
868
+ dma_memory_write(&address_space_memory, buf_addr + len, crc_ptr,
869
+ 4))) {
870
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bus error writing packet\n",
871
+ __func__);
872
+ emc_set_mista(emc, REG_MISTA_RXBERR);
873
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
874
+ emc_update_rx_irq(emc);
875
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
876
+ return len;
877
+ }
878
+
879
+ trace_npcm7xx_emc_received_packet(len);
880
+
881
+ /* Note: We've already verified len+4 <= 0xffff. */
882
+ rx_desc.status_and_length = len;
883
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
884
+ rx_desc.status_and_length += 4;
885
+ }
886
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXGD;
887
+ emc_set_mista(emc, REG_MISTA_RXGD);
888
+
889
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_RXINTR) {
890
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXINTR;
891
+ }
892
+ if (long_frame) {
893
+ rx_desc.status_and_length |= RX_DESC_STATUS_PTLE;
894
+ }
895
+
896
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
897
+ emc_update_rx_irq(emc);
898
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
899
+ return len;
900
+}
901
+
902
+static void emc_try_receive_next_packet(NPCM7xxEMCState *emc)
903
+{
904
+ if (emc_can_receive(qemu_get_queue(emc->nic))) {
905
+ qemu_flush_queued_packets(qemu_get_queue(emc->nic));
906
+ }
907
+}
908
+
909
+static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size)
910
+{
911
+ NPCM7xxEMCState *emc = opaque;
912
+ uint32_t reg = offset / sizeof(uint32_t);
913
+ uint32_t result;
914
+
915
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
916
+ qemu_log_mask(LOG_GUEST_ERROR,
917
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
918
+ __func__, offset);
919
+ return 0;
920
+ }
921
+
922
+ switch (reg) {
923
+ case REG_MIID:
924
+ /*
925
+ * We don't implement MII. For determinism, always return zero as
926
+ * writes record the last value written for debugging purposes.
927
+ */
928
+ qemu_log_mask(LOG_UNIMP, "%s: Read of MIID, returning 0\n", __func__);
929
+ result = 0;
930
+ break;
931
+ case REG_TSDR:
932
+ case REG_RSDR:
933
+ qemu_log_mask(LOG_GUEST_ERROR,
934
+ "%s: Read of write-only reg, %s/%d\n",
935
+ __func__, emc_reg_name(reg), reg);
936
+ return 0;
937
+ default:
938
+ result = emc->regs[reg];
939
+ break;
940
+ }
941
+
942
+ trace_npcm7xx_emc_reg_read(emc->emc_num, result, emc_reg_name(reg), reg);
943
+ return result;
944
+}
945
+
946
+static void npcm7xx_emc_write(void *opaque, hwaddr offset,
947
+ uint64_t v, unsigned size)
948
+{
949
+ NPCM7xxEMCState *emc = opaque;
950
+ uint32_t reg = offset / sizeof(uint32_t);
951
+ uint32_t value = v;
952
+
953
+ g_assert(size == sizeof(uint32_t));
954
+
955
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
956
+ qemu_log_mask(LOG_GUEST_ERROR,
957
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
958
+ __func__, offset);
959
+ return;
960
+ }
961
+
962
+ trace_npcm7xx_emc_reg_write(emc->emc_num, emc_reg_name(reg), reg, value);
963
+
964
+ switch (reg) {
965
+ case REG_CAMCMR:
966
+ emc->regs[reg] = value;
967
+ break;
968
+ case REG_CAMEN:
969
+ /* Only CAM0 is supported, don't pretend otherwise. */
970
+ if (value & ~1) {
971
+ qemu_log_mask(LOG_GUEST_ERROR,
972
+ "%s: Only CAM0 is supported, cannot enable others"
973
+ ": 0x%x\n",
974
+ __func__, value);
975
+ }
976
+ emc->regs[reg] = value & 1;
977
+ break;
978
+ case REG_CAMM_BASE + 0:
979
+ emc->regs[reg] = value;
980
+ emc->conf.macaddr.a[0] = value >> 24;
981
+ emc->conf.macaddr.a[1] = value >> 16;
982
+ emc->conf.macaddr.a[2] = value >> 8;
983
+ emc->conf.macaddr.a[3] = value >> 0;
984
+ break;
985
+ case REG_CAML_BASE + 0:
986
+ emc->regs[reg] = value;
987
+ emc->conf.macaddr.a[4] = value >> 24;
988
+ emc->conf.macaddr.a[5] = value >> 16;
989
+ break;
990
+ case REG_MCMDR: {
991
+ uint32_t prev;
992
+ if (value & REG_MCMDR_SWR) {
993
+ emc_soft_reset(emc);
994
+ /* On h/w the reset happens over multiple cycles. For now KISS. */
995
+ break;
996
+ }
997
+ prev = emc->regs[reg];
998
+ emc->regs[reg] = value;
999
+ /* Update tx state. */
1000
+ if (!(prev & REG_MCMDR_TXON) &&
1001
+ (value & REG_MCMDR_TXON)) {
1002
+ emc->regs[REG_CTXDSA] = emc->regs[REG_TXDLSA];
1003
+ /*
1004
+ * Linux kernel turns TX on with CPU still holding descriptor,
1005
+ * which suggests we should wait for a write to TSDR before trying
1006
+ * to send a packet: so we don't send one here.
1007
+ */
1008
+ } else if ((prev & REG_MCMDR_TXON) &&
1009
+ !(value & REG_MCMDR_TXON)) {
1010
+ emc->regs[REG_MGSTA] |= REG_MGSTA_TXHA;
1011
+ }
1012
+ if (!(value & REG_MCMDR_TXON)) {
1013
+ emc_halt_tx(emc, 0);
1014
+ }
1015
+ /* Update rx state. */
1016
+ if (!(prev & REG_MCMDR_RXON) &&
1017
+ (value & REG_MCMDR_RXON)) {
1018
+ emc->regs[REG_CRXDSA] = emc->regs[REG_RXDLSA];
1019
+ } else if ((prev & REG_MCMDR_RXON) &&
1020
+ !(value & REG_MCMDR_RXON)) {
1021
+ emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
1022
+ }
1023
+ if (!(value & REG_MCMDR_RXON)) {
1024
+ emc_halt_rx(emc, 0);
1025
+ }
1026
+ break;
1027
+ }
1028
+ case REG_TXDLSA:
1029
+ case REG_RXDLSA:
1030
+ case REG_DMARFC:
1031
+ case REG_MIID:
1032
+ emc->regs[reg] = value;
1033
+ break;
1034
+ case REG_MIEN:
1035
+ emc->regs[reg] = value;
1036
+ emc_update_irq_from_reg_change(emc);
1037
+ break;
1038
+ case REG_MISTA:
1039
+ /* Clear the bits that have 1 in "value". */
1040
+ emc->regs[reg] &= ~value;
1041
+ emc_update_irq_from_reg_change(emc);
1042
+ break;
1043
+ case REG_MGSTA:
1044
+ /* Clear the bits that have 1 in "value". */
1045
+ emc->regs[reg] &= ~value;
1046
+ break;
1047
+ case REG_TSDR:
1048
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_TXON) {
1049
+ emc->tx_active = true;
1050
+ /* Keep trying to send packets until we run out. */
1051
+ while (emc->tx_active) {
1052
+ emc_try_send_next_packet(emc);
1053
+ }
1054
+ }
1055
+ break;
1056
+ case REG_RSDR:
1057
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
1058
+ emc->rx_active = true;
1059
+ emc_try_receive_next_packet(emc);
1060
+ }
1061
+ break;
1062
+ case REG_MIIDA:
1063
+ emc->regs[reg] = value & ~REG_MIIDA_BUSY;
1064
+ break;
1065
+ case REG_MRPC:
1066
+ case REG_MRPCC:
1067
+ case REG_MREPC:
1068
+ case REG_CTXDSA:
1069
+ case REG_CTXBSA:
1070
+ case REG_CRXDSA:
1071
+ case REG_CRXBSA:
1072
+ qemu_log_mask(LOG_GUEST_ERROR,
1073
+ "%s: Write to read-only reg %s/%d\n",
1074
+ __func__, emc_reg_name(reg), reg);
1075
+ break;
1076
+ default:
1077
+ qemu_log_mask(LOG_UNIMP, "%s: Write to unimplemented reg %s/%d\n",
1078
+ __func__, emc_reg_name(reg), reg);
1079
+ break;
1080
+ }
1081
+}
1082
+
1083
+static const struct MemoryRegionOps npcm7xx_emc_ops = {
1084
+ .read = npcm7xx_emc_read,
1085
+ .write = npcm7xx_emc_write,
1086
+ .endianness = DEVICE_LITTLE_ENDIAN,
1087
+ .valid = {
1088
+ .min_access_size = 4,
1089
+ .max_access_size = 4,
1090
+ .unaligned = false,
1091
+ },
1092
+};
1093
+
1094
+static void emc_cleanup(NetClientState *nc)
1095
+{
1096
+ /* Nothing to do yet. */
1097
+}
1098
+
1099
+static NetClientInfo net_npcm7xx_emc_info = {
1100
+ .type = NET_CLIENT_DRIVER_NIC,
1101
+ .size = sizeof(NICState),
1102
+ .can_receive = emc_can_receive,
1103
+ .receive = emc_receive,
1104
+ .cleanup = emc_cleanup,
1105
+ .link_status_changed = emc_set_link,
1106
+};
1107
+
1108
+static void npcm7xx_emc_realize(DeviceState *dev, Error **errp)
1109
+{
1110
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
1111
+ SysBusDevice *sbd = SYS_BUS_DEVICE(emc);
1112
+
1113
+ memory_region_init_io(&emc->iomem, OBJECT(emc), &npcm7xx_emc_ops, emc,
1114
+ TYPE_NPCM7XX_EMC, 4 * KiB);
1115
+ sysbus_init_mmio(sbd, &emc->iomem);
1116
+ sysbus_init_irq(sbd, &emc->tx_irq);
1117
+ sysbus_init_irq(sbd, &emc->rx_irq);
1118
+
1119
+ qemu_macaddr_default_if_unset(&emc->conf.macaddr);
1120
+ emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf,
1121
+ object_get_typename(OBJECT(dev)), dev->id, emc);
1122
+ qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a);
1123
+}
1124
+
1125
+static void npcm7xx_emc_unrealize(DeviceState *dev)
1126
+{
1127
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
1128
+
1129
+ qemu_del_nic(emc->nic);
1130
+}
1131
+
1132
+static const VMStateDescription vmstate_npcm7xx_emc = {
1133
+ .name = TYPE_NPCM7XX_EMC,
1134
+ .version_id = 0,
1135
+ .minimum_version_id = 0,
1136
+ .fields = (VMStateField[]) {
1137
+ VMSTATE_UINT8(emc_num, NPCM7xxEMCState),
1138
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxEMCState, NPCM7XX_NUM_EMC_REGS),
1139
+ VMSTATE_BOOL(tx_active, NPCM7xxEMCState),
1140
+ VMSTATE_BOOL(rx_active, NPCM7xxEMCState),
1141
+ VMSTATE_END_OF_LIST(),
1142
+ },
1143
+};
1144
+
1145
+static Property npcm7xx_emc_properties[] = {
1146
+ DEFINE_NIC_PROPERTIES(NPCM7xxEMCState, conf),
1147
+ DEFINE_PROP_END_OF_LIST(),
1148
+};
1149
+
1150
+static void npcm7xx_emc_class_init(ObjectClass *klass, void *data)
1151
+{
1152
+ DeviceClass *dc = DEVICE_CLASS(klass);
1153
+
1154
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
1155
+ dc->desc = "NPCM7xx EMC Controller";
1156
+ dc->realize = npcm7xx_emc_realize;
1157
+ dc->unrealize = npcm7xx_emc_unrealize;
1158
+ dc->reset = npcm7xx_emc_reset;
1159
+ dc->vmsd = &vmstate_npcm7xx_emc;
1160
+ device_class_set_props(dc, npcm7xx_emc_properties);
1161
+}
1162
+
1163
+static const TypeInfo npcm7xx_emc_info = {
1164
+ .name = TYPE_NPCM7XX_EMC,
1165
+ .parent = TYPE_SYS_BUS_DEVICE,
1166
+ .instance_size = sizeof(NPCM7xxEMCState),
1167
+ .class_init = npcm7xx_emc_class_init,
1168
+};
1169
+
1170
+static void npcm7xx_emc_register_type(void)
1171
+{
1172
+ type_register_static(&npcm7xx_emc_info);
1173
+}
1174
+
1175
+type_init(npcm7xx_emc_register_type)
1176
diff --git a/hw/net/meson.build b/hw/net/meson.build
204
index XXXXXXX..XXXXXXX 100644
1177
index XXXXXXX..XXXXXXX 100644
205
--- a/hw/arm/virt-acpi-build.c
1178
--- a/hw/net/meson.build
206
+++ b/hw/arm/virt-acpi-build.c
1179
+++ b/hw/net/meson.build
207
@@ -XXX,XX +XXX,XX @@
1180
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c'))
208
#include "sysemu/reset.h"
1181
softmmu_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c'))
209
#include "kvm_arm.h"
1182
softmmu_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
210
#include "migration/vmstate.h"
1183
softmmu_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c'))
211
+#include "hw/acpi/ghes.h"
1184
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c'))
212
1185
213
#define ARM_SPI_BASE 32
1186
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
214
1187
softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
215
@@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
1188
diff --git a/hw/net/trace-events b/hw/net/trace-events
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
1189
index XXXXXXX..XXXXXXX 100644
228
--- a/hw/acpi/Kconfig
1190
--- a/hw/net/trace-events
229
+++ b/hw/acpi/Kconfig
1191
+++ b/hw/net/trace-events
230
@@ -XXX,XX +XXX,XX @@ config ACPI_HMAT
1192
@@ -XXX,XX +XXX,XX @@ imx_fec_receive_last(int last) "rx frame flags 0x%04x"
231
bool
1193
imx_enet_receive(size_t size) "len %zu"
232
depends on ACPI
1194
imx_enet_receive_len(uint64_t addr, int len) "rx_bd 0x%"PRIx64" length %d"
233
1195
imx_enet_receive_last(int last) "rx frame flags 0x%04x"
234
+config ACPI_APEI
1196
+
235
+ bool
1197
+# npcm7xx_emc.c
236
+ depends on ACPI
1198
+npcm7xx_emc_reset(int emc_num) "Resetting emc%d"
237
+
1199
+npcm7xx_emc_update_tx_irq(int level) "Setting tx irq to %d"
238
config ACPI_PCI
1200
+npcm7xx_emc_update_rx_irq(int level) "Setting rx irq to %d"
239
bool
1201
+npcm7xx_emc_set_mista(uint32_t flags) "ORing 0x%x into MISTA"
240
depends on ACPI && PCI
1202
+npcm7xx_emc_cpu_owned_desc(uint32_t addr) "Can't process cpu-owned descriptor @0x%x"
241
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
1203
+npcm7xx_emc_sent_packet(uint32_t len) "Sent %u byte packet"
242
index XXXXXXX..XXXXXXX 100644
1204
+npcm7xx_emc_tx_done(uint32_t ctxdsa) "TX done, CTXDSA=0x%x"
243
--- a/hw/acpi/Makefile.objs
1205
+npcm7xx_emc_can_receive(int can_receive) "Can receive: %d"
244
+++ b/hw/acpi/Makefile.objs
1206
+npcm7xx_emc_packet_filtered_out(const char* fail_reason) "Packet filtered out: %s"
245
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
1207
+npcm7xx_emc_packet_dropped(uint32_t len) "%u byte packet dropped"
246
common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
1208
+npcm7xx_emc_receiving_packet(uint32_t len) "Receiving %u byte packet"
247
common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o
1209
+npcm7xx_emc_received_packet(uint32_t len) "Received %u byte packet"
248
common-obj-$(CONFIG_ACPI_HMAT) += hmat.o
1210
+npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=0x%x"
249
+common-obj-$(CONFIG_ACPI_APEI) += ghes.o
1211
+npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int regno) "emc%d: 0x%x = reg[%s/%d]"
250
common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
1212
+npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t value) "emc%d: reg[%s/%d] = 0x%x"
251
common-obj-$(call lnot,$(CONFIG_PC)) += acpi-x86-stub.o
252
253
--
1213
--
254
2.20.1
1214
2.20.1
255
1215
256
1216
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Doug Evans <dje@google.com>
2
2
3
Record the GHEB address via fw_cfg file, when recording
3
This is a 10/100 ethernet device that has several features.
4
a error to CPER, it will use this address to find out
4
Only the ones needed by the Linux driver have been implemented.
5
Generic Error Data Entries and write the error.
5
See npcm7xx_emc.c for a list of unimplemented features.
6
6
7
In order to avoid migration failure, make hardware
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
error table address to a part of GED device instead
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
9
of global variable, then this address will be migrated
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
to target QEMU.
10
Signed-off-by: Doug Evans <dje@google.com>
11
11
Message-id: 20210218212453.831406-3-dje@google.com
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>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
13
---
19
include/hw/acpi/generic_event_device.h | 2 ++
14
docs/system/arm/nuvoton.rst | 3 ++-
20
include/hw/acpi/ghes.h | 6 ++++++
15
include/hw/arm/npcm7xx.h | 2 ++
21
hw/acpi/generic_event_device.c | 19 +++++++++++++++++++
16
hw/arm/npcm7xx.c | 50 +++++++++++++++++++++++++++++++++++--
22
hw/acpi/ghes.c | 14 ++++++++++++++
17
3 files changed, 52 insertions(+), 3 deletions(-)
23
hw/arm/virt-acpi-build.c | 8 ++++++++
24
5 files changed, 49 insertions(+)
25
18
26
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
19
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
27
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/acpi/generic_event_device.h
21
--- a/docs/system/arm/nuvoton.rst
29
+++ b/include/hw/acpi/generic_event_device.h
22
+++ b/docs/system/arm/nuvoton.rst
23
@@ -XXX,XX +XXX,XX @@ Supported devices
24
* Analog to Digital Converter (ADC)
25
* Pulse Width Modulation (PWM)
26
* SMBus controller (SMBF)
27
+ * Ethernet controller (EMC)
28
29
Missing devices
30
---------------
31
@@ -XXX,XX +XXX,XX @@ Missing devices
32
* Shared memory (SHM)
33
* eSPI slave interface
34
35
- * Ethernet controllers (GMAC and EMC)
36
+ * Ethernet controller (GMAC)
37
* USB device (USBD)
38
* Peripheral SPI controller (PSPI)
39
* SD/MMC host
40
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/arm/npcm7xx.h
43
+++ b/include/hw/arm/npcm7xx.h
30
@@ -XXX,XX +XXX,XX @@
44
@@ -XXX,XX +XXX,XX @@
31
45
#include "hw/misc/npcm7xx_gcr.h"
32
#include "hw/sysbus.h"
46
#include "hw/misc/npcm7xx_pwm.h"
33
#include "hw/acpi/memory_hotplug.h"
47
#include "hw/misc/npcm7xx_rng.h"
34
+#include "hw/acpi/ghes.h"
48
+#include "hw/net/npcm7xx_emc.h"
35
49
#include "hw/nvram/npcm7xx_otp.h"
36
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
50
#include "hw/timer/npcm7xx_timer.h"
37
51
#include "hw/ssi/npcm7xx_fiu.h"
38
@@ -XXX,XX +XXX,XX @@ typedef struct AcpiGedState {
52
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
39
GEDState ged_state;
53
EHCISysBusState ehci;
40
uint32_t ged_event_bitmap;
54
OHCISysBusState ohci;
41
qemu_irq irq;
55
NPCM7xxFIUState fiu[2];
42
+ AcpiGhesState ghes_state;
56
+ NPCM7xxEMCState emc[2];
43
} AcpiGedState;
57
} NPCM7xxState;
44
58
45
void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev,
59
#define TYPE_NPCM7XX "npcm7xx"
46
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
60
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
47
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
48
--- a/include/hw/acpi/ghes.h
62
--- a/hw/arm/npcm7xx.c
49
+++ b/include/hw/acpi/ghes.h
63
+++ b/hw/arm/npcm7xx.c
50
@@ -XXX,XX +XXX,XX @@ enum {
64
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
51
ACPI_HEST_SRC_ID_RESERVED,
65
NPCM7XX_UART1_IRQ,
66
NPCM7XX_UART2_IRQ,
67
NPCM7XX_UART3_IRQ,
68
+ NPCM7XX_EMC1RX_IRQ = 15,
69
+ NPCM7XX_EMC1TX_IRQ,
70
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
71
NPCM7XX_TIMER1_IRQ,
72
NPCM7XX_TIMER2_IRQ,
73
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
74
NPCM7XX_SMBUS15_IRQ,
75
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
76
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
77
+ NPCM7XX_EMC2RX_IRQ = 114,
78
+ NPCM7XX_EMC2TX_IRQ,
79
NPCM7XX_GPIO0_IRQ = 116,
80
NPCM7XX_GPIO1_IRQ,
81
NPCM7XX_GPIO2_IRQ,
82
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_smbus_addr[] = {
83
0xf008f000,
52
};
84
};
53
85
54
+typedef struct AcpiGhesState {
86
+/* Register base address for each EMC Module */
55
+ uint64_t ghes_addr_le;
87
+static const hwaddr npcm7xx_emc_addr[] = {
56
+} AcpiGhesState;
88
+ 0xf0825000,
57
+
89
+ 0xf0826000,
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
+};
90
+};
88
+
91
+
89
static const VMStateDescription vmstate_acpi_ged = {
92
static const struct {
90
.name = "acpi-ged",
93
hwaddr regs_addr;
91
.version_id = 1,
94
uint32_t unconnected_pins;
92
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_acpi_ged = {
95
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
93
},
96
for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
94
.subsections = (const VMStateDescription * []) {
97
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
95
&vmstate_memhp_state,
96
+ &vmstate_ghes_state,
97
NULL
98
}
98
}
99
};
99
+
100
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
100
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
101
index XXXXXXX..XXXXXXX 100644
101
+ object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
102
--- a/hw/acpi/ghes.c
102
+ }
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
}
103
}
117
+
104
118
+void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
105
static void npcm7xx_realize(DeviceState *dev, Error **errp)
119
+ GArray *hardware_error)
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
120
+{
107
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
121
+ /* Create a read-only fw_cfg file for GHES */
108
}
122
+ fw_cfg_add_file(s, ACPI_GHES_ERRORS_FW_CFG_FILE, hardware_error->data,
109
123
+ hardware_error->len);
110
+ /*
124
+
111
+ * EMC Modules. Cannot fail.
125
+ /* Create a read-write fw_cfg file for Address */
112
+ * The mapping of the device to its netdev backend works as follows:
126
+ fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
113
+ * emc[i] = nd_table[i]
127
+ NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
114
+ * This works around the inability to specify the netdev property for the
128
+}
115
+ * emc device: it's not pluggable and thus the -device option can't be
129
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
116
+ * used.
130
index XXXXXXX..XXXXXXX 100644
117
+ */
131
--- a/hw/arm/virt-acpi-build.c
118
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
132
+++ b/hw/arm/virt-acpi-build.c
119
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
133
@@ -XXX,XX +XXX,XX @@ void virt_acpi_setup(VirtMachineState *vms)
120
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
134
{
121
+ s->emc[i].emc_num = i;
135
AcpiBuildTables tables;
122
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->emc[i]);
136
AcpiBuildState *build_state;
123
+ if (nd_table[i].used) {
137
+ AcpiGedState *acpi_ged_state;
124
+ qemu_check_nic_model(&nd_table[i], TYPE_NPCM7XX_EMC);
138
125
+ qdev_set_nic_properties(DEVICE(sbd), &nd_table[i]);
139
if (!vms->fw_cfg) {
126
+ }
140
trace_virt_acpi_setup();
127
+ /*
141
@@ -XXX,XX +XXX,XX @@ void virt_acpi_setup(VirtMachineState *vms)
128
+ * The device exists regardless of whether it's connected to a QEMU
142
fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
129
+ * netdev backend. So always instantiate it even if there is no
143
acpi_data_len(tables.tcpalog));
130
+ * backend.
144
131
+ */
145
+ if (vms->ras) {
132
+ sysbus_realize(sbd, &error_abort);
146
+ assert(vms->acpi_dev);
133
+ sysbus_mmio_map(sbd, 0, npcm7xx_emc_addr[i]);
147
+ acpi_ged_state = ACPI_GED(vms->acpi_dev);
134
+ int tx_irq = i == 0 ? NPCM7XX_EMC1TX_IRQ : NPCM7XX_EMC2TX_IRQ;
148
+ acpi_ghes_add_fw_cfg(&acpi_ged_state->ghes_state,
135
+ int rx_irq = i == 0 ? NPCM7XX_EMC1RX_IRQ : NPCM7XX_EMC2RX_IRQ;
149
+ vms->fw_cfg, tables.hardware_errors);
136
+ /*
137
+ * N.B. The values for the second argument sysbus_connect_irq are
138
+ * chosen to match the registration order in npcm7xx_emc_realize.
139
+ */
140
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, tx_irq));
141
+ sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
150
+ }
142
+ }
151
+
143
+
152
build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update,
144
/*
153
build_state, tables.rsdp,
145
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
154
ACPI_BUILD_RSDP_FILE, 0);
146
* specified, but this is a programming error.
147
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
148
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
149
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
150
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
151
- create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
152
- create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
153
create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
154
create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
155
create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
155
--
156
--
156
2.20.1
157
2.20.1
157
158
158
159
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Doug Evans <dje@google.com>
2
2
3
Add APEI/GHES detailed design document
3
Reviewed-by: Hao Wu <wuhaotsh@google.com>
4
4
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
5
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
6
Signed-off-by: Doug Evans <dje@google.com>
7
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
7
Message-id: 20210218212453.831406-4-dje@google.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>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
docs/specs/acpi_hest_ghes.rst | 110 ++++++++++++++++++++++++++++++++++
10
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++
13
docs/specs/index.rst | 1 +
11
tests/qtest/meson.build | 3 +-
14
2 files changed, 111 insertions(+)
12
2 files changed, 864 insertions(+), 1 deletion(-)
15
create mode 100644 docs/specs/acpi_hest_ghes.rst
13
create mode 100644 tests/qtest/npcm7xx_emc-test.c
16
14
17
diff --git a/docs/specs/acpi_hest_ghes.rst b/docs/specs/acpi_hest_ghes.rst
15
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
18
new file mode 100644
16
new file mode 100644
19
index XXXXXXX..XXXXXXX
17
index XXXXXXX..XXXXXXX
20
--- /dev/null
18
--- /dev/null
21
+++ b/docs/specs/acpi_hest_ghes.rst
19
+++ b/tests/qtest/npcm7xx_emc-test.c
22
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
23
+APEI tables generating and CPER record
21
+/*
24
+======================================
22
+ * QTests for Nuvoton NPCM7xx EMC Modules.
25
+
23
+ *
26
+..
24
+ * Copyright 2020 Google LLC
27
+ Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
25
+ *
28
+
26
+ * This program is free software; you can redistribute it and/or modify it
29
+ This work is licensed under the terms of the GNU GPL, version 2 or later.
27
+ * under the terms of the GNU General Public License as published by the
30
+ See the COPYING file in the top-level directory.
28
+ * Free Software Foundation; either version 2 of the License, or
31
+
29
+ * (at your option) any later version.
32
+Design Details
30
+ *
33
+--------------
31
+ * This program is distributed in the hope that it will be useful, but WITHOUT
34
+
32
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
+::
33
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+
34
+ * for more details.
37
+ etc/acpi/tables etc/hardware_errors
35
+ */
38
+ ==================== ===============================
36
+
39
+ + +--------------------------+ +----------------------------+
37
+#include "qemu/osdep.h"
40
+ | | HEST | +--------->| error_block_address1 |------+
38
+#include "qemu-common.h"
41
+ | +--------------------------+ | +----------------------------+ |
39
+#include "libqos/libqos.h"
42
+ | | GHES1 | | +------->| error_block_address2 |------+-+
40
+#include "qapi/qmp/qdict.h"
43
+ | +--------------------------+ | | +----------------------------+ | |
41
+#include "qapi/qmp/qnum.h"
44
+ | | ................. | | | | .............. | | |
42
+#include "qemu/bitops.h"
45
+ | | error_status_address-----+-+ | -----------------------------+ | |
43
+#include "qemu/iov.h"
46
+ | | ................. | | +--->| error_block_addressN |------+-+---+
44
+
47
+ | | read_ack_register--------+-+ | | +----------------------------+ | | |
45
+/* Name of the emc device. */
48
+ | | read_ack_preserve | +-+---+--->| read_ack_register1 | | | |
46
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
49
+ | | read_ack_write | | | +----------------------------+ | | |
47
+
50
+ + +--------------------------+ | +-+--->| read_ack_register2 | | | |
48
+/* Timeout for various operations, in seconds. */
51
+ | | GHES2 | | | | +----------------------------+ | | |
49
+#define TIMEOUT_SECONDS 10
52
+ + +--------------------------+ | | | | ............. | | | |
50
+
53
+ | | ................. | | | | +----------------------------+ | | |
51
+/* Address in memory of the descriptor. */
54
+ | | error_status_address-----+---+ | | +->| read_ack_registerN | | | |
52
+#define DESC_ADDR (1 << 20) /* 1 MiB */
55
+ | | ................. | | | | +----------------------------+ | | |
53
+
56
+ | | read_ack_register--------+-----+ | | |Generic Error Status Block 1|<-----+ | |
54
+/* Address in memory of the data packet. */
57
+ | | read_ack_preserve | | | |-+------------------------+-+ | |
55
+#define DATA_ADDR (DESC_ADDR + 4096)
58
+ | | read_ack_write | | | | | CPER | | | |
56
+
59
+ + +--------------------------| | | | | CPER | | | |
57
+#define CRC_LENGTH 4
60
+ | | ............... | | | | | .... | | | |
58
+
61
+ + +--------------------------+ | | | | CPER | | | |
59
+#define NUM_TX_DESCRIPTORS 3
62
+ | | GHESN | | | |-+------------------------+-| | |
60
+#define NUM_RX_DESCRIPTORS 2
63
+ + +--------------------------+ | | |Generic Error Status Block 2|<-------+ |
61
+
64
+ | | ................. | | | |-+------------------------+-+ |
62
+/* Size of tx,rx test buffers. */
65
+ | | error_status_address-----+-------+ | | | CPER | | |
63
+#define TX_DATA_LEN 64
66
+ | | ................. | | | | CPER | | |
64
+#define RX_DATA_LEN 64
67
+ | | read_ack_register--------+---------+ | | .... | | |
65
+
68
+ | | read_ack_preserve | | | CPER | | |
66
+#define TX_STEP_COUNT 10000
69
+ | | read_ack_write | +-+------------------------+-+ |
67
+#define RX_STEP_COUNT 10000
70
+ + +--------------------------+ | .......... | |
68
+
71
+ |----------------------------+ |
69
+/* 32-bit register indices. */
72
+ |Generic Error Status Block N |<----------+
70
+typedef enum NPCM7xxPWMRegister {
73
+ |-+-------------------------+-+
71
+ /* Control registers. */
74
+ | | CPER | |
72
+ REG_CAMCMR,
75
+ | | CPER | |
73
+ REG_CAMEN,
76
+ | | .... | |
74
+
77
+ | | CPER | |
75
+ /* There are 16 CAMn[ML] registers. */
78
+ +-+-------------------------+-+
76
+ REG_CAMM_BASE,
79
+
77
+ REG_CAML_BASE,
80
+
78
+
81
+(1) QEMU generates the ACPI HEST table. This table goes in the current
79
+ REG_TXDLSA = 0x22,
82
+ "etc/acpi/tables" fw_cfg blob. Each error source has different
80
+ REG_RXDLSA,
83
+ notification types.
81
+ REG_MCMDR,
84
+
82
+ REG_MIID,
85
+(2) A new fw_cfg blob called "etc/hardware_errors" is introduced. QEMU
83
+ REG_MIIDA,
86
+ also needs to populate this blob. The "etc/hardware_errors" fw_cfg blob
84
+ REG_FFTCR,
87
+ contains an address registers table and an Error Status Data Block table.
85
+ REG_TSDR,
88
+
86
+ REG_RSDR,
89
+(3) The address registers table contains N Error Block Address entries
87
+ REG_DMARFC,
90
+ and N Read Ack Register entries. The size for each entry is 8-byte.
88
+ REG_MIEN,
91
+ The Error Status Data Block table contains N Error Status Data Block
89
+
92
+ entries. The size for each entry is 4096(0x1000) bytes. The total size
90
+ /* Status registers. */
93
+ for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
91
+ REG_MISTA,
94
+ N is the number of the kinds of hardware error sources.
92
+ REG_MGSTA,
95
+
93
+ REG_MPCNT,
96
+(4) QEMU generates the ACPI linker/loader script for the firmware. The
94
+ REG_MRPC,
97
+ firmware pre-allocates memory for "etc/acpi/tables", "etc/hardware_errors"
95
+ REG_MRPCC,
98
+ and copies blob contents there.
96
+ REG_MREPC,
99
+
97
+ REG_DMARFS,
100
+(5) QEMU generates N ADD_POINTER commands, which patch addresses in the
98
+ REG_CTXDSA,
101
+ "error_status_address" fields of the HEST table with a pointer to the
99
+ REG_CTXBSA,
102
+ corresponding "address registers" in the "etc/hardware_errors" blob.
100
+ REG_CRXDSA,
103
+
101
+ REG_CRXBSA,
104
+(6) QEMU generates N ADD_POINTER commands, which patch addresses in the
102
+
105
+ "read_ack_register" fields of the HEST table with a pointer to the
103
+ NPCM7XX_NUM_EMC_REGS,
106
+ corresponding "read_ack_register" within the "etc/hardware_errors" blob.
104
+} NPCM7xxPWMRegister;
107
+
105
+
108
+(7) QEMU generates N ADD_POINTER commands for the firmware, which patch
106
+enum { NUM_CAMML_REGS = 16 };
109
+ addresses in the "error_block_address" fields with a pointer to the
107
+
110
+ respective "Error Status Data Block" in the "etc/hardware_errors" blob.
108
+/* REG_CAMCMR fields */
111
+
109
+/* Enable CAM Compare */
112
+(8) QEMU defines a third and write-only fw_cfg blob which is called
110
+#define REG_CAMCMR_ECMP (1 << 4)
113
+ "etc/hardware_errors_addr". Through that blob, the firmware can send back
111
+/* Accept Unicast Packet */
114
+ the guest-side allocation addresses to QEMU. The "etc/hardware_errors_addr"
112
+#define REG_CAMCMR_AUP (1 << 0)
115
+ blob contains a 8-byte entry. QEMU generates a single WRITE_POINTER command
113
+
116
+ for the firmware. The firmware will write back the start address of
114
+/* REG_MCMDR fields */
117
+ "etc/hardware_errors" blob to the fw_cfg file "etc/hardware_errors_addr".
115
+/* Software Reset */
118
+
116
+#define REG_MCMDR_SWR (1 << 24)
119
+(9) When QEMU gets a SIGBUS from the kernel, QEMU writes CPER into corresponding
117
+/* Frame Transmission On */
120
+ "Error Status Data Block", guest memory, and then injects platform specific
118
+#define REG_MCMDR_TXON (1 << 8)
121
+ interrupt (in case of arm/virt machine it's Synchronous External Abort) as a
119
+/* Accept Long Packet */
122
+ notification which is necessary for notifying the guest.
120
+#define REG_MCMDR_ALP (1 << 1)
123
+
121
+/* Frame Reception On */
124
+(10) This notification (in virtual hardware) will be handled by the guest
122
+#define REG_MCMDR_RXON (1 << 0)
125
+ kernel, on receiving notification, guest APEI driver could read the CPER error
123
+
126
+ and take appropriate action.
124
+/* REG_MIEN fields */
127
+
125
+/* Enable Transmit Completion Interrupt */
128
+(11) kvm_arch_on_sigbus_vcpu() uses source_id as index in "etc/hardware_errors" to
126
+#define REG_MIEN_ENTXCP (1 << 18)
129
+ find out "Error Status Data Block" entry corresponding to error source. So supported
127
+/* Enable Transmit Interrupt */
130
+ source_id values should be assigned here and not be changed afterwards to make sure
128
+#define REG_MIEN_ENTXINTR (1 << 16)
131
+ that guest will write error into expected "Error Status Data Block" even if guest was
129
+/* Enable Receive Good Interrupt */
132
+ migrated to a newer QEMU.
130
+#define REG_MIEN_ENRXGD (1 << 4)
133
diff --git a/docs/specs/index.rst b/docs/specs/index.rst
131
+/* ENable Receive Interrupt */
132
+#define REG_MIEN_ENRXINTR (1 << 0)
133
+
134
+/* REG_MISTA fields */
135
+/* Transmit Bus Error Interrupt */
136
+#define REG_MISTA_TXBERR (1 << 24)
137
+/* Transmit Descriptor Unavailable Interrupt */
138
+#define REG_MISTA_TDU (1 << 23)
139
+/* Transmit Completion Interrupt */
140
+#define REG_MISTA_TXCP (1 << 18)
141
+/* Transmit Interrupt */
142
+#define REG_MISTA_TXINTR (1 << 16)
143
+/* Receive Bus Error Interrupt */
144
+#define REG_MISTA_RXBERR (1 << 11)
145
+/* Receive Descriptor Unavailable Interrupt */
146
+#define REG_MISTA_RDU (1 << 10)
147
+/* DMA Early Notification Interrupt */
148
+#define REG_MISTA_DENI (1 << 9)
149
+/* Maximum Frame Length Interrupt */
150
+#define REG_MISTA_DFOI (1 << 8)
151
+/* Receive Good Interrupt */
152
+#define REG_MISTA_RXGD (1 << 4)
153
+/* Packet Too Long Interrupt */
154
+#define REG_MISTA_PTLE (1 << 3)
155
+/* Receive Interrupt */
156
+#define REG_MISTA_RXINTR (1 << 0)
157
+
158
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
159
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
160
+
161
+struct NPCM7xxEMCTxDesc {
162
+ uint32_t flags;
163
+ uint32_t txbsa;
164
+ uint32_t status_and_length;
165
+ uint32_t ntxdsa;
166
+};
167
+
168
+struct NPCM7xxEMCRxDesc {
169
+ uint32_t status_and_length;
170
+ uint32_t rxbsa;
171
+ uint32_t reserved;
172
+ uint32_t nrxdsa;
173
+};
174
+
175
+/* NPCM7xxEMCTxDesc.flags values */
176
+/* Owner: 0 = cpu, 1 = emc */
177
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
178
+/* Transmit interrupt enable */
179
+#define TX_DESC_FLAG_INTEN (1 << 2)
180
+
181
+/* NPCM7xxEMCTxDesc.status_and_length values */
182
+/* Transmission complete */
183
+#define TX_DESC_STATUS_TXCP (1 << 19)
184
+/* Transmit interrupt */
185
+#define TX_DESC_STATUS_TXINTR (1 << 16)
186
+
187
+/* NPCM7xxEMCRxDesc.status_and_length values */
188
+/* Owner: 0b00 = cpu, 0b10 = emc */
189
+#define RX_DESC_STATUS_OWNER_SHIFT 30
190
+#define RX_DESC_STATUS_OWNER_MASK 0xc0000000
191
+/* Frame Reception Complete */
192
+#define RX_DESC_STATUS_RXGD (1 << 20)
193
+/* Packet too long */
194
+#define RX_DESC_STATUS_PTLE (1 << 19)
195
+/* Receive Interrupt */
196
+#define RX_DESC_STATUS_RXINTR (1 << 16)
197
+
198
+#define RX_DESC_PKT_LEN(word) ((uint32_t) (word) & 0xffff)
199
+
200
+typedef struct EMCModule {
201
+ int rx_irq;
202
+ int tx_irq;
203
+ uint64_t base_addr;
204
+} EMCModule;
205
+
206
+typedef struct TestData {
207
+ const EMCModule *module;
208
+} TestData;
209
+
210
+static const EMCModule emc_module_list[] = {
211
+ {
212
+ .rx_irq = 15,
213
+ .tx_irq = 16,
214
+ .base_addr = 0xf0825000
215
+ },
216
+ {
217
+ .rx_irq = 114,
218
+ .tx_irq = 115,
219
+ .base_addr = 0xf0826000
220
+ }
221
+};
222
+
223
+/* Returns the index of the EMC module. */
224
+static int emc_module_index(const EMCModule *mod)
225
+{
226
+ ptrdiff_t diff = mod - emc_module_list;
227
+
228
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(emc_module_list));
229
+
230
+ return diff;
231
+}
232
+
233
+static void packet_test_clear(void *sockets)
234
+{
235
+ int *test_sockets = sockets;
236
+
237
+ close(test_sockets[0]);
238
+ g_free(test_sockets);
239
+}
240
+
241
+static int *packet_test_init(int module_num, GString *cmd_line)
242
+{
243
+ int *test_sockets = g_new(int, 2);
244
+ int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets);
245
+ g_assert_cmpint(ret, != , -1);
246
+
247
+ /*
248
+ * KISS and use -nic. We specify two nics (both emc{0,1}) because there's
249
+ * currently no way to specify only emc1: The driver implicitly relies on
250
+ * emc[i] == nd_table[i].
251
+ */
252
+ if (module_num == 0) {
253
+ g_string_append_printf(cmd_line,
254
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " "
255
+ " -nic user,model=" TYPE_NPCM7XX_EMC " ",
256
+ test_sockets[1]);
257
+ } else {
258
+ g_string_append_printf(cmd_line,
259
+ " -nic user,model=" TYPE_NPCM7XX_EMC " "
260
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " ",
261
+ test_sockets[1]);
262
+ }
263
+
264
+ g_test_queue_destroy(packet_test_clear, test_sockets);
265
+ return test_sockets;
266
+}
267
+
268
+static uint32_t emc_read(QTestState *qts, const EMCModule *mod,
269
+ NPCM7xxPWMRegister regno)
270
+{
271
+ return qtest_readl(qts, mod->base_addr + regno * sizeof(uint32_t));
272
+}
273
+
274
+static void emc_write(QTestState *qts, const EMCModule *mod,
275
+ NPCM7xxPWMRegister regno, uint32_t value)
276
+{
277
+ qtest_writel(qts, mod->base_addr + regno * sizeof(uint32_t), value);
278
+}
279
+
280
+static void emc_read_tx_desc(QTestState *qts, uint32_t addr,
281
+ NPCM7xxEMCTxDesc *desc)
282
+{
283
+ qtest_memread(qts, addr, desc, sizeof(*desc));
284
+ desc->flags = le32_to_cpu(desc->flags);
285
+ desc->txbsa = le32_to_cpu(desc->txbsa);
286
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
287
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
288
+}
289
+
290
+static void emc_write_tx_desc(QTestState *qts, const NPCM7xxEMCTxDesc *desc,
291
+ uint32_t addr)
292
+{
293
+ NPCM7xxEMCTxDesc le_desc;
294
+
295
+ le_desc.flags = cpu_to_le32(desc->flags);
296
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
297
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
298
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
299
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
300
+}
301
+
302
+static void emc_read_rx_desc(QTestState *qts, uint32_t addr,
303
+ NPCM7xxEMCRxDesc *desc)
304
+{
305
+ qtest_memread(qts, addr, desc, sizeof(*desc));
306
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
307
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
308
+ desc->reserved = le32_to_cpu(desc->reserved);
309
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
310
+}
311
+
312
+static void emc_write_rx_desc(QTestState *qts, const NPCM7xxEMCRxDesc *desc,
313
+ uint32_t addr)
314
+{
315
+ NPCM7xxEMCRxDesc le_desc;
316
+
317
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
318
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
319
+ le_desc.reserved = cpu_to_le32(desc->reserved);
320
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
321
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
322
+}
323
+
324
+/*
325
+ * Reset the EMC module.
326
+ * The module must be reset before, e.g., TXDLSA,RXDLSA are changed.
327
+ */
328
+static bool emc_soft_reset(QTestState *qts, const EMCModule *mod)
329
+{
330
+ uint32_t val;
331
+ uint64_t end_time;
332
+
333
+ emc_write(qts, mod, REG_MCMDR, REG_MCMDR_SWR);
334
+
335
+ /*
336
+ * Wait for device to reset as the linux driver does.
337
+ * During reset the AHB reads 0 for all registers. So first wait for
338
+ * something that resets to non-zero, and then wait for SWR becoming 0.
339
+ */
340
+ end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
341
+
342
+ do {
343
+ qtest_clock_step(qts, 100);
344
+ val = emc_read(qts, mod, REG_FFTCR);
345
+ } while (val == 0 && g_get_monotonic_time() < end_time);
346
+ if (val != 0) {
347
+ do {
348
+ qtest_clock_step(qts, 100);
349
+ val = emc_read(qts, mod, REG_MCMDR);
350
+ if ((val & REG_MCMDR_SWR) == 0) {
351
+ /*
352
+ * N.B. The CAMs have been reset here, so macaddr matching of
353
+ * incoming packets will not work.
354
+ */
355
+ return true;
356
+ }
357
+ } while (g_get_monotonic_time() < end_time);
358
+ }
359
+
360
+ g_message("%s: Timeout expired", __func__);
361
+ return false;
362
+}
363
+
364
+/* Check emc registers are reset to default value. */
365
+static void test_init(gconstpointer test_data)
366
+{
367
+ const TestData *td = test_data;
368
+ const EMCModule *mod = td->module;
369
+ QTestState *qts = qtest_init("-machine quanta-gsj");
370
+ int i;
371
+
372
+#define CHECK_REG(regno, value) \
373
+ do { \
374
+ g_assert_cmphex(emc_read(qts, mod, (regno)), ==, (value)); \
375
+ } while (0)
376
+
377
+ CHECK_REG(REG_CAMCMR, 0);
378
+ CHECK_REG(REG_CAMEN, 0);
379
+ CHECK_REG(REG_TXDLSA, 0xfffffffc);
380
+ CHECK_REG(REG_RXDLSA, 0xfffffffc);
381
+ CHECK_REG(REG_MCMDR, 0);
382
+ CHECK_REG(REG_MIID, 0);
383
+ CHECK_REG(REG_MIIDA, 0x00900000);
384
+ CHECK_REG(REG_FFTCR, 0x0101);
385
+ CHECK_REG(REG_DMARFC, 0x0800);
386
+ CHECK_REG(REG_MIEN, 0);
387
+ CHECK_REG(REG_MISTA, 0);
388
+ CHECK_REG(REG_MGSTA, 0);
389
+ CHECK_REG(REG_MPCNT, 0x7fff);
390
+ CHECK_REG(REG_MRPC, 0);
391
+ CHECK_REG(REG_MRPCC, 0);
392
+ CHECK_REG(REG_MREPC, 0);
393
+ CHECK_REG(REG_DMARFS, 0);
394
+ CHECK_REG(REG_CTXDSA, 0);
395
+ CHECK_REG(REG_CTXBSA, 0);
396
+ CHECK_REG(REG_CRXDSA, 0);
397
+ CHECK_REG(REG_CRXBSA, 0);
398
+
399
+#undef CHECK_REG
400
+
401
+ for (i = 0; i < NUM_CAMML_REGS; ++i) {
402
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAMM_BASE + i * 2), ==,
403
+ 0);
404
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAML_BASE + i * 2), ==,
405
+ 0);
406
+ }
407
+
408
+ qtest_quit(qts);
409
+}
410
+
411
+static bool emc_wait_irq(QTestState *qts, const EMCModule *mod, int step,
412
+ bool is_tx)
413
+{
414
+ uint64_t end_time =
415
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
416
+
417
+ do {
418
+ if (qtest_get_irq(qts, is_tx ? mod->tx_irq : mod->rx_irq)) {
419
+ return true;
420
+ }
421
+ qtest_clock_step(qts, step);
422
+ } while (g_get_monotonic_time() < end_time);
423
+
424
+ g_message("%s: Timeout expired", __func__);
425
+ return false;
426
+}
427
+
428
+static bool emc_wait_mista(QTestState *qts, const EMCModule *mod, int step,
429
+ uint32_t flag)
430
+{
431
+ uint64_t end_time =
432
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
433
+
434
+ do {
435
+ uint32_t mista = emc_read(qts, mod, REG_MISTA);
436
+ if (mista & flag) {
437
+ return true;
438
+ }
439
+ qtest_clock_step(qts, step);
440
+ } while (g_get_monotonic_time() < end_time);
441
+
442
+ g_message("%s: Timeout expired", __func__);
443
+ return false;
444
+}
445
+
446
+static bool wait_socket_readable(int fd)
447
+{
448
+ fd_set read_fds;
449
+ struct timeval tv;
450
+ int rv;
451
+
452
+ FD_ZERO(&read_fds);
453
+ FD_SET(fd, &read_fds);
454
+ tv.tv_sec = TIMEOUT_SECONDS;
455
+ tv.tv_usec = 0;
456
+ rv = select(fd + 1, &read_fds, NULL, NULL, &tv);
457
+ if (rv == -1) {
458
+ perror("select");
459
+ } else if (rv == 0) {
460
+ g_message("%s: Timeout expired", __func__);
461
+ }
462
+ return rv == 1;
463
+}
464
+
465
+/* Initialize *desc (in host endian format). */
466
+static void init_tx_desc(NPCM7xxEMCTxDesc *desc, size_t count,
467
+ uint32_t desc_addr)
468
+{
469
+ g_assert(count >= 2);
470
+ memset(&desc[0], 0, sizeof(*desc) * count);
471
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
472
+ for (size_t i = 0; i < count - 1; ++i) {
473
+ desc[i].flags =
474
+ (TX_DESC_FLAG_OWNER_MASK | /* owner = 1: emc */
475
+ TX_DESC_FLAG_INTEN |
476
+ 0 | /* crc append = 0 */
477
+ 0 /* padding enable = 0 */);
478
+ desc[i].status_and_length =
479
+ (0 | /* collision count = 0 */
480
+ 0 | /* SQE = 0 */
481
+ 0 | /* PAU = 0 */
482
+ 0 | /* TXHA = 0 */
483
+ 0 | /* LC = 0 */
484
+ 0 | /* TXABT = 0 */
485
+ 0 | /* NCS = 0 */
486
+ 0 | /* EXDEF = 0 */
487
+ 0 | /* TXCP = 0 */
488
+ 0 | /* DEF = 0 */
489
+ 0 | /* TXINTR = 0 */
490
+ 0 /* length filled in later */);
491
+ desc[i].ntxdsa = desc_addr + (i + 1) * sizeof(*desc);
492
+ }
493
+}
494
+
495
+static void enable_tx(QTestState *qts, const EMCModule *mod,
496
+ const NPCM7xxEMCTxDesc *desc, size_t count,
497
+ uint32_t desc_addr, uint32_t mien_flags)
498
+{
499
+ /* Write the descriptors to guest memory. */
500
+ for (size_t i = 0; i < count; ++i) {
501
+ emc_write_tx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
502
+ }
503
+
504
+ /* Trigger sending the packet. */
505
+ /* The module must be reset before changing TXDLSA. */
506
+ g_assert(emc_soft_reset(qts, mod));
507
+ emc_write(qts, mod, REG_TXDLSA, desc_addr);
508
+ emc_write(qts, mod, REG_CTXDSA, ~0);
509
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENTXCP | mien_flags);
510
+ {
511
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
512
+ mcmdr |= REG_MCMDR_TXON;
513
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
514
+ }
515
+
516
+ /* Prod the device to send the packet. */
517
+ emc_write(qts, mod, REG_TSDR, 1);
518
+}
519
+
520
+static void emc_send_verify1(QTestState *qts, const EMCModule *mod, int fd,
521
+ bool with_irq, uint32_t desc_addr,
522
+ uint32_t next_desc_addr,
523
+ const char *test_data, int test_size)
524
+{
525
+ NPCM7xxEMCTxDesc result_desc;
526
+ uint32_t expected_mask, expected_value, recv_len;
527
+ int ret;
528
+ char buffer[TX_DATA_LEN];
529
+
530
+ g_assert(wait_socket_readable(fd));
531
+
532
+ /* Read the descriptor back. */
533
+ emc_read_tx_desc(qts, desc_addr, &result_desc);
534
+ /* Descriptor should be owned by cpu now. */
535
+ g_assert((result_desc.flags & TX_DESC_FLAG_OWNER_MASK) == 0);
536
+ /* Test the status bits, ignoring the length field. */
537
+ expected_mask = 0xffff << 16;
538
+ expected_value = TX_DESC_STATUS_TXCP;
539
+ if (with_irq) {
540
+ expected_value |= TX_DESC_STATUS_TXINTR;
541
+ }
542
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
543
+ expected_value);
544
+
545
+ /* Check data sent to the backend. */
546
+ recv_len = ~0;
547
+ ret = qemu_recv(fd, &recv_len, sizeof(recv_len), MSG_DONTWAIT);
548
+ g_assert_cmpint(ret, == , sizeof(recv_len));
549
+
550
+ g_assert(wait_socket_readable(fd));
551
+ memset(buffer, 0xff, sizeof(buffer));
552
+ ret = qemu_recv(fd, buffer, test_size, MSG_DONTWAIT);
553
+ g_assert_cmpmem(buffer, ret, test_data, test_size);
554
+}
555
+
556
+static void emc_send_verify(QTestState *qts, const EMCModule *mod, int fd,
557
+ bool with_irq)
558
+{
559
+ NPCM7xxEMCTxDesc desc[NUM_TX_DESCRIPTORS];
560
+ uint32_t desc_addr = DESC_ADDR;
561
+ static const char test1_data[] = "TEST1";
562
+ static const char test2_data[] = "Testing 1 2 3 ...";
563
+ uint32_t data1_addr = DATA_ADDR;
564
+ uint32_t data2_addr = data1_addr + sizeof(test1_data);
565
+ bool got_tdu;
566
+ uint32_t end_desc_addr;
567
+
568
+ /* Prepare test data buffer. */
569
+ qtest_memwrite(qts, data1_addr, test1_data, sizeof(test1_data));
570
+ qtest_memwrite(qts, data2_addr, test2_data, sizeof(test2_data));
571
+
572
+ init_tx_desc(&desc[0], NUM_TX_DESCRIPTORS, desc_addr);
573
+ desc[0].txbsa = data1_addr;
574
+ desc[0].status_and_length |= sizeof(test1_data);
575
+ desc[1].txbsa = data2_addr;
576
+ desc[1].status_and_length |= sizeof(test2_data);
577
+
578
+ enable_tx(qts, mod, &desc[0], NUM_TX_DESCRIPTORS, desc_addr,
579
+ with_irq ? REG_MIEN_ENTXINTR : 0);
580
+
581
+ /*
582
+ * It's problematic to observe the interrupt for each packet.
583
+ * Instead just wait until all the packets go out.
584
+ */
585
+ got_tdu = false;
586
+ while (!got_tdu) {
587
+ if (with_irq) {
588
+ g_assert_true(emc_wait_irq(qts, mod, TX_STEP_COUNT,
589
+ /*is_tx=*/true));
590
+ } else {
591
+ g_assert_true(emc_wait_mista(qts, mod, TX_STEP_COUNT,
592
+ REG_MISTA_TXINTR));
593
+ }
594
+ got_tdu = !!(emc_read(qts, mod, REG_MISTA) & REG_MISTA_TDU);
595
+ /* If we don't have TDU yet, reset the interrupt. */
596
+ if (!got_tdu) {
597
+ emc_write(qts, mod, REG_MISTA,
598
+ emc_read(qts, mod, REG_MISTA) & 0xffff0000);
599
+ }
600
+ }
601
+
602
+ end_desc_addr = desc_addr + 2 * sizeof(desc[0]);
603
+ g_assert_cmphex(emc_read(qts, mod, REG_CTXDSA), ==, end_desc_addr);
604
+ g_assert_cmphex(emc_read(qts, mod, REG_MISTA), ==,
605
+ REG_MISTA_TXCP | REG_MISTA_TXINTR | REG_MISTA_TDU);
606
+
607
+ emc_send_verify1(qts, mod, fd, with_irq,
608
+ desc_addr, end_desc_addr,
609
+ test1_data, sizeof(test1_data));
610
+ emc_send_verify1(qts, mod, fd, with_irq,
611
+ desc_addr + sizeof(desc[0]), end_desc_addr,
612
+ test2_data, sizeof(test2_data));
613
+}
614
+
615
+/* Initialize *desc (in host endian format). */
616
+static void init_rx_desc(NPCM7xxEMCRxDesc *desc, size_t count,
617
+ uint32_t desc_addr, uint32_t data_addr)
618
+{
619
+ g_assert_true(count >= 2);
620
+ memset(desc, 0, sizeof(*desc) * count);
621
+ desc[0].rxbsa = data_addr;
622
+ desc[0].status_and_length =
623
+ (0b10 << RX_DESC_STATUS_OWNER_SHIFT | /* owner = 10: emc */
624
+ 0 | /* RP = 0 */
625
+ 0 | /* ALIE = 0 */
626
+ 0 | /* RXGD = 0 */
627
+ 0 | /* PTLE = 0 */
628
+ 0 | /* CRCE = 0 */
629
+ 0 | /* RXINTR = 0 */
630
+ 0 /* length (filled in later) */);
631
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
632
+ desc[0].nrxdsa = desc_addr + sizeof(*desc);
633
+}
634
+
635
+static void enable_rx(QTestState *qts, const EMCModule *mod,
636
+ const NPCM7xxEMCRxDesc *desc, size_t count,
637
+ uint32_t desc_addr, uint32_t mien_flags,
638
+ uint32_t mcmdr_flags)
639
+{
640
+ /*
641
+ * Write the descriptor to guest memory.
642
+ * FWIW, IWBN if the docs said the buffer needs to be at least DMARFC
643
+ * bytes.
644
+ */
645
+ for (size_t i = 0; i < count; ++i) {
646
+ emc_write_rx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
647
+ }
648
+
649
+ /* Trigger receiving the packet. */
650
+ /* The module must be reset before changing RXDLSA. */
651
+ g_assert(emc_soft_reset(qts, mod));
652
+ emc_write(qts, mod, REG_RXDLSA, desc_addr);
653
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENRXGD | mien_flags);
654
+
655
+ /*
656
+ * We don't know what the device's macaddr is, so just accept all
657
+ * unicast packets (AUP).
658
+ */
659
+ emc_write(qts, mod, REG_CAMCMR, REG_CAMCMR_AUP);
660
+ emc_write(qts, mod, REG_CAMEN, 1 << 0);
661
+ {
662
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
663
+ mcmdr |= REG_MCMDR_RXON | mcmdr_flags;
664
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
665
+ }
666
+
667
+ /* Prod the device to accept a packet. */
668
+ emc_write(qts, mod, REG_RSDR, 1);
669
+}
670
+
671
+static void emc_recv_verify(QTestState *qts, const EMCModule *mod, int fd,
672
+ bool with_irq)
673
+{
674
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
675
+ uint32_t desc_addr = DESC_ADDR;
676
+ uint32_t data_addr = DATA_ADDR;
677
+ int ret;
678
+ uint32_t expected_mask, expected_value;
679
+ NPCM7xxEMCRxDesc result_desc;
680
+
681
+ /* Prepare test data buffer. */
682
+ const char test[RX_DATA_LEN] = "TEST";
683
+ int len = htonl(sizeof(test));
684
+ const struct iovec iov[] = {
685
+ {
686
+ .iov_base = &len,
687
+ .iov_len = sizeof(len),
688
+ },{
689
+ .iov_base = (char *) test,
690
+ .iov_len = sizeof(test),
691
+ },
692
+ };
693
+
694
+ /*
695
+ * Reset the device BEFORE sending a test packet, otherwise the packet
696
+ * may get swallowed by an active device of an earlier test.
697
+ */
698
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
699
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
700
+ with_irq ? REG_MIEN_ENRXINTR : 0, 0);
701
+
702
+ /* Send test packet to device's socket. */
703
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test));
704
+ g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
705
+
706
+ /* Wait for RX interrupt. */
707
+ if (with_irq) {
708
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
709
+ } else {
710
+ g_assert_true(emc_wait_mista(qts, mod, RX_STEP_COUNT, REG_MISTA_RXGD));
711
+ }
712
+
713
+ g_assert_cmphex(emc_read(qts, mod, REG_CRXDSA), ==,
714
+ desc_addr + sizeof(desc[0]));
715
+
716
+ expected_mask = 0xffff;
717
+ expected_value = (REG_MISTA_DENI |
718
+ REG_MISTA_RXGD |
719
+ REG_MISTA_RXINTR);
720
+ g_assert_cmphex((emc_read(qts, mod, REG_MISTA) & expected_mask),
721
+ ==, expected_value);
722
+
723
+ /* Read the descriptor back. */
724
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
725
+ /* Descriptor should be owned by cpu now. */
726
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
727
+ /* Test the status bits, ignoring the length field. */
728
+ expected_mask = 0xffff << 16;
729
+ expected_value = RX_DESC_STATUS_RXGD;
730
+ if (with_irq) {
731
+ expected_value |= RX_DESC_STATUS_RXINTR;
732
+ }
733
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
734
+ expected_value);
735
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
736
+ RX_DATA_LEN + CRC_LENGTH);
737
+
738
+ {
739
+ char buffer[RX_DATA_LEN];
740
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
741
+ g_assert_cmpstr(buffer, == , "TEST");
742
+ }
743
+}
744
+
745
+static void emc_test_ptle(QTestState *qts, const EMCModule *mod, int fd)
746
+{
747
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
748
+ uint32_t desc_addr = DESC_ADDR;
749
+ uint32_t data_addr = DATA_ADDR;
750
+ int ret;
751
+ NPCM7xxEMCRxDesc result_desc;
752
+ uint32_t expected_mask, expected_value;
753
+
754
+ /* Prepare test data buffer. */
755
+#define PTLE_DATA_LEN 1600
756
+ char test_data[PTLE_DATA_LEN];
757
+ int len = htonl(sizeof(test_data));
758
+ const struct iovec iov[] = {
759
+ {
760
+ .iov_base = &len,
761
+ .iov_len = sizeof(len),
762
+ },{
763
+ .iov_base = (char *) test_data,
764
+ .iov_len = sizeof(test_data),
765
+ },
766
+ };
767
+ memset(test_data, 42, sizeof(test_data));
768
+
769
+ /*
770
+ * Reset the device BEFORE sending a test packet, otherwise the packet
771
+ * may get swallowed by an active device of an earlier test.
772
+ */
773
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
774
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
775
+ REG_MIEN_ENRXINTR, REG_MCMDR_ALP);
776
+
777
+ /* Send test packet to device's socket. */
778
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test_data));
779
+ g_assert_cmpint(ret, == , sizeof(test_data) + sizeof(len));
780
+
781
+ /* Wait for RX interrupt. */
782
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
783
+
784
+ /* Read the descriptor back. */
785
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
786
+ /* Descriptor should be owned by cpu now. */
787
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
788
+ /* Test the status bits, ignoring the length field. */
789
+ expected_mask = 0xffff << 16;
790
+ expected_value = (RX_DESC_STATUS_RXGD |
791
+ RX_DESC_STATUS_PTLE |
792
+ RX_DESC_STATUS_RXINTR);
793
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
794
+ expected_value);
795
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
796
+ PTLE_DATA_LEN + CRC_LENGTH);
797
+
798
+ {
799
+ char buffer[PTLE_DATA_LEN];
800
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
801
+ g_assert(memcmp(buffer, test_data, PTLE_DATA_LEN) == 0);
802
+ }
803
+}
804
+
805
+static void test_tx(gconstpointer test_data)
806
+{
807
+ const TestData *td = test_data;
808
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
809
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
810
+ cmd_line);
811
+ QTestState *qts = qtest_init(cmd_line->str);
812
+
813
+ /*
814
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
815
+ * the fork and before the exec, but that will require some harness
816
+ * improvements.
817
+ */
818
+ close(test_sockets[1]);
819
+ /* Defensive programming */
820
+ test_sockets[1] = -1;
821
+
822
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
823
+
824
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
825
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
826
+
827
+ qtest_quit(qts);
828
+}
829
+
830
+static void test_rx(gconstpointer test_data)
831
+{
832
+ const TestData *td = test_data;
833
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
834
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
835
+ cmd_line);
836
+ QTestState *qts = qtest_init(cmd_line->str);
837
+
838
+ /*
839
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
840
+ * the fork and before the exec, but that will require some harness
841
+ * improvements.
842
+ */
843
+ close(test_sockets[1]);
844
+ /* Defensive programming */
845
+ test_sockets[1] = -1;
846
+
847
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
848
+
849
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
850
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
851
+ emc_test_ptle(qts, td->module, test_sockets[0]);
852
+
853
+ qtest_quit(qts);
854
+}
855
+
856
+static void emc_add_test(const char *name, const TestData* td,
857
+ GTestDataFunc fn)
858
+{
859
+ g_autofree char *full_name = g_strdup_printf(
860
+ "npcm7xx_emc/emc[%d]/%s", emc_module_index(td->module), name);
861
+ qtest_add_data_func(full_name, td, fn);
862
+}
863
+#define add_test(name, td) emc_add_test(#name, td, test_##name)
864
+
865
+int main(int argc, char **argv)
866
+{
867
+ TestData test_data_list[ARRAY_SIZE(emc_module_list)];
868
+
869
+ g_test_init(&argc, &argv, NULL);
870
+
871
+ for (int i = 0; i < ARRAY_SIZE(emc_module_list); ++i) {
872
+ TestData *td = &test_data_list[i];
873
+
874
+ td->module = &emc_module_list[i];
875
+
876
+ add_test(init, td);
877
+ add_test(tx, td);
878
+ add_test(rx, td);
879
+ }
880
+
881
+ return g_test_run();
882
+}
883
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
134
index XXXXXXX..XXXXXXX 100644
884
index XXXXXXX..XXXXXXX 100644
135
--- a/docs/specs/index.rst
885
--- a/tests/qtest/meson.build
136
+++ b/docs/specs/index.rst
886
+++ b/tests/qtest/meson.build
137
@@ -XXX,XX +XXX,XX @@ Contents:
887
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
138
ppc-spapr-xive
888
'npcm7xx_rng-test',
139
acpi_hw_reduced_hotplug
889
'npcm7xx_smbus-test',
140
tpm
890
'npcm7xx_timer-test',
141
+ acpi_hest_ghes
891
- 'npcm7xx_watchdog_timer-test']
892
+ 'npcm7xx_watchdog_timer-test'] + \
893
+ (slirp.found() ? ['npcm7xx_emc-test'] : [])
894
qtests_arm = \
895
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
896
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
142
--
897
--
143
2.20.1
898
2.20.1
144
899
145
900
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Now that we've converted all cases to gvec, there is quite a bit
3
We hint the 'has_rpu' property is no longer required since commit
4
of dead code at the end of the function. Remove it.
4
6908ec448b4 ("xlnx-zynqmp: Properly support the smp command line
5
option") which was released in QEMU v2.11.0.
5
6
6
Sink the call to gen_gvec_fn2i to the end, loading a function
7
Beside, this device is marked 'user_creatable = false', so the
7
pointer within the switch statement.
8
only thing that could be setting the property is the board code
9
that creates the device.
10
11
Since the property is not user-facing, we can remove it without
12
going through the deprecation process.
8
13
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20200513163245.17915-6-richard.henderson@linaro.org
16
Message-id: 20210219144350.1979905-1-f4bug@amsat.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
18
---
14
target/arm/translate-a64.c | 56 ++++++++++----------------------------
19
include/hw/arm/xlnx-zynqmp.h | 2 --
15
1 file changed, 14 insertions(+), 42 deletions(-)
20
hw/arm/xlnx-zynqmp.c | 6 ------
21
2 files changed, 8 deletions(-)
16
22
17
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
23
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate-a64.c
25
--- a/include/hw/arm/xlnx-zynqmp.h
20
+++ b/target/arm/translate-a64.c
26
+++ 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,
27
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
22
int size = 32 - clz32(immh) - 1;
28
bool secure;
23
int immhb = immh << 3 | immb;
29
/* Has the ARM Virtualization extensions? */
24
int shift = 2 * (8 << size) - immhb;
30
bool virt;
25
- bool accumulate = false;
31
- /* Has the RPU subsystem? */
26
- int dsize = is_q ? 128 : 64;
32
- bool has_rpu;
27
- int esize = 8 << size;
33
28
- int elements = dsize/esize;
34
/* CAN bus. */
29
- MemOp memop = size | (is_u ? 0 : MO_SIGN);
35
CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
30
- TCGv_i64 tcg_rn = new_tmp_a64(s);
36
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
31
- TCGv_i64 tcg_rd = new_tmp_a64(s);
37
index XXXXXXX..XXXXXXX 100644
32
- TCGv_i64 tcg_round;
38
--- a/hw/arm/xlnx-zynqmp.c
33
- uint64_t round_const;
39
+++ b/hw/arm/xlnx-zynqmp.c
34
- int i;
40
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
35
+ GVecGen2iFn *gvec_fn;
36
37
if (extract32(immh, 3, 1) && !is_q) {
38
unallocated_encoding(s);
39
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
40
41
switch (opcode) {
42
case 0x02: /* SSRA / USRA (accumulate) */
43
- gen_gvec_fn2i(s, is_q, rd, rn, shift,
44
- is_u ? gen_gvec_usra : gen_gvec_ssra, size);
45
- return;
46
+ gvec_fn = is_u ? gen_gvec_usra : gen_gvec_ssra;
47
+ break;
48
49
case 0x08: /* SRI */
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
}
41
}
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
}
42
}
94
43
95
- round_const = 1ULL << (shift - 1);
44
- if (s->has_rpu) {
96
- tcg_round = tcg_const_i64(round_const);
45
- info_report("The 'has_rpu' property is no longer required, to use the "
46
- "RPUs just use -smp 6.");
47
- }
97
-
48
-
98
- for (i = 0; i < elements; i++) {
49
xlnx_zynqmp_create_rpu(ms, s, boot_cpu, &err);
99
- read_vec_element(s, tcg_rn, rn, i, memop);
50
if (err) {
100
- if (accumulate) {
51
error_propagate(errp, err);
101
- read_vec_element(s, tcg_rd, rd, i, memop);
52
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
102
- }
53
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
103
-
54
DEFINE_PROP_BOOL("secure", XlnxZynqMPState, secure, false),
104
- handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
55
DEFINE_PROP_BOOL("virtualization", XlnxZynqMPState, virt, false),
105
- accumulate, is_u, size, shift);
56
- DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
106
-
57
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
107
- write_vec_element(s, tcg_rd, rd, i, size);
58
MemoryRegion *),
108
- }
59
DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
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
}
114
115
/* SHL/SLI - Vector shift left */
116
--
60
--
117
2.20.1
61
2.20.1
118
62
119
63
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
Always perform one call instead of two for 16-byte operands.
4
4
Use byte loads/stores directly into the vector register file
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
instead of extractions and deposits to a 64-bit local variable.
6
7
In order to easily receive pointers into the vector register file,
8
convert the helper to the gvec out-of-line signature. Move the
9
helper into vec_helper.c, where it can make use of H1 and clear_tail.
10
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200513163245.17915-16-richard.henderson@linaro.org
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Tested-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 20210224230532.276878-1-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
16
---
10
target/arm/helper.h | 10 +++
17
target/arm/helper-a64.h | 2 +-
11
target/arm/translate.h | 5 ++
18
target/arm/helper-a64.c | 32 ---------------------
12
target/arm/translate-a64.c | 8 ++-
19
target/arm/translate-a64.c | 58 +++++---------------------------------
13
target/arm/translate.c | 133 ++++++++++++++++++++++++++++++++++++-
20
target/arm/vec_helper.c | 48 +++++++++++++++++++++++++++++++
14
target/arm/vec_helper.c | 24 +++++++
21
4 files changed, 56 insertions(+), 84 deletions(-)
15
5 files changed, 176 insertions(+), 4 deletions(-)
22
16
23
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/helper-a64.h
19
--- a/target/arm/helper.h
26
+++ b/target/arm/helper-a64.h
20
+++ b/target/arm/helper.h
27
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(gvec_sli_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
28
DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
22
DEF_HELPER_FLAGS_3(gvec_sli_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
29
DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
23
DEF_HELPER_FLAGS_3(gvec_sli_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
30
DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr)
24
31
-DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32)
25
+DEF_HELPER_FLAGS_4(gvec_sabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
+DEF_HELPER_FLAGS_4(simd_tblx, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_4(gvec_sabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
DEF_HELPER_FLAGS_3(vfp_mulxs, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
27
+DEF_HELPER_FLAGS_4(gvec_sabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
DEF_HELPER_FLAGS_3(vfp_mulxd, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
28
+DEF_HELPER_FLAGS_4(gvec_sabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
DEF_HELPER_FLAGS_3(neon_ceq_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr)
29
+
36
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
30
+DEF_HELPER_FLAGS_4(gvec_uabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
index XXXXXXX..XXXXXXX 100644
31
+DEF_HELPER_FLAGS_4(gvec_uabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
--- a/target/arm/helper-a64.c
32
+DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
+++ b/target/arm/helper-a64.c
33
+DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
40
@@ -XXX,XX +XXX,XX @@ float64 HELPER(vfp_mulxd)(float64 a, float64 b, void *fpstp)
34
+
41
return float64_mul(a, b, fpst);
35
#ifdef TARGET_AARCH64
42
}
36
#include "helper-a64.h"
43
37
#include "helper-sve.h"
44
-uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
38
diff --git a/target/arm/translate.h b/target/arm/translate.h
45
- uint32_t rn, uint32_t numregs)
39
index XXXXXXX..XXXXXXX 100644
46
-{
40
--- a/target/arm/translate.h
47
- /* Helper function for SIMD TBL and TBX. We have to do the table
41
+++ b/target/arm/translate.h
48
- * lookup part for the 64 bits worth of indices we're passed in.
42
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
49
- * result is the initial results vector (either zeroes for TBL
43
void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
50
- * or some guest values for TBX), rn the register number where
44
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
51
- * the table starts, and numregs the number of registers in the table.
45
52
- * We return the results of the lookups.
46
+void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
53
- */
47
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
54
- int shift;
48
+void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
55
-
49
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
56
- for (shift = 0; shift < 64; shift += 8) {
50
+
57
- int index = extract64(indices, shift, 8);
51
/*
58
- if (index < 16 * numregs) {
52
* Forward to the isar_feature_* tests given a DisasContext pointer.
59
- /* Convert index (a byte offset into the virtual table
53
*/
60
- * which is a series of 128-bit vectors concatenated)
61
- * into the correct register element plus a bit offset
62
- * into that element, bearing in mind that the table
63
- * can wrap around from V31 to V0.
64
- */
65
- int elt = (rn * 2 + (index >> 3)) % 64;
66
- int bitidx = (index & 7) * 8;
67
- uint64_t *q = aa64_vfp_qreg(env, elt >> 1);
68
- uint64_t val = extract64(q[elt & 1], bitidx, 8);
69
-
70
- result = deposit64(result, shift, 8, val);
71
- }
72
- }
73
- return result;
74
-}
75
-
76
/* 64bit/double versions of the neon float compare functions */
77
uint64_t HELPER(neon_ceq_f64)(float64 a, float64 b, void *fpstp)
78
{
54
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
79
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
55
index XXXXXXX..XXXXXXX 100644
80
index XXXXXXX..XXXXXXX 100644
56
--- a/target/arm/translate-a64.c
81
--- a/target/arm/translate-a64.c
57
+++ b/target/arm/translate-a64.c
82
+++ b/target/arm/translate-a64.c
58
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
59
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smin, size);
84
int rm = extract32(insn, 16, 5);
60
}
85
int rn = extract32(insn, 5, 5);
86
int rd = extract32(insn, 0, 5);
87
- int is_tblx = extract32(insn, 12, 1);
88
- int len = extract32(insn, 13, 2);
89
- TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
90
- TCGv_i32 tcg_regno, tcg_numregs;
91
+ int is_tbx = extract32(insn, 12, 1);
92
+ int len = (extract32(insn, 13, 2) + 1) * 16;
93
94
if (op2 != 0) {
95
unallocated_encoding(s);
96
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
61
return;
97
return;
62
+ case 0xe: /* SABD, UABD */
98
}
63
+ if (u) {
99
64
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uabd, size);
100
- /* This does a table lookup: for every byte element in the input
65
+ } else {
101
- * we index into a table formed from up to four vector registers,
66
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size);
102
- * and then the output is the result of the lookups. Our helper
67
+ }
103
- * function does the lookup operation for a single 64 bit part of
68
+ return;
104
- * the input.
69
case 0x10: /* ADD, SUB */
105
- */
70
if (u) {
106
- tcg_resl = tcg_temp_new_i64();
71
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
107
- tcg_resh = NULL;
72
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
108
-
73
genenvfn = fns[size][u];
109
- if (is_tblx) {
74
break;
110
- read_vec_element(s, tcg_resl, rd, 0, MO_64);
75
}
111
- } else {
76
- case 0xe: /* SABD, UABD */
112
- tcg_gen_movi_i64(tcg_resl, 0);
77
case 0xf: /* SABA, UABA */
113
- }
78
{
114
-
79
static NeonGenTwoOpFn * const fns[3][2] = {
115
- if (is_q) {
80
diff --git a/target/arm/translate.c b/target/arm/translate.c
116
- tcg_resh = tcg_temp_new_i64();
81
index XXXXXXX..XXXXXXX 100644
117
- if (is_tblx) {
82
--- a/target/arm/translate.c
118
- read_vec_element(s, tcg_resh, rd, 1, MO_64);
83
+++ b/target/arm/translate.c
119
- } else {
84
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
120
- tcg_gen_movi_i64(tcg_resh, 0);
85
rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
121
- }
122
- }
123
-
124
- tcg_idx = tcg_temp_new_i64();
125
- tcg_regno = tcg_const_i32(rn);
126
- tcg_numregs = tcg_const_i32(len + 1);
127
- read_vec_element(s, tcg_idx, rm, 0, MO_64);
128
- gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
129
- tcg_regno, tcg_numregs);
130
- if (is_q) {
131
- read_vec_element(s, tcg_idx, rm, 1, MO_64);
132
- gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
133
- tcg_regno, tcg_numregs);
134
- }
135
- tcg_temp_free_i64(tcg_idx);
136
- tcg_temp_free_i32(tcg_regno);
137
- tcg_temp_free_i32(tcg_numregs);
138
-
139
- write_vec_element(s, tcg_resl, rd, 0, MO_64);
140
- tcg_temp_free_i64(tcg_resl);
141
-
142
- if (is_q) {
143
- write_vec_element(s, tcg_resh, rd, 1, MO_64);
144
- tcg_temp_free_i64(tcg_resh);
145
- }
146
- clear_vec_high(s, is_q, rd);
147
+ tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, rd),
148
+ vec_full_reg_offset(s, rm), cpu_env,
149
+ is_q ? 16 : 8, vec_full_reg_size(s),
150
+ (len << 6) | (is_tbx << 5) | rn,
151
+ gen_helper_simd_tblx);
86
}
152
}
87
153
88
+static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
154
/* ZIP/UZP/TRN
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
155
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
239
index XXXXXXX..XXXXXXX 100644
156
index XXXXXXX..XXXXXXX 100644
240
--- a/target/arm/vec_helper.c
157
--- a/target/arm/vec_helper.c
241
+++ b/target/arm/vec_helper.c
158
+++ b/target/arm/vec_helper.c
242
@@ -XXX,XX +XXX,XX @@ DO_CMP0(gvec_cgt0_h, int16_t, >)
159
@@ -XXX,XX +XXX,XX @@ DO_VRINT_RMODE(gvec_vrint_rm_h, helper_rinth, uint16_t)
243
DO_CMP0(gvec_cge0_h, int16_t, >=)
160
DO_VRINT_RMODE(gvec_vrint_rm_s, helper_rints, uint32_t)
244
161
245
#undef DO_CMP0
162
#undef DO_VRINT_RMODE
246
+
163
+
247
+#define DO_ABD(NAME, TYPE) \
164
+#ifdef TARGET_AARCH64
248
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
165
+void HELPER(simd_tblx)(void *vd, void *vm, void *venv, uint32_t desc)
249
+{ \
166
+{
250
+ intptr_t i, opr_sz = simd_oprsz(desc); \
167
+ const uint8_t *indices = vm;
251
+ TYPE *d = vd, *n = vn, *m = vm; \
168
+ CPUARMState *env = venv;
252
+ \
169
+ size_t oprsz = simd_oprsz(desc);
253
+ for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \
170
+ uint32_t rn = extract32(desc, SIMD_DATA_SHIFT, 5);
254
+ d[i] = n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \
171
+ bool is_tbx = extract32(desc, SIMD_DATA_SHIFT + 5, 1);
255
+ } \
172
+ uint32_t table_len = desc >> (SIMD_DATA_SHIFT + 6);
256
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
173
+ union {
174
+ uint8_t b[16];
175
+ uint64_t d[2];
176
+ } result;
177
+
178
+ /*
179
+ * We must construct the final result in a temp, lest the output
180
+ * overlaps the input table. For TBL, begin with zero; for TBX,
181
+ * begin with the original register contents. Note that we always
182
+ * copy 16 bytes here to avoid an extra branch; clearing the high
183
+ * bits of the register for oprsz == 8 is handled below.
184
+ */
185
+ if (is_tbx) {
186
+ memcpy(&result, vd, 16);
187
+ } else {
188
+ memset(&result, 0, 16);
189
+ }
190
+
191
+ for (size_t i = 0; i < oprsz; ++i) {
192
+ uint32_t index = indices[H1(i)];
193
+
194
+ if (index < table_len) {
195
+ /*
196
+ * Convert index (a byte offset into the virtual table
197
+ * which is a series of 128-bit vectors concatenated)
198
+ * into the correct register element, bearing in mind
199
+ * that the table can wrap around from V31 to V0.
200
+ */
201
+ const uint8_t *table = (const uint8_t *)
202
+ aa64_vfp_qreg(env, (rn + (index >> 4)) % 32);
203
+ result.b[H1(i)] = table[H1(index % 16)];
204
+ }
205
+ }
206
+
207
+ memcpy(vd, &result, 16);
208
+ clear_tail(vd, oprsz, simd_maxsz(desc));
257
+}
209
+}
258
+
210
+#endif
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
--
211
--
271
2.20.1
212
2.20.1
272
213
273
214
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Provide a functional interface for the vector expansion.
3
The STATUS register will be reset to IDLE in
4
This fits better with the existing set of helpers that
4
cnpcm7xx_smbus_enter_reset(), no need to preset
5
we provide for other operations.
5
it in instance_init().
6
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20200513163245.17915-10-richard.henderson@linaro.org
9
Message-id: 20210228224813.312532-1-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/translate.h | 10 ++-
12
hw/i2c/npcm7xx_smbus.c | 1 -
13
target/arm/translate-a64.c | 18 ++--
13
1 file changed, 1 deletion(-)
14
target/arm/translate-neon.inc.c | 23 +----
15
target/arm/translate.c | 146 +++++++++++++++++---------------
16
4 files changed, 95 insertions(+), 102 deletions(-)
17
14
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
15
diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate.h
17
--- a/hw/i2c/npcm7xx_smbus.c
21
+++ b/target/arm/translate.h
18
+++ b/hw/i2c/npcm7xx_smbus.c
22
@@ -XXX,XX +XXX,XX @@ void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
19
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_smbus_init(Object *obj)
23
void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
20
sysbus_init_mmio(sbd, &s->iomem);
24
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
21
25
22
s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
26
-extern const GVecGen3 cmtst_op[4];
23
- s->status = NPCM7XX_SMBUS_STATUS_IDLE;
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
}
24
}
46
25
47
-/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
26
static const VMStateDescription vmstate_npcm7xx_smbus = {
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
--
27
--
306
2.20.1
28
2.20.1
307
29
308
30
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: schspa <schspa@gmail.com>
2
2
3
The little end UUID is used in many places, so make
3
At the moment the following QEMU command line triggers an assertion
4
NVDIMM_UUID_LE to a common macro to convert the UUID
4
failure On xlnx-versal SOC:
5
to a little end array.
5
qemu-system-aarch64 \
6
-machine xlnx-versal-virt -nographic -smp 2 -m 128 \
7
-fsdev local,id=shareid,path=${HOME}/work,security_model=none \
8
-device virtio-9p-device,fsdev=shareid,mount_tag=share \
9
-fsdev local,id=shareid1,path=${HOME}/Music,security_model=none \
10
-device virtio-9p-device,fsdev=shareid1,mount_tag=share1
6
11
7
Reviewed-by: Xiang Zheng <zhengxiang9@huawei.com>
12
qemu-system-aarch64: ../migration/savevm.c:860:
8
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
13
vmstate_register_with_alias_id:
9
Message-id: 20200512030609.19593-2-gengdongjiu@huawei.com
14
Assertion `!se->compat || se->instance_id == 0' failed.
15
16
This problem was fixed on arm virt platform in commit f58b39d2d5b
17
("virtio-mmio: format transport base address in BusClass.get_dev_path")
18
19
It works perfectly on arm virt platform. but there is still there on
20
xlnx-versal SOC.
21
22
The main difference between arm virt and xlnx-versal is they use
23
different way to create virtio-mmio qdev. on arm virt, it calls
24
sysbus_create_simple("virtio-mmio", base, pic[irq]); which will call
25
sysbus_mmio_map internally and assign base address to subsys device
26
mmio correctly. but xlnx-versal's implements won't do this.
27
28
However, xlnx-versal can't switch to sysbus_create_simple() to create
29
virtio-mmio device. It's because xlnx-versal's cpu use
30
VersalVirt.soc.fpd.apu.mr as it's memory. which is subregion of
31
system_memory. sysbus_create_simple will add virtio to system_memory,
32
which can't be accessed by cpu.
33
34
Besides, xlnx-versal can't add sysbus_mmio_map api call too, because
35
this will add memory region to system_memory, and it can't be added
36
to VersalVirt.soc.fpd.apu.mr again.
37
38
We can solve this by assign correct base address offset on dev_path.
39
40
This path was test on aarch64 virt & xlnx-versal platform.
41
42
Signed-off-by: schspa <schspa@gmail.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
43
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
44
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
45
---
13
include/qemu/uuid.h | 27 +++++++++++++++++++++++++++
46
hw/virtio/virtio-mmio.c | 13 +++++++------
14
hw/acpi/nvdimm.c | 10 +++-------
47
1 file changed, 7 insertions(+), 6 deletions(-)
15
2 files changed, 30 insertions(+), 7 deletions(-)
16
48
17
diff --git a/include/qemu/uuid.h b/include/qemu/uuid.h
49
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
18
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
19
--- a/include/qemu/uuid.h
51
--- a/hw/virtio/virtio-mmio.c
20
+++ b/include/qemu/uuid.h
52
+++ b/hw/virtio/virtio-mmio.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
53
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
22
};
54
BusState *virtio_mmio_bus;
23
} QemuUUID;
55
VirtIOMMIOProxy *virtio_mmio_proxy;
24
56
char *proxy_path;
25
+/**
57
- SysBusDevice *proxy_sbd;
26
+ * UUID_LE - converts the fields of UUID to little-endian array,
58
char *path;
27
+ * each of parameters is the filed of UUID.
59
+ MemoryRegionSection section;
28
+ *
60
29
+ * @time_low: The low field of the timestamp
61
virtio_mmio_bus = qdev_get_parent_bus(dev);
30
+ * @time_mid: The middle field of the timestamp
62
virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
31
+ * @time_hi_and_version: The high field of the timestamp
63
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
32
+ * multiplexed with the version number
64
}
33
+ * @clock_seq_hi_and_reserved: The high field of the clock
65
34
+ * sequence multiplexed with the variant
66
/* Otherwise, we append the base address of the transport. */
35
+ * @clock_seq_low: The low field of the clock sequence
67
- proxy_sbd = SYS_BUS_DEVICE(virtio_mmio_proxy);
36
+ * @node0: The spatially unique node0 identifier
68
- assert(proxy_sbd->num_mmio == 1);
37
+ * @node1: The spatially unique node1 identifier
69
- assert(proxy_sbd->mmio[0].memory == &virtio_mmio_proxy->iomem);
38
+ * @node2: The spatially unique node2 identifier
70
+ section = memory_region_find(&virtio_mmio_proxy->iomem, 0, 0x200);
39
+ * @node3: The spatially unique node3 identifier
71
+ assert(section.mr);
40
+ * @node4: The spatially unique node4 identifier
72
41
+ * @node5: The spatially unique node5 identifier
73
if (proxy_path) {
42
+ */
74
path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path,
43
+#define UUID_LE(time_low, time_mid, time_hi_and_version, \
75
- proxy_sbd->mmio[0].addr);
44
+ clock_seq_hi_and_reserved, clock_seq_low, node0, node1, node2, \
76
+ section.offset_within_address_space);
45
+ node3, node4, node5) \
77
} else {
46
+ { (time_low) & 0xff, ((time_low) >> 8) & 0xff, ((time_low) >> 16) & 0xff, \
78
path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx,
47
+ ((time_low) >> 24) & 0xff, (time_mid) & 0xff, ((time_mid) >> 8) & 0xff, \
79
- proxy_sbd->mmio[0].addr);
48
+ (time_hi_and_version) & 0xff, ((time_hi_and_version) >> 8) & 0xff, \
80
+ section.offset_within_address_space);
49
+ (clock_seq_hi_and_reserved), (clock_seq_low), (node0), (node1), (node2),\
81
}
50
+ (node3), (node4), (node5) }
82
+ memory_region_unref(section.mr);
51
+
83
+
52
#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-" \
84
g_free(proxy_path);
53
"%02hhx%02hhx-%02hhx%02hhx-" \
85
return path;
54
"%02hhx%02hhx-" \
86
}
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
--
87
--
89
2.20.1
88
2.20.1
90
89
91
90
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Peter Collingbourne <pcc@google.com>
2
2
3
This patch builds Hardware Error Source Table(HEST) via fw_cfg blobs.
3
Section D6.7 of the ARM ARM states:
4
Now it only supports ARMv8 SEA, a type of Generic Hardware Error
5
Source version 2(GHESv2) error source. Afterwards, we can extend
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
4
10
This patch follows the spec ACPI 6.2 to build the Hardware Error
5
For the purpose of determining Tag Check Fault handling, unprivileged
11
Source table. For more detailed information, please refer to
6
load and store instructions are treated as if executed at EL0 when
12
document: docs/specs/acpi_hest_ghes.rst
7
executed at either:
8
- EL1, when the Effective value of PSTATE.UAO is 0.
9
- EL2, when both the Effective value of HCR_EL2.{E2H, TGE} is {1, 1}
10
and the Effective value of PSTATE.UAO is 0.
13
11
14
build_ghes_hw_error_notification() helper will help to add Hardware
12
ARM has confirmed a defect in the pseudocode function
15
Error Notification to ACPI tables without using packed C structures
13
AArch64.TagCheckFault that makes it inconsistent with the above
16
and avoid endianness issues as API doesn't need explicit conversion.
14
wording. The remedy is to adjust references to PSTATE.EL in that
15
function to instead refer to AArch64.AccessUsesEL(acctype), so
16
that unprivileged instructions use SCTLR_EL1.TCF0 and TFSRE0_EL1.
17
The exception type for synchronous tag check faults remains unchanged.
17
18
18
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
19
This patch implements the described change by partially reverting
19
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
20
commits 50244cc76abc and cc97b0019bb5.
20
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
21
21
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
22
Signed-off-by: Peter Collingbourne <pcc@google.com>
22
Message-id: 20200512030609.19593-6-gengdongjiu@huawei.com
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20210219201820.2672077-1-pcc@google.com
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
27
---
25
include/hw/acpi/ghes.h | 39 ++++++++++++
28
target/arm/helper.c | 2 +-
26
hw/acpi/ghes.c | 126 +++++++++++++++++++++++++++++++++++++++
29
target/arm/mte_helper.c | 13 +++++++++----
27
hw/arm/virt-acpi-build.c | 2 +
30
2 files changed, 10 insertions(+), 5 deletions(-)
28
3 files changed, 167 insertions(+)
29
31
30
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
31
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/acpi/ghes.h
34
--- a/target/arm/helper.c
33
+++ b/include/hw/acpi/ghes.h
35
+++ b/target/arm/helper.c
34
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
35
37
if (FIELD_EX32(flags, TBFLAG_A64, UNPRIV)
36
#include "hw/acpi/bios-linker-loader.h"
38
&& tbid
37
39
&& !(env->pstate & PSTATE_TCO)
38
+/*
40
- && (sctlr & SCTLR_TCF)
39
+ * Values for Hardware Error Notification Type field
41
+ && (sctlr & SCTLR_TCF0)
40
+ */
42
&& allocation_tag_access_enabled(env, 0, sctlr)) {
41
+enum AcpiGhesNotifyType {
43
flags = FIELD_DP32(flags, TBFLAG_A64, MTE0_ACTIVE, 1);
42
+ /* Polled */
44
}
43
+ ACPI_GHES_NOTIFY_POLLED = 0,
45
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
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
46
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/acpi/ghes.c
47
--- a/target/arm/mte_helper.c
82
+++ b/hw/acpi/ghes.c
48
+++ b/target/arm/mte_helper.c
83
@@ -XXX,XX +XXX,XX @@
49
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
84
#include "qemu/units.h"
50
reg_el = regime_el(env, arm_mmu_idx);
85
#include "hw/acpi/ghes.h"
51
sctlr = env->cp15.sctlr_el[reg_el];
86
#include "hw/acpi/aml-build.h"
52
87
+#include "qemu/error-report.h"
53
- el = arm_current_el(env);
88
54
- if (el == 0) {
89
#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
55
+ switch (arm_mmu_idx) {
90
#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
56
+ case ARMMMUIdx_E10_0:
91
@@ -XXX,XX +XXX,XX @@
57
+ case ARMMMUIdx_E20_0:
92
/* Now only support ARMv8 SEA notification type error source */
58
+ el = 0;
93
#define ACPI_GHES_ERROR_SOURCE_COUNT 1
59
tcf = extract64(sctlr, 38, 2);
94
60
- } else {
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
+ /*
111
+ * Length:
112
+ * Total length of the structure in bytes
113
+ */
114
+ build_append_int_noprefix(table, 28, 1);
115
+ /* Configuration Write Enable */
116
+ build_append_int_noprefix(table, 0, 2);
117
+ /* Poll Interval */
118
+ build_append_int_noprefix(table, 0, 4);
119
+ /* Vector */
120
+ build_append_int_noprefix(table, 0, 4);
121
+ /* Switch To Polling Threshold Value */
122
+ build_append_int_noprefix(table, 0, 4);
123
+ /* Switch To Polling Threshold Window */
124
+ build_append_int_noprefix(table, 0, 4);
125
+ /* Error Threshold Value */
126
+ build_append_int_noprefix(table, 0, 4);
127
+ /* Error Threshold Window */
128
+ build_append_int_noprefix(table, 0, 4);
129
+}
130
+
131
/*
132
* Build table for the hardware error fw_cfg blob.
133
* Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
134
@@ -XXX,XX +XXX,XX @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
135
bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE,
136
0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0);
137
}
138
+
139
+/* Build Generic Hardware Error Source version 2 (GHESv2) */
140
+static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
141
+{
142
+ uint64_t address_offset;
143
+ /*
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;
61
+ break;
180
+ default:
62
+ default:
181
+ error_report("Not support this error source");
63
+ el = reg_el;
182
+ abort();
64
tcf = extract64(sctlr, 40, 2);
183
+ }
184
+
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
}
65
}
238
66
239
if (ms->numa_state->num_nodes > 0) {
67
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
68
env->exception.vaddress = dirty_ptr;
69
70
is_write = FIELD_EX32(desc, MTEDESC, WRITE);
71
- syn = syn_data_abort_no_iss(el != 0, 0, 0, 0, 0, is_write, 0x11);
72
+ syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0,
73
+ is_write, 0x11);
74
raise_exception(env, EXCP_DATA_ABORT, syn, exception_target_el(env));
75
/* noreturn, but fall through to the assert anyway */
76
240
--
77
--
241
2.20.1
78
2.20.1
242
79
243
80
diff view generated by jsdifflib
1
From: Patrick Williams <patrick@stwcx.xyz>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Sonora Pass is a 2 socket x86 motherboard designed by Facebook
3
IDAU is specific to M-profile. KVM only supports A-profile.
4
and supported by OpenBMC. Strapping configuration was obtained
4
Restrict this interface to TCG, as it is pointless (and
5
from hardware and i2c configuration is based on dts found at:
5
confusing) on a KVM-only build.
6
6
7
https://github.com/facebook/openbmc-linux/blob/1633c87b8ba7c162095787c988979b748ba65dc8/arch/arm/boot/dts/aspeed-bmc-facebook-sonorapass.dts
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Booted a test image of http://github.com/facebook/openbmc to login
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
prompt.
10
Message-id: 20210221222617.2579610-2-f4bug@amsat.org
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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
12
---
18
hw/arm/aspeed.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++
13
target/arm/cpu.c | 7 -------
19
1 file changed, 78 insertions(+)
14
target/arm/cpu_tcg.c | 8 ++++++++
15
2 files changed, 8 insertions(+), 7 deletions(-)
20
16
21
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
17
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/aspeed.c
19
--- a/target/arm/cpu.c
24
+++ b/hw/arm/aspeed.c
20
+++ b/target/arm/cpu.c
25
@@ -XXX,XX +XXX,XX @@ struct AspeedBoardState {
21
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
26
SCU_AST2500_HW_STRAP_ACPI_ENABLE | \
22
.class_init = arm_cpu_class_init,
27
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
23
};
28
24
29
+/* Sonorapass hardware value: 0xF100D216 */
25
-static const TypeInfo idau_interface_type_info = {
30
+#define SONORAPASS_BMC_HW_STRAP1 ( \
26
- .name = TYPE_IDAU_INTERFACE,
31
+ SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
27
- .parent = TYPE_INTERFACE,
32
+ SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \
28
- .class_size = sizeof(IDAUInterfaceClass),
33
+ SCU_AST2500_HW_STRAP_UART_DEBUG | \
29
-};
34
+ SCU_AST2500_HW_STRAP_RESERVED28 | \
30
-
35
+ SCU_AST2500_HW_STRAP_DDR4_ENABLE | \
31
static void arm_cpu_register_types(void)
36
+ SCU_HW_STRAP_VGA_CLASS_CODE | \
37
+ SCU_HW_STRAP_LPC_RESET_PIN | \
38
+ SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER) | \
39
+ SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) | \
40
+ SCU_HW_STRAP_VGA_BIOS_ROM | \
41
+ SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
42
+ SCU_AST2500_HW_STRAP_RESERVED1)
43
+
44
/* Swift hardware value: 0xF11AD206 */
45
#define SWIFT_BMC_HW_STRAP1 ( \
46
AST2500_HW_STRAP1_DEFAULTS | \
47
@@ -XXX,XX +XXX,XX @@ static void swift_bmc_i2c_init(AspeedBoardState *bmc)
48
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x4a);
49
}
50
51
+static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc)
52
+{
53
+ AspeedSoCState *soc = &bmc->soc;
54
+
55
+ /* bus 2 : */
56
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x48);
57
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x49);
58
+ /* bus 2 : pca9546 @ 0x73 */
59
+
60
+ /* bus 3 : pca9548 @ 0x70 */
61
+
62
+ /* bus 4 : */
63
+ uint8_t *eeprom4_54 = g_malloc0(8 * 1024);
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
{
32
{
97
AspeedSoCState *soc = &bmc->soc;
33
const size_t cpu_count = ARRAY_SIZE(arm_cpus);
98
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_register_types(void)
99
mc->default_ram_size = 512 * MiB;
35
if (cpu_count) {
36
size_t i;
37
38
- type_register_static(&idau_interface_type_info);
39
for (i = 0; i < cpu_count; ++i) {
40
arm_cpu_register(&arm_cpus[i]);
41
}
42
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/cpu_tcg.c
45
+++ b/target/arm/cpu_tcg.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "hw/core/tcg-cpu-ops.h"
48
#endif /* CONFIG_TCG */
49
#include "internals.h"
50
+#include "target/arm/idau.h"
51
52
/* CPU models. These are not needed for the AArch64 linux-user build. */
53
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
54
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
55
{ .name = "pxa270-c5", .initfn = pxa270c5_initfn },
100
};
56
};
101
57
102
+static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
58
+static const TypeInfo idau_interface_type_info = {
103
+{
59
+ .name = TYPE_IDAU_INTERFACE,
104
+ MachineClass *mc = MACHINE_CLASS(oc);
60
+ .parent = TYPE_INTERFACE,
105
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
61
+ .class_size = sizeof(IDAUInterfaceClass),
106
+
107
+ mc->desc = "OCP SonoraPass BMC (ARM1176)";
108
+ amc->soc_name = "ast2500-a1";
109
+ amc->hw_strap1 = SONORAPASS_BMC_HW_STRAP1;
110
+ amc->fmc_model = "mx66l1g45g";
111
+ amc->spi_model = "mx66l1g45g";
112
+ amc->num_cs = 2;
113
+ amc->i2c_init = sonorapass_bmc_i2c_init;
114
+ mc->default_ram_size = 512 * MiB;
115
+};
62
+};
116
+
63
+
117
static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data)
64
static void arm_tcg_cpu_register_types(void)
118
{
65
{
119
MachineClass *mc = MACHINE_CLASS(oc);
66
size_t i;
120
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = {
67
121
.name = MACHINE_TYPE_NAME("swift-bmc"),
68
+ type_register_static(&idau_interface_type_info);
122
.parent = TYPE_ASPEED_MACHINE,
69
for (i = 0; i < ARRAY_SIZE(arm_tcg_cpus); ++i) {
123
.class_init = aspeed_machine_swift_class_init,
70
arm_cpu_register(&arm_tcg_cpus[i]);
124
+ }, {
71
}
125
+ .name = MACHINE_TYPE_NAME("sonorapass-bmc"),
126
+ .parent = TYPE_ASPEED_MACHINE,
127
+ .class_init = aspeed_machine_sonorapass_class_init,
128
}, {
129
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
130
.parent = TYPE_ASPEED_MACHINE,
131
--
72
--
132
2.20.1
73
2.20.1
133
74
134
75
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Provide a functional interface for the vector expansion.
3
We will move this code in the next commit. Clean it up
4
This fits better with the existing set of helpers that
4
first to avoid checkpatch.pl errors.
5
we provide for other operations.
6
5
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210221222617.2579610-3-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
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>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/translate.h | 7 +-
11
target/arm/cpu.c | 12 ++++++++----
13
target/arm/translate-a64.c | 4 +-
12
1 file changed, 8 insertions(+), 4 deletions(-)
14
target/arm/translate-neon.inc.c | 16 +----
15
target/arm/translate.c | 117 +++++++++++++++++---------------
16
4 files changed, 71 insertions(+), 73 deletions(-)
17
13
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate.h
16
--- a/target/arm/cpu.c
21
+++ b/target/arm/translate.h
17
+++ b/target/arm/cpu.c
22
@@ -XXX,XX +XXX,XX @@ void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
18
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
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
}
19
}
68
20
69
-#define DO_3SAME_GVEC3_NO_SZ_3(INSN, OPARRAY) \
21
static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
70
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
22
- /* power_control should be set to maximum latency. Again,
71
- uint32_t rn_ofs, uint32_t rm_ofs, \
23
+ /*
72
- uint32_t oprsz, uint32_t maxsz) \
24
+ * power_control should be set to maximum latency. Again,
73
- { \
25
* default to 0 and set by private hook
74
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
26
*/
75
- oprsz, maxsz, &OPARRAY[vece]); \
27
{ .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
76
- } \
28
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
77
- DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s)
29
set_feature(&cpu->env, ARM_FEATURE_NEON);
78
-
30
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
79
-
31
set_feature(&cpu->env, ARM_FEATURE_EL3);
80
-DO_3SAME_GVEC3_NO_SZ_3(VMLA, mla_op)
32
- /* Note that A9 supports the MP extensions even for
81
-DO_3SAME_GVEC3_NO_SZ_3(VMLS, mls_op)
33
+ /*
82
-
34
+ * Note that A9 supports the MP extensions even for
83
#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \
35
* A9UP and single-core A9MP (which are both different
84
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
36
* and valid configurations; we don't model A9UP).
85
uint32_t rn_ofs, uint32_t rm_ofs, \
37
*/
86
diff --git a/target/arm/translate.c b/target/arm/translate.c
38
@@ -XXX,XX +XXX,XX @@ static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
87
index XXXXXXX..XXXXXXX 100644
39
{
88
--- a/target/arm/translate.c
40
MachineState *ms = MACHINE(qdev_get_machine());
89
+++ b/target/arm/translate.c
41
90
@@ -XXX,XX +XXX,XX @@ static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
42
- /* Linux wants the number of processors from here.
91
/* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
43
+ /*
92
* these tables are shared with AArch64 which does support them.
44
+ * Linux wants the number of processors from here.
93
*/
45
* Might as well set the interrupt-controller bit too.
94
+void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
46
*/
95
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
47
return ((ms->smp.cpus - 1) << 24) | (1 << 23);
96
+{
48
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
97
+ static const TCGOpcode vecop_list[] = {
49
cpu->isar.id_mmfr1 = 0x40000000;
98
+ INDEX_op_mul_vec, INDEX_op_add_vec, 0
50
cpu->isar.id_mmfr2 = 0x01240000;
99
+ };
51
cpu->isar.id_mmfr3 = 0x02102211;
100
+ static const GVecGen3 ops[4] = {
52
- /* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
101
+ { .fni4 = gen_mla8_i32,
53
+ /*
102
+ .fniv = gen_mla_vec,
54
+ * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
103
+ .load_dest = true,
55
* table 4-41 gives 0x02101110, which includes the arm div insns.
104
+ .opt_opc = vecop_list,
56
*/
105
+ .vece = MO_8 },
57
cpu->isar.id_isar0 = 0x02101110;
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
--
58
--
216
2.20.1
59
2.20.1
217
60
218
61
diff view generated by jsdifflib
1
Convert the VQSHL, VRSHL and VQRSHL insns in the 3-reg-same
1
For a long time now the UI layer has guaranteed that the console
2
group to decodetree. We have already implemented the size==0b11
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
3
case of these insns; this commit handles the remaining sizes.
3
code from the milkymist display device which was handling the
4
possibility that the console surface was some other format.
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-8-peter.maydell@linaro.org
8
Message-id: 20210215103215.4944-2-peter.maydell@linaro.org
8
---
9
---
9
target/arm/neon-dp.decode | 30 ++++++++++++++++++-----
10
hw/arm/musicpal.c | 64 ++++++++++++++++++-----------------------------
10
target/arm/translate-neon.inc.c | 43 +++++++++++++++++++++++++++++++++
11
1 file changed, 24 insertions(+), 40 deletions(-)
11
target/arm/translate.c | 22 +++--------------
12
3 files changed, 70 insertions(+), 25 deletions(-)
13
12
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
15
--- a/hw/arm/musicpal.c
17
+++ b/target/arm/neon-dp.decode
16
+++ b/hw/arm/musicpal.c
18
@@ -XXX,XX +XXX,XX @@ VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
17
@@ -XXX,XX +XXX,XX @@ static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
19
@3same_64_rev .... ... . . . 11 .... .... .... . q:1 . . .... \
18
}
20
&3same vm=%vn_dp vn=%vm_dp vd=%vd_dp size=3
19
}
21
20
22
-VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
21
-#define SET_LCD_PIXEL(depth, type) \
23
-VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
22
-static inline void glue(set_lcd_pixel, depth) \
24
-VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
23
- (musicpal_lcd_state *s, int x, int y, type col) \
25
-VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
24
-{ \
26
-VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
25
- int dx, dy; \
27
-VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
26
- DisplaySurface *surface = qemu_console_surface(s->con); \
27
- type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
28
-\
29
- for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
30
- for (dx = 0; dx < 3; dx++, pixel++) \
31
- *pixel = col; \
32
+static inline void set_lcd_pixel32(musicpal_lcd_state *s,
33
+ int x, int y, uint32_t col)
28
+{
34
+{
29
+ VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
35
+ int dx, dy;
30
+ VQSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_rev
36
+ DisplaySurface *surface = qemu_console_surface(s->con);
31
+}
37
+ uint32_t *pixel =
32
+{
38
+ &((uint32_t *) surface_data(surface))[(y * 128 * 3 + x) * 3];
33
+ VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
39
+
34
+ VQSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_rev
40
+ for (dy = 0; dy < 3; dy++, pixel += 127 * 3) {
35
+}
41
+ for (dx = 0; dx < 3; dx++, pixel++) {
36
+{
42
+ *pixel = col;
37
+ VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
43
+ }
38
+ VRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_rev
44
+ }
39
+}
45
}
40
+{
46
-SET_LCD_PIXEL(8, uint8_t)
41
+ VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
47
-SET_LCD_PIXEL(16, uint16_t)
42
+ VRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_rev
48
-SET_LCD_PIXEL(32, uint32_t)
43
+}
49
44
+{
50
static void lcd_refresh(void *opaque)
45
+ VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
51
{
46
+ VQRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_rev
52
musicpal_lcd_state *s = opaque;
47
+}
53
- DisplaySurface *surface = qemu_console_surface(s->con);
48
+{
54
int x, y, col;
49
+ VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
55
50
+ VQRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_rev
56
- switch (surface_bits_per_pixel(surface)) {
51
+}
57
- case 0:
52
58
- return;
53
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
59
-#define LCD_REFRESH(depth, func) \
54
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
60
- case depth: \
55
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
61
- col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
56
index XXXXXXX..XXXXXXX 100644
62
- scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
57
--- a/target/arm/translate-neon.inc.c
63
- scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
58
+++ b/target/arm/translate-neon.inc.c
64
- for (x = 0; x < 128; x++) { \
59
@@ -XXX,XX +XXX,XX @@ DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
65
- for (y = 0; y < 64; y++) { \
60
return do_3same(s, a, gen_##INSN##_3s); \
66
- if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
67
- glue(set_lcd_pixel, depth)(s, x, y, col); \
68
- } else { \
69
- glue(set_lcd_pixel, depth)(s, x, y, 0); \
70
- } \
71
- } \
72
- } \
73
- break;
74
- LCD_REFRESH(8, rgb_to_pixel8)
75
- LCD_REFRESH(16, rgb_to_pixel16)
76
- LCD_REFRESH(32, (is_surface_bgr(surface) ?
77
- rgb_to_pixel32bgr : rgb_to_pixel32))
78
- default:
79
- hw_error("unsupported colour depth %i\n",
80
- surface_bits_per_pixel(surface));
81
+ col = rgb_to_pixel32(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff),
82
+ scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff),
83
+ scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff));
84
+ for (x = 0; x < 128; x++) {
85
+ for (y = 0; y < 64; y++) {
86
+ if (s->video_ram[x + (y / 8) * 128] & (1 << (y % 8))) {
87
+ set_lcd_pixel32(s, x, y, col);
88
+ } else {
89
+ set_lcd_pixel32(s, x, y, 0);
90
+ }
91
+ }
61
}
92
}
62
93
63
+/*
94
dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
64
+ * Some helper functions need to be passed the cpu_env. In order
65
+ * to use those with the gvec APIs like tcg_gen_gvec_3() we need
66
+ * to create wrapper functions whose prototype is a NeonGenTwoOpFn()
67
+ * and which call a NeonGenTwoOpEnvFn().
68
+ */
69
+#define WRAP_ENV_FN(WRAPNAME, FUNC) \
70
+ static void WRAPNAME(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m) \
71
+ { \
72
+ FUNC(d, cpu_env, n, m); \
73
+ }
74
+
75
+#define DO_3SAME_32_ENV(INSN, FUNC) \
76
+ WRAP_ENV_FN(gen_##INSN##_tramp8, gen_helper_neon_##FUNC##8); \
77
+ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##16); \
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
--
95
--
160
2.20.1
96
2.20.1
161
97
162
98
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
3
code from the tc6393xb display device which was handling the
4
possibility that the console surface was some other format.
2
5
3
Provide a functional interface for the vector expansion.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
This fits better with the existing set of helpers that
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
we provide for other operations.
8
Message-id: 20210215103215.4944-3-peter.maydell@linaro.org
9
---
10
include/ui/console.h | 10 ----------
11
hw/display/tc6393xb.c | 33 +--------------------------------
12
2 files changed, 1 insertion(+), 42 deletions(-)
6
13
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/include/ui/console.h b/include/ui/console.h
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-13-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate.h | 5 ++++
13
target/arm/translate-a64.c | 34 ++----------------------
14
target/arm/translate.c | 54 +++++++++++++++++++-------------------
15
3 files changed, 34 insertions(+), 59 deletions(-)
16
17
diff --git a/target/arm/translate.h b/target/arm/translate.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate.h
16
--- a/include/ui/console.h
20
+++ b/target/arm/translate.h
17
+++ b/include/ui/console.h
21
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
18
@@ -XXX,XX +XXX,XX @@ PixelFormat qemu_default_pixelformat(int bpp);
22
void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
19
DisplaySurface *qemu_create_displaysurface(int width, int height);
23
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
20
void qemu_free_displaysurface(DisplaySurface *surface);
24
21
25
+void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
22
-static inline int is_surface_bgr(DisplaySurface *surface)
26
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
27
+void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
28
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
29
+
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
-{
23
-{
47
- tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
24
- if (PIXMAN_FORMAT_BPP(surface->format) == 32 &&
48
- vec_full_reg_offset(s, rn),
25
- PIXMAN_FORMAT_TYPE(surface->format) == PIXMAN_TYPE_ABGR) {
49
- vec_full_reg_offset(s, rm), cpu_env,
26
- return 1;
50
- is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
27
- } else {
28
- return 0;
29
- }
51
-}
30
-}
52
-
31
-
53
/* Expand a 3-operand + fpstatus pointer + simd data value operation using
32
static inline int is_buffer_shared(DisplaySurface *surface)
54
* an out-of-line helper.
33
{
55
*/
34
return !(surface->flags & QEMU_ALLOCATED_FLAG);
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
35
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
57
36
index XXXXXXX..XXXXXXX 100644
58
switch (opcode) {
37
--- a/hw/display/tc6393xb.c
59
case 0x0: /* SQRDMLAH (vector) */
38
+++ b/hw/display/tc6393xb.c
60
- switch (size) {
39
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
61
- case 1:
40
(uint32_t) addr, value & 0xff);
62
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
41
}
42
43
-#define BITS 8
44
-#include "tc6393xb_template.h"
45
-#define BITS 15
46
-#include "tc6393xb_template.h"
47
-#define BITS 16
48
-#include "tc6393xb_template.h"
49
-#define BITS 24
50
-#include "tc6393xb_template.h"
51
#define BITS 32
52
#include "tc6393xb_template.h"
53
54
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
55
{
56
- DisplaySurface *surface = qemu_console_surface(s->con);
57
-
58
- switch (surface_bits_per_pixel(surface)) {
59
- case 8:
60
- tc6393xb_draw_graphic8(s);
63
- break;
61
- break;
64
- case 2:
62
- case 15:
65
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
63
- tc6393xb_draw_graphic15(s);
64
- break;
65
- case 16:
66
- tc6393xb_draw_graphic16(s);
67
- break;
68
- case 24:
69
- tc6393xb_draw_graphic24(s);
70
- break;
71
- case 32:
72
- tc6393xb_draw_graphic32(s);
66
- break;
73
- break;
67
- default:
74
- default:
68
- g_assert_not_reached();
75
- printf("tc6393xb: unknown depth %d\n",
69
- }
76
- surface_bits_per_pixel(surface));
70
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqrdmlah_qc, size);
77
- return;
71
return;
78
- }
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
-
79
-
97
-/* Expand v8.1 simd helper. */
80
+ tc6393xb_draw_graphic32(s);
98
-static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
81
dpy_gfx_update_full(s->con);
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
}
82
}
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
83
168
--
84
--
169
2.20.1
85
2.20.1
170
86
171
87
diff view generated by jsdifflib
1
Convert the Neon VRHADD and VHSUB 3-reg-same insns to decodetree.
1
Now the template header is included only for BITS==32, expand
2
(These are all the other insns in 3-reg-same which were using
2
out all the macros that depended on the BITS setting.
3
GEN_NEON_INTEGER_OP() and which are not pairwise or
4
reversed-operands.)
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200512163904.10918-7-peter.maydell@linaro.org
6
Message-id: 20210215103215.4944-4-peter.maydell@linaro.org
9
---
7
---
10
target/arm/neon-dp.decode | 6 ++++++
8
hw/display/tc6393xb_template.h | 35 ++++------------------------------
11
target/arm/translate-neon.inc.c | 4 ++++
9
1 file changed, 4 insertions(+), 31 deletions(-)
12
target/arm/translate.c | 8 ++------
13
3 files changed, 12 insertions(+), 6 deletions(-)
14
10
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
11
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
13
--- a/hw/display/tc6393xb_template.h
18
+++ b/target/arm/neon-dp.decode
14
+++ b/hw/display/tc6393xb_template.h
19
@@ -XXX,XX +XXX,XX @@ VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
15
@@ -XXX,XX +XXX,XX @@
20
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
16
* with this program; if not, see <http://www.gnu.org/licenses/>.
21
VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same
17
*/
22
18
23
+VRHADD_S_3s 1111 001 0 0 . .. .... .... 0001 . . . 0 .... @3same
19
-#if BITS == 8
24
+VRHADD_U_3s 1111 001 1 0 . .. .... .... 0001 . . . 0 .... @3same
20
-# define SET_PIXEL(addr, color) (*(uint8_t *)addr = color)
25
+
21
-#elif BITS == 15 || BITS == 16
26
@3same_logic .... ... . . . .. .... .... .... . q:1 .. .... \
22
-# define SET_PIXEL(addr, color) (*(uint16_t *)addr = color)
27
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0
23
-#elif BITS == 24
28
24
-# define SET_PIXEL(addr, color) \
29
@@ -XXX,XX +XXX,XX @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic
25
- do { \
30
VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic
26
- addr[0] = color; \
31
VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic
27
- addr[1] = (color) >> 8; \
32
28
- addr[2] = (color) >> 16; \
33
+VHSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 0 .... @3same
29
- } while (0)
34
+VHSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 0 .... @3same
30
-#elif BITS == 32
35
+
31
-# define SET_PIXEL(addr, color) (*(uint32_t *)addr = color)
36
VQSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 1 .... @3same
32
-#else
37
VQSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 1 .... @3same
33
-# error unknown bit depth
38
34
-#endif
39
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
35
-
40
index XXXXXXX..XXXXXXX 100644
36
-
41
--- a/target/arm/translate-neon.inc.c
37
-static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
42
+++ b/target/arm/translate-neon.inc.c
38
+static void tc6393xb_draw_graphic32(TC6393xbState *s)
43
@@ -XXX,XX +XXX,XX @@ DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
39
{
44
40
DisplaySurface *surface = qemu_console_surface(s->con);
45
DO_3SAME_32(VHADD_S, hadd_s)
41
int i;
46
DO_3SAME_32(VHADD_U, hadd_u)
42
@@ -XXX,XX +XXX,XX @@ static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
47
+DO_3SAME_32(VHSUB_S, hsub_s)
43
data_buffer = s->vram_ptr;
48
+DO_3SAME_32(VHSUB_U, hsub_u)
44
data_display = surface_data(surface);
49
+DO_3SAME_32(VRHADD_S, rhadd_s)
45
for(i = 0; i < s->scr_height; i++) {
50
+DO_3SAME_32(VRHADD_U, rhadd_u)
46
-#if (BITS == 16)
51
diff --git a/target/arm/translate.c b/target/arm/translate.c
47
- memcpy(data_display, data_buffer, s->scr_width * 2);
52
index XXXXXXX..XXXXXXX 100644
48
- data_buffer += s->scr_width;
53
--- a/target/arm/translate.c
49
- data_display += surface_stride(surface);
54
+++ b/target/arm/translate.c
50
-#else
55
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
51
int j;
56
case NEON_3R_VSHL:
52
- for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) {
57
case NEON_3R_SHA:
53
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
58
case NEON_3R_VHADD:
54
uint16_t color = *data_buffer;
59
+ case NEON_3R_VRHADD:
55
- uint32_t dest_color = glue(rgb_to_pixel, BITS)(
60
+ case NEON_3R_VHSUB:
56
+ uint32_t dest_color = rgb_to_pixel32(
61
case NEON_3R_VABD:
57
((color & 0xf800) * 0x108) >> 11,
62
case NEON_3R_VABA:
58
((color & 0x7e0) * 0x41) >> 9,
63
/* Already handled by decodetree */
59
((color & 0x1f) * 0x21) >> 2
64
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
60
);
65
tmp2 = neon_load_reg(rm, pass);
61
- SET_PIXEL(data_display, dest_color);
62
+ *(uint32_t *)data_display = dest_color;
66
}
63
}
67
switch (op) {
64
-#endif
68
- case NEON_3R_VRHADD:
65
}
69
- GEN_NEON_INTEGER_OP(rhadd);
66
}
70
- break;
67
-
71
- case NEON_3R_VHSUB:
68
-#undef BITS
72
- GEN_NEON_INTEGER_OP(hsub);
69
-#undef SET_PIXEL
73
- break;
74
case NEON_3R_VQSHL:
75
GEN_NEON_INTEGER_OP_ENV(qshl);
76
break;
77
--
70
--
78
2.20.1
71
2.20.1
79
72
80
73
diff view generated by jsdifflib
1
The usual location for the env argument in the argument list of a TCG helper
1
The function tc6393xb_draw_graphic32() is called in exactly one place,
2
is immediately after the return-value argument. recps_f32 and rsqrts_f32
2
so just inline the function body at its callsite. This allows us to
3
differ in that they put it at the end.
3
drop the template header entirely.
4
4
5
Move the env argument to its usual place; this will allow us to
5
The code move includes a single added space after 'for' to fix
6
more easily use these helper functions with the gvec APIs.
6
the coding style.
7
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200512163904.10918-16-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20210215103215.4944-5-peter.maydell@linaro.org
11
---
12
---
12
target/arm/helper.h | 4 ++--
13
hw/display/tc6393xb_template.h | 45 ----------------------------------
13
target/arm/translate.c | 4 ++--
14
hw/display/tc6393xb.c | 23 ++++++++++++++---
14
target/arm/vfp_helper.c | 4 ++--
15
2 files changed, 19 insertions(+), 49 deletions(-)
15
3 files changed, 6 insertions(+), 6 deletions(-)
16
delete mode 100644 hw/display/tc6393xb_template.h
16
17
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
19
deleted file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- a/hw/display/tc6393xb_template.h
22
+++ /dev/null
23
@@ -XXX,XX +XXX,XX @@
24
-/*
25
- * Toshiba TC6393XB I/O Controller.
26
- * Found in Sharp Zaurus SL-6000 (tosa) or some
27
- * Toshiba e-Series PDAs.
28
- *
29
- * FB support code. Based on G364 fb emulator
30
- *
31
- * Copyright (c) 2007 Hervé Poussineau
32
- *
33
- * This program is free software; you can redistribute it and/or
34
- * modify it under the terms of the GNU General Public License as
35
- * published by the Free Software Foundation; either version 2 of
36
- * the License, or (at your option) any later version.
37
- *
38
- * This program is distributed in the hope that it will be useful,
39
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
40
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
- * GNU General Public License for more details.
42
- *
43
- * You should have received a copy of the GNU General Public License along
44
- * with this program; if not, see <http://www.gnu.org/licenses/>.
45
- */
46
-
47
-static void tc6393xb_draw_graphic32(TC6393xbState *s)
48
-{
49
- DisplaySurface *surface = qemu_console_surface(s->con);
50
- int i;
51
- uint16_t *data_buffer;
52
- uint8_t *data_display;
53
-
54
- data_buffer = s->vram_ptr;
55
- data_display = surface_data(surface);
56
- for(i = 0; i < s->scr_height; i++) {
57
- int j;
58
- for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
59
- uint16_t color = *data_buffer;
60
- uint32_t dest_color = rgb_to_pixel32(
61
- ((color & 0xf800) * 0x108) >> 11,
62
- ((color & 0x7e0) * 0x41) >> 9,
63
- ((color & 0x1f) * 0x21) >> 2
64
- );
65
- *(uint32_t *)data_display = dest_color;
66
- }
67
- }
68
-}
69
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
18
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
71
--- a/hw/display/tc6393xb.c
20
+++ b/target/arm/helper.h
72
+++ b/hw/display/tc6393xb.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, f16, f64, ptr, i32)
73
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
22
DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
74
(uint32_t) addr, value & 0xff);
23
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
75
}
24
76
25
-DEF_HELPER_3(recps_f32, f32, f32, f32, env)
77
-#define BITS 32
26
-DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
78
-#include "tc6393xb_template.h"
27
+DEF_HELPER_3(recps_f32, f32, env, f32, f32)
79
-
28
+DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
80
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
29
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
30
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
31
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate.c
35
+++ b/target/arm/translate.c
36
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
37
tcg_temp_free_ptr(fpstatus);
38
} else {
39
if (size == 0) {
40
- gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
41
+ gen_helper_recps_f32(tmp, cpu_env, tmp, tmp2);
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
{
81
{
59
float_status *s = &env->vfp.standard_fp_status;
82
- tc6393xb_draw_graphic32(s);
60
if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
83
+ DisplaySurface *surface = qemu_console_surface(s->con);
61
@@ -XXX,XX +XXX,XX @@ float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
84
+ int i;
62
return float32_sub(float32_two, float32_mul(a, b, s), s);
85
+ uint16_t *data_buffer;
86
+ uint8_t *data_display;
87
+
88
+ data_buffer = s->vram_ptr;
89
+ data_display = surface_data(surface);
90
+ for (i = 0; i < s->scr_height; i++) {
91
+ int j;
92
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
93
+ uint16_t color = *data_buffer;
94
+ uint32_t dest_color = rgb_to_pixel32(
95
+ ((color & 0xf800) * 0x108) >> 11,
96
+ ((color & 0x7e0) * 0x41) >> 9,
97
+ ((color & 0x1f) * 0x21) >> 2
98
+ );
99
+ *(uint32_t *)data_display = dest_color;
100
+ }
101
+ }
102
dpy_gfx_update_full(s->con);
63
}
103
}
64
104
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
--
105
--
71
2.20.1
106
2.20.1
72
107
73
108
diff view generated by jsdifflib
1
Convert the Neon VADD, VSUB, VABD 3-reg-same insns to decodetree.
1
The omap_lcdc template header is already only included once, for
2
We already have gvec helpers for addition and subtraction, but must
2
DEPTH==32, but it still has all the macro-driven parameterization
3
add one for fabd.
3
for other depths. Expand out all the macros in the header.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-12-peter.maydell@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210215103215.4944-6-peter.maydell@linaro.org
8
---
9
---
9
target/arm/helper.h | 3 ++-
10
hw/display/omap_lcd_template.h | 67 ++++++++++++++--------------------
10
target/arm/neon-dp.decode | 8 ++++++++
11
1 file changed, 28 insertions(+), 39 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/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
15
--- a/hw/display/omap_lcd_template.h
20
+++ b/target/arm/helper.h
16
+++ b/hw/display/omap_lcd_template.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(neon_qneg_s16, TCG_CALL_NO_RWG, i32, env, i32)
22
DEF_HELPER_FLAGS_2(neon_qneg_s32, TCG_CALL_NO_RWG, i32, env, i32)
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 @@
17
@@ -XXX,XX +XXX,XX @@
43
@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
18
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
19
*/
45
20
46
+# For FP insns the high bit of 'size' is used as part of opcode decode
21
-#if DEPTH == 32
47
+@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
22
-# define BPP 4
48
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
23
-# define PIXEL_TYPE uint32_t
49
+
24
-#else
50
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
25
-# error unsupport depth
51
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
26
-#endif
52
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
27
-
53
@@ -XXX,XX +XXX,XX @@ SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
28
/*
54
vm=%vm_dp vn=%vn_dp vd=%vd_dp
29
* 2-bit colour
55
30
*/
56
VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
31
-static void glue(draw_line2_, DEPTH)(void *opaque,
57
+
32
- uint8_t *d, const uint8_t *s, int width, int deststep)
58
+VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
33
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
59
+VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
34
+ int width, int deststep)
60
+VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
35
{
61
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
36
uint16_t *pal = opaque;
62
index XXXXXXX..XXXXXXX 100644
37
uint8_t v, r, g, b;
63
--- a/target/arm/neon_helper.c
38
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
64
+++ b/target/arm/neon_helper.c
39
r = (pal[v & 3] >> 4) & 0xf0;
65
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_qneg_s64)(CPUARMState *env, uint64_t x)
40
g = pal[v & 3] & 0xf0;
41
b = (pal[v & 3] << 4) & 0xf0;
42
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
43
- d += BPP;
44
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
45
+ d += 4;
46
v >>= 2;
47
r = (pal[v & 3] >> 4) & 0xf0;
48
g = pal[v & 3] & 0xf0;
49
b = (pal[v & 3] << 4) & 0xf0;
50
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
51
- d += BPP;
52
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
53
+ d += 4;
54
v >>= 2;
55
r = (pal[v & 3] >> 4) & 0xf0;
56
g = pal[v & 3] & 0xf0;
57
b = (pal[v & 3] << 4) & 0xf0;
58
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
59
- d += BPP;
60
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
61
+ d += 4;
62
v >>= 2;
63
r = (pal[v & 3] >> 4) & 0xf0;
64
g = pal[v & 3] & 0xf0;
65
b = (pal[v & 3] << 4) & 0xf0;
66
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
67
- d += BPP;
68
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
69
+ d += 4;
70
s ++;
71
width -= 4;
72
} while (width > 0);
73
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
74
/*
75
* 4-bit colour
76
*/
77
-static void glue(draw_line4_, DEPTH)(void *opaque,
78
- uint8_t *d, const uint8_t *s, int width, int deststep)
79
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
80
+ int width, int deststep)
81
{
82
uint16_t *pal = opaque;
83
uint8_t v, r, g, b;
84
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
85
r = (pal[v & 0xf] >> 4) & 0xf0;
86
g = pal[v & 0xf] & 0xf0;
87
b = (pal[v & 0xf] << 4) & 0xf0;
88
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
89
- d += BPP;
90
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
91
+ d += 4;
92
v >>= 4;
93
r = (pal[v & 0xf] >> 4) & 0xf0;
94
g = pal[v & 0xf] & 0xf0;
95
b = (pal[v & 0xf] << 4) & 0xf0;
96
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
97
- d += BPP;
98
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
99
+ d += 4;
100
s ++;
101
width -= 2;
102
} while (width > 0);
103
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
104
/*
105
* 8-bit colour
106
*/
107
-static void glue(draw_line8_, DEPTH)(void *opaque,
108
- uint8_t *d, const uint8_t *s, int width, int deststep)
109
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
110
+ int width, int deststep)
111
{
112
uint16_t *pal = opaque;
113
uint8_t v, r, g, b;
114
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line8_, DEPTH)(void *opaque,
115
r = (pal[v] >> 4) & 0xf0;
116
g = pal[v] & 0xf0;
117
b = (pal[v] << 4) & 0xf0;
118
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
119
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
120
s ++;
121
- d += BPP;
122
+ d += 4;
123
} while (-- width != 0);
66
}
124
}
67
125
68
/* NEON Float helpers. */
126
/*
69
-uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b, void *fpstp)
127
* 12-bit colour
70
-{
128
*/
71
- float_status *fpst = fpstp;
129
-static void glue(draw_line12_, DEPTH)(void *opaque,
72
- float32 f0 = make_float32(a);
130
- uint8_t *d, const uint8_t *s, int width, int deststep)
73
- float32 f1 = make_float32(b);
131
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
74
- return float32_val(float32_abs(float32_sub(f0, f1, fpst)));
132
+ int width, int deststep)
75
-}
133
{
76
134
uint16_t v;
77
/* Floating point comparisons produce an integer result.
135
uint8_t r, g, b;
78
* Note that EQ doesn't signal InvalidOp for QNaNs but GE and GT do.
136
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line12_, DEPTH)(void *opaque,
79
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
137
r = (v >> 4) & 0xf0;
80
index XXXXXXX..XXXXXXX 100644
138
g = v & 0xf0;
81
--- a/target/arm/translate-neon.inc.c
139
b = (v << 4) & 0xf0;
82
+++ b/target/arm/translate-neon.inc.c
140
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
83
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPADD, padd_u)
141
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
84
142
s += 2;
85
DO_3SAME_VQDMULH(VQDMULH, qdmulh)
143
- d += BPP;
86
DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
144
+ d += 4;
87
+
145
} while (-- width != 0);
88
+/*
89
+ * For all the functions using this macro, size == 1 means fp16,
90
+ * which is an architecture extension we don't implement yet.
91
+ */
92
+#define DO_3S_FP_GVEC(INSN,FUNC) \
93
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
94
+ uint32_t rn_ofs, uint32_t rm_ofs, \
95
+ uint32_t oprsz, uint32_t maxsz) \
96
+ { \
97
+ TCGv_ptr fpst = get_fpstatus_ptr(1); \
98
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \
99
+ oprsz, maxsz, 0, FUNC); \
100
+ tcg_temp_free_ptr(fpst); \
101
+ } \
102
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
103
+ { \
104
+ if (a->size != 0) { \
105
+ /* TODO fp16 support */ \
106
+ return false; \
107
+ } \
108
+ return do_3same(s, a, gen_##INSN##_3s); \
109
+ }
110
+
111
+
112
+DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
113
+DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
114
+DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
115
diff --git a/target/arm/translate.c b/target/arm/translate.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/target/arm/translate.c
118
+++ b/target/arm/translate.c
119
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
120
switch (op) {
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
}
146
}
153
147
154
+static float32 float32_abd(float32 op1, float32 op2, float_status *stat)
148
/*
155
+{
149
* 16-bit colour
156
+ return float32_abs(float32_sub(op1, op2, stat));
150
*/
157
+}
151
-static void glue(draw_line16_, DEPTH)(void *opaque,
158
+
152
- uint8_t *d, const uint8_t *s, int width, int deststep)
159
#define DO_3OP(NAME, FUNC, TYPE) \
153
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
160
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
154
+ int width, int deststep)
161
{ \
155
{
162
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_ftsmul_h, float16_ftsmul, float16)
156
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
163
DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32)
157
memcpy(d, s, width * 2);
164
DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64)
158
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line16_, DEPTH)(void *opaque,
165
159
r = (v >> 8) & 0xf8;
166
+DO_3OP(gvec_fabd_s, float32_abd, float32)
160
g = (v >> 3) & 0xfc;
167
+
161
b = (v << 3) & 0xf8;
168
#ifdef TARGET_AARCH64
162
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
169
163
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
170
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
164
s += 2;
165
- d += BPP;
166
+ d += 4;
167
} while (-- width != 0);
168
#endif
169
}
170
-
171
-#undef DEPTH
172
-#undef BPP
173
-#undef PIXEL_TYPE
171
--
174
--
172
2.20.1
175
2.20.1
173
176
174
177
diff view generated by jsdifflib
New patch
1
The draw_line16_32() function in the omap_lcdc template header
2
includes an ifdef for the case where HOST_WORDS_BIGENDIAN matches
3
TARGET_WORDS_BIGENDIAN. This is trying to optimise for "source
4
bitmap and destination bitmap format match", but it is broken,
5
because in this function the formats don't match: the source is
6
16-bit colour and the destination is 32-bit colour, so a memcpy()
7
will produce corrupted graphics output. Drop the bogus ifdef.
1
8
9
This bug was introduced in commit ea644cf343129, when we dropped
10
support for DEPTH values other than 32 from the template header.
11
The old #if line was
12
#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
13
and this was mistakenly changed to
14
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
15
rather than deleting the #if as now having an always-false condition.
16
17
Fixes: ea644cf343129
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20210215103215.4944-7-peter.maydell@linaro.org
22
---
23
hw/display/omap_lcd_template.h | 4 ----
24
1 file changed, 4 deletions(-)
25
26
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/display/omap_lcd_template.h
29
+++ b/hw/display/omap_lcd_template.h
30
@@ -XXX,XX +XXX,XX @@ static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
31
static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
32
int width, int deststep)
33
{
34
-#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
35
- memcpy(d, s, width * 2);
36
-#else
37
uint16_t v;
38
uint8_t r, g, b;
39
40
@@ -XXX,XX +XXX,XX @@ static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
41
s += 2;
42
d += 4;
43
} while (-- width != 0);
44
-#endif
45
}
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
1
Convert the Neon VQDMULH and VQRDMULH 3-reg-same insns to
1
Fix some minor coding style issues in the template header,
2
decodetree. These are the last integer operations in the
2
so checkpatch doesn't complain when we move the code.
3
3-reg-same group.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-11-peter.maydell@linaro.org
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210215103215.4944-8-peter.maydell@linaro.org
8
---
8
---
9
target/arm/neon-dp.decode | 3 +++
9
hw/display/omap_lcd_template.h | 6 +++---
10
target/arm/translate-neon.inc.c | 24 ++++++++++++++++++++++++
10
1 file changed, 3 insertions(+), 3 deletions(-)
11
target/arm/translate.c | 24 +-----------------------
12
3 files changed, 28 insertions(+), 23 deletions(-)
13
11
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
14
--- a/hw/display/omap_lcd_template.h
17
+++ b/target/arm/neon-dp.decode
15
+++ b/hw/display/omap_lcd_template.h
18
@@ -XXX,XX +XXX,XX @@ VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
16
@@ -XXX,XX +XXX,XX @@ static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
19
VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
17
b = (pal[v & 3] << 4) & 0xf0;
20
VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
18
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
21
19
d += 4;
22
+VQDMULH_3s 1111 001 0 0 . .. .... .... 1011 . . . 0 .... @3same
20
- s ++;
23
+VQRDMULH_3s 1111 001 1 0 . .. .... .... 1011 . . . 0 .... @3same
21
+ s++;
24
+
22
width -= 4;
25
VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0
23
} while (width > 0);
26
24
}
27
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
25
@@ -XXX,XX +XXX,XX @@ static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
26
b = (pal[v & 0xf] << 4) & 0xf0;
29
index XXXXXXX..XXXXXXX 100644
27
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
30
--- a/target/arm/translate-neon.inc.c
28
d += 4;
31
+++ b/target/arm/translate-neon.inc.c
29
- s ++;
32
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPMIN_S, pmin_s)
30
+ s++;
33
DO_3SAME_PAIR(VPMAX_U, pmax_u)
31
width -= 2;
34
DO_3SAME_PAIR(VPMIN_U, pmin_u)
32
} while (width > 0);
35
DO_3SAME_PAIR(VPADD, padd_u)
33
}
36
+
34
@@ -XXX,XX +XXX,XX @@ static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
37
+#define DO_3SAME_VQDMULH(INSN, FUNC) \
35
g = pal[v] & 0xf0;
38
+ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##_s16); \
36
b = (pal[v] << 4) & 0xf0;
39
+ WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##_s32); \
37
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
40
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
38
- s ++;
41
+ uint32_t rn_ofs, uint32_t rm_ofs, \
39
+ s++;
42
+ uint32_t oprsz, uint32_t maxsz) \
40
d += 4;
43
+ { \
41
} while (-- width != 0);
44
+ static const GVecGen3 ops[2] = { \
42
}
45
+ { .fni4 = gen_##INSN##_tramp16 }, \
46
+ { .fni4 = gen_##INSN##_tramp32 }, \
47
+ }; \
48
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece - 1]); \
49
+ } \
50
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
51
+ { \
52
+ if (a->size != 1 && a->size != 2) { \
53
+ return false; \
54
+ } \
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
62
--- a/target/arm/translate.c
63
+++ b/target/arm/translate.c
64
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
65
case NEON_3R_VPMAX:
66
case NEON_3R_VPMIN:
67
case NEON_3R_VPADD_VQRDMLAH:
68
+ case NEON_3R_VQDMULH_VQRDMULH:
69
/* Already handled by decodetree */
70
return 1;
71
}
72
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
73
tmp2 = neon_load_reg(rm, pass);
74
}
75
switch (op) {
76
- case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
77
- if (!u) { /* VQDMULH */
78
- switch (size) {
79
- case 1:
80
- gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
81
- break;
82
- case 2:
83
- gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
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
--
43
--
103
2.20.1
44
2.20.1
104
45
105
46
diff view generated by jsdifflib
1
Convert the Neon SHA instructions in the 3-reg-same group
1
We only include the template header once, so just inline it into the
2
to decodetree.
2
source file for the device.
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
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210215103215.4944-9-peter.maydell@linaro.org
7
---
8
---
8
target/arm/neon-dp.decode | 10 +++
9
hw/display/omap_lcd_template.h | 154 ---------------------------------
9
target/arm/translate-neon.inc.c | 139 ++++++++++++++++++++++++++++++++
10
hw/display/omap_lcdc.c | 127 ++++++++++++++++++++++++++-
10
target/arm/translate.c | 46 +----------
11
2 files changed, 125 insertions(+), 156 deletions(-)
11
3 files changed, 151 insertions(+), 44 deletions(-)
12
delete mode 100644 hw/display/omap_lcd_template.h
12
13
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
15
deleted file mode 100644
16
index XXXXXXX..XXXXXXX
17
--- a/hw/display/omap_lcd_template.h
18
+++ /dev/null
19
@@ -XXX,XX +XXX,XX @@
20
-/*
21
- * QEMU OMAP LCD Emulator templates
22
- *
23
- * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
24
- *
25
- * Redistribution and use in source and binary forms, with or without
26
- * modification, are permitted provided that the following conditions
27
- * are met:
28
- *
29
- * 1. Redistributions of source code must retain the above copyright
30
- * notice, this list of conditions and the following disclaimer.
31
- * 2. Redistributions in binary form must reproduce the above copyright
32
- * notice, this list of conditions and the following disclaimer in
33
- * the documentation and/or other materials provided with the
34
- * distribution.
35
- *
36
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
37
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
38
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
40
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
41
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
42
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
- */
48
-
49
-/*
50
- * 2-bit colour
51
- */
52
-static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
53
- int width, int deststep)
54
-{
55
- uint16_t *pal = opaque;
56
- uint8_t v, r, g, b;
57
-
58
- do {
59
- v = ldub_p((void *) s);
60
- r = (pal[v & 3] >> 4) & 0xf0;
61
- g = pal[v & 3] & 0xf0;
62
- b = (pal[v & 3] << 4) & 0xf0;
63
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
64
- d += 4;
65
- v >>= 2;
66
- r = (pal[v & 3] >> 4) & 0xf0;
67
- g = pal[v & 3] & 0xf0;
68
- b = (pal[v & 3] << 4) & 0xf0;
69
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
70
- d += 4;
71
- v >>= 2;
72
- r = (pal[v & 3] >> 4) & 0xf0;
73
- g = pal[v & 3] & 0xf0;
74
- b = (pal[v & 3] << 4) & 0xf0;
75
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
76
- d += 4;
77
- v >>= 2;
78
- r = (pal[v & 3] >> 4) & 0xf0;
79
- g = pal[v & 3] & 0xf0;
80
- b = (pal[v & 3] << 4) & 0xf0;
81
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
82
- d += 4;
83
- s++;
84
- width -= 4;
85
- } while (width > 0);
86
-}
87
-
88
-/*
89
- * 4-bit colour
90
- */
91
-static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
92
- int width, int deststep)
93
-{
94
- uint16_t *pal = opaque;
95
- uint8_t v, r, g, b;
96
-
97
- do {
98
- v = ldub_p((void *) s);
99
- r = (pal[v & 0xf] >> 4) & 0xf0;
100
- g = pal[v & 0xf] & 0xf0;
101
- b = (pal[v & 0xf] << 4) & 0xf0;
102
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
103
- d += 4;
104
- v >>= 4;
105
- r = (pal[v & 0xf] >> 4) & 0xf0;
106
- g = pal[v & 0xf] & 0xf0;
107
- b = (pal[v & 0xf] << 4) & 0xf0;
108
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
109
- d += 4;
110
- s++;
111
- width -= 2;
112
- } while (width > 0);
113
-}
114
-
115
-/*
116
- * 8-bit colour
117
- */
118
-static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
119
- int width, int deststep)
120
-{
121
- uint16_t *pal = opaque;
122
- uint8_t v, r, g, b;
123
-
124
- do {
125
- v = ldub_p((void *) s);
126
- r = (pal[v] >> 4) & 0xf0;
127
- g = pal[v] & 0xf0;
128
- b = (pal[v] << 4) & 0xf0;
129
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
130
- s++;
131
- d += 4;
132
- } while (-- width != 0);
133
-}
134
-
135
-/*
136
- * 12-bit colour
137
- */
138
-static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
139
- int width, int deststep)
140
-{
141
- uint16_t v;
142
- uint8_t r, g, b;
143
-
144
- do {
145
- v = lduw_le_p((void *) s);
146
- r = (v >> 4) & 0xf0;
147
- g = v & 0xf0;
148
- b = (v << 4) & 0xf0;
149
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
150
- s += 2;
151
- d += 4;
152
- } while (-- width != 0);
153
-}
154
-
155
-/*
156
- * 16-bit colour
157
- */
158
-static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
159
- int width, int deststep)
160
-{
161
- uint16_t v;
162
- uint8_t r, g, b;
163
-
164
- do {
165
- v = lduw_le_p((void *) s);
166
- r = (v >> 8) & 0xf8;
167
- g = (v >> 3) & 0xfc;
168
- b = (v << 3) & 0xf8;
169
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
170
- s += 2;
171
- d += 4;
172
- } while (-- width != 0);
173
-}
174
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
14
index XXXXXXX..XXXXXXX 100644
175
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
176
--- a/hw/display/omap_lcdc.c
16
+++ b/target/arm/neon-dp.decode
177
+++ b/hw/display/omap_lcdc.c
17
@@ -XXX,XX +XXX,XX @@ VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
178
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
18
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
179
19
180
#define draw_line_func drawfn
20
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
181
21
+
182
-#define DEPTH 32
22
+SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
183
-#include "omap_lcd_template.h"
23
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
184
+/*
24
+SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... \
185
+ * 2-bit colour
25
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
186
+ */
26
+SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \
187
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
27
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
188
+ int width, int deststep)
28
+SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
189
+{
29
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
190
+ uint16_t *pal = opaque;
30
+
191
+ uint8_t v, r, g, b;
31
VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
192
+
32
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
193
+ do {
33
index XXXXXXX..XXXXXXX 100644
194
+ v = ldub_p((void *) s);
34
--- a/target/arm/translate-neon.inc.c
195
+ r = (pal[v & 3] >> 4) & 0xf0;
35
+++ b/target/arm/translate-neon.inc.c
196
+ g = pal[v & 3] & 0xf0;
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
197
+ b = (pal[v & 3] << 4) & 0xf0;
37
198
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
38
DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
199
+ d += 4;
39
DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)
200
+ v >>= 2;
40
+
201
+ r = (pal[v & 3] >> 4) & 0xf0;
41
+static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a)
202
+ g = pal[v & 3] & 0xf0;
42
+{
203
+ b = (pal[v & 3] << 4) & 0xf0;
43
+ TCGv_ptr ptr1, ptr2, ptr3;
204
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
44
+ TCGv_i32 tmp;
205
+ d += 4;
45
+
206
+ v >>= 2;
46
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
207
+ r = (pal[v & 3] >> 4) & 0xf0;
47
+ !dc_isar_feature(aa32_sha1, s)) {
208
+ g = pal[v & 3] & 0xf0;
48
+ return false;
209
+ b = (pal[v & 3] << 4) & 0xf0;
49
+ }
210
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
50
+
211
+ d += 4;
51
+ /* UNDEF accesses to D16-D31 if they don't exist. */
212
+ v >>= 2;
52
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
213
+ r = (pal[v & 3] >> 4) & 0xf0;
53
+ ((a->vd | a->vn | a->vm) & 0x10)) {
214
+ g = pal[v & 3] & 0xf0;
54
+ return false;
215
+ b = (pal[v & 3] << 4) & 0xf0;
55
+ }
216
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
56
+
217
+ d += 4;
57
+ if ((a->vn | a->vm | a->vd) & 1) {
218
+ s++;
58
+ return false;
219
+ width -= 4;
59
+ }
220
+ } while (width > 0);
60
+
221
+}
61
+ if (!vfp_access_check(s)) {
222
+
62
+ return true;
223
+/*
63
+ }
224
+ * 4-bit colour
64
+
225
+ */
65
+ ptr1 = vfp_reg_ptr(true, a->vd);
226
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
66
+ ptr2 = vfp_reg_ptr(true, a->vn);
227
+ int width, int deststep)
67
+ ptr3 = vfp_reg_ptr(true, a->vm);
228
+{
68
+ tmp = tcg_const_i32(a->optype);
229
+ uint16_t *pal = opaque;
69
+ gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp);
230
+ uint8_t v, r, g, b;
70
+ tcg_temp_free_i32(tmp);
231
+
71
+ tcg_temp_free_ptr(ptr1);
232
+ do {
72
+ tcg_temp_free_ptr(ptr2);
233
+ v = ldub_p((void *) s);
73
+ tcg_temp_free_ptr(ptr3);
234
+ r = (pal[v & 0xf] >> 4) & 0xf0;
74
+
235
+ g = pal[v & 0xf] & 0xf0;
75
+ return true;
236
+ b = (pal[v & 0xf] << 4) & 0xf0;
76
+}
237
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
77
+
238
+ d += 4;
78
+static bool trans_SHA256H_3s(DisasContext *s, arg_SHA256H_3s *a)
239
+ v >>= 4;
79
+{
240
+ r = (pal[v & 0xf] >> 4) & 0xf0;
80
+ TCGv_ptr ptr1, ptr2, ptr3;
241
+ g = pal[v & 0xf] & 0xf0;
81
+
242
+ b = (pal[v & 0xf] << 4) & 0xf0;
82
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
243
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
83
+ !dc_isar_feature(aa32_sha2, s)) {
244
+ d += 4;
84
+ return false;
245
+ s++;
85
+ }
246
+ width -= 2;
86
+
247
+ } while (width > 0);
87
+ /* UNDEF accesses to D16-D31 if they don't exist. */
248
+}
88
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
249
+
89
+ ((a->vd | a->vn | a->vm) & 0x10)) {
250
+/*
90
+ return false;
251
+ * 8-bit colour
91
+ }
252
+ */
92
+
253
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
93
+ if ((a->vn | a->vm | a->vd) & 1) {
254
+ int width, int deststep)
94
+ return false;
255
+{
95
+ }
256
+ uint16_t *pal = opaque;
96
+
257
+ uint8_t v, r, g, b;
97
+ if (!vfp_access_check(s)) {
258
+
98
+ return true;
259
+ do {
99
+ }
260
+ v = ldub_p((void *) s);
100
+
261
+ r = (pal[v] >> 4) & 0xf0;
101
+ ptr1 = vfp_reg_ptr(true, a->vd);
262
+ g = pal[v] & 0xf0;
102
+ ptr2 = vfp_reg_ptr(true, a->vn);
263
+ b = (pal[v] << 4) & 0xf0;
103
+ ptr3 = vfp_reg_ptr(true, a->vm);
264
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
104
+ gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
265
+ s++;
105
+ tcg_temp_free_ptr(ptr1);
266
+ d += 4;
106
+ tcg_temp_free_ptr(ptr2);
267
+ } while (-- width != 0);
107
+ tcg_temp_free_ptr(ptr3);
268
+}
108
+
269
+
109
+ return true;
270
+/*
110
+}
271
+ * 12-bit colour
111
+
272
+ */
112
+static bool trans_SHA256H2_3s(DisasContext *s, arg_SHA256H2_3s *a)
273
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
113
+{
274
+ int width, int deststep)
114
+ TCGv_ptr ptr1, ptr2, ptr3;
275
+{
115
+
276
+ uint16_t v;
116
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
277
+ uint8_t r, g, b;
117
+ !dc_isar_feature(aa32_sha2, s)) {
278
+
118
+ return false;
279
+ do {
119
+ }
280
+ v = lduw_le_p((void *) s);
120
+
281
+ r = (v >> 4) & 0xf0;
121
+ /* UNDEF accesses to D16-D31 if they don't exist. */
282
+ g = v & 0xf0;
122
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
283
+ b = (v << 4) & 0xf0;
123
+ ((a->vd | a->vn | a->vm) & 0x10)) {
284
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
124
+ return false;
285
+ s += 2;
125
+ }
286
+ d += 4;
126
+
287
+ } while (-- width != 0);
127
+ if ((a->vn | a->vm | a->vd) & 1) {
288
+}
128
+ return false;
289
+
129
+ }
290
+/*
130
+
291
+ * 16-bit colour
131
+ if (!vfp_access_check(s)) {
292
+ */
132
+ return true;
293
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
133
+ }
294
+ int width, int deststep)
134
+
295
+{
135
+ ptr1 = vfp_reg_ptr(true, a->vd);
296
+ uint16_t v;
136
+ ptr2 = vfp_reg_ptr(true, a->vn);
297
+ uint8_t r, g, b;
137
+ ptr3 = vfp_reg_ptr(true, a->vm);
298
+
138
+ gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
299
+ do {
139
+ tcg_temp_free_ptr(ptr1);
300
+ v = lduw_le_p((void *) s);
140
+ tcg_temp_free_ptr(ptr2);
301
+ r = (v >> 8) & 0xf8;
141
+ tcg_temp_free_ptr(ptr3);
302
+ g = (v >> 3) & 0xfc;
142
+
303
+ b = (v << 3) & 0xf8;
143
+ return true;
304
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
144
+}
305
+ s += 2;
145
+
306
+ d += 4;
146
+static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a)
307
+ } while (-- width != 0);
147
+{
308
+}
148
+ TCGv_ptr ptr1, ptr2, ptr3;
309
149
+
310
static void omap_update_display(void *opaque)
150
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
311
{
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
- }
233
- }
234
- tcg_temp_free_ptr(ptr1);
235
- tcg_temp_free_ptr(ptr2);
236
- tcg_temp_free_ptr(ptr3);
237
- return 0;
238
-
239
case NEON_3R_VPADD_VQRDMLAH:
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
}
250
--
312
--
251
2.20.1
313
2.20.1
252
314
253
315
diff view generated by jsdifflib
1
Convert the Neon integer VPADD 3-reg-same insns to decodetree. These
1
The macro draw_line_func is used only once; just expand it.
2
are 'pairwise' operations. (Note that VQRDMLAH, which shares the
3
same primary opcode but has U=1, has already been converted.)
4
2
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-10-peter.maydell@linaro.org
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210215103215.4944-10-peter.maydell@linaro.org
8
---
7
---
9
target/arm/neon-dp.decode | 2 ++
8
hw/display/omap_lcdc.c | 4 +---
10
target/arm/translate-neon.inc.c | 2 ++
9
1 file changed, 1 insertion(+), 3 deletions(-)
11
target/arm/translate.c | 19 +------------------
12
3 files changed, 5 insertions(+), 18 deletions(-)
13
10
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
11
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
13
--- a/hw/display/omap_lcdc.c
17
+++ b/target/arm/neon-dp.decode
14
+++ b/hw/display/omap_lcdc.c
18
@@ -XXX,XX +XXX,XX @@ VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
15
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
19
VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
16
qemu_irq_lower(s->irq);
20
VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
17
}
21
18
22
+VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0
19
-#define draw_line_func drawfn
23
+
24
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
25
26
SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
27
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-neon.inc.c
30
+++ b/target/arm/translate-neon.inc.c
31
@@ -XXX,XX +XXX,XX @@ static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn)
32
#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
33
#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
34
#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
35
+#define gen_helper_neon_padd_u32 tcg_gen_add_i32
36
37
DO_3SAME_PAIR(VPMAX_S, pmax_s)
38
DO_3SAME_PAIR(VPMIN_S, pmin_s)
39
DO_3SAME_PAIR(VPMAX_U, pmax_u)
40
DO_3SAME_PAIR(VPMIN_U, pmin_u)
41
+DO_3SAME_PAIR(VPADD, padd_u)
42
diff --git a/target/arm/translate.c b/target/arm/translate.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/translate.c
45
+++ b/target/arm/translate.c
46
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
47
return 1;
48
}
49
switch (op) {
50
- case NEON_3R_VPADD_VQRDMLAH:
51
- if (!u) {
52
- break; /* VPADD */
53
- }
54
- /* VQRDMLAH : handled by decodetree */
55
- return 1;
56
-
20
-
57
case NEON_3R_VFM_VQRDMLSH:
21
/*
58
if (!u) {
22
* 2-bit colour
59
/* VFM, VFMS */
23
*/
60
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
24
@@ -XXX,XX +XXX,XX @@ static void omap_update_display(void *opaque)
61
case NEON_3R_VQRSHL:
25
{
62
case NEON_3R_VPMAX:
26
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
63
case NEON_3R_VPMIN:
27
DisplaySurface *surface;
64
+ case NEON_3R_VPADD_VQRDMLAH:
28
- draw_line_func draw_line;
65
/* Already handled by decodetree */
29
+ drawfn draw_line;
66
return 1;
30
int size, height, first, last;
67
}
31
int width, linesize, step, bpp, frame_offset;
68
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
32
hwaddr frame_base;
69
}
70
pairwise = 0;
71
switch (op) {
72
- case NEON_3R_VPADD_VQRDMLAH:
73
- pairwise = 1;
74
- break;
75
case NEON_3R_FLOAT_ARITH:
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
}
80
}
81
break;
82
- case NEON_3R_VPADD_VQRDMLAH:
83
- switch (size) {
84
- case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
85
- case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
86
- case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
87
- default: abort();
88
- }
89
- break;
90
case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
91
{
92
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
93
--
33
--
94
2.20.1
34
2.20.1
95
35
96
36
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel, RGB. The TCX code already
3
assumes 32bpp, but it still has some checks of is_surface_bgr()
4
in an attempt to support 32bpp BGR. is_surface_bgr() will always
5
return false for the qemu_console_surface(), unless the display
6
device itself has deliberately created an alternate-format
7
surface via a function like qemu_create_displaysurface_from().
2
8
3
Must clear the tail for AdvSIMD when SVE is enabled.
9
Drop the never-used BGR-handling code, and assert that we have
10
a 32-bit surface rather than just doing nothing if it isn't.
4
11
5
Fixes: ca40a6e6e39
6
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-15-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20210215102149.20513-1-peter.maydell@linaro.org
11
---
16
---
12
target/arm/vec_helper.c | 2 ++
17
hw/display/tcx.c | 31 ++++++++-----------------------
13
1 file changed, 2 insertions(+)
18
1 file changed, 8 insertions(+), 23 deletions(-)
14
19
15
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
20
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/vec_helper.c
22
--- a/hw/display/tcx.c
18
+++ b/target/arm/vec_helper.c
23
+++ b/hw/display/tcx.c
19
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
24
@@ -XXX,XX +XXX,XX @@ static int tcx_check_dirty(TCXState *s, DirtyBitmapSnapshot *snap,
20
d[i + j] = TYPE##_mul(n[i + j], mm, stat); \
25
21
} \
26
static void update_palette_entries(TCXState *s, int start, int end)
22
} \
27
{
23
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
28
- DisplaySurface *surface = qemu_console_surface(s->con);
29
int i;
30
31
for (i = start; i < end; i++) {
32
- if (is_surface_bgr(surface)) {
33
- s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
34
- } else {
35
- s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
36
- }
37
+ s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
38
}
39
tcx_set_dirty(s, 0, memory_region_size(&s->vram_mem));
24
}
40
}
25
41
@@ -XXX,XX +XXX,XX @@ static void tcx_draw_cursor32(TCXState *s1, uint8_t *d,
26
DO_MUL_IDX(gvec_fmul_idx_h, float16, H2)
27
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \
28
mm, a[i + j], 0, stat); \
29
} \
30
} \
31
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
32
}
42
}
33
43
34
DO_FMLA_IDX(gvec_fmla_idx_h, float16, H2)
44
/*
45
- XXX Could be much more optimal:
46
- * detect if line/page/whole screen is in 24 bit mode
47
- * if destination is also BGR, use memcpy
48
- */
49
+ * XXX Could be much more optimal:
50
+ * detect if line/page/whole screen is in 24 bit mode
51
+ */
52
static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
53
const uint8_t *s, int width,
54
const uint32_t *cplane,
55
const uint32_t *s24)
56
{
57
- DisplaySurface *surface = qemu_console_surface(s1->con);
58
- int x, bgr, r, g, b;
59
+ int x, r, g, b;
60
uint8_t val, *p8;
61
uint32_t *p = (uint32_t *)d;
62
uint32_t dval;
63
- bgr = is_surface_bgr(surface);
64
for(x = 0; x < width; x++, s++, s24++) {
65
if (be32_to_cpu(*cplane) & 0x03000000) {
66
/* 24-bit direct, BGR order */
67
@@ -XXX,XX +XXX,XX @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
68
b = *p8++;
69
g = *p8++;
70
r = *p8;
71
- if (bgr)
72
- dval = rgb_to_pixel32bgr(r, g, b);
73
- else
74
- dval = rgb_to_pixel32(r, g, b);
75
+ dval = rgb_to_pixel32(r, g, b);
76
} else {
77
/* 8-bit pseudocolor */
78
val = *s;
79
@@ -XXX,XX +XXX,XX @@ static void tcx_update_display(void *opaque)
80
int y, y_start, dd, ds;
81
uint8_t *d, *s;
82
83
- if (surface_bits_per_pixel(surface) != 32) {
84
- return;
85
- }
86
+ assert(surface_bits_per_pixel(surface) == 32);
87
88
page = 0;
89
y_start = -1;
90
@@ -XXX,XX +XXX,XX @@ static void tcx24_update_display(void *opaque)
91
uint8_t *d, *s;
92
uint32_t *cptr, *s24;
93
94
- if (surface_bits_per_pixel(surface) != 32) {
95
- return;
96
- }
97
+ assert(surface_bits_per_pixel(surface) == 32);
98
99
page = 0;
100
y_start = -1;
35
--
101
--
36
2.20.1
102
2.20.1
37
103
38
104
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The AN524 has a different SYSCLK frequency from the AN505 and AN521;
2
make the SYSCLK frequency a field in the MPS2TZMachineClass rather
3
than a compile-time constant so we can support the AN524.
2
4
3
Provide a functional interface for the vector expansion.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
This fits better with the existing set of helpers that
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
we provide for other operations.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-2-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 10 ++++++----
11
1 file changed, 6 insertions(+), 4 deletions(-)
6
12
7
Macro-ize the 5 nearly identical comparisons.
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
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-7-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/translate.h | 16 ++-
15
target/arm/translate-a64.c | 22 ++--
16
target/arm/translate.c | 254 ++++++++-----------------------------
17
3 files changed, 74 insertions(+), 218 deletions(-)
18
19
diff --git a/target/arm/translate.h b/target/arm/translate.h
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate.h
15
--- a/hw/arm/mps2-tz.c
22
+++ b/target/arm/translate.h
16
+++ b/hw/arm/mps2-tz.c
23
@@ -XXX,XX +XXX,XX @@ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
24
uint64_t vfp_expand_imm(int size, uint8_t imm8);
18
MachineClass parent;
25
19
MPS2TZFPGAType fpga_type;
26
/* Vector operations shared between ARM and AArch64. */
20
uint32_t scc_id;
27
-extern const GVecGen2 ceq0_op[4];
21
+ uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
28
-extern const GVecGen2 clt0_op[4];
22
const char *armsse_type;
29
-extern const GVecGen2 cgt0_op[4];
23
};
30
-extern const GVecGen2 cle0_op[4];
24
31
-extern const GVecGen2 cge0_op[4];
25
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
32
+void gen_gvec_ceq0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
26
33
+ uint32_t opr_sz, uint32_t max_sz);
27
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
34
+void gen_gvec_clt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
28
35
+ uint32_t opr_sz, uint32_t max_sz);
29
-/* Main SYSCLK frequency in Hz */
36
+void gen_gvec_cgt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
30
-#define SYSCLK_FRQ 20000000
37
+ uint32_t opr_sz, uint32_t max_sz);
31
/* Slow 32Khz S32KCLK frequency in Hz */
38
+void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
32
#define S32KCLK_FRQ (32 * 1000)
39
+ uint32_t opr_sz, uint32_t max_sz);
33
40
+void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
41
+ uint32_t opr_sz, uint32_t max_sz);
35
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
42
+
36
const char *name, hwaddr size)
43
extern const GVecGen3 mla_op[4];
37
{
44
extern const GVecGen3 mls_op[4];
38
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
45
extern const GVecGen3 cmtst_op[4];
39
CMSDKAPBUART *uart = opaque;
46
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
40
int i = uart - &mms->uart[0];
47
index XXXXXXX..XXXXXXX 100644
41
int rxirqno = i * 2;
48
--- a/target/arm/translate-a64.c
42
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
49
+++ b/target/arm/translate-a64.c
43
50
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
44
object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART);
51
is_q ? 16 : 8, vec_full_reg_size(s));
45
qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
46
- qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
47
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
48
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
49
s = SYS_BUS_DEVICE(uart);
50
sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
51
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
52
53
/* These clocks don't need migration because they are fixed-frequency */
54
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
55
- clock_set_hz(mms->sysclk, SYSCLK_FRQ);
56
+ clock_set_hz(mms->sysclk, mmc->sysclk_frq);
57
mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
58
clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
59
60
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
61
mmc->fpga_type = FPGA_AN505;
62
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
63
mmc->scc_id = 0x41045050;
64
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
65
mmc->armsse_type = TYPE_IOTKIT;
52
}
66
}
53
67
54
-/* Expand a 2-operand AdvSIMD vector operation using an op descriptor. */
68
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
55
-static void gen_gvec_op2(DisasContext *s, bool is_q, int rd,
69
mmc->fpga_type = FPGA_AN521;
56
- int rn, const GVecGen2 *gvec_op)
70
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
57
-{
71
mmc->scc_id = 0x41045210;
58
- tcg_gen_gvec_2(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
72
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
59
- is_q ? 16 : 8, vec_full_reg_size(s), gvec_op);
73
mmc->armsse_type = TYPE_SSE200;
60
-}
61
-
62
/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
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
}
74
}
97
75
98
-static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a)
99
-{
100
- tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0);
101
- tcg_gen_neg_i32(d, d);
102
-}
103
-
104
-static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a)
105
-{
106
- tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0);
107
- tcg_gen_neg_i64(d, d);
108
-}
109
-
110
-static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
111
-{
112
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
113
- tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero);
114
- tcg_temp_free_vec(zero);
115
-}
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
--
76
--
377
2.20.1
77
2.20.1
378
78
379
79
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Currently the MPS2 SCC device implements a fixed number of OSCCLK
2
values (3). The variant of this device in the MPS3 AN524 board has 6
3
OSCCLK values. Switch to using a PROP_ARRAY, which allows board code
4
to specify how large the OSCCLK array should be as well as its
5
values.
2
6
3
These operations do not touch fp_status.
7
With a variable-length property array, the SCC no longer specifies
8
default values for the OSCCLKs, so we must set them explicitly in the
9
board code. This defaults are actually incorrect for the an521 and
10
an505; we will correct this bug in a following patch.
4
11
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
This is a migration compatibility break for all the mps boards.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
7
Message-id: 20200513163245.17915-12-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20210215115138.20465-3-peter.maydell@linaro.org
9
---
18
---
10
target/arm/helper.h | 4 ++--
19
include/hw/misc/mps2-scc.h | 7 +++----
11
target/arm/translate-a64.c | 5 ++---
20
hw/arm/mps2-tz.c | 5 +++++
12
target/arm/translate.c | 12 ++----------
21
hw/arm/mps2.c | 5 +++++
13
target/arm/vfp_helper.c | 5 ++---
22
hw/misc/mps2-scc.c | 24 +++++++++++++-----------
14
4 files changed, 8 insertions(+), 18 deletions(-)
23
4 files changed, 26 insertions(+), 15 deletions(-)
15
24
16
diff --git a/target/arm/helper.h b/target/arm/helper.h
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
17
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.h
27
--- a/include/hw/misc/mps2-scc.h
19
+++ b/target/arm/helper.h
28
+++ b/include/hw/misc/mps2-scc.h
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
29
@@ -XXX,XX +XXX,XX @@
21
DEF_HELPER_FLAGS_2(rsqrte_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
30
#define TYPE_MPS2_SCC "mps2-scc"
22
DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
31
OBJECT_DECLARE_SIMPLE_TYPE(MPS2SCC, MPS2_SCC)
23
DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
32
24
-DEF_HELPER_2(recpe_u32, i32, i32, ptr)
33
-#define NUM_OSCCLK 3
25
-DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr)
34
-
26
+DEF_HELPER_FLAGS_1(recpe_u32, TCG_CALL_NO_RWG, i32, i32)
35
struct MPS2SCC {
27
+DEF_HELPER_FLAGS_1(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32)
36
/*< private >*/
28
DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32)
37
SysBusDevice parent_obj;
29
38
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
30
DEF_HELPER_3(shl_cc, i32, env, i32, i32)
39
uint32_t dll;
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
40
uint32_t aid;
41
uint32_t id;
42
- uint32_t oscclk[NUM_OSCCLK];
43
- uint32_t oscclk_reset[NUM_OSCCLK];
44
+ uint32_t num_oscclk;
45
+ uint32_t *oscclk;
46
+ uint32_t *oscclk_reset;
47
};
48
49
#endif
50
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
32
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-a64.c
52
--- a/hw/arm/mps2-tz.c
34
+++ b/target/arm/translate-a64.c
53
+++ b/hw/arm/mps2-tz.c
35
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode,
54
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
36
55
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
37
switch (opcode) {
56
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
38
case 0x3c: /* URECPE */
57
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
39
- gen_helper_recpe_u32(tcg_res, tcg_op, fpst);
58
+ /* This will need to be per-FPGA image eventually */
40
+ gen_helper_recpe_u32(tcg_res, tcg_op);
59
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
41
break;
60
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
42
case 0x3d: /* FRECPE */
61
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
43
gen_helper_recpe_f32(tcg_res, tcg_op, fpst);
62
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
44
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
63
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
45
unallocated_encoding(s);
64
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
46
return;
65
}
47
}
66
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
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
67
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/translate.c
68
--- a/hw/arm/mps2.c
64
+++ b/target/arm/translate.c
69
+++ b/hw/arm/mps2.c
65
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
70
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
66
break;
71
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
67
}
72
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
68
case NEON_2RM_VRECPE:
73
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
69
- {
74
+ /* All these FPGA images have the same OSCCLK configuration */
70
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
75
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
71
- gen_helper_recpe_u32(tmp, tmp, fpstatus);
76
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
72
- tcg_temp_free_ptr(fpstatus);
77
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
73
+ gen_helper_recpe_u32(tmp, tmp);
78
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
74
break;
79
sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
75
- }
80
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
76
case NEON_2RM_VRSQRTE:
81
object_initialize_child(OBJECT(mms), "fpgaio",
77
- {
82
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
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
83
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/vfp_helper.c
84
--- a/hw/misc/mps2-scc.c
90
+++ b/target/arm/vfp_helper.c
85
+++ b/hw/misc/mps2-scc.c
91
@@ -XXX,XX +XXX,XX @@ float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
86
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
92
return make_float64(val);
87
{
88
trace_mps2_scc_cfg_write(function, device, value);
89
90
- if (function != 1 || device >= NUM_OSCCLK) {
91
+ if (function != 1 || device >= s->num_oscclk) {
92
qemu_log_mask(LOG_GUEST_ERROR,
93
"MPS2 SCC config write: bad function %d device %d\n",
94
function, device);
95
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
96
static bool scc_cfg_read(MPS2SCC *s, unsigned function,
97
unsigned device, uint32_t *value)
98
{
99
- if (function != 1 || device >= NUM_OSCCLK) {
100
+ if (function != 1 || device >= s->num_oscclk) {
101
qemu_log_mask(LOG_GUEST_ERROR,
102
"MPS2 SCC config read: bad function %d device %d\n",
103
function, device);
104
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
105
s->cfgctrl = 0x100000;
106
s->cfgstat = 0;
107
s->dll = 0xffff0001;
108
- for (i = 0; i < NUM_OSCCLK; i++) {
109
+ for (i = 0; i < s->num_oscclk; i++) {
110
s->oscclk[i] = s->oscclk_reset[i];
111
}
112
for (i = 0; i < ARRAY_SIZE(s->led); i++) {
113
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
114
LED_COLOR_GREEN, name);
115
g_free(name);
116
}
117
+
118
+ s->oscclk = g_new0(uint32_t, s->num_oscclk);
93
}
119
}
94
120
95
-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
121
static const VMStateDescription mps2_scc_vmstate = {
96
+uint32_t HELPER(recpe_u32)(uint32_t a)
122
.name = "mps2-scc",
97
{
123
- .version_id = 1,
98
- /* float_status *s = fpstp; */
124
- .minimum_version_id = 1,
99
int input, estimate;
125
+ .version_id = 2,
100
126
+ .minimum_version_id = 2,
101
if ((a & 0x80000000) == 0) {
127
.fields = (VMStateField[]) {
102
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
128
VMSTATE_UINT32(cfg0, MPS2SCC),
103
return deposit32(0, (32 - 9), 9, estimate);
129
VMSTATE_UINT32(cfg1, MPS2SCC),
104
}
130
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_scc_vmstate = {
105
131
VMSTATE_UINT32(cfgctrl, MPS2SCC),
106
-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
132
VMSTATE_UINT32(cfgstat, MPS2SCC),
107
+uint32_t HELPER(rsqrte_u32)(uint32_t a)
133
VMSTATE_UINT32(dll, MPS2SCC),
108
{
134
- VMSTATE_UINT32_ARRAY(oscclk, MPS2SCC, NUM_OSCCLK),
109
int estimate;
135
+ VMSTATE_VARRAY_UINT32(oscclk, MPS2SCC, num_oscclk,
136
+ 0, vmstate_info_uint32, uint32_t),
137
VMSTATE_END_OF_LIST()
138
}
139
};
140
@@ -XXX,XX +XXX,XX @@ static Property mps2_scc_properties[] = {
141
DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0),
142
DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
143
DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0),
144
- /* These are the initial settings for the source clocks on the board.
145
+ /*
146
+ * These are the initial settings for the source clocks on the board.
147
* In hardware they can be configured via a config file read by the
148
* motherboard configuration controller to suit the FPGA image.
149
- * These default values are used by most of the standard FPGA images.
150
*/
151
- DEFINE_PROP_UINT32("oscclk0", MPS2SCC, oscclk_reset[0], 50000000),
152
- DEFINE_PROP_UINT32("oscclk1", MPS2SCC, oscclk_reset[1], 24576000),
153
- DEFINE_PROP_UINT32("oscclk2", MPS2SCC, oscclk_reset[2], 25000000),
154
+ DEFINE_PROP_ARRAY("oscclk", MPS2SCC, num_oscclk, oscclk_reset,
155
+ qdev_prop_uint32, uint32_t),
156
DEFINE_PROP_END_OF_LIST(),
157
};
110
158
111
--
159
--
112
2.20.1
160
2.20.1
113
161
114
162
diff view generated by jsdifflib
New patch
1
We were previously using the default OSCCLK settings, which are
2
correct for the older MPS2 boards (mps2-an385, mps2-an386,
3
mps2-an500, mps2-an511), but wrong for the mps2-an505 and mps2-511
4
implemented in mps2-tz.c. Now we're setting the values explicitly we
5
can fix them to be correct.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210215115138.20465-4-peter.maydell@linaro.org
11
---
12
hw/arm/mps2-tz.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
18
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
20
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
21
/* This will need to be per-FPGA image eventually */
22
qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
23
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
24
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
25
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
26
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
27
qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
28
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
29
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
30
--
31
2.20.1
32
33
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The AN505 and AN511 happen to share the same OSCCLK values, but the
2
AN524 will have a different set (and more of them), so split the
3
settings out to be per-board.
2
4
3
The functions eliminate duplication of the special cases for
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
this operation. They match up with the GVecGen2iFn typedef.
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-5-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 23 ++++++++++++++++++-----
11
1 file changed, 18 insertions(+), 5 deletions(-)
5
12
6
Add out-of-line helpers. We got away with only having inline
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.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
14
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
15
--- a/hw/arm/mps2-tz.c
27
+++ b/target/arm/helper.h
16
+++ b/hw/arm/mps2-tz.c
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(gvec_ursra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
29
DEF_HELPER_FLAGS_3(gvec_ursra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
18
MPS2TZFPGAType fpga_type;
30
DEF_HELPER_FLAGS_3(gvec_ursra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
19
uint32_t scc_id;
31
20
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
32
+DEF_HELPER_FLAGS_3(gvec_sri_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
21
+ uint32_t len_oscclk;
33
+DEF_HELPER_FLAGS_3(gvec_sri_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
22
+ const uint32_t *oscclk;
34
+DEF_HELPER_FLAGS_3(gvec_sri_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
23
const char *armsse_type;
35
+DEF_HELPER_FLAGS_3(gvec_sri_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
24
};
25
26
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
27
/* Slow 32Khz S32KCLK frequency in Hz */
28
#define S32KCLK_FRQ (32 * 1000)
29
30
+static const uint32_t an505_oscclk[] = {
31
+ 40000000,
32
+ 24580000,
33
+ 25000000,
34
+};
36
+
35
+
37
+DEF_HELPER_FLAGS_3(gvec_sli_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
36
/* Create an alias of an entire original MemoryRegion @orig
38
+DEF_HELPER_FLAGS_3(gvec_sli_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
37
* located at @base in the memory map.
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
*/
38
*/
70
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
71
index XXXXXXX..XXXXXXX 100644
40
MPS2SCC *scc = opaque;
72
--- a/target/arm/translate-a64.c
41
DeviceState *sccdev;
73
+++ b/target/arm/translate-a64.c
42
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
74
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op2(DisasContext *s, bool is_q, int rd,
43
+ uint32_t i;
75
is_q ? 16 : 8, vec_full_reg_size(s), gvec_op);
44
45
object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC);
46
sccdev = DEVICE(scc);
47
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
48
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
49
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
50
- /* This will need to be per-FPGA image eventually */
51
- qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
52
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
53
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
54
- qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
55
+ qdev_prop_set_uint32(sccdev, "len-oscclk", mmc->len_oscclk);
56
+ for (i = 0; i < mmc->len_oscclk; i++) {
57
+ g_autofree char *propname = g_strdup_printf("oscclk[%u]", i);
58
+ qdev_prop_set_uint32(sccdev, propname, mmc->oscclk[i]);
59
+ }
60
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
61
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
76
}
62
}
77
63
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
78
-/* Expand a 2-operand + immediate AdvSIMD vector operation using
64
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
79
- * an op descriptor.
65
mmc->scc_id = 0x41045050;
80
- */
66
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
81
-static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd,
67
+ mmc->oscclk = an505_oscclk;
82
- int rn, int64_t imm, const GVecGen2i *gvec_op)
68
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
83
-{
69
mmc->armsse_type = TYPE_IOTKIT;
84
- tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
85
- is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op);
86
-}
87
-
88
/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
89
static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
90
int rn, int rm, const GVecGen3 *gvec_op)
91
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
92
gen_gvec_fn2i(s, is_q, rd, rn, shift,
93
is_u ? gen_gvec_usra : gen_gvec_ssra, size);
94
return;
95
+
96
case 0x08: /* SRI */
97
- /* Shift count same as element size is valid but does nothing. */
98
- if (shift == 8 << size) {
99
- goto done;
100
- }
101
- gen_gvec_op2i(s, is_q, rd, rn, shift, &sri_op[size]);
102
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sri, size);
103
return;
104
105
case 0x00: /* SSHR / USHR */
106
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
107
}
108
tcg_temp_free_i64(tcg_round);
109
110
- done:
111
clear_vec_high(s, is_q, rd);
112
}
70
}
113
71
114
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
72
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
115
}
73
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
116
74
mmc->scc_id = 0x41045210;
117
if (insert) {
75
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
118
- gen_gvec_op2i(s, is_q, rd, rn, shift, &sli_op[size]);
76
+ mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
119
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sli, size);
77
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
120
} else {
78
mmc->armsse_type = TYPE_SSE200;
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
}
79
}
154
80
155
-static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
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
--
81
--
398
2.20.1
82
2.20.1
399
83
400
84
diff view generated by jsdifflib
1
Convert the Neon VHADD insns in the 3-reg-same group to decodetree.
1
The MPS2 board has 2 LEDs, but the MPS3 board has 10 LEDs. The
2
FPGAIO device is similar on both sets of boards, but the LED0
3
register has correspondingly more bits that have an effect. Add a
4
device property for number of LEDs.
2
5
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200512163904.10918-5-peter.maydell@linaro.org
9
Message-id: 20210215115138.20465-6-peter.maydell@linaro.org
6
---
10
---
7
target/arm/neon-dp.decode | 2 ++
11
include/hw/misc/mps2-fpgaio.h | 5 ++++-
8
target/arm/translate-neon.inc.c | 24 ++++++++++++++++++++++++
12
hw/misc/mps2-fpgaio.c | 31 +++++++++++++++++++++++--------
9
target/arm/translate.c | 4 +---
13
2 files changed, 27 insertions(+), 9 deletions(-)
10
3 files changed, 27 insertions(+), 3 deletions(-)
11
14
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
17
--- a/include/hw/misc/mps2-fpgaio.h
15
+++ b/target/arm/neon-dp.decode
18
+++ b/include/hw/misc/mps2-fpgaio.h
16
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
17
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
20
#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
18
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
21
OBJECT_DECLARE_SIMPLE_TYPE(MPS2FPGAIO, MPS2_FPGAIO)
19
22
20
+VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
23
+#define MPS2FPGAIO_MAX_LEDS 32
21
+VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
24
+
22
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
25
struct MPS2FPGAIO {
23
VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same
26
/*< private >*/
24
27
SysBusDevice parent_obj;
25
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
28
29
/*< public >*/
30
MemoryRegion iomem;
31
- LEDState *led[2];
32
+ LEDState *led[MPS2FPGAIO_MAX_LEDS];
33
+ uint32_t num_leds;
34
35
uint32_t led0;
36
uint32_t prescale;
37
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
26
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-neon.inc.c
39
--- a/hw/misc/mps2-fpgaio.c
28
+++ b/target/arm/translate-neon.inc.c
40
+++ b/hw/misc/mps2-fpgaio.c
29
@@ -XXX,XX +XXX,XX @@ DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64)
41
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
30
DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64)
42
31
DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64)
43
switch (offset) {
32
DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
44
case A_LED0:
45
- s->led0 = value & 0x3;
46
- led_set_state(s->led[0], value & 0x01);
47
- led_set_state(s->led[1], value & 0x02);
48
+ if (s->num_leds != 0) {
49
+ uint32_t i;
33
+
50
+
34
+#define DO_3SAME_32(INSN, FUNC) \
51
+ s->led0 = value & MAKE_64BIT_MASK(0, s->num_leds);
35
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
52
+ for (i = 0; i < s->num_leds; i++) {
36
+ uint32_t rn_ofs, uint32_t rm_ofs, \
53
+ led_set_state(s->led[i], value & (1 << i));
37
+ uint32_t oprsz, uint32_t maxsz) \
54
+ }
38
+ { \
55
+ }
39
+ static const GVecGen3 ops[4] = { \
56
break;
40
+ { .fni4 = gen_helper_neon_##FUNC##8 }, \
57
case A_PRESCALE:
41
+ { .fni4 = gen_helper_neon_##FUNC##16 }, \
58
resync_counter(s);
42
+ { .fni4 = gen_helper_neon_##FUNC##32 }, \
59
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_reset(DeviceState *dev)
43
+ { 0 }, \
60
s->pscntr = 0;
44
+ }; \
61
s->pscntr_sync_ticks = now;
45
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \
62
46
+ } \
63
- for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) {
47
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
64
+ for (size_t i = 0; i < s->num_leds; i++) {
48
+ { \
65
device_cold_reset(DEVICE(s->led[i]));
49
+ if (a->size > 2) { \
66
}
50
+ return false; \
67
}
51
+ } \
68
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_init(Object *obj)
52
+ return do_3same(s, a, gen_##INSN##_3s); \
69
static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
70
{
71
MPS2FPGAIO *s = MPS2_FPGAIO(dev);
72
+ uint32_t i;
73
74
- s->led[0] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
75
- LED_COLOR_GREEN, "USERLED0");
76
- s->led[1] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
77
- LED_COLOR_GREEN, "USERLED1");
78
+ if (s->num_leds > MPS2FPGAIO_MAX_LEDS) {
79
+ error_setg(errp, "num-leds cannot be greater than %d",
80
+ MPS2FPGAIO_MAX_LEDS);
81
+ return;
53
+ }
82
+ }
54
+
83
+
55
+DO_3SAME_32(VHADD_S, hadd_s)
84
+ for (i = 0; i < s->num_leds; i++) {
56
+DO_3SAME_32(VHADD_U, hadd_u)
85
+ g_autofree char *ledname = g_strdup_printf("USERLED%d", i);
57
diff --git a/target/arm/translate.c b/target/arm/translate.c
86
+ s->led[i] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
58
index XXXXXXX..XXXXXXX 100644
87
+ LED_COLOR_GREEN, ledname);
59
--- a/target/arm/translate.c
88
+ }
60
+++ b/target/arm/translate.c
89
}
61
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
90
62
case NEON_3R_VML:
91
static bool mps2_fpgaio_counters_needed(void *opaque)
63
case NEON_3R_VSHL:
92
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_fpgaio_vmstate = {
64
case NEON_3R_SHA:
93
static Property mps2_fpgaio_properties[] = {
65
+ case NEON_3R_VHADD:
94
/* Frequency of the prescale counter */
66
/* Already handled by decodetree */
95
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
67
return 1;
96
+ /* Number of LEDs controlled by LED0 register */
68
}
97
+ DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
69
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
98
DEFINE_PROP_END_OF_LIST(),
70
tmp2 = neon_load_reg(rm, pass);
99
};
71
}
100
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
--
101
--
80
2.20.1
102
2.20.1
81
103
82
104
diff view generated by jsdifflib
New patch
1
MPS3 boards have an extra SWITCH register in the FPGAIO block which
2
reports the value of some switches. Implement this, governed by a
3
property the board code can use to specify whether whether it exists.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-7-peter.maydell@linaro.org
9
---
10
include/hw/misc/mps2-fpgaio.h | 1 +
11
hw/misc/mps2-fpgaio.c | 10 ++++++++++
12
2 files changed, 11 insertions(+)
13
14
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/mps2-fpgaio.h
17
+++ b/include/hw/misc/mps2-fpgaio.h
18
@@ -XXX,XX +XXX,XX @@ struct MPS2FPGAIO {
19
MemoryRegion iomem;
20
LEDState *led[MPS2FPGAIO_MAX_LEDS];
21
uint32_t num_leds;
22
+ bool has_switches;
23
24
uint32_t led0;
25
uint32_t prescale;
26
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/mps2-fpgaio.c
29
+++ b/hw/misc/mps2-fpgaio.c
30
@@ -XXX,XX +XXX,XX @@ REG32(CLK100HZ, 0x14)
31
REG32(COUNTER, 0x18)
32
REG32(PRESCALE, 0x1c)
33
REG32(PSCNTR, 0x20)
34
+REG32(SWITCH, 0x28)
35
REG32(MISC, 0x4c)
36
37
static uint32_t counter_from_tickoff(int64_t now, int64_t tick_offset, int frq)
38
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
39
resync_counter(s);
40
r = s->pscntr;
41
break;
42
+ case A_SWITCH:
43
+ if (!s->has_switches) {
44
+ goto bad_offset;
45
+ }
46
+ /* User-togglable board switches. We don't model that, so report 0. */
47
+ r = 0;
48
+ break;
49
default:
50
+ bad_offset:
51
qemu_log_mask(LOG_GUEST_ERROR,
52
"MPS2 FPGAIO read: bad offset %x\n", (int) offset);
53
r = 0;
54
@@ -XXX,XX +XXX,XX @@ static Property mps2_fpgaio_properties[] = {
55
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
56
/* Number of LEDs controlled by LED0 register */
57
DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
58
+ DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
59
DEFINE_PROP_END_OF_LIST(),
60
};
61
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Set the FPGAIO num-leds and have-switches properties explicitly
2
per-board, rather than relying on the defaults. The AN505 and AN521
3
both have the same settings as the default values, but the AN524 will
4
be different.
2
5
3
The functions eliminate duplication of the special cases for
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
this operation. They match up with the GVecGen2iFn typedef.
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210215115138.20465-8-peter.maydell@linaro.org
10
---
11
hw/arm/mps2-tz.c | 9 +++++++++
12
1 file changed, 9 insertions(+)
5
13
6
Add out-of-line helpers. We got away with only having inline
14
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.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-2-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 | 15 +---
20
target/arm/translate.c | 161 ++++++++++++++++++++++---------------
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
15
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
16
--- a/hw/arm/mps2-tz.c
27
+++ b/target/arm/helper.h
17
+++ b/hw/arm/mps2-tz.c
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_pmull_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
18
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
29
19
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
30
DEF_HELPER_FLAGS_4(neon_pmull_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
uint32_t len_oscclk;
31
21
const uint32_t *oscclk;
32
+DEF_HELPER_FLAGS_3(gvec_ssra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
22
+ uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
33
+DEF_HELPER_FLAGS_3(gvec_ssra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
23
+ bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
34
+DEF_HELPER_FLAGS_3(gvec_ssra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
24
const char *armsse_type;
35
+DEF_HELPER_FLAGS_3(gvec_ssra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
25
};
36
+
26
37
+DEF_HELPER_FLAGS_3(gvec_usra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
27
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
38
+DEF_HELPER_FLAGS_3(gvec_usra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
28
const char *name, hwaddr size)
39
+DEF_HELPER_FLAGS_3(gvec_usra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
29
{
40
+DEF_HELPER_FLAGS_3(gvec_usra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
30
MPS2FPGAIO *fpgaio = opaque;
41
+
31
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
42
#ifdef TARGET_AARCH64
32
43
#include "helper-a64.h"
33
object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO);
44
#include "helper-sve.h"
34
+ qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
45
diff --git a/target/arm/translate.h b/target/arm/translate.h
35
+ qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
46
index XXXXXXX..XXXXXXX 100644
36
sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
47
--- a/target/arm/translate.h
37
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
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
+
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 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
}
38
}
103
39
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
104
-static const TCGOpcode vecop_list_ssra[] = {
40
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
105
- INDEX_op_sari_vec, INDEX_op_add_vec, 0
41
mmc->oscclk = an505_oscclk;
106
-};
42
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
107
+void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
43
+ mmc->fpgaio_num_leds = 2;
108
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
44
+ mmc->fpgaio_has_switches = false;
109
+{
45
mmc->armsse_type = TYPE_IOTKIT;
110
+ static const TCGOpcode vecop_list[] = {
111
+ INDEX_op_sari_vec, INDEX_op_add_vec, 0
112
+ };
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
{
178
@@ -XXX,XX +XXX,XX @@ static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
179
tcg_gen_add_vec(vece, d, d, a);
180
}
46
}
181
47
182
-static const TCGOpcode vecop_list_usra[] = {
48
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
183
- INDEX_op_shri_vec, INDEX_op_add_vec, 0
49
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
184
-};
50
mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
185
+void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
51
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
186
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
52
+ mmc->fpgaio_num_leds = 2;
187
+{
53
+ mmc->fpgaio_has_switches = false;
188
+ static const TCGOpcode vecop_list[] = {
54
mmc->armsse_type = TYPE_SSE200;
189
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
190
+ };
191
+ static const GVecGen2i ops[4] = {
192
+ { .fni8 = gen_usra8_i64,
193
+ .fniv = gen_usra_vec,
194
+ .fno = gen_helper_gvec_usra_b,
195
+ .load_dest = true,
196
+ .opt_opc = vecop_list,
197
+ .vece = MO_8, },
198
+ { .fni8 = gen_usra16_i64,
199
+ .fniv = gen_usra_vec,
200
+ .fno = gen_helper_gvec_usra_h,
201
+ .load_dest = true,
202
+ .opt_opc = vecop_list,
203
+ .vece = MO_16, },
204
+ { .fni4 = gen_usra32_i32,
205
+ .fniv = gen_usra_vec,
206
+ .fno = gen_helper_gvec_usra_s,
207
+ .load_dest = true,
208
+ .opt_opc = vecop_list,
209
+ .vece = MO_32, },
210
+ { .fni8 = gen_usra64_i64,
211
+ .fniv = gen_usra_vec,
212
+ .fno = gen_helper_gvec_usra_d,
213
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
214
+ .load_dest = true,
215
+ .opt_opc = vecop_list,
216
+ .vece = MO_64, },
217
+ };
218
219
-const GVecGen2i usra_op[4] = {
220
- { .fni8 = gen_usra8_i64,
221
- .fniv = gen_usra_vec,
222
- .load_dest = true,
223
- .opt_opc = vecop_list_usra,
224
- .vece = MO_8, },
225
- { .fni8 = gen_usra16_i64,
226
- .fniv = gen_usra_vec,
227
- .load_dest = true,
228
- .opt_opc = vecop_list_usra,
229
- .vece = MO_16, },
230
- { .fni4 = gen_usra32_i32,
231
- .fniv = gen_usra_vec,
232
- .load_dest = true,
233
- .opt_opc = vecop_list_usra,
234
- .vece = MO_32, },
235
- { .fni8 = gen_usra64_i64,
236
- .fniv = gen_usra_vec,
237
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
238
- .load_dest = true,
239
- .opt_opc = vecop_list_usra,
240
- .vece = MO_64, },
241
-};
242
+ /* tszimm encoding produces immediates in the range [1..esize]. */
243
+ tcg_debug_assert(shift > 0);
244
+ tcg_debug_assert(shift <= (8 << vece));
245
+
246
+ /*
247
+ * Shifts larger than the element size are architecturally valid.
248
+ * Unsigned results in all zeros as input to accumulate: nop.
249
+ */
250
+ if (shift < (8 << vece)) {
251
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
252
+ } else {
253
+ /* Nop, but we do need to clear the tail. */
254
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
255
+ }
256
+}
257
258
static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
259
{
260
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
261
case 1: /* VSRA */
262
/* Right shift comes here negative. */
263
shift = -shift;
264
- /* Shifts larger than the element size are architecturally
265
- * valid. Unsigned results in all zeros; signed results
266
- * in all sign bits.
267
- */
268
- if (!u) {
269
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
270
- MIN(shift, (8 << size) - 1),
271
- &ssra_op[size]);
272
- } else if (shift >= 8 << size) {
273
- /* rd += 0 */
274
+ if (u) {
275
+ gen_gvec_usra(size, rd_ofs, rm_ofs, shift,
276
+ vec_size, vec_size);
277
} else {
278
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
279
- shift, &usra_op[size]);
280
+ gen_gvec_ssra(size, rd_ofs, rm_ofs, shift,
281
+ vec_size, vec_size);
282
}
283
return 0;
284
285
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
286
index XXXXXXX..XXXXXXX 100644
287
--- a/target/arm/vec_helper.c
288
+++ b/target/arm/vec_helper.c
289
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_sqsub_d)(void *vd, void *vq, void *vn,
290
clear_tail(d, oprsz, simd_maxsz(desc));
291
}
55
}
292
56
293
+
294
+#define DO_SRA(NAME, TYPE) \
295
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
296
+{ \
297
+ intptr_t i, oprsz = simd_oprsz(desc); \
298
+ int shift = simd_data(desc); \
299
+ TYPE *d = vd, *n = vn; \
300
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
301
+ d[i] += n[i] >> shift; \
302
+ } \
303
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
304
+}
305
+
306
+DO_SRA(gvec_ssra_b, int8_t)
307
+DO_SRA(gvec_ssra_h, int16_t)
308
+DO_SRA(gvec_ssra_s, int32_t)
309
+DO_SRA(gvec_ssra_d, int64_t)
310
+
311
+DO_SRA(gvec_usra_b, uint8_t)
312
+DO_SRA(gvec_usra_h, uint16_t)
313
+DO_SRA(gvec_usra_s, uint32_t)
314
+DO_SRA(gvec_usra_d, uint64_t)
315
+
316
+#undef DO_SRA
317
+
318
/*
319
* Convert float16 to float32, raising no exceptions and
320
* preserving exceptional values, including SNaN.
321
--
57
--
322
2.20.1
58
2.20.1
323
59
324
60
diff view generated by jsdifflib
1
Convert the Neon integer VPMAX and VPMIN 3-reg-same insns to
1
In the mps2-tz board code, we handle devices whose interrupt lines
2
decodetree. These are 'pairwise' operations.
2
must be wired to all CPUs by creating IRQ splitter devices for the
3
AN521, because it has 2 CPUs, but wiring the device IRQ directly to
4
the SSE/IoTKit input for the AN505, which has only 1 CPU.
5
6
We can avoid making an explicit check on the board type constant by
7
instead creating and using the IRQ splitters for any board with more
8
than 1 CPU. This avoids having to add extra cases to the
9
conditionals every time we add new boards.
3
10
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200512163904.10918-9-peter.maydell@linaro.org
14
Message-id: 20210215115138.20465-9-peter.maydell@linaro.org
7
---
15
---
8
target/arm/neon-dp.decode | 9 +++++
16
hw/arm/mps2-tz.c | 19 +++++++++----------
9
target/arm/translate-neon.inc.c | 71 +++++++++++++++++++++++++++++++++
17
1 file changed, 9 insertions(+), 10 deletions(-)
10
target/arm/translate.c | 17 +-------
11
3 files changed, 82 insertions(+), 15 deletions(-)
12
18
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
19
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
21
--- a/hw/arm/mps2-tz.c
16
+++ b/target/arm/neon-dp.decode
22
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
18
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
24
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
19
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
25
{
20
26
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
21
+@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
27
- MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
22
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
28
+ MachineClass *mc = MACHINE_GET_CLASS(mms);
23
+
29
24
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
30
assert(irqno < MPS2TZ_NUMIRQ);
25
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
31
26
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
32
- switch (mmc->fpga_type) {
27
@@ -XXX,XX +XXX,XX @@ VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same
33
- case FPGA_AN505:
28
VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
34
- return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
29
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
35
- case FPGA_AN521:
30
36
+ if (mc->max_cpus > 1) {
31
+VPMAX_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 0 .... @3same_q0
37
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
32
+VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
38
- default:
33
+
39
- g_assert_not_reached();
34
+VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
40
+ } else {
35
+VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
41
+ return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
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
+ }
57
+
58
+ /* UNDEF accesses to D16-D31 if they don't exist. */
59
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
60
+ ((a->vd | a->vn | a->vm) & 0x10)) {
61
+ return false;
62
+ }
63
+
64
+ if (a->size == 3) {
65
+ return false;
66
+ }
67
+
68
+ if (!vfp_access_check(s)) {
69
+ return true;
70
+ }
71
+
72
+ assert(a->q == 0); /* enforced by decode patterns */
73
+
74
+ /*
75
+ * Note that we have to be careful not to clobber the source operands
76
+ * in the "vm == vd" case by storing the result of the first pass too
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
+ */
80
+ tmp = neon_load_reg(a->vn, 0);
81
+ tmp2 = neon_load_reg(a->vn, 1);
82
+ fn(tmp, tmp, tmp2);
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
}
42
}
125
}
43
}
126
44
127
-/* 32-bit pairwise ops end up the same as the elementwise versions. */
45
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
128
-#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
46
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
129
-#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
47
130
-#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
48
/*
131
-#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
49
- * The AN521 needs us to create splitters to feed the IRQ inputs
132
-
50
- * for each CPU in the SSE-200 from each device in the board.
133
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
51
+ * If this board has more than one CPU, then we need to create splitters
134
switch ((size << 1) | u) { \
52
+ * to feed the IRQ inputs for each CPU in the SSE from each device in the
135
case 0: \
53
+ * board. If there is only one CPU, we can just wire the device IRQ
136
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
54
+ * directly to the SSE's IRQ input.
137
case NEON_3R_VQSHL:
55
*/
138
case NEON_3R_VRSHL:
56
- if (mmc->fpga_type == FPGA_AN521) {
139
case NEON_3R_VQRSHL:
57
+ if (mc->max_cpus > 1) {
140
+ case NEON_3R_VPMAX:
58
for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
141
+ case NEON_3R_VPMIN:
59
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
142
/* Already handled by decodetree */
60
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
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
--
61
--
169
2.20.1
62
2.20.1
170
63
171
64
diff view generated by jsdifflib
1
GDB's remote protocol requires M-profile cores to use the feature
1
The AN524 has more interrupt lines than the AN505 and AN521; make
2
name 'org.gnu.gdb.arm.m-profile' instead of the 'org.gnu.gdb.arm.core'
2
numirq board-specific rather than a compile-time constant.
3
feature used for A- and R-profile cores. We weren't doing this, which
4
meant GDB treated our M-profile cores like A-profile ones. This mostly
5
doesn't matter, but for instance means that it doesn't correctly
6
handle backtraces where an M-profile exception frame is involved.
7
3
8
Ship a copy of GDB's arm-m-profile.xml and use it on the M-profile
4
Since the difference is small (92 on the current boards and 95 on the
9
cores. The integer registers have the same offsets as the
5
new one) we don't dynamically allocate the cpu_irq_splitter[] array
10
arm-core.xml, but register 25 is the M-profile XPSR rather than the
6
but leave it as a fixed length array whose size is the maximum needed
11
A-profile CPSR, so we need to update arm_cpu_gdb_read_register() and
7
for any of the boards.
12
arm_cpu_gdb_write_register() to handle XSPR reads and writes.
13
8
14
Fixes: https://bugs.launchpad.net/qemu/+bug/1877136
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20200507134755.13997-1-peter.maydell@linaro.org
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210215115138.20465-10-peter.maydell@linaro.org
18
---
13
---
19
configure | 4 ++--
14
hw/arm/mps2-tz.c | 15 ++++++++++-----
20
target/arm/cpu_tcg.c | 1 +
15
1 file changed, 10 insertions(+), 5 deletions(-)
21
target/arm/gdbstub.c | 22 ++++++++++++++++++----
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
16
26
diff --git a/configure b/configure
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.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
18
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/cpu_tcg.c
19
--- a/hw/arm/mps2-tz.c
50
+++ b/target/arm/cpu_tcg.c
20
+++ b/hw/arm/mps2-tz.c
51
@@ -XXX,XX +XXX,XX @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
21
@@ -XXX,XX +XXX,XX @@
52
#endif
22
#include "hw/qdev-clock.h"
53
23
#include "qom/object.h"
54
cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
24
55
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
25
-#define MPS2TZ_NUMIRQ 92
26
+#define MPS2TZ_NUMIRQ_MAX 92
27
28
typedef enum MPS2TZFPGAType {
29
FPGA_AN505,
30
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
31
const uint32_t *oscclk;
32
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
33
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
34
+ int numirq; /* Number of external interrupts */
35
const char *armsse_type;
36
};
37
38
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
39
SplitIRQ sec_resp_splitter;
40
qemu_or_irq uart_irq_orgate;
41
DeviceState *lan9118;
42
- SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
43
+ SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX];
44
Clock *sysclk;
45
Clock *s32kclk;
46
};
47
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
48
{
49
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
50
MachineClass *mc = MACHINE_GET_CLASS(mms);
51
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
52
53
- assert(irqno < MPS2TZ_NUMIRQ);
54
+ assert(irqno < mmc->numirq);
55
56
if (mc->max_cpus > 1) {
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
59
iotkitdev = DEVICE(&mms->iotkit);
60
object_property_set_link(OBJECT(&mms->iotkit), "memory",
61
OBJECT(system_memory), &error_abort);
62
- qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
63
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
64
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
65
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
66
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
67
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
68
* board. If there is only one CPU, we can just wire the device IRQ
69
* directly to the SSE's IRQ input.
70
*/
71
+ assert(mmc->numirq <= MPS2TZ_NUMIRQ_MAX);
72
if (mc->max_cpus > 1) {
73
- for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
74
+ for (i = 0; i < mmc->numirq; i++) {
75
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
76
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
77
78
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
79
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
80
mmc->fpgaio_num_leds = 2;
81
mmc->fpgaio_has_switches = false;
82
+ mmc->numirq = 92;
83
mmc->armsse_type = TYPE_IOTKIT;
56
}
84
}
57
85
58
static const ARMCPUInfo arm_tcg_cpus[] = {
86
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
59
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
87
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
60
index XXXXXXX..XXXXXXX 100644
88
mmc->fpgaio_num_leds = 2;
61
--- a/target/arm/gdbstub.c
89
mmc->fpgaio_has_switches = false;
62
+++ b/target/arm/gdbstub.c
90
+ mmc->numirq = 92;
63
@@ -XXX,XX +XXX,XX @@ int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
91
mmc->armsse_type = TYPE_SSE200;
64
}
92
}
65
return gdb_get_reg32(mem_buf, 0);
93
66
case 25:
67
- /* CPSR */
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
+ /*
87
+ * Don't allow writing to XPSR.Exception as it can cause
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
+ */
92
+ xpsr_write(env, tmp, ~XPSR_EXCP);
93
+ } else {
94
+ cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
95
+ }
96
return 4;
97
}
98
/* Unknown register. */
99
diff --git a/gdb-xml/arm-m-profile.xml b/gdb-xml/arm-m-profile.xml
100
new file mode 100644
101
index XXXXXXX..XXXXXXX
102
--- /dev/null
103
+++ b/gdb-xml/arm-m-profile.xml
104
@@ -XXX,XX +XXX,XX @@
105
+<?xml version="1.0"?>
106
+<!-- Copyright (C) 2010-2020 Free Software Foundation, Inc.
107
+
108
+ Copying and distribution of this file, with or without modification,
109
+ are permitted in any medium without royalty provided the copyright
110
+ notice and this notice are preserved. -->
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
--
94
--
133
2.20.1
95
2.20.1
134
96
135
97
diff view generated by jsdifflib
1
Convert the Neon fp VMAX/VMIN/VMAXNM/VMINNM/VRECPS/VRSQRTS 3-reg-same
1
The AN524 version of the SCC interface has different behaviour for
2
insns to decodetree. (These are all the remaining non-accumulation
2
some of the CFG registers; implement it.
3
instructions in this group.)
3
4
Each board in this family can have minor differences in the meaning
5
of the CFG registers, so rather than trying to specify all the
6
possible semantics via individual device properties, we make the
7
behaviour conditional on the part-number field of the SCC_ID register
8
which the board code already passes us.
9
10
For the AN524, the differences are:
11
* CFG3 is reserved rather than being board switches
12
* CFG5 is a new register ("ACLK Frequency in Hz")
13
* CFG6 is a new register ("Clock divider for BRAM")
14
15
We implement both of the new registers as reads-as-written.
4
16
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-17-peter.maydell@linaro.org
19
Message-id: 20210215115138.20465-11-peter.maydell@linaro.org
8
---
20
---
9
target/arm/neon-dp.decode | 6 +++
21
include/hw/misc/mps2-scc.h | 3 ++
10
target/arm/translate-neon.inc.c | 70 +++++++++++++++++++++++++++++++++
22
hw/misc/mps2-scc.c | 71 ++++++++++++++++++++++++++++++++++++--
11
target/arm/translate.c | 42 +-------------------
23
2 files changed, 72 insertions(+), 2 deletions(-)
12
3 files changed, 78 insertions(+), 40 deletions(-)
13
24
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
15
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
27
--- a/include/hw/misc/mps2-scc.h
17
+++ b/target/arm/neon-dp.decode
28
+++ b/include/hw/misc/mps2-scc.h
18
@@ -XXX,XX +XXX,XX @@ VCGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
29
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
19
VACGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 1 .... @3same_fp
30
20
VCGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 0 .... @3same_fp
31
uint32_t cfg0;
21
VACGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 1 .... @3same_fp
32
uint32_t cfg1;
22
+VMAX_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 0 .... @3same_fp
33
+ uint32_t cfg2;
23
+VMIN_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 0 .... @3same_fp
34
uint32_t cfg4;
24
VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
35
+ uint32_t cfg5;
25
VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
36
+ uint32_t cfg6;
26
+VRECPS_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
37
uint32_t cfgdata_rtn;
27
+VRSQRTS_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
38
uint32_t cfgdata_out;
28
+VMAXNM_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
39
uint32_t cfgctrl;
29
+VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
40
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
30
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
31
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-neon.inc.c
42
--- a/hw/misc/mps2-scc.c
33
+++ b/target/arm/translate-neon.inc.c
43
+++ b/hw/misc/mps2-scc.c
34
@@ -XXX,XX +XXX,XX @@ DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false)
44
@@ -XXX,XX +XXX,XX @@
35
DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false)
45
36
DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
46
REG32(CFG0, 0)
37
DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
47
REG32(CFG1, 4)
38
+DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
48
+REG32(CFG2, 8)
39
+DO_3S_FP(VMIN, gen_helper_vfp_mins, false)
49
REG32(CFG3, 0xc)
40
50
REG32(CFG4, 0x10)
41
static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
51
+REG32(CFG5, 0x14)
42
TCGv_ptr fpstatus)
52
+REG32(CFG6, 0x18)
43
@@ -XXX,XX +XXX,XX @@ static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
53
REG32(CFGDATA_RTN, 0xa0)
44
DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
54
REG32(CFGDATA_OUT, 0xa4)
45
DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
55
REG32(CFGCTRL, 0xa8)
46
56
@@ -XXX,XX +XXX,XX @@ REG32(DLL, 0x100)
47
+static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
57
REG32(AID, 0xFF8)
58
REG32(ID, 0xFFC)
59
60
+static int scc_partno(MPS2SCC *s)
48
+{
61
+{
49
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
62
+ /* Return the partno field of the SCC_ID (0x524, 0x511, etc) */
50
+ return false;
63
+ return extract32(s->id, 4, 8);
51
+ }
52
+
53
+ if (a->size != 0) {
54
+ /* TODO fp16 support */
55
+ return false;
56
+ }
57
+
58
+ return do_3same_fp(s, a, gen_helper_vfp_maxnums, false);
59
+}
64
+}
60
+
65
+
61
+static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
66
/* Handle a write via the SYS_CFG channel to the specified function/device.
62
+{
67
* Return false on error (reported to guest via SYS_CFGCTRL ERROR bit).
63
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
68
*/
64
+ return false;
69
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
65
+ }
70
case A_CFG1:
66
+
71
r = s->cfg1;
67
+ if (a->size != 0) {
72
break;
68
+ /* TODO fp16 support */
73
+ case A_CFG2:
69
+ return false;
74
+ if (scc_partno(s) != 0x524) {
70
+ }
75
+ /* CFG2 reserved on other boards */
71
+
76
+ goto bad_offset;
72
+ return do_3same_fp(s, a, gen_helper_vfp_minnums, false);
77
+ }
73
+}
78
+ r = s->cfg2;
74
+
79
+ break;
75
+WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32)
80
case A_CFG3:
76
+
81
+ if (scc_partno(s) == 0x524) {
77
+static void gen_VRECPS_fp_3s(unsigned vece, uint32_t rd_ofs,
82
+ /* CFG3 reserved on AN524 */
78
+ uint32_t rn_ofs, uint32_t rm_ofs,
83
+ goto bad_offset;
79
+ uint32_t oprsz, uint32_t maxsz)
84
+ }
80
+{
85
/* These are user-settable DIP switches on the board. We don't
81
+ static const GVecGen3 ops = { .fni4 = gen_VRECPS_tramp };
86
* model that, so just return zeroes.
82
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
87
*/
83
+}
88
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
84
+
89
case A_CFG4:
85
+static bool trans_VRECPS_fp_3s(DisasContext *s, arg_3same *a)
90
r = s->cfg4;
86
+{
91
break;
87
+ if (a->size != 0) {
92
+ case A_CFG5:
88
+ /* TODO fp16 support */
93
+ if (scc_partno(s) != 0x524) {
89
+ return false;
94
+ /* CFG5 reserved on other boards */
90
+ }
95
+ goto bad_offset;
91
+
96
+ }
92
+ return do_3same(s, a, gen_VRECPS_fp_3s);
97
+ r = s->cfg5;
93
+}
98
+ break;
94
+
99
+ case A_CFG6:
95
+WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32)
100
+ if (scc_partno(s) != 0x524) {
96
+
101
+ /* CFG6 reserved on other boards */
97
+static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs,
102
+ goto bad_offset;
98
+ uint32_t rn_ofs, uint32_t rm_ofs,
103
+ }
99
+ uint32_t oprsz, uint32_t maxsz)
104
+ r = s->cfg6;
100
+{
105
+ break;
101
+ static const GVecGen3 ops = { .fni4 = gen_VRSQRTS_tramp };
106
case A_CFGDATA_RTN:
102
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
107
r = s->cfgdata_rtn;
103
+}
108
break;
104
+
109
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
105
+static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
110
r = s->id;
106
+{
111
break;
107
+ if (a->size != 0) {
112
default:
108
+ /* TODO fp16 support */
113
+ bad_offset:
109
+ return false;
114
qemu_log_mask(LOG_GUEST_ERROR,
110
+ }
115
"MPS2 SCC read: bad offset %x\n", (int) offset);
111
+
116
r = 0;
112
+ return do_3same(s, a, gen_VRSQRTS_fp_3s);
117
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
113
+}
118
led_set_state(s->led[i], extract32(value, i, 1));
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
}
119
}
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
120
break;
132
return 1;
121
+ case A_CFG2:
133
}
122
+ if (scc_partno(s) != 0x524) {
134
switch (op) {
123
+ /* CFG2 reserved on other boards */
135
- case NEON_3R_FLOAT_MINMAX:
124
+ goto bad_offset;
136
- if (u) {
125
+ }
137
- return 1; /* VPMIN/VPMAX handled by decodetree */
126
+ /* AN524: QSPI Select signal */
138
- }
127
+ s->cfg2 = value;
139
- break;
128
+ break;
140
- case NEON_3R_FLOAT_MISC:
129
+ case A_CFG5:
141
- /* VMAXNM/VMINNM in ARMv8 */
130
+ if (scc_partno(s) != 0x524) {
142
- if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
131
+ /* CFG5 reserved on other boards */
143
- return 1;
132
+ goto bad_offset;
144
- }
133
+ }
145
- break;
134
+ /* AN524: ACLK frequency in Hz */
146
case NEON_3R_VFM_VQRDMLSH:
135
+ s->cfg5 = value;
147
if (!dc_isar_feature(aa32_simdfmac, s)) {
136
+ break;
148
return 1;
137
+ case A_CFG6:
149
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
138
+ if (scc_partno(s) != 0x524) {
150
tmp = neon_load_reg(rn, pass);
139
+ /* CFG6 reserved on other boards */
151
tmp2 = neon_load_reg(rm, pass);
140
+ goto bad_offset;
152
switch (op) {
141
+ }
153
- case NEON_3R_FLOAT_MINMAX:
142
+ /* AN524: Clock divider for BRAM */
154
- {
143
+ s->cfg6 = value;
155
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
144
+ break;
156
- if (size == 0) {
145
case A_CFGDATA_OUT:
157
- gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
146
s->cfgdata_out = value;
158
- } else {
147
break;
159
- gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
148
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
160
- }
149
s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8));
161
- tcg_temp_free_ptr(fpstatus);
150
break;
162
- break;
151
default:
163
- }
152
+ bad_offset:
164
- case NEON_3R_FLOAT_MISC:
153
qemu_log_mask(LOG_GUEST_ERROR,
165
- if (u) {
154
"MPS2 SCC write: bad offset 0x%x\n", (int) offset);
166
- /* VMAXNM/VMINNM */
155
break;
167
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
156
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
168
- if (size == 0) {
157
trace_mps2_scc_reset();
169
- gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
158
s->cfg0 = 0;
170
- } else {
159
s->cfg1 = 0;
171
- gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
160
+ s->cfg2 = 0;
172
- }
161
+ s->cfg5 = 0;
173
- tcg_temp_free_ptr(fpstatus);
162
+ s->cfg6 = 0;
174
- } else {
163
s->cfgdata_rtn = 0;
175
- if (size == 0) {
164
s->cfgdata_out = 0;
176
- gen_helper_recps_f32(tmp, cpu_env, tmp, tmp2);
165
s->cfgctrl = 0x100000;
177
- } else {
166
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
178
- gen_helper_rsqrts_f32(tmp, cpu_env, tmp, tmp2);
167
179
- }
168
static const VMStateDescription mps2_scc_vmstate = {
180
- }
169
.name = "mps2-scc",
181
- break;
170
- .version_id = 2,
182
case NEON_3R_VFM_VQRDMLSH:
171
- .minimum_version_id = 2,
183
{
172
+ .version_id = 3,
184
/* VFMA, VFMS: fused multiply-add */
173
+ .minimum_version_id = 3,
174
.fields = (VMStateField[]) {
175
VMSTATE_UINT32(cfg0, MPS2SCC),
176
VMSTATE_UINT32(cfg1, MPS2SCC),
177
+ VMSTATE_UINT32(cfg2, MPS2SCC),
178
+ /* cfg3, cfg4 are read-only so need not be migrated */
179
+ VMSTATE_UINT32(cfg5, MPS2SCC),
180
+ VMSTATE_UINT32(cfg6, MPS2SCC),
181
VMSTATE_UINT32(cfgdata_rtn, MPS2SCC),
182
VMSTATE_UINT32(cfgdata_out, MPS2SCC),
183
VMSTATE_UINT32(cfgctrl, MPS2SCC),
185
--
184
--
186
2.20.1
185
2.20.1
187
186
188
187
diff view generated by jsdifflib
1
Convert the Neon float VPMIN, VPMAX and VPADD 3-reg-same insns to
1
On the MPS2 boards, the first 32 interrupt lines are entirely
2
decodetree. These are the only remaining 'pairwise' operations,
2
internal to the SSE; interrupt lines for devices outside the SSE
3
so we can delete the pairwise-specific bits of the old decoder's
3
start at 32. In the application notes that document each FPGA image,
4
for-each-element loop now.
4
the interrupt wiring is documented from the point of view of the CPU,
5
so '0' is the first of the SSE's interrupts and the devices in the
6
FPGA image itself are '32' and up: so the UART 0 Receive interrupt is
7
32, the SPI #0 interrupt is 51, and so on.
8
9
Within our implementation, because the external interrupts must be
10
connected to the EXP_IRQ[0...n] lines of the SSE object, we made the
11
get_sse_irq_in() function take an irqno whose values start at 0 for
12
the first FPGA device interrupt. In this numbering scheme the UART 0
13
Receive interrupt is 0, the SPI #0 interrupt is 19, and so on.
14
15
The result of these two different numbering schemes has been that
16
half of the devices were wired up to the wrong IRQs: the UART IRQs
17
are wired up correctly, but the DMA and SPI devices were passing
18
start-at-32 values to get_sse_irq_in() and so being mis-connected.
19
20
Fix the bug by making get_sse_irq_in() take values specified with the
21
same scheme that the hardware manuals use, to avoid confusion.
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
Message-id: 20210215115138.20465-12-peter.maydell@linaro.org
9
---
26
---
10
target/arm/neon-dp.decode | 5 +++
27
hw/arm/mps2-tz.c | 24 +++++++++++++++++-------
11
target/arm/translate-neon.inc.c | 63 +++++++++++++++++++++++++++++++++
28
1 file changed, 17 insertions(+), 7 deletions(-)
12
target/arm/translate.c | 63 +++++----------------------------
13
3 files changed, 76 insertions(+), 55 deletions(-)
14
29
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
30
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
32
--- a/hw/arm/mps2-tz.c
18
+++ b/target/arm/neon-dp.decode
33
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
20
# For FP insns the high bit of 'size' is used as part of opcode decode
35
21
@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
36
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
22
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
37
{
23
+@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \
38
- /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
24
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
39
+ /*
25
40
+ * Return a qemu_irq which will signal IRQ n to all CPUs in the
26
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
41
+ * SSE. The irqno should be as the CPU sees it, so the first
27
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
42
+ * external-to-the-SSE interrupt is 32.
28
@@ -XXX,XX +XXX,XX @@ VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
43
+ */
29
44
MachineClass *mc = MACHINE_GET_CLASS(mms);
30
VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
45
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
31
VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
46
32
+VPADD_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 0 .... @3same_fp_q0
47
- assert(irqno < mmc->numirq);
33
VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
48
+ assert(irqno >= 32 && irqno < (mmc->numirq + 32));
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
+
49
+
67
+ /*
50
+ /*
68
+ * Note that we have to be careful not to clobber the source operands
51
+ * Convert from "CPU irq number" (as listed in the FPGA image
69
+ * in the "vm == vd" case by storing the result of the first pass too
52
+ * documentation) to the SSE external-interrupt number.
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
+ */
53
+ */
73
+ fpstatus = get_fpstatus_ptr(1);
54
+ irqno -= 32;
74
+ tmp = neon_load_reg(a->vn, 0);
55
75
+ tmp2 = neon_load_reg(a->vn, 1);
56
if (mc->max_cpus > 1) {
76
+ fn(tmp, tmp, tmp2, fpstatus);
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
77
+ tcg_temp_free_i32(tmp2);
58
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
78
+
59
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
79
+ tmp3 = neon_load_reg(a->vm, 0);
60
CMSDKAPBUART *uart = opaque;
80
+ tmp2 = neon_load_reg(a->vm, 1);
61
int i = uart - &mms->uart[0];
81
+ fn(tmp3, tmp3, tmp2, fpstatus);
62
- int rxirqno = i * 2;
82
+ tcg_temp_free_i32(tmp2);
63
- int txirqno = i * 2 + 1;
83
+ tcg_temp_free_ptr(fpstatus);
64
- int combirqno = i + 10;
84
+
65
+ int rxirqno = i * 2 + 32;
85
+ neon_store_reg(a->vd, 0, tmp);
66
+ int txirqno = i * 2 + 33;
86
+ neon_store_reg(a->vd, 1, tmp3);
67
+ int combirqno = i + 42;
87
+ return true;
68
SysBusDevice *s;
88
+}
69
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
89
+
70
90
+/*
71
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
91
+ * For all the functions using this macro, size == 1 means fp16,
72
92
+ * which is an architecture extension we don't implement yet.
73
s = SYS_BUS_DEVICE(mms->lan9118);
93
+ */
74
sysbus_realize_and_unref(s, &error_fatal);
94
+#define DO_3S_FP_PAIR(INSN,FUNC) \
75
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16));
95
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
76
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
96
+ { \
77
return sysbus_mmio_get_region(s, 0);
97
+ if (a->size != 0) { \
78
}
98
+ /* TODO fp16 support */ \
79
99
+ return false; \
80
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
100
+ } \
81
&error_fatal);
101
+ return do_3same_fp_pair(s, a, FUNC); \
82
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
102
+ }
83
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
103
+
84
- get_sse_irq_in(mms, 15));
104
+DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds)
85
+ get_sse_irq_in(mms, 47));
105
+DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs)
86
106
+DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins)
87
/* Most of the devices in the FPGA are behind Peripheral Protection
107
diff --git a/target/arm/translate.c b/target/arm/translate.c
88
* Controllers. The required order for initializing things is:
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
- }
155
-
156
for (pass = 0; pass < (q ? 4 : 2); pass++) {
157
158
- if (pairwise) {
159
- /* Pairwise. */
160
- if (pass < 1) {
161
- tmp = neon_load_reg(rn, 0);
162
- tmp2 = neon_load_reg(rn, 1);
163
- } else {
164
- tmp = neon_load_reg(rm, 0);
165
- tmp2 = neon_load_reg(rm, 1);
166
- }
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
--
89
--
217
2.20.1
90
2.20.1
218
91
219
92
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The mps2-tz code uses PPCPortInfo data structures to define what
2
devices are present and how they are wired up. Currently we use
3
these to specify device types and addresses, but hard-code the
4
interrupt line wiring in each make_* helper function. This works for
5
the two boards we have at the moment, but the AN524 has some devices
6
with different interrupt assignments.
2
7
3
Pass a pointer directly to env->vfp.qc[0], rather than env.
8
This commit adds the framework to allow PPCPortInfo structures to
4
This will allow SVE2, which does not modify QC, to pass a
9
specify interrupt numbers. We add an array of interrupt numbers to
5
pointer to dummy storage.
10
the PPCPortInfo struct, and pass it through to the make_* helpers.
11
The following commit will change the make_* helpers over to using the
12
framework.
6
13
7
Change the return type of inl_qrdml.h_s16 to match the
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
sense of the operation: signed.
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210215115138.20465-13-peter.maydell@linaro.org
17
---
18
hw/arm/mps2-tz.c | 36 ++++++++++++++++++++++++------------
19
1 file changed, 24 insertions(+), 12 deletions(-)
9
20
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200513163245.17915-14-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
target/arm/translate.c | 18 ++++++++---
16
target/arm/vec_helper.c | 70 +++++++++++++++++++++++------------------
17
2 files changed, 54 insertions(+), 34 deletions(-)
18
19
diff --git a/target/arm/translate.c b/target/arm/translate.c
20
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate.c
23
--- a/hw/arm/mps2-tz.c
22
+++ b/target/arm/translate.c
24
+++ b/hw/arm/mps2-tz.c
23
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
25
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
24
[NEON_2RM_VCVT_UF] = 0x4,
26
* needs to be plugged into the downstream end of the PPC port.
25
};
27
*/
26
28
typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
27
+static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
29
- const char *name, hwaddr size);
28
+ uint32_t opr_sz, uint32_t max_sz,
30
+ const char *name, hwaddr size,
29
+ gen_helper_gvec_3_ptr *fn)
31
+ const int *irqs);
30
+{
32
31
+ TCGv_ptr qc_ptr = tcg_temp_new_ptr();
33
typedef struct PPCPortInfo {
32
+
34
const char *name;
33
+ tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc));
35
@@ -XXX,XX +XXX,XX @@ typedef struct PPCPortInfo {
34
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr,
36
void *opaque;
35
+ opr_sz, max_sz, 0, fn);
37
hwaddr addr;
36
+ tcg_temp_free_ptr(qc_ptr);
38
hwaddr size;
37
+}
39
+ int irqs[3]; /* currently no device needs more IRQ lines than this */
38
+
40
} PPCPortInfo;
39
void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
41
40
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
42
typedef struct PPCInfo {
43
@@ -XXX,XX +XXX,XX @@ typedef struct PPCInfo {
44
} PPCInfo;
45
46
static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
47
- void *opaque,
48
- const char *name, hwaddr size)
49
+ void *opaque,
50
+ const char *name, hwaddr size,
51
+ const int *irqs)
41
{
52
{
42
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
53
/* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
43
gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
54
* and return a pointer to its MemoryRegion.
44
};
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
45
tcg_debug_assert(vece >= 1 && vece <= 2);
46
- tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
47
- opr_sz, max_sz, 0, fns[vece - 1]);
48
+ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
49
}
56
}
50
57
51
void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
58
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
52
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
59
- const char *name, hwaddr size)
53
gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
60
+ const char *name, hwaddr size,
54
};
61
+ const int *irqs)
55
tcg_debug_assert(vece >= 1 && vece <= 2);
62
{
56
- tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
63
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
57
- opr_sz, max_sz, 0, fns[vece - 1]);
64
CMSDKAPBUART *uart = opaque;
58
+ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
65
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
59
}
66
}
60
67
61
#define GEN_CMP0(NAME, COND) \
68
static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
62
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
69
- const char *name, hwaddr size)
63
index XXXXXXX..XXXXXXX 100644
70
+ const char *name, hwaddr size,
64
--- a/target/arm/vec_helper.c
71
+ const int *irqs)
65
+++ b/target/arm/vec_helper.c
66
@@ -XXX,XX +XXX,XX @@
67
#define H4(x) (x)
68
#endif
69
70
-#define SET_QC() env->vfp.qc[0] = 1
71
-
72
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
73
{
72
{
74
uint64_t *d = vd + opr_sz;
73
MPS2SCC *scc = opaque;
75
@@ -XXX,XX +XXX,XX @@ static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
74
DeviceState *sccdev;
75
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
76
}
76
}
77
77
78
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
78
static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
79
-static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
79
- const char *name, hwaddr size)
80
- int16_t src2, int16_t src3)
80
+ const char *name, hwaddr size,
81
+static int16_t inl_qrdmlah_s16(int16_t src1, int16_t src2,
81
+ const int *irqs)
82
+ int16_t src3, uint32_t *sat)
83
{
82
{
84
/* Simplify:
83
MPS2FPGAIO *fpgaio = opaque;
85
* = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
84
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
86
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
85
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
87
ret = ((int32_t)src3 << 15) + ret + (1 << 14);
86
}
88
ret >>= 15;
87
89
if (ret != (int16_t)ret) {
88
static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
90
- SET_QC();
89
- const char *name, hwaddr size)
91
+ *sat = 1;
90
+ const char *name, hwaddr size,
92
ret = (ret < 0 ? -0x8000 : 0x7fff);
91
+ const int *irqs)
93
}
94
return ret;
95
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
96
uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
97
uint32_t src2, uint32_t src3)
98
{
92
{
99
- uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
93
SysBusDevice *s;
100
- uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
94
NICInfo *nd = &nd_table[0];
101
+ uint32_t *sat = &env->vfp.qc[0];
95
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
102
+ uint16_t e1 = inl_qrdmlah_s16(src1, src2, src3, sat);
103
+ uint16_t e2 = inl_qrdmlah_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat);
104
return deposit32(e1, 16, 16, e2);
105
}
96
}
106
97
107
void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
98
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
108
- void *ve, uint32_t desc)
99
- const char *name, hwaddr size)
109
+ void *vq, uint32_t desc)
100
+ const char *name, hwaddr size,
101
+ const int *irqs)
110
{
102
{
111
uintptr_t opr_sz = simd_oprsz(desc);
103
TZMPC *mpc = opaque;
112
int16_t *d = vd;
104
int i = mpc - &mms->ssram_mpc[0];
113
int16_t *n = vn;
105
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
114
int16_t *m = vm;
115
- CPUARMState *env = ve;
116
uintptr_t i;
117
118
for (i = 0; i < opr_sz / 2; ++i) {
119
- d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
120
+ d[i] = inl_qrdmlah_s16(n[i], m[i], d[i], vq);
121
}
122
clear_tail(d, opr_sz, simd_maxsz(desc));
123
}
106
}
124
107
125
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
108
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
126
-static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
109
- const char *name, hwaddr size)
127
- int16_t src2, int16_t src3)
110
+ const char *name, hwaddr size,
128
+static int16_t inl_qrdmlsh_s16(int16_t src1, int16_t src2,
111
+ const int *irqs)
129
+ int16_t src3, uint32_t *sat)
130
{
112
{
131
/* Similarly, using subtraction:
113
PL080State *dma = opaque;
132
* = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
114
int i = dma - &mms->dma[0];
133
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
115
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
134
ret = ((int32_t)src3 << 15) - ret + (1 << 14);
116
}
135
ret >>= 15;
117
136
if (ret != (int16_t)ret) {
118
static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
137
- SET_QC();
119
- const char *name, hwaddr size)
138
+ *sat = 1;
120
+ const char *name, hwaddr size,
139
ret = (ret < 0 ? -0x8000 : 0x7fff);
121
+ const int *irqs)
140
}
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
143
uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
144
uint32_t src2, uint32_t src3)
145
{
122
{
146
- uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
123
/*
147
- uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
124
* The AN505 has five PL022 SPI controllers.
148
+ uint32_t *sat = &env->vfp.qc[0];
125
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
149
+ uint16_t e1 = inl_qrdmlsh_s16(src1, src2, src3, sat);
150
+ uint16_t e2 = inl_qrdmlsh_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat);
151
return deposit32(e1, 16, 16, e2);
152
}
126
}
153
127
154
void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
128
static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
155
- void *ve, uint32_t desc)
129
- const char *name, hwaddr size)
156
+ void *vq, uint32_t desc)
130
+ const char *name, hwaddr size,
131
+ const int *irqs)
157
{
132
{
158
uintptr_t opr_sz = simd_oprsz(desc);
133
ArmSbconI2CState *i2c = opaque;
159
int16_t *d = vd;
134
SysBusDevice *s;
160
int16_t *n = vn;
135
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
161
int16_t *m = vm;
136
continue;
162
- CPUARMState *env = ve;
137
}
163
uintptr_t i;
138
164
139
- mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
165
for (i = 0; i < opr_sz / 2; ++i) {
140
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size,
166
- d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
141
+ pinfo->irqs);
167
+ d[i] = inl_qrdmlsh_s16(n[i], m[i], d[i], vq);
142
portname = g_strdup_printf("port[%d]", port);
168
}
143
object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
169
clear_tail(d, opr_sz, simd_maxsz(desc));
144
&error_fatal);
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
+
197
void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
198
- void *ve, uint32_t desc)
199
+ void *vq, uint32_t desc)
200
{
201
uintptr_t opr_sz = simd_oprsz(desc);
202
int32_t *d = vd;
203
int32_t *n = vn;
204
int32_t *m = vm;
205
- CPUARMState *env = ve;
206
uintptr_t i;
207
208
for (i = 0; i < opr_sz / 4; ++i) {
209
- d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
210
+ d[i] = inl_qrdmlah_s32(n[i], m[i], d[i], vq);
211
}
212
clear_tail(d, opr_sz, simd_maxsz(desc));
213
}
214
215
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
216
-uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
217
- int32_t src2, int32_t src3)
218
+static int32_t inl_qrdmlsh_s32(int32_t src1, int32_t src2,
219
+ int32_t src3, uint32_t *sat)
220
{
221
/* Simplify similarly to int_qrdmlsh_s16 above. */
222
int64_t ret = (int64_t)src1 * src2;
223
ret = ((int64_t)src3 << 31) - ret + (1 << 30);
224
ret >>= 31;
225
if (ret != (int32_t)ret) {
226
- SET_QC();
227
+ *sat = 1;
228
ret = (ret < 0 ? INT32_MIN : INT32_MAX);
229
}
230
return ret;
231
}
232
233
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
234
+ int32_t src2, int32_t src3)
235
+{
236
+ uint32_t *sat = &env->vfp.qc[0];
237
+ return inl_qrdmlsh_s32(src1, src2, src3, sat);
238
+}
239
+
240
void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
241
- void *ve, uint32_t desc)
242
+ void *vq, uint32_t desc)
243
{
244
uintptr_t opr_sz = simd_oprsz(desc);
245
int32_t *d = vd;
246
int32_t *n = vn;
247
int32_t *m = vm;
248
- CPUARMState *env = ve;
249
uintptr_t i;
250
251
for (i = 0; i < opr_sz / 4; ++i) {
252
- d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
253
+ d[i] = inl_qrdmlsh_s32(n[i], m[i], d[i], vq);
254
}
255
clear_tail(d, opr_sz, simd_maxsz(desc));
256
}
257
--
145
--
258
2.20.1
146
2.20.1
259
147
260
148
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Move the specification of the IRQ information for the uart, ethernet,
2
dma and spi devices to the data structures. (The other devices
3
handled by the PPCPortInfo structures don't have any interrupt lines
4
we need to wire up.)
2
5
3
Provide a functional interface for the vector expansion.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
This fits better with the existing set of helpers that
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
we provide for other operations.
8
Message-id: 20210215115138.20465-14-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 52 +++++++++++++++++++++++-------------------------
11
1 file changed, 25 insertions(+), 27 deletions(-)
6
12
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-11-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate.h | 13 +-
13
target/arm/translate-a64.c | 22 ++-
14
target/arm/translate-neon.inc.c | 19 +--
15
target/arm/translate.c | 228 +++++++++++++++++---------------
16
4 files changed, 147 insertions(+), 135 deletions(-)
17
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate.h
15
--- a/hw/arm/mps2-tz.c
21
+++ b/target/arm/translate.h
16
+++ b/hw/arm/mps2-tz.c
22
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
17
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
23
void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
18
const char *name, hwaddr size,
24
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
19
const int *irqs)
25
26
-extern const GVecGen4 uqadd_op[4];
27
-extern const GVecGen4 sqadd_op[4];
28
-extern const GVecGen4 uqsub_op[4];
29
-extern const GVecGen4 sqsub_op[4];
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
+
45
void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
46
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
47
void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
48
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
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
{
20
{
120
diff --git a/target/arm/translate.c b/target/arm/translate.c
21
+ /* The irq[] array is tx, rx, combined, in that order */
121
index XXXXXXX..XXXXXXX 100644
22
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
122
--- a/target/arm/translate.c
23
CMSDKAPBUART *uart = opaque;
123
+++ b/target/arm/translate.c
24
int i = uart - &mms->uart[0];
124
@@ -XXX,XX +XXX,XX @@ static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
25
- int rxirqno = i * 2 + 32;
125
tcg_temp_free_vec(x);
26
- int txirqno = i * 2 + 33;
27
- int combirqno = i + 42;
28
SysBusDevice *s;
29
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
30
31
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
32
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
33
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
34
s = SYS_BUS_DEVICE(uart);
35
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
36
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno));
37
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
38
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
39
sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
40
sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
41
- sysbus_connect_irq(s, 4, get_sse_irq_in(mms, combirqno));
42
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqs[2]));
43
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
126
}
44
}
127
45
128
-static const TCGOpcode vecop_list_uqadd[] = {
46
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
129
- INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
47
130
-};
48
s = SYS_BUS_DEVICE(mms->lan9118);
131
-
49
sysbus_realize_and_unref(s, &error_fatal);
132
-const GVecGen4 uqadd_op[4] = {
50
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
133
- { .fniv = gen_uqadd_vec,
51
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
134
- .fno = gen_helper_gvec_uqadd_b,
52
return sysbus_mmio_get_region(s, 0);
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
}
53
}
191
54
192
-static const TCGOpcode vecop_list_sqadd[] = {
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
193
- INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
56
const char *name, hwaddr size,
194
-};
57
const int *irqs)
195
-
58
{
196
-const GVecGen4 sqadd_op[4] = {
59
+ /* The irq[] array is DMACINTR, DMACINTERR, DMACINTTC, in that order */
197
- { .fniv = gen_sqadd_vec,
60
PL080State *dma = opaque;
198
- .fno = gen_helper_gvec_sqadd_b,
61
int i = dma - &mms->dma[0];
199
- .opt_opc = vecop_list_sqadd,
62
SysBusDevice *s;
200
- .write_aofs = true,
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
201
- .vece = MO_8 },
64
202
- { .fniv = gen_sqadd_vec,
65
s = SYS_BUS_DEVICE(dma);
203
- .fno = gen_helper_gvec_sqadd_h,
66
/* Wire up DMACINTR, DMACINTERR, DMACINTTC */
204
- .opt_opc = vecop_list_sqadd,
67
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3));
205
- .write_aofs = true,
68
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3));
206
- .vece = MO_16 },
69
- sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3));
207
- { .fniv = gen_sqadd_vec,
70
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
208
- .fno = gen_helper_gvec_sqadd_s,
71
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
209
- .opt_opc = vecop_list_sqadd,
72
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqs[2]));
210
- .write_aofs = true,
73
211
- .vece = MO_32 },
74
g_free(mscname);
212
- { .fniv = gen_sqadd_vec,
75
return sysbus_mmio_get_region(s, 0);
213
- .fno = gen_helper_gvec_sqadd_d,
76
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
214
- .opt_opc = vecop_list_sqadd,
77
* lines are set via the "MISC" register in the MPS2 FPGAIO device.
215
- .write_aofs = true,
78
*/
216
- .vece = MO_64 },
79
PL022State *spi = opaque;
217
-};
80
- int i = spi - &mms->spi[0];
218
+void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
81
SysBusDevice *s;
219
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
82
220
+{
83
object_initialize_child(OBJECT(mms), name, spi, TYPE_PL022);
221
+ static const TCGOpcode vecop_list[] = {
84
sysbus_realize(SYS_BUS_DEVICE(spi), &error_fatal);
222
+ INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
85
s = SYS_BUS_DEVICE(spi);
223
+ };
86
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i));
224
+ static const GVecGen4 ops[4] = {
87
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
225
+ { .fniv = gen_sqadd_vec,
88
return sysbus_mmio_get_region(s, 0);
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
}
89
}
255
90
256
-static const TCGOpcode vecop_list_uqsub[] = {
91
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
257
- INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
92
}, {
258
-};
93
.name = "apb_ppcexp1",
259
-
94
.ports = {
260
-const GVecGen4 uqsub_op[4] = {
95
- { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000 },
261
- { .fniv = gen_uqsub_vec,
96
- { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000 },
262
- .fno = gen_helper_gvec_uqsub_b,
97
- { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000 },
263
- .opt_opc = vecop_list_uqsub,
98
- { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000 },
264
- .write_aofs = true,
99
- { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000 },
265
- .vece = MO_8 },
100
- { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
266
- { .fniv = gen_uqsub_vec,
101
- { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
267
- .fno = gen_helper_gvec_uqsub_h,
102
- { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
268
- .opt_opc = vecop_list_uqsub,
103
- { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
269
- .write_aofs = true,
104
- { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
270
- .vece = MO_16 },
105
+ { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000, { 51 } },
271
- { .fniv = gen_uqsub_vec,
106
+ { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000, { 52 } },
272
- .fno = gen_helper_gvec_uqsub_s,
107
+ { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000, { 53 } },
273
- .opt_opc = vecop_list_uqsub,
108
+ { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000, { 54 } },
274
- .write_aofs = true,
109
+ { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000, { 55 } },
275
- .vece = MO_32 },
110
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000, { 32, 33, 42 } },
276
- { .fniv = gen_uqsub_vec,
111
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000, { 34, 35, 43 } },
277
- .fno = gen_helper_gvec_uqsub_d,
112
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000, { 36, 37, 44 } },
278
- .opt_opc = vecop_list_uqsub,
113
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000, { 38, 39, 45 } },
279
- .write_aofs = true,
114
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000, { 40, 41, 46 } },
280
- .vece = MO_64 },
115
{ "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
281
-};
116
{ "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
282
+void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
117
{ "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
283
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
118
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
284
+{
119
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
285
+ static const TCGOpcode vecop_list[] = {
120
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
286
+ INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
121
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
287
+ };
122
- { "eth", make_eth_dev, NULL, 0x42000000, 0x100000 },
288
+ static const GVecGen4 ops[4] = {
123
+ { "eth", make_eth_dev, NULL, 0x42000000, 0x100000, { 48 } },
289
+ { .fniv = gen_uqsub_vec,
124
},
290
+ .fno = gen_helper_gvec_uqsub_b,
125
}, {
291
+ .opt_opc = vecop_list,
126
.name = "ahb_ppcexp1",
292
+ .write_aofs = true,
127
.ports = {
293
+ .vece = MO_8 },
128
- { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000 },
294
+ { .fniv = gen_uqsub_vec,
129
- { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000 },
295
+ .fno = gen_helper_gvec_uqsub_h,
130
- { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000 },
296
+ .opt_opc = vecop_list,
131
- { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000 },
297
+ .write_aofs = true,
132
+ { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000, { 58, 56, 57 } },
298
+ .vece = MO_16 },
133
+ { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000, { 61, 59, 60 } },
299
+ { .fniv = gen_uqsub_vec,
134
+ { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000, { 64, 62, 63 } },
300
+ .fno = gen_helper_gvec_uqsub_s,
135
+ { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000, { 67, 65, 66 } },
301
+ .opt_opc = vecop_list,
136
},
302
+ .write_aofs = true,
137
},
303
+ .vece = MO_32 },
138
};
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
--
139
--
381
2.20.1
140
2.20.1
382
141
383
142
diff view generated by jsdifflib
1
Convert the Neon VABA and VABD insns in the 3-reg-same group to
1
We create an OR gate to wire together the overflow IRQs for all the
2
decodetree.
2
UARTs on the board; this has to have twice the number of inputs as
3
there are UARTs, since each UART feeds it a TX overflow and an RX
4
overflow interrupt line. Replace the hardcoded '10' with a
5
calculation based on the size of the uart[] array in the
6
MPS2TZMachineState. (We rely on OR gate inputs that are never wired
7
up or asserted being treated as always-zero.)
3
8
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200512163904.10918-6-peter.maydell@linaro.org
11
Message-id: 20210215115138.20465-15-peter.maydell@linaro.org
7
---
12
---
8
target/arm/neon-dp.decode | 6 ++++++
13
hw/arm/mps2-tz.c | 11 ++++++++---
9
target/arm/translate-neon.inc.c | 4 ++++
14
1 file changed, 8 insertions(+), 3 deletions(-)
10
target/arm/translate.c | 22 ++--------------------
11
3 files changed, 12 insertions(+), 20 deletions(-)
12
15
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
18
--- a/hw/arm/mps2-tz.c
16
+++ b/target/arm/neon-dp.decode
19
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@ VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
20
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
18
VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
21
*/
19
VMIN_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 1 .... @3same
22
memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
20
23
21
+VABD_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 0 .... @3same
24
- /* The overflow IRQs for all UARTs are ORed together.
22
+VABD_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 0 .... @3same
25
+ /*
23
+
26
+ * The overflow IRQs for all UARTs are ORed together.
24
+VABA_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 1 .... @3same
27
* Tx, Rx and "combined" IRQs are sent to the NVIC separately.
25
+VABA_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 1 .... @3same
28
- * Create the OR gate for this.
26
+
29
+ * Create the OR gate for this: it has one input for the TX overflow
27
VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same
30
+ * and one for the RX overflow for each UART we might have.
28
VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
31
+ * (If the board has fewer than the maximum possible number of UARTs
29
32
+ * those inputs are never wired up and are treated as always-zero.)
30
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
*/
31
index XXXXXXX..XXXXXXX 100644
34
object_initialize_child(OBJECT(mms), "uart-irq-orgate",
32
--- a/target/arm/translate-neon.inc.c
35
&mms->uart_irq_orgate, TYPE_OR_IRQ);
33
+++ b/target/arm/translate-neon.inc.c
36
- object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines", 10,
34
@@ -XXX,XX +XXX,XX @@ DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
37
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines",
35
DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla)
38
+ 2 * ARRAY_SIZE(mms->uart),
36
DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls)
39
&error_fatal);
37
DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst)
40
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
38
+DO_3SAME_NO_SZ_3(VABD_S, gen_gvec_sabd)
41
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
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
--
42
--
86
2.20.1
43
2.20.1
87
44
88
45
diff view generated by jsdifflib
1
Convert the Neon VQRDMLAH and VQRDMLSH insns in the 3-reg-same group
1
The AN505 and AN521 have the same device layout, but the AN524 is
2
to decodetree. These don't use do_3same() because they want to
2
somewhat different. Allow for more than one PPCInfo array, which can
3
operate on VFP double registers, whose offsets are different from the
3
be selected based on the board type.
4
neon_reg_offset() calculations do_3same does.
5
4
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200512163904.10918-2-peter.maydell@linaro.org
7
Message-id: 20210215115138.20465-16-peter.maydell@linaro.org
9
---
8
---
10
target/arm/neon-dp.decode | 3 +++
9
hw/arm/mps2-tz.c | 16 ++++++++++++++--
11
target/arm/translate-neon.inc.c | 15 +++++++++++++++
10
1 file changed, 14 insertions(+), 2 deletions(-)
12
target/arm/translate.c | 14 ++------------
13
3 files changed, 20 insertions(+), 12 deletions(-)
14
11
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
14
--- a/hw/arm/mps2-tz.c
18
+++ b/target/arm/neon-dp.decode
15
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@ VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same
16
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
20
17
MemoryRegion *system_memory = get_system_memory();
21
VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
18
DeviceState *iotkitdev;
22
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
19
DeviceState *dev_splitter;
23
+
20
+ const PPCInfo *ppcs;
24
+VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
21
+ int num_ppcs;
25
+VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
22
int i;
26
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
23
27
index XXXXXXX..XXXXXXX 100644
24
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
28
--- a/target/arm/translate-neon.inc.c
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
29
+++ b/target/arm/translate-neon.inc.c
26
* + wire up the PPC's control lines to the IoTKit object
30
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
27
*/
31
}
28
32
return do_3same(s, a, gen_VMUL_p_3s);
29
- const PPCInfo ppcs[] = { {
33
}
30
+ const PPCInfo an505_ppcs[] = { {
34
+
31
.name = "apb_ppcexp0",
35
+#define DO_VQRDMLAH(INSN, FUNC) \
32
.ports = {
36
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
33
{ "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
37
+ { \
34
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
38
+ if (!dc_isar_feature(aa32_rdm, s)) { \
35
},
39
+ return false; \
36
};
40
+ } \
37
41
+ if (a->size != 1 && a->size != 2) { \
38
- for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
42
+ return false; \
39
+ switch (mmc->fpga_type) {
43
+ } \
40
+ case FPGA_AN505:
44
+ return do_3same(s, a, FUNC); \
41
+ case FPGA_AN521:
42
+ ppcs = an505_ppcs;
43
+ num_ppcs = ARRAY_SIZE(an505_ppcs);
44
+ break;
45
+ default:
46
+ g_assert_not_reached();
45
+ }
47
+ }
46
+
48
+
47
+DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
49
+ for (i = 0; i < num_ppcs; i++) {
48
+DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)
50
const PPCInfo *ppcinfo = &ppcs[i];
49
diff --git a/target/arm/translate.c b/target/arm/translate.c
51
TZPPC *ppc = &mms->ppc[i];
50
index XXXXXXX..XXXXXXX 100644
52
DeviceState *ppcdev;
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
--
53
--
82
2.20.1
54
2.20.1
83
55
84
56
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
The AN505 and AN521 have the same layout of RAM; the AN524 does not.
2
2
Replace the current hard-coding of where the RAM is and which parts
3
kvm_arch_on_sigbus_vcpu() error injection uses source_id as
3
of it are behind which MPCs with a data-driven approach.
4
index in etc/hardware_errors to find out Error Status Data
4
5
Block entry corresponding to error source. So supported source_id
6
values should be assigned here and not be changed afterwards to
7
make sure that guest will write error into expected Error Status
8
Data Block.
9
10
Before QEMU writes a new error to ACPI table, it will check whether
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
15
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
16
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
17
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
18
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
19
Message-id: 20200512030609.19593-9-gengdongjiu@huawei.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-17-peter.maydell@linaro.org
21
---
8
---
22
include/hw/acpi/ghes.h | 1 +
9
hw/arm/mps2-tz.c | 175 +++++++++++++++++++++++++++++++++++++----------
23
hw/acpi/ghes.c | 219 +++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 138 insertions(+), 37 deletions(-)
24
2 files changed, 220 insertions(+)
11
25
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
26
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/acpi/ghes.h
14
--- a/hw/arm/mps2-tz.c
29
+++ b/include/hw/acpi/ghes.h
15
+++ b/hw/arm/mps2-tz.c
30
@@ -XXX,XX +XXX,XX @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
31
void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
32
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
33
GArray *hardware_errors);
34
+int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
35
#endif
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 @@
16
@@ -XXX,XX +XXX,XX @@
41
#include "qemu/error-report.h"
17
#include "qom/object.h"
42
#include "hw/acpi/generic_event_device.h"
18
43
#include "hw/nvram/fw_cfg.h"
19
#define MPS2TZ_NUMIRQ_MAX 92
44
+#include "qemu/uuid.h"
20
+#define MPS2TZ_RAM_MAX 4
45
21
46
#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
22
typedef enum MPS2TZFPGAType {
47
#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
23
FPGA_AN505,
48
@@ -XXX,XX +XXX,XX @@
24
FPGA_AN521,
49
/* Address offset in Generic Address Structure(GAS) */
25
} MPS2TZFPGAType;
50
#define GAS_ADDR_OFFSET 4
51
26
52
+/*
27
+/*
53
+ * The total size of Generic Error Data Entry
28
+ * Define the layout of RAM in a board, including which parts are
54
+ * ACPI 6.1/6.2: 18.3.2.7.1 Generic Error Data,
29
+ * behind which MPCs.
55
+ * Table 18-343 Generic Error Data Entry
30
+ * mrindex specifies the index into mms->ram[] to use for the backing RAM;
31
+ * -1 means "use the system RAM".
56
+ */
32
+ */
57
+#define ACPI_GHES_DATA_LENGTH 72
33
+typedef struct RAMInfo {
58
+
34
+ const char *name;
59
+/* The memory section CPER size, UEFI 2.6: N.2.5 Memory Error Section */
35
+ uint32_t base;
60
+#define ACPI_GHES_MEM_CPER_LENGTH 80
36
+ uint32_t size;
61
+
37
+ int mpc; /* MPC number, -1 for "not behind an MPC" */
62
+/* Masks for block_status flags */
38
+ int mrindex;
63
+#define ACPI_GEBS_UNCORRECTABLE 1
39
+ int flags;
40
+} RAMInfo;
64
+
41
+
65
+/*
42
+/*
66
+ * Total size for Generic Error Status Block except Generic Error Data Entries
43
+ * Flag values:
67
+ * ACPI 6.2: 18.3.2.7.1 Generic Error Data,
44
+ * IS_ALIAS: this RAM area is an alias to the upstream end of the
68
+ * Table 18-380 Generic Error Status Block
45
+ * MPC specified by its .mpc value
69
+ */
46
+ */
70
+#define ACPI_GHES_GESB_SIZE 20
47
+#define IS_ALIAS 1
71
+
48
+
72
+/*
49
struct MPS2TZMachineClass {
73
+ * Values for error_severity field
50
MachineClass parent;
74
+ */
51
MPS2TZFPGAType fpga_type;
75
+enum AcpiGenericErrorSeverity {
52
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
76
+ ACPI_CPER_SEV_RECOVERABLE = 0,
53
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
77
+ ACPI_CPER_SEV_FATAL = 1,
54
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
78
+ ACPI_CPER_SEV_CORRECTED = 2,
55
int numirq; /* Number of external interrupts */
79
+ ACPI_CPER_SEV_NONE = 3,
56
+ const RAMInfo *raminfo;
57
const char *armsse_type;
58
};
59
60
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
61
MachineState parent;
62
63
ARMSSE iotkit;
64
- MemoryRegion ssram[3];
65
- MemoryRegion ssram1_m;
66
+ MemoryRegion ram[MPS2TZ_RAM_MAX];
67
MPS2SCC scc;
68
MPS2FPGAIO fpgaio;
69
TZPPC ppc[5];
70
- TZMPC ssram_mpc[3];
71
+ TZMPC mpc[3];
72
PL022State spi[5];
73
ArmSbconI2CState i2c[4];
74
UnimplementedDeviceState i2s_audio;
75
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
76
25000000,
77
};
78
79
+static const RAMInfo an505_raminfo[] = { {
80
+ .name = "ssram-0",
81
+ .base = 0x00000000,
82
+ .size = 0x00400000,
83
+ .mpc = 0,
84
+ .mrindex = 0,
85
+ }, {
86
+ .name = "ssram-1",
87
+ .base = 0x28000000,
88
+ .size = 0x00200000,
89
+ .mpc = 1,
90
+ .mrindex = 1,
91
+ }, {
92
+ .name = "ssram-2",
93
+ .base = 0x28200000,
94
+ .size = 0x00200000,
95
+ .mpc = 2,
96
+ .mrindex = 2,
97
+ }, {
98
+ .name = "ssram-0-alias",
99
+ .base = 0x00400000,
100
+ .size = 0x00400000,
101
+ .mpc = 0,
102
+ .mrindex = 3,
103
+ .flags = IS_ALIAS,
104
+ }, {
105
+ /* Use the largest bit of contiguous RAM as our "system memory" */
106
+ .name = "mps.ram",
107
+ .base = 0x80000000,
108
+ .size = 16 * MiB,
109
+ .mpc = -1,
110
+ .mrindex = -1,
111
+ }, {
112
+ .name = NULL,
113
+ },
80
+};
114
+};
81
+
115
+
82
/*
116
+static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
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
+{
117
+{
99
+ const uint8_t fru_text[20] = {0};
118
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
100
+
119
+ const RAMInfo *p;
101
+ /* Section Type */
120
+
102
+ g_array_append_vals(table, section_type, 16);
121
+ for (p = mmc->raminfo; p->name; p++) {
103
+
122
+ if (p->mpc == mpc && !(p->flags & IS_ALIAS)) {
104
+ /* Error Severity */
123
+ return p;
105
+ build_append_int_noprefix(table, error_severity, 4);
124
+ }
106
+ /* Revision */
125
+ }
107
+ build_append_int_noprefix(table, 0x300, 2);
126
+ /* if raminfo array doesn't have an entry for each MPC this is a bug */
108
+ /* Validation Bits */
127
+ g_assert_not_reached();
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
+}
128
+}
124
+
129
+
125
+/*
130
+static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
126
+ * Generic Error Status Block
131
+ const RAMInfo *raminfo)
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
+{
132
+{
133
+ /* Block Status */
133
+ /* Return an initialized MemoryRegion for the RAMInfo. */
134
+ build_append_int_noprefix(table, block_status, 4);
134
+ MemoryRegion *ram;
135
+ /* Raw Data Offset */
135
+
136
+ build_append_int_noprefix(table, raw_data_offset, 4);
136
+ if (raminfo->mrindex < 0) {
137
+ /* Raw Data Length */
137
+ /* Means this RAMInfo is for QEMU's "system memory" */
138
+ build_append_int_noprefix(table, raw_data_length, 4);
138
+ MachineState *machine = MACHINE(mms);
139
+ /* Data Length */
139
+ return machine->ram;
140
+ build_append_int_noprefix(table, data_length, 4);
140
+ }
141
+ /* Error Severity */
141
+
142
+ build_append_int_noprefix(table, error_severity, 4);
142
+ assert(raminfo->mrindex < MPS2TZ_RAM_MAX);
143
+ ram = &mms->ram[raminfo->mrindex];
144
+
145
+ memory_region_init_ram(ram, NULL, raminfo->name,
146
+ raminfo->size, &error_fatal);
147
+ return ram;
143
+}
148
+}
144
+
149
+
145
+/* UEFI 2.6: N.2.5 Memory Error Section */
150
/* Create an alias of an entire original MemoryRegion @orig
146
+static void acpi_ghes_build_append_mem_cper(GArray *table,
151
* located at @base in the memory map.
147
+ uint64_t error_physical_addr)
152
*/
153
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
154
const int *irqs)
155
{
156
TZMPC *mpc = opaque;
157
- int i = mpc - &mms->ssram_mpc[0];
158
- MemoryRegion *ssram = &mms->ssram[i];
159
+ int i = mpc - &mms->mpc[0];
160
MemoryRegion *upstream;
161
- char *mpcname = g_strdup_printf("%s-mpc", name);
162
- static uint32_t ramsize[] = { 0x00400000, 0x00200000, 0x00200000 };
163
- static uint32_t rambase[] = { 0x00000000, 0x28000000, 0x28200000 };
164
+ const RAMInfo *raminfo = find_raminfo_for_mpc(mms, i);
165
+ MemoryRegion *ram = mr_for_raminfo(mms, raminfo);
166
167
- memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal);
168
-
169
- object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC);
170
- object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ssram),
171
+ object_initialize_child(OBJECT(mms), name, mpc, TYPE_TZ_MPC);
172
+ object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ram),
173
&error_fatal);
174
sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal);
175
/* Map the upstream end of the MPC into system memory */
176
upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
177
- memory_region_add_subregion(get_system_memory(), rambase[i], upstream);
178
+ memory_region_add_subregion(get_system_memory(), raminfo->base, upstream);
179
/* and connect its interrupt to the IoTKit */
180
qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
181
qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
182
"mpcexp_status", i));
183
184
- /* The first SSRAM is a special case as it has an alias; accesses to
185
- * the alias region at 0x00400000 must also go to the MPC upstream.
186
- */
187
- if (i == 0) {
188
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", upstream, 0x00400000);
189
- }
190
-
191
- g_free(mpcname);
192
/* Return the register interface MR for our caller to map behind the PPC */
193
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
194
}
195
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
196
return sysbus_mmio_get_region(s, 0);
197
}
198
199
+static void create_non_mpc_ram(MPS2TZMachineState *mms)
148
+{
200
+{
149
+ /*
201
+ /*
150
+ * Memory Error Record
202
+ * Handle the RAMs which are either not behind MPCs or which are
203
+ * aliases to another MPC.
151
+ */
204
+ */
152
+
205
+ const RAMInfo *p;
153
+ /* Validation Bits */
206
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
154
+ build_append_int_noprefix(table,
207
+
155
+ (1ULL << 14) | /* Type Valid */
208
+ for (p = mmc->raminfo; p->name; p++) {
156
+ (1ULL << 1) /* Physical Address Valid */,
209
+ if (p->flags & IS_ALIAS) {
157
+ 8);
210
+ SysBusDevice *mpc_sbd = SYS_BUS_DEVICE(&mms->mpc[p->mpc]);
158
+ /* Error Status */
211
+ MemoryRegion *upstream = sysbus_mmio_get_region(mpc_sbd, 1);
159
+ build_append_int_noprefix(table, 0, 8);
212
+ make_ram_alias(&mms->ram[p->mrindex], p->name, upstream, p->base);
160
+ /* Physical Address */
213
+ } else if (p->mpc == -1) {
161
+ build_append_int_noprefix(table, error_physical_addr, 8);
214
+ /* RAM not behind an MPC */
162
+ /* Skip all the detailed information normally found in such a record */
215
+ MemoryRegion *mr = mr_for_raminfo(mms, p);
163
+ build_append_int_noprefix(table, 0, 48);
216
+ memory_region_add_subregion(get_system_memory(), p->base, mr);
164
+ /* Memory Error Type */
217
+ }
165
+ build_append_int_noprefix(table, 0 /* Unknown error */, 1);
218
+ }
166
+ /* Skip all the detailed information normally found in such a record */
167
+ build_append_int_noprefix(table, 0, 7);
168
+}
219
+}
169
+
220
+
170
+static int acpi_ghes_record_mem_error(uint64_t error_block_address,
221
static void mps2tz_common_init(MachineState *machine)
171
+ uint64_t error_physical_addr)
222
{
172
+{
223
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
173
+ GArray *block;
224
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
174
+
225
qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
175
+ /* Memory Error Section Type */
226
qdev_get_gpio_in(dev_splitter, 0));
176
+ const uint8_t uefi_cper_mem_sec[] =
227
177
+ UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
228
- /* The IoTKit sets up much of the memory layout, including
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
+ /*
229
+ /*
192
+ * Check whether it will run out of the preallocated memory if adding a new
230
+ * The IoTKit sets up much of the memory layout, including
193
+ * generic error data entry
231
* the aliases between secure and non-secure regions in the
194
+ */
232
- * address space. The FPGA itself contains:
195
+ if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) {
233
- *
196
+ error_report("Not enough memory to record new CPER!!!");
234
- * 0x00000000..0x003fffff SSRAM1
197
+ g_array_free(block, true);
235
- * 0x00400000..0x007fffff alias of SSRAM1
198
+ return -1;
236
- * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
199
+ }
237
- * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
200
+
238
- * 0x80000000..0x80ffffff 16MB PSRAM
201
+ /* Build the new generic error status block header */
239
- */
202
+ acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
240
-
203
+ 0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE);
241
- /* The FPGA images have an odd combination of different RAMs,
204
+
242
+ * address space, and also most of the devices in the system.
205
+ /* Build this new generic error data entry header */
243
+ * The FPGA itself contains various RAMs and some additional devices.
206
+ acpi_ghes_generic_error_data(block, uefi_cper_mem_sec,
244
+ * The FPGA images have an odd combination of different RAMs,
207
+ ACPI_CPER_SEV_RECOVERABLE, 0, 0,
245
* because in hardware they are different implementations and
208
+ ACPI_GHES_MEM_CPER_LENGTH, fru_id, 0);
246
* connected to different buses, giving varying performance/size
209
+
247
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
210
+ /* Build the memory section CPER for above new generic error data entry */
248
- * call the 16MB our "system memory", as it's the largest lump.
211
+ acpi_ghes_build_append_mem_cper(block, error_physical_addr);
249
+ * call the largest lump our "system memory".
212
+
250
*/
213
+ /* Write the generic error data entry into guest memory */
251
- memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
214
+ cpu_physical_memory_write(error_block_address, block->data, block->len);
252
215
+
253
/*
216
+ g_array_free(block, true);
254
* The overflow IRQs for all UARTs are ORed together.
217
+
255
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
218
+ return 0;
256
const PPCInfo an505_ppcs[] = { {
219
+}
257
.name = "apb_ppcexp0",
220
+
258
.ports = {
221
/*
259
- { "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
222
* Build table for the hardware error fw_cfg blob.
260
- { "ssram-1", make_mpc, &mms->ssram_mpc[1], 0x58008000, 0x1000 },
223
* Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
261
- { "ssram-2", make_mpc, &mms->ssram_mpc[2], 0x58009000, 0x1000 },
224
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
262
+ { "ssram-0-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
225
fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
263
+ { "ssram-1-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
226
NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
264
+ { "ssram-2-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
227
}
265
},
228
+
266
}, {
229
+int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
267
.name = "apb_ppcexp1",
230
+{
268
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
231
+ uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0;
269
232
+ uint64_t start_addr;
270
create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
233
+ bool ret = -1;
271
234
+ AcpiGedState *acpi_ged_state;
272
+ create_non_mpc_ram(mms);
235
+ AcpiGhesState *ags;
273
+
236
+
274
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
237
+ assert(source_id < ACPI_HEST_SRC_ID_RESERVED);
275
}
238
+
276
239
+ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
277
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
240
+ NULL));
278
mmc->fpgaio_num_leds = 2;
241
+ g_assert(acpi_ged_state);
279
mmc->fpgaio_has_switches = false;
242
+ ags = &acpi_ged_state->ghes_state;
280
mmc->numirq = 92;
243
+
281
+ mmc->raminfo = an505_raminfo;
244
+ start_addr = le64_to_cpu(ags->ghes_addr_le);
282
mmc->armsse_type = TYPE_IOTKIT;
245
+
283
}
246
+ if (physical_address) {
284
247
+
285
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
248
+ if (source_id < ACPI_HEST_SRC_ID_RESERVED) {
286
mmc->fpgaio_num_leds = 2;
249
+ start_addr += source_id * sizeof(uint64_t);
287
mmc->fpgaio_has_switches = false;
250
+ }
288
mmc->numirq = 92;
251
+
289
+ mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
252
+ cpu_physical_memory_read(start_addr, &error_block_addr,
290
mmc->armsse_type = TYPE_SSE200;
253
+ sizeof(error_block_addr));
291
}
254
+
292
255
+ error_block_addr = le64_to_cpu(error_block_addr);
256
+
257
+ read_ack_register_addr = start_addr +
258
+ ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
259
+
260
+ cpu_physical_memory_read(read_ack_register_addr,
261
+ &read_ack_register, sizeof(read_ack_register));
262
+
263
+ /* zero means OSPM does not acknowledge the error */
264
+ if (!read_ack_register) {
265
+ error_report("OSPM does not acknowledge previous error,"
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
--
293
--
285
2.20.1
294
2.20.1
286
295
287
296
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
Instead of hardcoding the MachineClass default_ram_size and
2
default_ram_id fields, set them on class creation by finding the
3
entry in the RAMInfo array which is marked as being the QEMU system
4
RAM.
2
5
3
kvm_hwpoison_page_add() and kvm_unpoison_all() will both
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
be used by X86 and ARM platforms, so moving them into
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
"accel/kvm/kvm-all.c" to avoid duplicate code.
8
Message-id: 20210215115138.20465-18-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 24 ++++++++++++++++++++++--
11
1 file changed, 22 insertions(+), 2 deletions(-)
6
12
7
For architectures that don't use the poison-list functionality
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.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
14
index XXXXXXX..XXXXXXX 100644
25
--- a/include/sysemu/kvm_int.h
15
--- a/hw/arm/mps2-tz.c
26
+++ b/include/sysemu/kvm_int.h
16
+++ b/hw/arm/mps2-tz.c
27
@@ -XXX,XX +XXX,XX @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
17
@@ -XXX,XX +XXX,XX @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
28
AddressSpace *as, int as_id);
18
29
19
mc->init = mps2tz_common_init;
30
void kvm_set_max_memslot_size(hwaddr max_slot_size);
20
iic->check = mps2_tz_idau_check;
31
+
21
- mc->default_ram_size = 16 * MiB;
32
+/**
22
- mc->default_ram_id = "mps.ram";
33
+ * kvm_hwpoison_page_add:
34
+ *
35
+ * Parameters:
36
+ * @ram_addr: the address in the RAM for the poisoned page
37
+ *
38
+ * Add a poisoned page to the list
39
+ *
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
}
59
60
+typedef struct HWPoisonPage {
61
+ ram_addr_t ram_addr;
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
+}
23
+}
78
+
24
+
79
+void kvm_hwpoison_page_add(ram_addr_t ram_addr)
25
+static void mps2tz_set_default_ram_info(MPS2TZMachineClass *mmc)
80
+{
26
+{
81
+ HWPoisonPage *page;
27
+ /*
28
+ * Set mc->default_ram_size and default_ram_id from the
29
+ * information in mmc->raminfo.
30
+ */
31
+ MachineClass *mc = MACHINE_CLASS(mmc);
32
+ const RAMInfo *p;
82
+
33
+
83
+ QLIST_FOREACH(page, &hwpoison_page_list, list) {
34
+ for (p = mmc->raminfo; p->name; p++) {
84
+ if (page->ram_addr == ram_addr) {
35
+ if (p->mrindex < 0) {
36
+ /* Found the entry for "system memory" */
37
+ mc->default_ram_size = p->size;
38
+ mc->default_ram_id = p->name;
85
+ return;
39
+ return;
86
+ }
40
+ }
87
+ }
41
+ }
88
+ page = g_new(HWPoisonPage, 1);
42
+ g_assert_not_reached();
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
}
99
100
+ qemu_register_reset(kvm_unpoison_all, NULL);
101
+
102
if (s->kernel_irqchip_allowed) {
103
kvm_irqchip_create(s);
104
}
105
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/i386/kvm.c
108
+++ b/target/i386/kvm.c
109
@@ -XXX,XX +XXX,XX @@
110
#include "sysemu/sysemu.h"
111
#include "sysemu/hw_accel.h"
112
#include "sysemu/kvm_int.h"
113
-#include "sysemu/reset.h"
114
#include "sysemu/runstate.h"
115
#include "kvm_i386.h"
116
#include "hyperv.h"
117
@@ -XXX,XX +XXX,XX @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index)
118
}
119
}
43
}
120
44
121
-
45
static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
122
-typedef struct HWPoisonPage {
46
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
123
- ram_addr_t ram_addr;
47
mmc->numirq = 92;
124
- QLIST_ENTRY(HWPoisonPage) list;
48
mmc->raminfo = an505_raminfo;
125
-} HWPoisonPage;
49
mmc->armsse_type = TYPE_IOTKIT;
126
-
50
+ mps2tz_set_default_ram_info(mmc);
127
-static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
51
}
128
- QLIST_HEAD_INITIALIZER(hwpoison_page_list);
52
129
-
53
static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
130
-static void kvm_unpoison_all(void *param)
54
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
131
-{
55
mmc->numirq = 92;
132
- HWPoisonPage *page, *next_page;
56
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
133
-
57
mmc->armsse_type = TYPE_SSE200;
134
- QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
58
+ mps2tz_set_default_ram_info(mmc);
135
- QLIST_REMOVE(page, list);
59
}
136
- qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
60
137
- g_free(page);
61
static const TypeInfo mps2tz_info = {
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
}
162
- qemu_register_reset(kvm_unpoison_all, NULL);
163
164
shadow_mem = object_property_get_int(OBJECT(s), "kvm-shadow-mem", &error_abort);
165
if (shadow_mem != -1) {
166
--
62
--
167
2.20.1
63
2.20.1
168
64
169
65
diff view generated by jsdifflib
1
Convert the Neon integer 3-reg-same compare insns VCGE, VCGT,
1
The AN505 and AN521 don't have any read-only memory, but the AN524
2
VCEQ, VACGE and VACGT to decodetree.
2
does; add a flag to ROMInfo to mark a region as ROM.
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-15-peter.maydell@linaro.org
6
Message-id: 20210215115138.20465-19-peter.maydell@linaro.org
7
---
7
---
8
target/arm/neon-dp.decode | 5 +++++
8
hw/arm/mps2-tz.c | 6 ++++++
9
target/arm/translate-neon.inc.c | 6 +++++
9
1 file changed, 6 insertions(+)
10
target/arm/translate.c | 39 ++-------------------------------
11
3 files changed, 13 insertions(+), 37 deletions(-)
12
10
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
11
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
13
--- a/hw/arm/mps2-tz.c
16
+++ b/target/arm/neon-dp.decode
14
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@ VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
15
@@ -XXX,XX +XXX,XX @@ typedef struct RAMInfo {
18
VMLA_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
16
* Flag values:
19
VMLS_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 1 .... @3same_fp
17
* IS_ALIAS: this RAM area is an alias to the upstream end of the
20
VMUL_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
18
* MPC specified by its .mpc value
21
+VCEQ_fp_3s 1111 001 0 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
19
+ * IS_ROM: this RAM area is read-only
22
+VCGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
20
*/
23
+VACGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 1 .... @3same_fp
21
#define IS_ALIAS 1
24
+VCGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 0 .... @3same_fp
22
+#define IS_ROM 2
25
+VACGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 1 .... @3same_fp
23
26
VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
24
struct MPS2TZMachineClass {
27
VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
25
MachineClass parent;
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
26
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
29
index XXXXXXX..XXXXXXX 100644
27
if (raminfo->mrindex < 0) {
30
--- a/target/arm/translate-neon.inc.c
28
/* Means this RAMInfo is for QEMU's "system memory" */
31
+++ b/target/arm/translate-neon.inc.c
29
MachineState *machine = MACHINE(mms);
32
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s)
30
+ assert(!(raminfo->flags & IS_ROM));
33
return do_3same_fp(s, a, FUNC, READS_VD); \
31
return machine->ram;
34
}
32
}
35
33
36
+DO_3S_FP(VCEQ, gen_helper_neon_ceq_f32, false)
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
37
+DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false)
35
38
+DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false)
36
memory_region_init_ram(ram, NULL, raminfo->name,
39
+DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
37
raminfo->size, &error_fatal);
40
+DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
38
+ if (raminfo->flags & IS_ROM) {
41
+
39
+ memory_region_set_readonly(ram, true);
42
static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
40
+ }
43
TCGv_ptr fpstatus)
41
return ram;
44
{
42
}
45
diff --git a/target/arm/translate.c b/target/arm/translate.c
43
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
--
44
--
110
2.20.1
45
2.20.1
111
46
112
47
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The armv7m_load_kernel() function takes a mem_size argument which it
2
expects to be the size of the memory region at guest address 0. (It
3
uses this argument only as a limit on how large a raw image file it
4
can load at address zero).
2
5
3
Create vectorized versions of handle_shri_with_rndacc
6
Instead of hardcoding this value, find the RAMInfo corresponding to
4
for shift+round and shift+round+accumulate. Add out-of-line
7
the 0 address and extract its size.
5
helpers in preparation for longer vector lengths from SVE.
6
8
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-3-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210215115138.20465-20-peter.maydell@linaro.org
11
---
13
---
12
target/arm/helper.h | 20 ++
14
hw/arm/mps2-tz.c | 17 ++++++++++++++++-
13
target/arm/translate.h | 9 +
15
1 file changed, 16 insertions(+), 1 deletion(-)
14
target/arm/translate-a64.c | 11 +-
15
target/arm/translate.c | 463 +++++++++++++++++++++++++++++++++++--
16
target/arm/vec_helper.c | 50 ++++
17
5 files changed, 527 insertions(+), 26 deletions(-)
18
16
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.h
19
--- a/hw/arm/mps2-tz.c
22
+++ b/target/arm/helper.h
20
+++ b/hw/arm/mps2-tz.c
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(gvec_usra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
21
@@ -XXX,XX +XXX,XX @@ static void create_non_mpc_ram(MPS2TZMachineState *mms)
24
DEF_HELPER_FLAGS_3(gvec_usra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
25
DEF_HELPER_FLAGS_3(gvec_usra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
26
27
+DEF_HELPER_FLAGS_3(gvec_srshr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_3(gvec_srshr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_3(gvec_srshr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
30
+DEF_HELPER_FLAGS_3(gvec_srshr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
31
+
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
+
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 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
}
22
}
99
}
23
}
100
24
101
+/*
25
+static uint32_t boot_ram_size(MPS2TZMachineState *mms)
102
+ * Shift one less than the requested amount, and the low bit is
103
+ * the rounding bit. For the 8 and 16-bit operations, because we
104
+ * mask the low bit, we can perform a normal integer shift instead
105
+ * of a vector shift.
106
+ */
107
+static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
108
+{
26
+{
109
+ TCGv_i64 t = tcg_temp_new_i64();
27
+ /* Return the size of the RAM block at guest address zero */
28
+ const RAMInfo *p;
29
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
110
+
30
+
111
+ tcg_gen_shri_i64(t, a, sh - 1);
31
+ for (p = mmc->raminfo; p->name; p++) {
112
+ tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
32
+ if (p->base == 0) {
113
+ tcg_gen_vec_sar8i_i64(d, a, sh);
33
+ return p->size;
114
+ tcg_gen_vec_add8_i64(d, d, t);
34
+ }
115
+ tcg_temp_free_i64(t);
35
+ }
36
+ g_assert_not_reached();
116
+}
37
+}
117
+
38
+
118
+static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
39
static void mps2tz_common_init(MachineState *machine)
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
{
40
{
519
uint64_t mask = dup_const(MO_8, 0xff >> shift);
41
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
520
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
42
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
521
}
43
522
return 0;
44
create_non_mpc_ram(mms);
523
45
524
+ case 2: /* VRSHR */
46
- armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
525
+ /* Right shift comes here negative. */
47
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
526
+ shift = -shift;
48
+ boot_ram_size(mms));
527
+ if (u) {
49
}
528
+ gen_gvec_urshr(size, rd_ofs, rm_ofs, shift,
50
529
+ vec_size, vec_size);
51
static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
530
+ } else {
531
+ gen_gvec_srshr(size, rd_ofs, rm_ofs, shift,
532
+ vec_size, vec_size);
533
+ }
534
+ return 0;
535
+
536
+ case 3: /* VRSRA */
537
+ /* Right shift comes here negative. */
538
+ shift = -shift;
539
+ if (u) {
540
+ gen_gvec_ursra(size, rd_ofs, rm_ofs, shift,
541
+ vec_size, vec_size);
542
+ } else {
543
+ gen_gvec_srsra(size, rd_ofs, rm_ofs, shift,
544
+ vec_size, vec_size);
545
+ }
546
+ return 0;
547
+
548
case 4: /* VSRI */
549
if (!u) {
550
return 1;
551
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
552
neon_load_reg64(cpu_V0, rm + pass);
553
tcg_gen_movi_i64(cpu_V1, imm);
554
switch (op) {
555
- case 2: /* VRSHR */
556
- case 3: /* VRSRA */
557
- if (u)
558
- gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
559
- else
560
- gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
561
- break;
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
/*
661
* Convert float16 to float32, raising no exceptions and
662
* preserving exceptional values, including SNaN.
663
--
52
--
664
2.20.1
53
2.20.1
665
54
666
55
diff view generated by jsdifflib
1
Convert the Neon floating point VFMA and VFMS insn to decodetree.
1
Add support for the mps3-an524 board; this is an SSE-200 based FPGA
2
These are the last insns in the 3-reg-same group so we can
2
image, like the existing mps2-an521. It has a usefully larger amount
3
remove all the support/loop code from the old decoder.
3
of RAM, and a PL031 RTC, as well as some more minor differences.
4
5
In real hardware this image runs on a newer generation of the FPGA
6
board, the MPS3 rather than the older MPS2. Architecturally the two
7
boards are similar, so we implement the MPS3 boards in the mps2-tz.c
8
file as variations of the existing MPS2 boards.
4
9
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-18-peter.maydell@linaro.org
12
Message-id: 20210215115138.20465-21-peter.maydell@linaro.org
8
---
13
---
9
target/arm/neon-dp.decode | 3 +
14
hw/arm/mps2-tz.c | 139 +++++++++++++++++++++++++++++++++++++++++++++--
10
target/arm/translate-neon.inc.c | 41 ++++++++
15
1 file changed, 135 insertions(+), 4 deletions(-)
11
target/arm/translate.c | 176 +-------------------------------
16
12
3 files changed, 46 insertions(+), 174 deletions(-)
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
19
--- a/hw/arm/mps2-tz.c
17
+++ b/target/arm/neon-dp.decode
20
+++ b/hw/arm/mps2-tz.c
18
@@ -XXX,XX +XXX,XX @@ SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \
21
@@ -XXX,XX +XXX,XX @@
19
SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
22
* This source file covers the following FPGA images, for TrustZone cores:
20
vm=%vm_dp vn=%vn_dp vd=%vd_dp
23
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
21
24
* "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
22
+VFMA_fp_3s 1111 001 0 0 . 0 . .... .... 1100 ... 1 .... @3same_fp
25
+ * "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
23
+VFMS_fp_3s 1111 001 0 0 . 1 . .... .... 1100 ... 1 .... @3same_fp
26
*
24
+
27
* Links to the TRM for the board itself and to the various Application
25
VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
28
* Notes which document the FPGA images can be found here:
26
29
@@ -XXX,XX +XXX,XX @@
27
VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
30
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
31
* Application Note AN521:
29
index XXXXXXX..XXXXXXX 100644
32
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
30
--- a/target/arm/translate-neon.inc.c
33
+ * Application Note AN524:
31
+++ b/target/arm/translate-neon.inc.c
34
+ * https://developer.arm.com/documentation/dai0524/latest/
32
@@ -XXX,XX +XXX,XX @@ static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
35
*
33
return do_3same(s, a, gen_VRSQRTS_fp_3s);
36
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
37
* (ARM ECM0601256) for the details of some of the device layout:
38
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
39
- * Similarly, the AN521 uses the SSE-200, and the SSE-200 TRM defines
40
+ * Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
41
* most of the device layout:
42
* http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
43
*
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/qdev-clock.h"
46
#include "qom/object.h"
47
48
-#define MPS2TZ_NUMIRQ_MAX 92
49
+#define MPS2TZ_NUMIRQ_MAX 95
50
#define MPS2TZ_RAM_MAX 4
51
52
typedef enum MPS2TZFPGAType {
53
FPGA_AN505,
54
FPGA_AN521,
55
+ FPGA_AN524,
56
} MPS2TZFPGAType;
57
58
/*
59
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
60
TZPPC ppc[5];
61
TZMPC mpc[3];
62
PL022State spi[5];
63
- ArmSbconI2CState i2c[4];
64
+ ArmSbconI2CState i2c[5];
65
UnimplementedDeviceState i2s_audio;
66
UnimplementedDeviceState gpio[4];
67
UnimplementedDeviceState gfx;
68
+ UnimplementedDeviceState cldc;
69
+ UnimplementedDeviceState rtc;
70
PL080State dma[4];
71
TZMSC msc[4];
72
- CMSDKAPBUART uart[5];
73
+ CMSDKAPBUART uart[6];
74
SplitIRQ sec_resp_splitter;
75
qemu_or_irq uart_irq_orgate;
76
DeviceState *lan9118;
77
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
78
#define TYPE_MPS2TZ_MACHINE "mps2tz"
79
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
80
#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
81
+#define TYPE_MPS3TZ_AN524_MACHINE MACHINE_TYPE_NAME("mps3-an524")
82
83
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
84
85
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
86
25000000,
87
};
88
89
+static const uint32_t an524_oscclk[] = {
90
+ 24000000,
91
+ 32000000,
92
+ 50000000,
93
+ 50000000,
94
+ 24576000,
95
+ 23750000,
96
+};
97
+
98
static const RAMInfo an505_raminfo[] = { {
99
.name = "ssram-0",
100
.base = 0x00000000,
101
@@ -XXX,XX +XXX,XX @@ static const RAMInfo an505_raminfo[] = { {
102
},
103
};
104
105
+static const RAMInfo an524_raminfo[] = { {
106
+ .name = "bram",
107
+ .base = 0x00000000,
108
+ .size = 512 * KiB,
109
+ .mpc = 0,
110
+ .mrindex = 0,
111
+ }, {
112
+ .name = "sram",
113
+ .base = 0x20000000,
114
+ .size = 32 * 4 * KiB,
115
+ .mpc = 1,
116
+ .mrindex = 1,
117
+ }, {
118
+ /* We don't model QSPI flash yet; for now expose it as simple ROM */
119
+ .name = "QSPI",
120
+ .base = 0x28000000,
121
+ .size = 8 * MiB,
122
+ .mpc = 1,
123
+ .mrindex = 2,
124
+ .flags = IS_ROM,
125
+ }, {
126
+ .name = "DDR",
127
+ .base = 0x60000000,
128
+ .size = 2 * GiB,
129
+ .mpc = 2,
130
+ .mrindex = -1,
131
+ }, {
132
+ .name = NULL,
133
+ },
134
+};
135
+
136
static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
137
{
138
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
139
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
140
},
141
};
142
143
+ const PPCInfo an524_ppcs[] = { {
144
+ .name = "apb_ppcexp0",
145
+ .ports = {
146
+ { "bram-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
147
+ { "qspi-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
148
+ { "ddr-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
149
+ },
150
+ }, {
151
+ .name = "apb_ppcexp1",
152
+ .ports = {
153
+ { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000 },
154
+ { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000 },
155
+ { "spi0", make_spi, &mms->spi[0], 0x41202000, 0x1000, { 52 } },
156
+ { "spi1", make_spi, &mms->spi[1], 0x41203000, 0x1000, { 53 } },
157
+ { "spi2", make_spi, &mms->spi[2], 0x41204000, 0x1000, { 54 } },
158
+ { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000 },
159
+ { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000 },
160
+ { /* port 7 reserved */ },
161
+ { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000 },
162
+ },
163
+ }, {
164
+ .name = "apb_ppcexp2",
165
+ .ports = {
166
+ { "scc", make_scc, &mms->scc, 0x41300000, 0x1000 },
167
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
168
+ 0x41301000, 0x1000 },
169
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x41302000, 0x1000 },
170
+ { "uart0", make_uart, &mms->uart[0], 0x41303000, 0x1000, { 32, 33, 42 } },
171
+ { "uart1", make_uart, &mms->uart[1], 0x41304000, 0x1000, { 34, 35, 43 } },
172
+ { "uart2", make_uart, &mms->uart[2], 0x41305000, 0x1000, { 36, 37, 44 } },
173
+ { "uart3", make_uart, &mms->uart[3], 0x41306000, 0x1000, { 38, 39, 45 } },
174
+ { "uart4", make_uart, &mms->uart[4], 0x41307000, 0x1000, { 40, 41, 46 } },
175
+ { "uart5", make_uart, &mms->uart[5], 0x41308000, 0x1000, { 124, 125, 126 } },
176
+
177
+ { /* port 9 reserved */ },
178
+ { "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
179
+ { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
180
+ },
181
+ }, {
182
+ .name = "ahb_ppcexp0",
183
+ .ports = {
184
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
185
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
186
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
187
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
188
+ { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
189
+ },
190
+ },
191
+ };
192
+
193
switch (mmc->fpga_type) {
194
case FPGA_AN505:
195
case FPGA_AN521:
196
ppcs = an505_ppcs;
197
num_ppcs = ARRAY_SIZE(an505_ppcs);
198
break;
199
+ case FPGA_AN524:
200
+ ppcs = an524_ppcs;
201
+ num_ppcs = ARRAY_SIZE(an524_ppcs);
202
+ break;
203
default:
204
g_assert_not_reached();
205
}
206
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
207
mps2tz_set_default_ram_info(mmc);
34
}
208
}
35
209
36
+static void gen_VFMA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
210
+static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
37
+ TCGv_ptr fpstatus)
38
+{
211
+{
39
+ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
212
+ MachineClass *mc = MACHINE_CLASS(oc);
213
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
214
+
215
+ mc->desc = "ARM MPS3 with AN524 FPGA image for dual Cortex-M33";
216
+ mc->default_cpus = 2;
217
+ mc->min_cpus = mc->default_cpus;
218
+ mc->max_cpus = mc->default_cpus;
219
+ mmc->fpga_type = FPGA_AN524;
220
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
221
+ mmc->scc_id = 0x41045240;
222
+ mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
223
+ mmc->oscclk = an524_oscclk;
224
+ mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
225
+ mmc->fpgaio_num_leds = 10;
226
+ mmc->fpgaio_has_switches = true;
227
+ mmc->numirq = 95;
228
+ mmc->raminfo = an524_raminfo;
229
+ mmc->armsse_type = TYPE_SSE200;
230
+ mps2tz_set_default_ram_info(mmc);
40
+}
231
+}
41
+
232
+
42
+static bool trans_VFMA_fp_3s(DisasContext *s, arg_3same *a)
233
static const TypeInfo mps2tz_info = {
43
+{
234
.name = TYPE_MPS2TZ_MACHINE,
44
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
235
.parent = TYPE_MACHINE,
45
+ return false;
236
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2tz_an521_info = {
46
+ }
237
.class_init = mps2tz_an521_class_init,
47
+
238
};
48
+ if (a->size != 0) {
239
49
+ /* TODO fp16 support */
240
+static const TypeInfo mps3tz_an524_info = {
50
+ return false;
241
+ .name = TYPE_MPS3TZ_AN524_MACHINE,
51
+ }
242
+ .parent = TYPE_MPS2TZ_MACHINE,
52
+
243
+ .class_init = mps3tz_an524_class_init,
53
+ return do_3same_fp(s, a, gen_VFMA_fp_3s, true);
244
+};
54
+}
245
+
55
+
246
static void mps2tz_machine_init(void)
56
+static void gen_VFMS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
57
+ TCGv_ptr fpstatus)
58
+{
59
+ gen_helper_vfp_negs(vn, vn);
60
+ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
61
+}
62
+
63
+static bool trans_VFMS_fp_3s(DisasContext *s, arg_3same *a)
64
+{
65
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
66
+ return false;
67
+ }
68
+
69
+ if (a->size != 0) {
70
+ /* TODO fp16 support */
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
{
247
{
79
/* FP operations handled pairwise 32 bits at a time */
248
type_register_static(&mps2tz_info);
80
diff --git a/target/arm/translate.c b/target/arm/translate.c
249
type_register_static(&mps2tz_an505_info);
81
index XXXXXXX..XXXXXXX 100644
250
type_register_static(&mps2tz_an521_info);
82
--- a/target/arm/translate.c
251
+ type_register_static(&mps3tz_an524_info);
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
}
252
}
87
253
88
-/* Symbolic constants for op fields for Neon 3-register same-length.
254
type_init(mps2tz_machine_init);
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
--
255
--
275
2.20.1
256
2.20.1
276
257
277
258
diff view generated by jsdifflib
1
Convert the Neon integer VMUL, VMLA, and VMLS 3-reg-same inssn to
1
The AN524 has a USB controller (an ISP1763); we don't have a model of
2
decodetree.
2
it but we should provide a stub "unimplemented-device" for it. This
3
is slightly complicated because the USB controller shares a PPC port
4
with the ethernet controller.
3
5
4
We don't have a gvec helper for multiply-accumulate, so VMLA and VMLS
6
Implement a make_* function which provides creates a container
5
need a loop function do_3same_fp(). This takes a reads_vd parameter
7
MemoryRegion with both the ethernet controller and an
6
to do_3same_fp() which tells it to load the old value into vd before
8
unimplemented-device stub for the USB controller.
7
calling the callback function, in the same way that the do_vfp_3op_sp()
8
and do_vfp_3op_dp() functions in translate-vfp.inc.c work. (The
9
only uses in this patch pass reads_vd == true, but later commits
10
will use reads_vd == false.)
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
9
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-id: 20200512163904.10918-14-peter.maydell@linaro.org
13
Message-id: 20210215115138.20465-22-peter.maydell@linaro.org
27
---
14
---
28
target/arm/neon-dp.decode | 3 ++
15
hw/arm/mps2-tz.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
29
target/arm/translate-neon.inc.c | 81 +++++++++++++++++++++++++++++++++
16
1 file changed, 47 insertions(+), 1 deletion(-)
30
target/arm/translate.c | 17 +------
31
3 files changed, 85 insertions(+), 16 deletions(-)
32
17
33
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
18
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
34
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/neon-dp.decode
20
--- a/hw/arm/mps2-tz.c
36
+++ b/target/arm/neon-dp.decode
21
+++ b/hw/arm/mps2-tz.c
37
@@ -XXX,XX +XXX,XX @@ VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
22
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
38
VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
23
39
VPADD_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 0 .... @3same_fp_q0
24
ARMSSE iotkit;
40
VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
25
MemoryRegion ram[MPS2TZ_RAM_MAX];
41
+VMLA_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
26
+ MemoryRegion eth_usb_container;
42
+VMLS_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 1 .... @3same_fp
27
+
43
+VMUL_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
28
MPS2SCC scc;
44
VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
29
MPS2FPGAIO fpgaio;
45
VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
30
TZPPC ppc[5];
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
31
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
47
index XXXXXXX..XXXXXXX 100644
32
UnimplementedDeviceState gfx;
48
--- a/target/arm/translate-neon.inc.c
33
UnimplementedDeviceState cldc;
49
+++ b/target/arm/translate-neon.inc.c
34
UnimplementedDeviceState rtc;
50
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPADD, padd_u)
35
+ UnimplementedDeviceState usb;
51
DO_3SAME_VQDMULH(VQDMULH, qdmulh)
36
PL080State dma[4];
52
DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
37
TZMSC msc[4];
53
38
CMSDKAPBUART uart[6];
54
+static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
55
+ bool reads_vd)
40
return sysbus_mmio_get_region(s, 0);
41
}
42
43
+static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
44
+ const char *name, hwaddr size,
45
+ const int *irqs)
56
+{
46
+{
57
+ /*
47
+ /*
58
+ * FP operations handled elementwise 32 bits at a time.
48
+ * The AN524 makes the ethernet and USB share a PPC port.
59
+ * If reads_vd is true then the old value of Vd will be
49
+ * irqs[] is the ethernet IRQ.
60
+ * loaded before calling the callback function. This is
61
+ * used for multiply-accumulate type operations.
62
+ */
50
+ */
63
+ TCGv_i32 tmp, tmp2;
51
+ SysBusDevice *s;
64
+ int pass;
52
+ NICInfo *nd = &nd_table[0];
65
+
53
+
66
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
54
+ memory_region_init(&mms->eth_usb_container, OBJECT(mms),
67
+ return false;
55
+ "mps2-tz-eth-usb-container", 0x200000);
68
+ }
69
+
56
+
70
+ /* UNDEF accesses to D16-D31 if they don't exist. */
57
+ /*
71
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
58
+ * In hardware this is a LAN9220; the LAN9118 is software compatible
72
+ ((a->vd | a->vn | a->vm) & 0x10)) {
59
+ * except that it doesn't support the checksum-offload feature.
73
+ return false;
60
+ */
74
+ }
61
+ qemu_check_nic_model(nd, "lan9118");
62
+ mms->lan9118 = qdev_new(TYPE_LAN9118);
63
+ qdev_set_nic_properties(mms->lan9118, nd);
75
+
64
+
76
+ if ((a->vn | a->vm | a->vd) & a->q) {
65
+ s = SYS_BUS_DEVICE(mms->lan9118);
77
+ return false;
66
+ sysbus_realize_and_unref(s, &error_fatal);
78
+ }
67
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
79
+
68
+
80
+ if (!vfp_access_check(s)) {
69
+ memory_region_add_subregion(&mms->eth_usb_container,
81
+ return true;
70
+ 0, sysbus_mmio_get_region(s, 0));
82
+ }
83
+
71
+
84
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
72
+ /* The USB OTG controller is an ISP1763; we don't have a model of it. */
85
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
73
+ object_initialize_child(OBJECT(mms), "usb-otg",
86
+ tmp = neon_load_reg(a->vn, pass);
74
+ &mms->usb, TYPE_UNIMPLEMENTED_DEVICE);
87
+ tmp2 = neon_load_reg(a->vm, pass);
75
+ qdev_prop_set_string(DEVICE(&mms->usb), "name", "usb-otg");
88
+ if (reads_vd) {
76
+ qdev_prop_set_uint64(DEVICE(&mms->usb), "size", 0x100000);
89
+ TCGv_i32 tmp_rd = neon_load_reg(a->vd, pass);
77
+ s = SYS_BUS_DEVICE(&mms->usb);
90
+ fn(tmp_rd, tmp, tmp2, fpstatus);
78
+ sysbus_realize(s, &error_fatal);
91
+ neon_store_reg(a->vd, pass, tmp_rd);
79
+
92
+ tcg_temp_free_i32(tmp);
80
+ memory_region_add_subregion(&mms->eth_usb_container,
93
+ } else {
81
+ 0x100000, sysbus_mmio_get_region(s, 0));
94
+ fn(tmp, tmp, tmp2, fpstatus);
82
+
95
+ neon_store_reg(a->vd, pass, tmp);
83
+ return &mms->eth_usb_container;
96
+ }
97
+ tcg_temp_free_i32(tmp2);
98
+ }
99
+ tcg_temp_free_ptr(fpstatus);
100
+ return true;
101
+}
84
+}
102
+
85
+
103
/*
86
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
104
* For all the functions using this macro, size == 1 means fp16,
87
const char *name, hwaddr size,
105
* which is an architecture extension we don't implement yet.
88
const int *irqs)
106
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
89
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
107
DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
90
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
108
DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
91
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
109
DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
92
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
110
+DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s)
93
- { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
111
+
94
+ { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 48 } },
112
+/*
95
},
113
+ * For all the functions using this macro, size == 1 means fp16,
96
},
114
+ * which is an architecture extension we don't implement yet.
97
};
115
+ */
116
+#define DO_3S_FP(INSN,FUNC,READS_VD) \
117
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
118
+ { \
119
+ if (a->size != 0) { \
120
+ /* TODO fp16 support */ \
121
+ return false; \
122
+ } \
123
+ return do_3same_fp(s, a, FUNC, READS_VD); \
124
+ }
125
+
126
+static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
127
+ TCGv_ptr fpstatus)
128
+{
129
+ gen_helper_vfp_muls(vn, vn, vm, fpstatus);
130
+ gen_helper_vfp_adds(vd, vd, vn, fpstatus);
131
+}
132
+
133
+static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
134
+ TCGv_ptr fpstatus)
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
{
145
diff --git a/target/arm/translate.c b/target/arm/translate.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/target/arm/translate.c
148
+++ b/target/arm/translate.c
149
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
150
case NEON_3R_VPADD_VQRDMLAH:
151
case NEON_3R_VQDMULH_VQRDMULH:
152
case NEON_3R_FLOAT_ARITH:
153
+ case NEON_3R_FLOAT_MULTIPLY:
154
/* Already handled by decodetree */
155
return 1;
156
}
157
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
158
tmp = neon_load_reg(rn, pass);
159
tmp2 = neon_load_reg(rm, pass);
160
switch (op) {
161
- case NEON_3R_FLOAT_MULTIPLY:
162
- {
163
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
164
- gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
165
- if (!u) {
166
- tcg_temp_free_i32(tmp2);
167
- tmp2 = neon_load_reg(rd, pass);
168
- if (size == 0) {
169
- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
170
- } else {
171
- gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
172
- }
173
- }
174
- tcg_temp_free_ptr(fpstatus);
175
- break;
176
- }
177
case NEON_3R_FLOAT_CMP:
178
{
179
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
180
--
98
--
181
2.20.1
99
2.20.1
182
100
183
101
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
The AN524 has a PL031 RTC, which we have a model of; provide it
2
rather than an unimplemented-device stub.
2
3
3
RAS Virtualization feature is not supported now, so
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
add a RAS machine option and disable it by default.
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-23-peter.maydell@linaro.org
8
---
9
hw/arm/mps2-tz.c | 22 ++++++++++++++++++++--
10
1 file changed, 20 insertions(+), 2 deletions(-)
5
11
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
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>
13
---
14
include/hw/arm/virt.h | 1 +
15
hw/arm/virt.c | 23 +++++++++++++++++++++++
16
2 files changed, 24 insertions(+)
17
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/virt.h
14
--- a/hw/arm/mps2-tz.c
21
+++ b/include/hw/arm/virt.h
15
+++ b/hw/arm/mps2-tz.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct {
16
@@ -XXX,XX +XXX,XX @@
23
bool highmem_ecam;
17
#include "hw/misc/tz-msc.h"
24
bool its;
18
#include "hw/arm/armsse.h"
25
bool virt;
19
#include "hw/dma/pl080.h"
26
+ bool ras;
20
+#include "hw/rtc/pl031.h"
27
OnOffAuto acpi;
21
#include "hw/ssi/pl022.h"
28
VirtGICType gic_version;
22
#include "hw/i2c/arm_sbcon_i2c.h"
29
VirtIOMMUType iommu;
23
#include "hw/net/lan9118.h"
30
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
24
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
31
index XXXXXXX..XXXXXXX 100644
25
UnimplementedDeviceState gpio[4];
32
--- a/hw/arm/virt.c
26
UnimplementedDeviceState gfx;
33
+++ b/hw/arm/virt.c
27
UnimplementedDeviceState cldc;
34
@@ -XXX,XX +XXX,XX @@ static void virt_set_acpi(Object *obj, Visitor *v, const char *name,
28
- UnimplementedDeviceState rtc;
35
visit_type_OnOffAuto(v, name, &vms->acpi, errp);
29
UnimplementedDeviceState usb;
30
+ PL031State rtc;
31
PL080State dma[4];
32
TZMSC msc[4];
33
CMSDKAPBUART uart[6];
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
35
return sysbus_mmio_get_region(s, 0);
36
}
36
}
37
37
38
+static bool virt_get_ras(Object *obj, Error **errp)
38
+static MemoryRegion *make_rtc(MPS2TZMachineState *mms, void *opaque,
39
+ const char *name, hwaddr size,
40
+ const int *irqs)
39
+{
41
+{
40
+ VirtMachineState *vms = VIRT_MACHINE(obj);
42
+ PL031State *pl031 = opaque;
43
+ SysBusDevice *s;
41
+
44
+
42
+ return vms->ras;
45
+ object_initialize_child(OBJECT(mms), name, pl031, TYPE_PL031);
46
+ s = SYS_BUS_DEVICE(pl031);
47
+ sysbus_realize(s, &error_fatal);
48
+ /*
49
+ * The board docs don't give an IRQ number for the PL031, so
50
+ * presumably it is not connected.
51
+ */
52
+ return sysbus_mmio_get_region(s, 0);
43
+}
53
+}
44
+
54
+
45
+static void virt_set_ras(Object *obj, bool value, Error **errp)
55
static void create_non_mpc_ram(MPS2TZMachineState *mms)
46
+{
47
+ VirtMachineState *vms = VIRT_MACHINE(obj);
48
+
49
+ vms->ras = value;
50
+}
51
+
52
static char *virt_get_gic_version(Object *obj, Error **errp)
53
{
56
{
54
VirtMachineState *vms = VIRT_MACHINE(obj);
57
/*
55
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
56
"Valid values are none and smmuv3",
59
57
NULL);
60
{ /* port 9 reserved */ },
58
61
{ "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
59
+ /* Default disallows RAS instantiation */
62
- { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
60
+ vms->ras = false;
63
+ { "rtc", make_rtc, &mms->rtc, 0x4130b000, 0x1000 },
61
+ object_property_add_bool(obj, "ras", virt_get_ras,
64
},
62
+ virt_set_ras, NULL);
65
}, {
63
+ object_property_set_description(obj, "ras",
66
.name = "ahb_ppcexp0",
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
--
67
--
72
2.20.1
68
2.20.1
73
69
74
70
diff view generated by jsdifflib
New patch
1
Add brief documentation of the new mps3-an524 board.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215115138.20465-24-peter.maydell@linaro.org
7
---
8
docs/system/arm/mps2.rst | 24 ++++++++++++++++++------
9
1 file changed, 18 insertions(+), 6 deletions(-)
10
11
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
12
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/system/arm/mps2.rst
14
+++ b/docs/system/arm/mps2.rst
15
@@ -XXX,XX +XXX,XX @@
16
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
17
-================================================================================================================
18
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
19
+=========================================================================================================================================
20
21
These board models all use Arm M-profile CPUs.
22
23
-The Arm MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
24
-FPGA but is otherwise the same as the 2). Since the CPU itself
25
-and most of the devices are in the FPGA, the details of the board
26
-as seen by the guest depend significantly on the FPGA image.
27
+The Arm MPS2, MPS2+ and MPS3 dev boards are FPGA based (the 2+ has a
28
+bigger FPGA but is otherwise the same as the 2; the 3 has a bigger
29
+FPGA again, can handle 4GB of RAM and has a USB controller and QSPI flash).
30
+
31
+Since the CPU itself and most of the devices are in the FPGA, the
32
+details of the board as seen by the guest depend significantly on the
33
+FPGA image.
34
35
QEMU models the following FPGA images:
36
37
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
38
Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
39
``mps2-an521``
40
Dual Cortex-M33 as documented in Arm Application Note AN521
41
+``mps3-an524``
42
+ Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
43
44
Differences between QEMU and real hardware:
45
46
- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
47
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
48
if zbt_boot_ctrl is always zero)
49
+- AN524 remapping of low memory to either BRAM or to QSPI flash is
50
+ unimplemented (QEMU always maps this to BRAM, ignoring the
51
+ SCC CFG_REG0 memory-remap bit)
52
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
53
visible difference is that the LAN9118 doesn't support checksum
54
offloading
55
+- QEMU does not model the QSPI flash in MPS3 boards as real QSPI
56
+ flash, but only as simple ROM, so attempting to rewrite the flash
57
+ from the guest will fail
58
+- QEMU does not model the USB controller in MPS3 boards
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
1
Convert the 64-bit element insns in the 3-reg-same group
1
Update old infocenter.arm.com URLs to the equivalent developer.arm.com
2
to decodetree. This covers VQSHL, VRSHL and VQRSHL where
2
ones (the old URLs should redirect, but we might as well avoid the
3
size==0b11.
3
redirection notice, and the new URLs are pleasantly shorter).
4
5
This commit covers the links to the MPS2 board TRM, the various
6
Application Notes, the IoTKit and SSE-200 documents.
4
7
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200512163904.10918-4-peter.maydell@linaro.org
10
Message-id: 20210215115138.20465-25-peter.maydell@linaro.org
8
---
11
---
9
target/arm/neon-dp.decode | 13 +++++++++++
12
include/hw/arm/armsse.h | 4 ++--
10
target/arm/translate-neon.inc.c | 24 +++++++++++++++++++++
13
include/hw/misc/armsse-cpuid.h | 2 +-
11
target/arm/translate.c | 38 ++-------------------------------
14
include/hw/misc/armsse-mhu.h | 2 +-
12
3 files changed, 39 insertions(+), 36 deletions(-)
15
include/hw/misc/iotkit-secctl.h | 2 +-
13
16
include/hw/misc/iotkit-sysctl.h | 2 +-
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
17
include/hw/misc/iotkit-sysinfo.h | 2 +-
15
index XXXXXXX..XXXXXXX 100644
18
include/hw/misc/mps2-fpgaio.h | 2 +-
16
--- a/target/arm/neon-dp.decode
19
hw/arm/mps2-tz.c | 11 +++++------
17
+++ b/target/arm/neon-dp.decode
20
hw/misc/armsse-cpuid.c | 2 +-
18
@@ -XXX,XX +XXX,XX @@ VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same
21
hw/misc/armsse-mhu.c | 2 +-
19
VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same_rev
22
hw/misc/iotkit-sysctl.c | 2 +-
20
VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
23
hw/misc/iotkit-sysinfo.c | 2 +-
21
24
hw/misc/mps2-fpgaio.c | 2 +-
22
+# Insns operating on 64-bit elements (size!=0b11 handled elsewhere)
25
hw/misc/mps2-scc.c | 2 +-
23
+# The _rev suffix indicates that Vn and Vm are reversed (as explained
26
14 files changed, 19 insertions(+), 20 deletions(-)
24
+# by the comment for the @3same_rev format).
27
25
+@3same_64_rev .... ... . . . 11 .... .... .... . q:1 . . .... \
28
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
26
+ &3same vm=%vn_dp vn=%vm_dp vd=%vd_dp size=3
29
index XXXXXXX..XXXXXXX 100644
27
+
30
--- a/include/hw/arm/armsse.h
28
+VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
31
+++ b/include/hw/arm/armsse.h
29
+VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
32
@@ -XXX,XX +XXX,XX @@
30
+VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
33
* hardware, which include the IoT Kit and the SSE-050, SSE-100 and
31
+VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
34
* SSE-200. Currently we model:
32
+VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
35
* - the Arm IoT Kit which is documented in
33
+VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
36
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
34
+
37
+ * https://developer.arm.com/documentation/ecm0601256/latest
35
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
38
* - the SSE-200 which is documented in
36
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
39
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
37
VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
40
+ * https://developer.arm.com/documentation/101104/latest/
38
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
41
*
39
index XXXXXXX..XXXXXXX 100644
42
* The IoTKit contains:
40
--- a/target/arm/translate-neon.inc.c
43
* a Cortex-M33
41
+++ b/target/arm/translate-neon.inc.c
44
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
42
@@ -XXX,XX +XXX,XX @@ static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a)
45
index XXXXXXX..XXXXXXX 100644
43
46
--- a/include/hw/misc/armsse-cpuid.h
44
return true;
47
+++ b/include/hw/misc/armsse-cpuid.h
45
}
48
@@ -XXX,XX +XXX,XX @@
46
+
49
/*
47
+#define DO_3SAME_64(INSN, FUNC) \
50
* This is a model of the "CPU_IDENTITY" register block which is part of the
48
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
51
* Arm SSE-200 and documented in
49
+ uint32_t rn_ofs, uint32_t rm_ofs, \
52
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
50
+ uint32_t oprsz, uint32_t maxsz) \
53
+ * https://developer.arm.com/documentation/101104/latest/
51
+ { \
54
*
52
+ static const GVecGen3 op = { .fni8 = FUNC }; \
55
* QEMU interface:
53
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &op); \
56
* + QOM property "CPUID": the value to use for the CPUID register
54
+ } \
57
diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h
55
+ DO_3SAME(INSN, gen_##INSN##_3s)
58
index XXXXXXX..XXXXXXX 100644
56
+
59
--- a/include/hw/misc/armsse-mhu.h
57
+#define DO_3SAME_64_ENV(INSN, FUNC) \
60
+++ b/include/hw/misc/armsse-mhu.h
58
+ static void gen_##INSN##_elt(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m) \
61
@@ -XXX,XX +XXX,XX @@
59
+ { \
62
/*
60
+ FUNC(d, cpu_env, n, m); \
63
* This is a model of the Message Handling Unit (MHU) which is part of the
61
+ } \
64
* Arm SSE-200 and documented in
62
+ DO_3SAME_64(INSN, gen_##INSN##_elt)
65
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
63
+
66
+ * https://developer.arm.com/documentation/101104/latest/
64
+DO_3SAME_64(VRSHL_S64, gen_helper_neon_rshl_s64)
67
*
65
+DO_3SAME_64(VRSHL_U64, gen_helper_neon_rshl_u64)
68
* QEMU interface:
66
+DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64)
69
* + sysbus MMIO region 0: the system information register bank
67
+DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64)
70
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
68
+DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64)
71
index XXXXXXX..XXXXXXX 100644
69
+DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
72
--- a/include/hw/misc/iotkit-secctl.h
70
diff --git a/target/arm/translate.c b/target/arm/translate.c
73
+++ b/include/hw/misc/iotkit-secctl.h
71
index XXXXXXX..XXXXXXX 100644
74
@@ -XXX,XX +XXX,XX @@
72
--- a/target/arm/translate.c
75
73
+++ b/target/arm/translate.c
76
/* This is a model of the security controller which is part of the
74
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
77
* Arm IoT Kit and documented in
75
}
78
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
76
79
+ * https://developer.arm.com/documentation/ecm0601256/latest
77
if (size == 3) {
80
*
78
- /* 64-bit element instructions. */
81
* QEMU interface:
79
- for (pass = 0; pass < (q ? 2 : 1); pass++) {
82
* + sysbus MMIO region 0 is the "secure privilege control block" registers
80
- neon_load_reg64(cpu_V0, rn + pass);
83
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
81
- neon_load_reg64(cpu_V1, rm + pass);
84
index XXXXXXX..XXXXXXX 100644
82
- switch (op) {
85
--- a/include/hw/misc/iotkit-sysctl.h
83
- case NEON_3R_VQSHL:
86
+++ b/include/hw/misc/iotkit-sysctl.h
84
- if (u) {
87
@@ -XXX,XX +XXX,XX @@
85
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
88
/*
86
- cpu_V1, cpu_V0);
89
* This is a model of the "system control element" which is part of the
87
- } else {
90
* Arm IoTKit and documented in
88
- gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
91
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
89
- cpu_V1, cpu_V0);
92
+ * https://developer.arm.com/documentation/ecm0601256/latest
90
- }
93
* Specifically, it implements the "system information block" and
91
- break;
94
* "system control register" blocks.
92
- case NEON_3R_VRSHL:
95
*
93
- if (u) {
96
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
94
- gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
97
index XXXXXXX..XXXXXXX 100644
95
- } else {
98
--- a/include/hw/misc/iotkit-sysinfo.h
96
- gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
99
+++ b/include/hw/misc/iotkit-sysinfo.h
97
- }
100
@@ -XXX,XX +XXX,XX @@
98
- break;
101
/*
99
- case NEON_3R_VQRSHL:
102
* This is a model of the "system information block" which is part of the
100
- if (u) {
103
* Arm IoTKit and documented in
101
- gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
104
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
102
- cpu_V1, cpu_V0);
105
+ * https://developer.arm.com/documentation/ecm0601256/latest
103
- } else {
106
* QEMU interface:
104
- gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
107
* + QOM property "SYS_VERSION": value to use for SYS_VERSION register
105
- cpu_V1, cpu_V0);
108
* + QOM property "SYS_CONFIG": value to use for SYS_CONFIG register
106
- }
109
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
107
- break;
110
index XXXXXXX..XXXXXXX 100644
108
- default:
111
--- a/include/hw/misc/mps2-fpgaio.h
109
- abort();
112
+++ b/include/hw/misc/mps2-fpgaio.h
110
- }
113
@@ -XXX,XX +XXX,XX @@
111
- neon_store_reg64(cpu_V0, rd + pass);
114
/* This is a model of the FPGAIO register block in the AN505
112
- }
115
* FPGA image for the MPS2 dev board; it is documented in the
113
- return 0;
116
* application note:
114
+ /* 64-bit element instructions: handled by decodetree */
117
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
115
+ return 1;
118
+ * https://developer.arm.com/documentation/dai0505/latest/
116
}
119
*
117
pairwise = 0;
120
* QEMU interface:
118
switch (op) {
121
* + sysbus MMIO region 0: the register bank
122
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hw/arm/mps2-tz.c
125
+++ b/hw/arm/mps2-tz.c
126
@@ -XXX,XX +XXX,XX @@
127
* https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
128
*
129
* Board TRM:
130
- * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
131
+ * https://developer.arm.com/documentation/100112/latest/
132
* Application Note AN505:
133
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
134
+ * https://developer.arm.com/documentation/dai0505/latest/
135
* Application Note AN521:
136
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
137
+ * https://developer.arm.com/documentation/dai0521/latest/
138
* Application Note AN524:
139
* https://developer.arm.com/documentation/dai0524/latest/
140
*
141
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
142
* (ARM ECM0601256) for the details of some of the device layout:
143
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
144
+ * https://developer.arm.com/documentation/ecm0601256/latest
145
* Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
146
* most of the device layout:
147
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
148
- *
149
+ * https://developer.arm.com/documentation/101104/latest/
150
*/
151
152
#include "qemu/osdep.h"
153
diff --git a/hw/misc/armsse-cpuid.c b/hw/misc/armsse-cpuid.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/misc/armsse-cpuid.c
156
+++ b/hw/misc/armsse-cpuid.c
157
@@ -XXX,XX +XXX,XX @@
158
/*
159
* This is a model of the "CPU_IDENTITY" register block which is part of the
160
* Arm SSE-200 and documented in
161
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
162
+ * https://developer.arm.com/documentation/101104/latest/
163
*
164
* It consists of one read-only CPUID register (set by QOM property), plus the
165
* usual ID registers.
166
diff --git a/hw/misc/armsse-mhu.c b/hw/misc/armsse-mhu.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/misc/armsse-mhu.c
169
+++ b/hw/misc/armsse-mhu.c
170
@@ -XXX,XX +XXX,XX @@
171
/*
172
* This is a model of the Message Handling Unit (MHU) which is part of the
173
* Arm SSE-200 and documented in
174
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
175
+ * https://developer.arm.com/documentation/101104/latest/
176
*/
177
178
#include "qemu/osdep.h"
179
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/misc/iotkit-sysctl.c
182
+++ b/hw/misc/iotkit-sysctl.c
183
@@ -XXX,XX +XXX,XX @@
184
/*
185
* This is a model of the "system control element" which is part of the
186
* Arm IoTKit and documented in
187
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
188
+ * https://developer.arm.com/documentation/ecm0601256/latest
189
* Specifically, it implements the "system control register" blocks.
190
*/
191
192
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/hw/misc/iotkit-sysinfo.c
195
+++ b/hw/misc/iotkit-sysinfo.c
196
@@ -XXX,XX +XXX,XX @@
197
/*
198
* This is a model of the "system information block" which is part of the
199
* Arm IoTKit and documented in
200
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
201
+ * https://developer.arm.com/documentation/ecm0601256/latest
202
* It consists of 2 read-only version/config registers, plus the
203
* usual ID registers.
204
*/
205
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
206
index XXXXXXX..XXXXXXX 100644
207
--- a/hw/misc/mps2-fpgaio.c
208
+++ b/hw/misc/mps2-fpgaio.c
209
@@ -XXX,XX +XXX,XX @@
210
/* This is a model of the "FPGA system control and I/O" block found
211
* in the AN505 FPGA image for the MPS2 devboard.
212
* It is documented in AN505:
213
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
214
+ * https://developer.arm.com/documentation/dai0505/latest/
215
*/
216
217
#include "qemu/osdep.h"
218
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
219
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/misc/mps2-scc.c
221
+++ b/hw/misc/mps2-scc.c
222
@@ -XXX,XX +XXX,XX @@
223
* found in the FPGA images of MPS2 development boards.
224
*
225
* Documentation of it can be found in the MPS2 TRM:
226
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100112_0100_03_en/index.html
227
+ * https://developer.arm.com/documentation/100112/latest/
228
* and also in the Application Notes documenting individual FPGA images.
229
*/
230
119
--
231
--
120
2.20.1
232
2.20.1
121
233
122
234
diff view generated by jsdifflib