Gilles Grimaud <[email protected]> writes:

> From: gilles grimaud <[email protected]>
>
> Build Cortex-M0+ guest programs from assembly sources to exercise the
> minimal Pico boot path, UART0 output, and the Cortex-M0+ MPU. Keep the
> vector table at the XIP base so these tests match the initial
> synthetic boot stub without depending on boot2 or the later flash
> controller model.
>
> Signed-off-by: gilles grimaud <[email protected]>
> ---
>  MAINTAINERS                            |   1 +
>  tests/tcg/arm/Makefile.softmmu-target  |  24 ++++

Just FYI there is an update coming to tests/tcg that converts the build
to meson. The change should be relatively mechanical to make.

>  tests/tcg/arm/system/rp2040-boot.S     |  30 ++++
>  tests/tcg/arm/system/rp2040-minimal.ld |  40 ++++++
>  tests/tcg/arm/system/rp2040-mpu.S      | 183 +++++++++++++++++++++++++
>  tests/tcg/arm/system/rp2040-mpu.ref    |   5 +
>  tests/tcg/arm/system/rp2040-uart.S     |  53 +++++++
>  tests/tcg/arm/system/rp2040-uart.ref   |   1 +
>  8 files changed, 337 insertions(+)
>  create mode 100644 tests/tcg/arm/system/rp2040-boot.S
>  create mode 100644 tests/tcg/arm/system/rp2040-minimal.ld
>  create mode 100644 tests/tcg/arm/system/rp2040-mpu.S
>  create mode 100644 tests/tcg/arm/system/rp2040-mpu.ref
>  create mode 100644 tests/tcg/arm/system/rp2040-uart.S
>  create mode 100644 tests/tcg/arm/system/rp2040-uart.ref
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8fd7385d83..b000b3287d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1042,6 +1042,7 @@ S: Maintained
>  F: hw/*/rp2040*
>  F: include/hw/*/rp2040*
>  F: hw/arm/raspi_pico.c
> +F: tests/tcg/arm/system/rp2040*
>  
>  Real View
>  M: Peter Maydell <[email protected]>
> diff --git a/tests/tcg/arm/Makefile.softmmu-target 
> b/tests/tcg/arm/Makefile.softmmu-target
> index 3e8a9b4073..429416ca58 100644
> --- a/tests/tcg/arm/Makefile.softmmu-target
> +++ b/tests/tcg/arm/Makefile.softmmu-target
> @@ -20,6 +20,30 @@ run-test-armv6m-undef: QEMU_OPTS=-semihosting-config 
> enable=on,target=native,cha
>  
>  ARM_TESTS+=test-armv6m-undef
>  
> +RP2040_TESTS=rp2040-boot rp2040-uart rp2040-mpu
> +
> +$(RP2040_TESTS): %: %.S rp2040-minimal.ld
> +     $(CC) -mcpu=cortex-m0plus -mthumb -mfloat-abi=soft \
> +             -Wl,--build-id=none -x assembler-with-cpp \
> +             $< -o $@ -nostdlib -static \
> +             -T $(ARM_SRC)/rp2040-minimal.ld
> +
> +run-rp2040-boot: QEMU_OPTS=-M raspi-pico \
> +     -semihosting-config enable=on,target=native -kernel
> +
> +run-rp2040-uart run-rp2040-mpu: QEMU_OPTS=-M raspi-pico \
> +     -serial chardev:output \
> +     -semihosting-config enable=on,target=native -kernel
> +
> +run-rp2040-uart run-rp2040-mpu: run-rp2040-%: rp2040-%
> +     $(call run-test, $<, \
> +       $(QEMU) -monitor none -display none \
> +               -chardev file$(COMMA)path=$<.out$(COMMA)id=output \
> +               $(QEMU_OPTS) $<)
> +     $(call diff-out,$<,$(ARM_SRC)/$<.ref)
> +
> +ARM_TESTS+=$(RP2040_TESTS)
> +
>  # These objects provide the basic boot code and helper functions for all 
> tests
>  CRT_OBJS=boot.o
>  
> diff --git a/tests/tcg/arm/system/rp2040-boot.S 
> b/tests/tcg/arm/system/rp2040-boot.S
> new file mode 100644
> index 0000000000..0537a54d44
> --- /dev/null
> +++ b/tests/tcg/arm/system/rp2040-boot.S
> @@ -0,0 +1,30 @@
> +/*
> + * Raspberry Pi Pico boot smoke test.
> + *
> + * Copyright 2026 Gilles Grimaud
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +.syntax unified
> +.cpu cortex-m0plus
> +.thumb
> +
> +#define SRAM_END 0x20042000
> +#define SYS_EXIT 0x18
> +#define ADP_STOPPED_APPLICATION_EXIT 0x20026
> +
> +.section .vectors, "a", %progbits
> +vector_table:
> +    .word SRAM_END
> +    .word reset_handler + 1
> +
> +.section .text, "ax", %progbits
> +.thumb_func
> +.global reset_handler
> +reset_handler:
> +    movs r0, SYS_EXIT
> +    ldr r1, =ADP_STOPPED_APPLICATION_EXIT
> +    bkpt 0xab
> +
> +1:
> +    b 1b
> diff --git a/tests/tcg/arm/system/rp2040-minimal.ld 
> b/tests/tcg/arm/system/rp2040-minimal.ld
> new file mode 100644
> index 0000000000..ebfbac8cf2
> --- /dev/null
> +++ b/tests/tcg/arm/system/rp2040-minimal.ld
> @@ -0,0 +1,40 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +ENTRY(reset_handler)
> +
> +MEMORY
> +{
> +    FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 2M
> +    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
> +}
> +
> +SECTIONS
> +{
> +    .vectors ORIGIN(FLASH) :
> +    {
> +        KEEP(*(.vectors))
> +    } > FLASH
> +
> +    .text :
> +    {
> +        *(.text*)
> +        *(.rodata*)
> +    } > FLASH
> +
> +    .data :
> +    {
> +        *(.data*)
> +    } > SRAM AT > FLASH
> +
> +    .bss (NOLOAD) :
> +    {
> +        *(.bss*)
> +        *(COMMON)
> +    } > SRAM
> +
> +    /DISCARD/ :
> +    {
> +        *(.ARM.attributes)
> +        *(.comment)
> +    }
> +}
> diff --git a/tests/tcg/arm/system/rp2040-mpu.S 
> b/tests/tcg/arm/system/rp2040-mpu.S
> new file mode 100644
> index 0000000000..a3aef55f5f
> --- /dev/null
> +++ b/tests/tcg/arm/system/rp2040-mpu.S
> @@ -0,0 +1,183 @@
> +/*
> + * Raspberry Pi Pico Cortex-M0+ MPU test.
> + *
> + * Copyright 2026 Gilles Grimaud
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +.syntax unified
> +.cpu cortex-m0plus
> +.thumb
> +
> +#define SRAM_END 0x20042000
> +#define TEST_ADDRESS 0x20001000
> +#define TEST_VALUE 0x12345678
> +#define UART0_DR 0x40034000
> +#define MPU_TYPE 0xe000ed90
> +#define MPU_CTRL 0xe000ed94
> +#define MPU_RNR 0xe000ed98
> +#define MPU_RBAR 0xe000ed9c
> +#define MPU_RASR 0xe000eda0
> +#define MPU_TYPE_DREGION_MASK 0x0000ff00
> +#define MPU_TYPE_DREGION_SHIFT 8
> +#define MPU_CTRL_ENABLE_PRIVDEFENA 0x05
> +#define MPU_RASR_SRAM_FULL_ACCESS 0x03000025
> +#define MPU_RASR_XIP_READ_ONLY 0x06000039
> +#define MPU_RASR_TEST_PRIV_RW 0x0100000f
> +#define SYS_EXIT 0x18
> +#define ADP_STOPPED_APPLICATION_EXIT 0x20026
> +#define ADP_STOPPED_RUNTIME_ERROR 0x20023
> +
> +.section .vectors, "a", %progbits
> +vector_table:
> +    .word SRAM_END
> +    .word reset_handler + 1
> +    .word default_handler + 1
> +    .word hardfault_handler + 1
> +
> +.section .text, "ax", %progbits
> +.thumb_func
> +.global reset_handler
> +reset_handler:
> +    ldr r0, =start_message
> +    bl puts
> +
> +    ldr r0, =MPU_TYPE
> +    ldr r0, [r0]
> +    ldr r1, =MPU_TYPE_DREGION_MASK
> +    ands r0, r1
> +    lsrs r0, r0, MPU_TYPE_DREGION_SHIFT
> +    cmp r0, 8
> +    bne fail_type
> +
> +    ldr r0, =type_message
> +    bl puts
> +
> +    ldr r4, =TEST_ADDRESS
> +    ldr r5, =TEST_VALUE
> +    str r5, [r4]
> +    ldr r0, [r4]
> +    cmp r0, r5
> +    bne fail_plain
> +
> +    ldr r0, =plain_message
> +    bl puts
> +
> +    movs r0, 0
> +    ldr r1, =0x20000000
> +    ldr r2, =MPU_RASR_SRAM_FULL_ACCESS
> +    bl configure_region
> +
> +    movs r0, 1
> +    movs r1, 0
> +    ldr r2, =MPU_RASR_XIP_READ_ONLY
> +    bl configure_region
> +
> +    movs r0, 2
> +    ldr r1, =TEST_ADDRESS
> +    ldr r2, =MPU_RASR_TEST_PRIV_RW
> +    bl configure_region
> +
> +    ldr r0, =MPU_CTRL
> +    movs r1, MPU_CTRL_ENABLE_PRIVDEFENA
> +    str r1, [r0]
> +    dsb
> +    isb
> +
> +    ldr r0, [r4]
> +    cmp r0, r5
> +    bne fail_privileged
> +
> +    ldr r0, =privileged_message
> +    bl puts
> +
> +    movs r0, 1
> +    msr control, r0
> +    isb
> +
> +    ldr r0, [r4]
> +    ldr r0, =fail_no_fault_message
> +    b test_failed
> +
> +.thumb_func
> +configure_region:
> +    ldr r3, =MPU_RNR
> +    str r0, [r3]
> +    ldr r3, =MPU_RBAR
> +    str r1, [r3]
> +    ldr r3, =MPU_RASR
> +    str r2, [r3]
> +    bx lr
> +
> +fail_type:
> +    ldr r0, =fail_type_message
> +    b test_failed
> +
> +fail_plain:
> +    ldr r0, =fail_plain_message
> +    b test_failed
> +
> +fail_privileged:
> +    ldr r0, =fail_privileged_message
> +
> +test_failed:
> +    bl puts
> +    movs r0, SYS_EXIT
> +    ldr r1, =ADP_STOPPED_RUNTIME_ERROR
> +    bkpt 0xab
> +
> +1:
> +    b 1b
> +
> +.thumb_func
> +hardfault_handler:
> +    ldr r0, =ok_message
> +    bl puts
> +    movs r0, SYS_EXIT
> +    ldr r1, =ADP_STOPPED_APPLICATION_EXIT
> +    bkpt 0xab
> +
> +2:
> +    b 2b
> +
> +.thumb_func
> +default_handler:
> +    ldr r0, =fail_exception_message
> +    b test_failed
> +
> +.thumb_func
> +puts:
> +    ldr r2, =UART0_DR
> +
> +3:
> +    ldrb r1, [r0]
> +    cmp r1, 0
> +    beq 4f
> +    str r1, [r2]
> +    adds r0, 1
> +    b 3b
> +
> +4:
> +    bx lr
> +
> +.section .rodata, "a", %progbits
> +start_message:
> +    .asciz "PICO TCG MPU START\n"
> +type_message:
> +    .asciz "PICO TCG MPU TYPE\n"
> +plain_message:
> +    .asciz "PICO TCG MPU PLAIN\n"
> +privileged_message:
> +    .asciz "PICO TCG MPU PRIV\n"
> +ok_message:
> +    .asciz "PICO TCG MPU OK\n"
> +fail_type_message:
> +    .asciz "PICO TCG MPU FAIL: TYPE\n"
> +fail_plain_message:
> +    .asciz "PICO TCG MPU FAIL: PLAIN\n"
> +fail_privileged_message:
> +    .asciz "PICO TCG MPU FAIL: PRIV\n"
> +fail_no_fault_message:
> +    .asciz "PICO TCG MPU FAIL: NOFAULT\n"
> +fail_exception_message:
> +    .asciz "PICO TCG MPU FAIL: EXCEPTION\n"
> diff --git a/tests/tcg/arm/system/rp2040-mpu.ref 
> b/tests/tcg/arm/system/rp2040-mpu.ref
> new file mode 100644
> index 0000000000..e55590ea16
> --- /dev/null
> +++ b/tests/tcg/arm/system/rp2040-mpu.ref
> @@ -0,0 +1,5 @@
> +PICO TCG MPU START
> +PICO TCG MPU TYPE
> +PICO TCG MPU PLAIN
> +PICO TCG MPU PRIV
> +PICO TCG MPU OK
> diff --git a/tests/tcg/arm/system/rp2040-uart.S 
> b/tests/tcg/arm/system/rp2040-uart.S
> new file mode 100644
> index 0000000000..bdb58cc7f2
> --- /dev/null
> +++ b/tests/tcg/arm/system/rp2040-uart.S
> @@ -0,0 +1,53 @@
> +/*
> + * Raspberry Pi Pico UART boot smoke test.
> + *
> + * Copyright 2026 Gilles Grimaud
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +.syntax unified
> +.cpu cortex-m0plus
> +.thumb
> +
> +#define SRAM_END 0x20042000
> +#define UART0_DR 0x40034000
> +#define SYS_EXIT 0x18
> +#define ADP_STOPPED_APPLICATION_EXIT 0x20026
> +
> +.section .vectors, "a", %progbits
> +vector_table:
> +    .word SRAM_END
> +    .word reset_handler + 1
> +    .word default_handler + 1
> +    .word default_handler + 1
> +
> +.section .text, "ax", %progbits
> +.thumb_func
> +.global reset_handler
> +reset_handler:
> +    ldr r0, =UART0_DR
> +    ldr r1, =message
> +
> +1:
> +    ldrb r2, [r1]
> +    cmp r2, 0
> +    beq 2f
> +    str r2, [r0]
> +    adds r1, 1
> +    b 1b
> +
> +2:
> +    movs r0, SYS_EXIT
> +    ldr r1, =ADP_STOPPED_APPLICATION_EXIT
> +    bkpt 0xab
> +
> +3:
> +    b 3b
> +
> +.thumb_func
> +default_handler:
> +    b default_handler
> +
> +.section .rodata, "a", %progbits
> +message:
> +    .asciz "PICO TCG UART OK\n"
> diff --git a/tests/tcg/arm/system/rp2040-uart.ref 
> b/tests/tcg/arm/system/rp2040-uart.ref
> new file mode 100644
> index 0000000000..1ef16e8299
> --- /dev/null
> +++ b/tests/tcg/arm/system/rp2040-uart.ref
> @@ -0,0 +1 @@
> +PICO TCG UART OK

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro

Reply via email to