Cache clean of translation tables stops execution?

Hi,

I am currently working on an integrity enforcer running in a modified version of the ARM trusted firmware in EL3. To gain access to the memory I added 4 1GiB entries to the translation tables located in the TTBR0_EL3.

Now I am trying to hook the pagefault handler of the kernel and soon realized that the values read from the pt_regs struct in EL1 do not match up with what I read in EL3. I figured this may very well be due to caching issues as I was using device attributes to cause the least amount of trouble (as my GB mapping also spans across device memory). Interestingly enough I could use the `dc cvac` instruction in combination with my GB virtual address to clean the cache before accessing the struct and the values match up.

For my enforcer to work I need to parse and change the initial pagetables at a certain point. So for the sake of consistency I tried expanding the cache clean to every access on the translation table of EL1 and EL2 by placing a `asm volatile("dsb sy; dc cvac, %[address]; dsb sy")` before accessing the memory of the translation table. The scan runs without any noticeable issue and the changes are done but after returning to EL1 nothing happens anymore. To verify that I placed a printk right after the smc that causes the initial parsing and it does not print anything after that. It does continue exectution when I remove the `dc cvac` instruction before the translation table read.

I dont understand what part of the cache cleaning could interfere with code execution after the eret.

I tried different attributes in the MAIR_EL3 for my GB mapping as well (uncacheable Normal Memory, Write-{Back,Through} non-transient Normal Memory) but none of them behaved any different.

Is there any documentation towards how the data cache behaves in context changes and towards different ELs? I couldnt find any and am a little confused as I could clean the data cache with my EL3 virtual address but when setting the attributes to write-through normal memory I still didnt read the same values without cleaning the cache first. If I can clean that cache line with the address how come I do not read the values from it when reading?

Any help/hint/intuition is appreciated.

I am developing and testing on a LeMaker version Hikey Board (Kirin 620 SoC, ARM Cortex-A53 CPU) and building on the sources listed here.

Parents
  • So the execution stop issue should have been related to me removing write access to certain data areas of the kernel, probably including the printk buffer. As i was using printk in the pagefault itself I created an infinite loop.

    I didnt make any progress on the data reading however. I set my attributes to be the same as the kernel(0xFF) and TLBI ALLE3 but still read different values than printed by the kernel.

Reply
  • So the execution stop issue should have been related to me removing write access to certain data areas of the kernel, probably including the printk buffer. As i was using printk in the pagefault itself I created an infinite loop.

    I didnt make any progress on the data reading however. I set my attributes to be the same as the kernel(0xFF) and TLBI ALLE3 but still read different values than printed by the kernel.

Children
No data
More questions in this forum