FEAT_RME: NS EL1/0 Address Translation from EL3 fails

Host environment

  • Operating system: Arch Linux
  • OS/kernel version: 6.8.1-zen1-1-zen
  • Architecture: x86
  • QEMU flavor: qemu-system-aarch64
  • QEMU version: 8.2.91; master branch commit 5012e522
  • QEMU command line: qemu-system-aarch64 -machine virt,secure=on,gic-version=3,virtualization=on,iommu=smmuv3,ras=on -cpu max,x-rme=on -m 1G -icount 4 -smp 1

Emulated/Virtualized environment

  • Operating system: Linux
  • OS/kernel version: Linux version 6.2.0-rc1
  • Architecture: aarch64

Description of problem

I'm playing around with the QEMU RME Stack (TF-A, TF-RMM, Linux/KVM) for a research project.
For this I want to access some virtual normal world memory address from within EL3. To translate the address to the physical address I use the AT instructions (e.g., ats1e2r).
If the NW memory is initially mapped in the GPT as GPT_GPI_ANY, this works fine, however, if the NW memory is mapped as GPT_GPI_NS the address translation fails with the error 0b100101/GPT on PTW.
However, EL3/Root World should be able to access memory from all PAS, and therefore, if I understand the ARM documentation correctly, should also be able to execute a PTW for an address marked NS in the GPT.

Steps to reproduce

  1. Setup GPT with some memory marked as GPT_GPI_NS
  2. Forward some NW virtual address from the kernel to EL3
  3. Execute a PTW on this address via the AT instructions.

Additional information

I also took a look into the QEMU source code and potentially found the issue.
When executing a PTW we execute target/arm/ptw.c:granule_protection_check.
The function extracts the target page's GPI (`ptw.c:440'):

 switch (gpi) {
    case 0b0000: /* no access */
        break;
    case 0b1111: /* all access */
        return true;
    case 0b1000:
    case 0b1001:
    case 0b1010:
    case 0b1011:
        if (pspace == (gpi & 3)) {
            return true;
        }
        break;
    default:
        goto fault_walk; /* reserved */
    }

The if statement checks if the current pstate (previously set to ptw->in_space) is the same security state as the one contained in the GPI.
If this is not the case, we generate a GPF.
However, I think the code misses the fact, that EL3/Root world can access memory from each PAS, meaning that the if statement should be something like

if (pspace == (gpi & 3) || (pspace == ARMSS_Root)) {
            return true;
}

Additionally, as both Secure and Realm World can also access Normal World memory, similar checks should also be added in such cases.

I have a patch prepared for this, however, I first want to check in if I'm in line with the Arm ARM or if I'm missing something and EL3 is indeed not supposed to execute PTWs for NS memory.