Check the instruction subsets of e500mc, e5500 and e6500 through the existing TCG test framework. System emulation allows checking SRR0 and ESR on program exceptions. Run e500mc in 32-bit computation mode and e5500/e6500 in 64-bit computation mode.
Add shared ppce500 startup code, a linker script and assembly helpers. Use the existing UART and GPIO power-off devices to report results and terminate QEMU. Register the system targets in ppc/system and ppc64/system, sharing the assembly sources. Test that unsupported floating-point instructions raise precise illegal instruction exceptions. Also check cmpb, prtyw and prtyd on e500mc. Signed-off-by: Bin Meng <[email protected]> --- meson_options.txt | 4 ++ scripts/meson-buildoptions.sh | 2 + tests/tcg/meson.build | 1 + tests/tcg/ppc/meson.build | 5 ++ tests/tcg/ppc/system/README | 22 +++++++ tests/tcg/ppc/system/boot.S | 92 ++++++++++++++++++++++++++++++ tests/tcg/ppc/system/isa.out | 1 + tests/tcg/ppc/system/kernel.ld | 18 ++++++ tests/tcg/ppc/system/macros.inc | 56 ++++++++++++++++++ tests/tcg/ppc/system/meson.build | 39 +++++++++++++ tests/tcg/ppc/system/unsupported.S | 31 ++++++++++ tests/tcg/ppc64/meson.build | 2 + tests/tcg/ppc64/system/meson.build | 32 +++++++++++ 13 files changed, 305 insertions(+) create mode 100644 tests/tcg/ppc/meson.build create mode 100644 tests/tcg/ppc/system/README create mode 100644 tests/tcg/ppc/system/boot.S create mode 100644 tests/tcg/ppc/system/isa.out create mode 100644 tests/tcg/ppc/system/kernel.ld create mode 100644 tests/tcg/ppc/system/macros.inc create mode 100644 tests/tcg/ppc/system/meson.build create mode 100644 tests/tcg/ppc/system/unsupported.S create mode 100644 tests/tcg/ppc64/system/meson.build diff --git a/meson_options.txt b/meson_options.txt index c9247e9de1..c75c8d7db7 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -465,6 +465,10 @@ option('tcg_tests_cross_cc_or1k', type: 'string', description: 'cc for or1k tcg tests') option('tcg_tests_cross_cflags_or1k', type: 'string', description: 'cflags for or1k tcg tests') +option('tcg_tests_cross_cc_ppc', type: 'string', + description: 'cc for ppc tcg tests') +option('tcg_tests_cross_cflags_ppc', type: 'string', + description: 'cflags for ppc tcg tests') option('tcg_tests_cross_cc_ppc64', type: 'string', description: 'cc for ppc64 tcg tests') option('tcg_tests_cross_cflags_ppc64', type: 'string', diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 064e1429a4..5bac2bcf7c 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -545,6 +545,7 @@ _meson_option_parse() { --tcg-tests-cross-cc-mips64r6el=*) quote_sh "-Dtcg_tests_cross_cc_mips64r6el=$2" ;; --tcg-tests-cross-cc-mipsel=*) quote_sh "-Dtcg_tests_cross_cc_mipsel=$2" ;; --tcg-tests-cross-cc-or1k=*) quote_sh "-Dtcg_tests_cross_cc_or1k=$2" ;; + --tcg-tests-cross-cc-ppc=*) quote_sh "-Dtcg_tests_cross_cc_ppc=$2" ;; --tcg-tests-cross-cc-ppc64=*) quote_sh "-Dtcg_tests_cross_cc_ppc64=$2" ;; --tcg-tests-cross-cc-ppc64le=*) quote_sh "-Dtcg_tests_cross_cc_ppc64le=$2" ;; --tcg-tests-cross-cc-riscv64=*) quote_sh "-Dtcg_tests_cross_cc_riscv64=$2" ;; @@ -571,6 +572,7 @@ _meson_option_parse() { --tcg-tests-cross-cflags-mips64r6el=*) quote_sh "-Dtcg_tests_cross_cflags_mips64r6el=$2" ;; --tcg-tests-cross-cflags-mipsel=*) quote_sh "-Dtcg_tests_cross_cflags_mipsel=$2" ;; --tcg-tests-cross-cflags-or1k=*) quote_sh "-Dtcg_tests_cross_cflags_or1k=$2" ;; + --tcg-tests-cross-cflags-ppc=*) quote_sh "-Dtcg_tests_cross_cflags_ppc=$2" ;; --tcg-tests-cross-cflags-ppc64=*) quote_sh "-Dtcg_tests_cross_cflags_ppc64=$2" ;; --tcg-tests-cross-cflags-ppc64le=*) quote_sh "-Dtcg_tests_cross_cflags_ppc64le=$2" ;; --tcg-tests-cross-cflags-riscv64=*) quote_sh "-Dtcg_tests_cross_cflags_riscv64=$2" ;; diff --git a/tests/tcg/meson.build b/tests/tcg/meson.build index 4c0e30756d..5976540526 100644 --- a/tests/tcg/meson.build +++ b/tests/tcg/meson.build @@ -184,6 +184,7 @@ subdir('mipsel') subdir('mips64') subdir('mips64el') subdir('or1k') +subdir('ppc') subdir('ppc64') subdir('ppc64le') subdir('riscv64') diff --git a/tests/tcg/ppc/meson.build b/tests/tcg/ppc/meson.build new file mode 100644 index 0000000000..869b8906c5 --- /dev/null +++ b/tests/tcg/ppc/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2026 Process Mission + +subdir('system') diff --git a/tests/tcg/ppc/system/README b/tests/tcg/ppc/system/README new file mode 100644 index 0000000000..37a0fca951 --- /dev/null +++ b/tests/tcg/ppc/system/README @@ -0,0 +1,22 @@ +These Book E ISA tests use the generic tests/tcg build and test runner. +They run on ppce500 with e500mc, e5500 and e6500 CPU models. System mode +allows checking SRR0 and ESR on illegal instructions. The ppc target runs +e500mc in 32-bit computation mode; ppc64 runs e5500/e6500 in 64-bit mode. + +The cross compiler builds freestanding ELF32 executables for ppc with +-m32 and ELF64 executables for ppc64 with -m64. No target libc or +multilib runtime is needed. The boot stub uses the initial RAM mapping +provided by ppce500 -kernel, maps the CCSR area, and installs a program +exception handler. Results go to UART0, and the existing GPIO power-off +line terminates QEMU. The standard run_and_diff wrapper compares the +output with isa.out. + +Configure QEMU with ppc-softmmu and/or ppc64-softmmu enabled. Compilers +are found through the usual TCG cross-compiler detection or containers; +--cross-cc-ppc and --cross-cc-ppc64 can select them explicitly. Run with: + + make check-tcg-ppc-softmmu + make check-tcg-ppc64-softmmu + +These targets are generated only when configure finds a usable cross +compiler or container. If missing, check the TCG tests configure summary. diff --git a/tests/tcg/ppc/system/boot.S b/tests/tcg/ppc/system/boot.S new file mode 100644 index 0000000000..2176205bcc --- /dev/null +++ b/tests/tcg/ppc/system/boot.S @@ -0,0 +1,92 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2026 Process Mission + */ + +#include "macros.inc" + + .section .text.start, "ax" + .globl _start +_start: + /* Map CCSR at VA 0xfe000000 to PA 0xfe0000000 in TLB1[1] */ + load32 r3, 0x10010000 + mtspr SPR_BOOKE_MAS0, r3 /* MAS0 */ + load32 r3, 0xc0000500 + mtspr SPR_BOOKE_MAS1, r3 /* MAS1: valid, protected, 1 MiB */ + load32 r3, 0xfe00000a + mtspr SPR_BOOKE_MAS2, r3 /* MAS2: cache inhibited, guarded */ + load32 r3, 0xe000003f + mtspr SPR_BOOKE_MAS3, r3 /* MAS3: RPN and permissions */ + li r3, 15 + mtspr SPR_BOOKE_MAS7, r3 /* MAS7 */ + tlbwe + isync + + load_addr r3, vectors + mtspr SPR_BOOKE_IVPR, r3 /* IVPR */ + li r3, 0x600 + mtspr SPR_BOOKE_IVOR6, r3 /* IVOR6: program exception */ + li r14, 0 /* No program exception expected */ + +#ifdef _LP64 + load32 r3, 0x80002000 +#else + li r3, 0x2000 +#endif + mtmsr r3 /* Enable FP and select computation mode */ + isync + b test_main + + .section .vectors, "ax" +vectors: + .space 0x600 +program_exception: + mfspr r3, SPR_SRR0 /* SRR0 must name the illegal instruction */ +#ifdef _LP64 + cmpd r3, r14 +#else + cmpw r3, r14 +#endif + bne unexpected_exception + mfspr r3, SPR_BOOKE_ESR /* ESR must contain only PIL */ + load32 r5, 0x08000000 + cmpw r3, r5 + bne unexpected_exception + mtspr SPR_SRR0, r15 + rfi +unexpected_exception: + b fail + + .text + .globl pass, fail +pass: + load_addr r3, pass_message + b report +fail: + load_addr r3, fail_message +report: + load32 r4, 0xfe004500 /* UART0 */ + rlwinm r4, r4, 0, 0, 31 /* Zero extend the address on 64-bit cores */ +1: + lbz r5, 0(r3) + cmpwi r5, 0 + beq 2f + stb r5, 0(r4) + addi r3, r3, 1 + b 1b +2: + /* GPIO pin 0 is the ppce500 power-off line */ + load32 r4, 0xfe0ff000 + rlwinm r4, r4, 0, 0, 31 + load32 r5, 0x80000000 + stw r5, 0(r4) /* Direction: output */ + stw r5, 8(r4) /* Data: assert pin 0 */ +3: + b 3b + + .section .rodata +pass_message: + .asciz "ISA:PASS\n" +fail_message: + .asciz "ISA:FAIL\n" diff --git a/tests/tcg/ppc/system/isa.out b/tests/tcg/ppc/system/isa.out new file mode 100644 index 0000000000..34dabaf8bb --- /dev/null +++ b/tests/tcg/ppc/system/isa.out @@ -0,0 +1 @@ +ISA:PASS diff --git a/tests/tcg/ppc/system/kernel.ld b/tests/tcg/ppc/system/kernel.ld new file mode 100644 index 0000000000..3f18a3e087 --- /dev/null +++ b/tests/tcg/ppc/system/kernel.ld @@ -0,0 +1,18 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2026 Process Mission + */ + +ENTRY(_start) + +SECTIONS +{ + . = 0x100000; + .text : { *(.text.start) *(.text) } + . = ALIGN(0x10000); + .vectors : { *(.vectors) } + .rodata : { *(.rodata) } + .data : { *(.data) } + .bss : { *(.bss) } +} diff --git a/tests/tcg/ppc/system/macros.inc b/tests/tcg/ppc/system/macros.inc new file mode 100644 index 0000000000..ec58f68cbd --- /dev/null +++ b/tests/tcg/ppc/system/macros.inc @@ -0,0 +1,56 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2026 Process Mission + */ + +#define SPR_SRR0 0x01a +#define SPR_BOOKE_ESR 0x03e +#define SPR_BOOKE_IVPR 0x03f +#define SPR_BOOKE_IVOR6 0x196 +#define SPR_BOOKE_MAS0 0x270 +#define SPR_BOOKE_MAS1 0x271 +#define SPR_BOOKE_MAS2 0x272 +#define SPR_BOOKE_MAS3 0x273 +#define SPR_BOOKE_MAS7 0x3b0 + + .macro load32 reg, value + lis \reg, ((\value) >> 16) & 0xffff + ori \reg, \reg, (\value) & 0xffff + .endm + + .macro load_addr reg, symbol + lis \reg, \symbol@ha + addi \reg, \reg, \symbol@l + .endm + + .macro load_value reg, value +#ifdef _LP64 + load32 \reg, (\value) >> 32 + sldi \reg, \reg, 32 + oris \reg, \reg, ((\value) >> 16) & 0xffff + ori \reg, \reg, (\value) & 0xffff +#else + load32 \reg, \value +#endif + .endm + + .macro check_value reg, value + load_value r12, \value +#ifdef _LP64 + cmpd \reg, r12 +#else + cmpw \reg, r12 +#endif + bne fail + .endm + + .macro check_illegal insn:vararg + load_addr r14, 1f + load_addr r15, 2f +1: + \insn + b fail /* Executing the instruction is a failure */ +2: + li r14, 0 + .endm diff --git a/tests/tcg/ppc/system/meson.build b/tests/tcg/ppc/system/meson.build new file mode 100644 index 0000000000..1598348656 --- /dev/null +++ b/tests/tcg/ppc/system/meson.build @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2026 Process Mission + +# Shared settings and sources for the ppc and ppc64 system targets +ppc_system_link_script = files('kernel.ld')[0] +ppc_system_boot = files('boot.S')[0] +ppc_system_cflags = ['-nostdlib', '-ffreestanding', '-mcpu=power6', + '-Wa,-mregnames', '-Wa,--noexecstack', + '-Wl,--build-id=none', + '-Wl,-T', ppc_system_link_script, ppc_system_boot] +ppc_system_qemu_args = ['-M', 'ppce500', '-accel', 'tcg', '-display', 'none', + '-serial', 'stdio', '-monitor', 'none', '-nic', 'none'] +ppc_system_sources = ['unsupported.S'] + +tests = [] +foreach src: ppc_system_sources + tests += { + 'system/' + src: { + 'exe_name': fs.stem(src) + '-e500mc-32', + 'cflags': ppc_system_cflags + ['-m32', '-DE500MC'], + 'qemu_args': ppc_system_qemu_args + ['-cpu', 'e500mc', '-kernel'], + 'expected_output': 'system/isa.out', + } + } +endforeach + +if 'qemu-system-ppc' in emulators + tcg_tests += { + 'ppc-softmmu': { + 'cc': 'powerpc-linux-gnu-gcc', + 'cc_dockerfile': 'debian-all-test-cross', + 'folder': 'ppc', + 'gdb_arch': 'ppc', + 'qemu': emulators['qemu-system-ppc'], + 'tests': tests, + } + } +endif diff --git a/tests/tcg/ppc/system/unsupported.S b/tests/tcg/ppc/system/unsupported.S new file mode 100644 index 0000000000..1737646b35 --- /dev/null +++ b/tests/tcg/ppc/system/unsupported.S @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2026 Process Mission + */ + +#include "macros.inc" + + .text + .globl test_main +test_main: + /* Valid memory prevents address faults from hiding decode errors */ + load_addr r4, scratch + check_illegal fcpsgn f0, f0, f0 + check_illegal fcpsgn. f0, f0, f0 + check_illegal lfiwax f0, 0, r4 + check_illegal lfdp f0, 0(r4) + check_illegal lfdpx f0, 0, r4 + check_illegal stfdp f0, 0(r4) + check_illegal stfdpx f0, 0, r4 +#ifdef E500MC + check_illegal cmpb r11, r9, r10 + check_illegal prtyw r11, r9 + check_illegal prtyd r11, r9 +#endif + b pass + + .data + .balign 16 +scratch: + .space 16 diff --git a/tests/tcg/ppc64/meson.build b/tests/tcg/ppc64/meson.build index 8cca4d65a4..6aa79fff28 100644 --- a/tests/tcg/ppc64/meson.build +++ b/tests/tcg/ppc64/meson.build @@ -3,6 +3,8 @@ cc_feat_cflags = { 'power10': '-mcpu=power10', } +subdir('system') + tests = [] # Multi arch tests diff --git a/tests/tcg/ppc64/system/meson.build b/tests/tcg/ppc64/system/meson.build new file mode 100644 index 0000000000..ca398860e3 --- /dev/null +++ b/tests/tcg/ppc64/system/meson.build @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2026 Process Mission + +ppc64_system_cflags = ppc_system_cflags + ['-m64'] +tests = [] +foreach cpu: ['e5500', 'e6500'] + sources = ppc_system_sources + foreach src: sources + tests += { + '../ppc/system/' + src: { + 'exe_name': fs.stem(src) + '-' + cpu + '-64', + 'cflags': ppc64_system_cflags, + 'qemu_args': ppc_system_qemu_args + ['-cpu', cpu, '-kernel'], + 'expected_output': '../ppc/system/isa.out', + } + } + endforeach +endforeach + +if 'qemu-system-ppc64' in emulators + tcg_tests += { + 'ppc64-softmmu': { + 'cc': 'powerpc64-linux-gnu-gcc', + 'cc_dockerfile': 'debian-all-test-cross', + 'folder': 'ppc64', + 'gdb_arch': 'ppc64', + 'qemu': emulators['qemu-system-ppc64'], + 'tests': tests, + } + } +endif -- 2.53.0
