I'm on an embedded system (Zynq from Xilinx. It uses ARMv7, Cortex-A9), and running Linux. I need to ensure that no access to a certain physical memory range is ever made, either accidentally by the kernel-space or the user. I can signal, data abort, or anything else, but that hardware attempt must not go further than the MMU.

In bare-metal mode and U-Boot, I have direct access to the TLB's location, and can restrict memory access on a hardware level by configuring the MMU to data abort should any read or write access occur. I want to do this in Linux, where even a mmap() would throw a data abort.

The reasoning:

In Zynq, 2GB of address space is allocated to a range that might never respond on a hardware level. ARM's AXI/AMBA protocol says that a host can never "give up" on an attempt to access an address, even if nothing is there. If I de-reference a pointer where no hardware resides, the entire chip hangs.

I know I can "just not give sudo" or "just write good drivers", but this is before that level even. I want to, in the early boot, set up the MMU's TLB to completely data abort if my super user does some bad coding. I'd rather not hack boot.S, but modify the TLB directly, then use the API to flush it.

  • I'm looking into page table entries; perhaps those can set all attributes of an MMU? – IDLacrosseplayer Jun 24 '15 at 1:35
  • Umm... if the system memory map tells the kernel that isn't a valid address range, then it won't ever try to use it, at least barring some bug that is just as likely to just corrupt some other random, but valid ram and crash the system anyhow. – psusi Jun 24 '15 at 21:55

The Linux kernel has options to restrict what physical address ranges it will use as RAM, but that won't prevent buggy drivers or access through /dev/mem to escape those ranges. You won't gain anything from modifying the MMU configuration during the boot stage, because the kernel will take control of the MMU after that anyway. If you want to be absolutely sure that the Linux system won't access certain memory ranges, you need some external control.

Your architecture offers a way to restrict what the Linux kernel can access: TrustZone (or more precisely TrustZone plus the memory firewall)¹. I doubt that you'll find a turnkey solution for what you're doing, you'll need to do a bit of coding. Fortunately, documentation about TrustZone on Zync is available. Here's the basic idea:

  • The processor boots in S mode. Set up the TrustZone control registers to disable non-secure access in that bad 2GB range.
  • Once this is done, switch to NS mode and branch to the normal bootloader.
  • If Linux tries to access the blocked 2GB range, the request will be blocked before it reaches the memory bus, and will instead trigger an abort (imprecise abort, if any caching or prefetching is involved).

¹ Recent ARM processors offer another way, which is to run a hypervisor, but that isn't available on a Cortex-A9.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.