Skip to content

qemu-system-arm regression: NonSecure World can change Secure World MMU mapping.

Host environment

  • Operating system: Windows, Linux
  • OS/kernel version: Windows 10, Linux 6.10.10
  • Architecture: Guest:x86, Host:ARM
  • QEMU flavor: qemu-system-arm
  • QEMU version: 9.1.0
  • QEMU command line: qemu-system-arm -machine mcimx6ul-evk -cpu cortex-a7 -m 512M -semihosting

Emulated/Virtualized environment

  • Operating system: ARM Bare Metal (TamaGo)
  • Architecture: ARM (ARMv7)

Description of problem

A NonSecure execution context is able to override MMU L1 translation table flags set by Secure context on Secure World memory.

This is not consistent with the same code running on real hardware and it's a regression over past qemu releases as 9.0.0 behaves correctly.

Steps to reproduce

This has been tested with GoTEE-example as follows:

# building tamago
wget https://github.com/usbarmory/tamago-go/archive/refs/tags/latest.zip
unzip latest.zip
cd tamago-go-latest/src && ./all.bash
cd ../bin && export TAMAGO=`pwd`/go

# building and running GoTEE-example
wget https://github.com/usbarmory/GoTEE-example/archive/refs/heads/master.zip
unzip master.zip
cd GoTEE-example
export TARGET=usbarmory && make clean && make nonsecure_os_go && make trusted_applet_go && make trusted_os && make qemu

Actual result (qemu 9.1.0)

qemu-system-arm -machine mcimx6ul-evk -cpu cortex-a7 -m 512M -nographic -monitor none -serial null -serial stdio -net none -semihosting -kernel bin/trusted_os_usbarmory.elf
tamago/arm (go1.23.1) • TEE security monitor (Secure World system/monitor)
...
> gotee
00:00:03 SM loaded applet addr:0x10000000 entry:0x100824fc size:5010875
00:00:03 SM loaded kernel addr:0x80000000 entry:0x800818e8 size:4475501
00:00:03 SM waiting for applet and kernel
00:00:03 SM starting mode:USR sp:0x12000000 pc:0x100824fc ns:false
00:00:03 SM starting mode:SYS sp:0x00000000 pc:0x800818e8 ns:true
00:00:03    r0:00000001  r1:00000030  r2:00000030  r3:80476050
00:00:03    r4:00000047  r5:804320c0  r6:00000047  r7:00000000
00:00:03    r8:80476050  r9:00000001 r10:8040a128 r11:8030668c cpsr:200001d7 (ABT)
00:00:03   r12:00000074  sp:8043acd4  lr:8017d1ac  pc:9800000c spsr:200001d6 (MON)
00:00:03 SM stopped mode:SYS sp:0x8043acd4 lr:0x8017d1ac pc:0x9800000c ns:true err:ABT
00:00:03        :0
00:00:03        :0
...

Expected result (qemu 9.0.0)

qemu-system-arm -machine mcimx6ul-evk -cpu cortex-a7 -m 512M -nographic -monitor none -serial null -serial stdio -net none -semihosting -kernel bin/trusted_os_usbarmory.elf
tamago/arm (go1.23.1) • TEE security monitor (Secure World system/monitor)
...
> gotee
00:00:02 SM loaded applet addr:0x10000000 entry:0x100824fc size:5010875
00:00:02 SM loaded kernel addr:0x80000000 entry:0x800818e8 size:4476055
00:00:02 SM waiting for applet and kernel
00:00:02 SM starting mode:USR sp:0x12000000 pc:0x100824fc ns:false
00:00:02 SM starting mode:SYS sp:0x00000000 pc:0x800818e8 ns:true
00:00:02 tamago/arm (go1.23.1) • TEE user applet
00:00:02 tamago/arm (go1.23.1) • system/supervisor (Non-secure:true)
00:00:02 supervisor is about to yield back
00:00:02 SM stopped mode:SYS sp:0x8043aee8 lr:0x8017cf44 pc:0x8017d360 ns:true err:<nil>
...

Additional information

The issue relates to the fact that the NonSecure World, at startup, configures the MMU with the NX bit for the entire address space not belonging to its firmware .text area.

On real hardware this MMU configuration by NonSecure world does not affect the Secure World translation tables.

On qemu 9.1.0, however it does and this is inconsistent with real hardware behavior. On qemu 9.0.0 the behaviour is correct so the issue has been introduced between these two releases.

The switch between Secure and NonSecure is done here.

The MMU first level address table which sets the NX bit is done here.

Possibly related issues

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information