Arm Community
Arm Community
  • Site
  • User
  • Site
  • Search
  • User
Arm Community blogs
Arm Community blogs
Architectures and Processors blog What is eXecute-Only-Memory (XOM)?
  • Blogs
  • Mentions
  • Sub-Groups
  • Tags
  • Jump...
  • Cancel
More blogs in Arm Community blogs
  • AI blog

  • Announcements

  • Architectures and Processors blog

  • Automotive blog

  • Embedded and Microcontrollers blog

  • Internet of Things (IoT) blog

  • Laptops and Desktops blog

  • Mobile, Graphics, and Gaming blog

  • Operating Systems blog

  • Servers and Cloud Computing blog

  • SoC Design and Simulation blog

  • Tools, Software and IDEs blog

Tell us what you think
Tags
  • Cortex-M
  • TrustZone
  • Tutorial
  • Memory
Actions
  • RSS
  • More
  • Cancel
Related blog posts
Related forum threads

What is eXecute-Only-Memory (XOM)?

Joseph Yiu
Joseph Yiu
July 3, 2017
5 minute read time.

An introduction to eXecute-only-Memory

eXecute-Only-Memory (XOM) is a firmware protection technique to help prevent 3rd parties from stealing or reverse engineering firmware, and at the same time allowing 3rd parties to add additional software to the chips and utilize the protected APIs in XOM. This technique is separated from chip-level, read-out-protection, which can block the read-back of the entire firmware.

eXecute-Only-Memory

How to enable XOM

To enable XOM, hardware system design arrangement is needed – it is impossible to implement XOM with just software. In a system with XOM, the bus system is designed so that a section of the program memory can be accessed only with instruction fetches. A transaction-filtering mechanism must be in place to enable this:

  • In systems with AHB/AHB5 bus protocol, bit 0 of the HPROT signals indicates if a transfer is an instruction fetch or a data access.
  • In system with AXI bus protocol, bit 2 of the ARPROT/AWPROT signals indicates if a transfer is an instruction fetch or a data access.

A data transfer to a XOM address range should be blocked, for example, by ignoring the transfer and return read data as 0. Instruction fetches are handled as normal. As a result, program stored in the XOM can be executed (the processor can fetch program code from XOM), but the program cannot be read back by debugger (debug accesses are marked as data transfers), or by other software running on the processor.

System designers must ensure that other bus masters in the systems (e.g. DMA controller) generate correct HPROT[0]/AxPROT[2] signal levels for the transfers.

Due to the nature of XOM, the program code placed in XOM cannot contain literal data. System designers must also make sure that exception vector tables are not placed inside XOM. To generate immediate data values in program sequences, the processor can use MOVW and MOVT instruction to generate 32-bit constants. Since Armv6-M architecture does not support MOVW and MOVT instructions, XOM is unsuitable for Cortex-M0 and Cortex-M0+ processors.

The XOM mechanism does not require Memory Protection Unit (MPU) – do not confuse XOM and XN (eXecute-Never) attribute in MPU. XN is a memory attribute to prevent a section of memory from being used as program memory.  For example, a communication data buffer can contain code injected by attackers using communication interface, and therefore, designers can mark such memory with XN to help prevent execution of injected code.

XOM mechanism is independent from TrustZone Security Extension. It can be used on Armv7-M or Armv8-M processors, with or without the TrustZone feature. XOM can coexist with TrustZone to allow software developers to protect their Secure firmware asset, even if the Secure programming environment needs to be accessible by a third party. It can also be used for protecting firmware in the Non-secure world.

Toolchain support

Since XOM program regions do not allow literal data accesses, compiler switches are implemented to handle XOM support.

In Arm Compiler 5, the “--execute_only” command line option is available.

In Arm Compiler 6, the “-mexecute-only” command line option is available.

gcc supports XOM in form of “-mpure-code” option and a PureCode attribute.

For users of Keil MDK (Microcontroller Development Kit), the eXecute-Only-Memory is support in project configuration GUI:

XOM Keil MDK

For users of IAR Embedded Workbench for Arm, eXecute-Only-Memory is also supported:

 XOM IAR Embedded Workbench for Arm

When XOM support option is used, in general, the performance of the applications could be reduced in some cases. For example, this can be caused by the restriction of not allowing table branches. However, in the cases where the memory system has wait states and cache systems are used, compiling code with XOM option can avoid cache misses in data cache and could help performance if cache miss rate in instruction cache is small.

Please note that the resulted code size could increase when using XOM options. 

Limitations of XOM protection

Although XOM can prevent program code from being read directly, data used by the application is not protected. For example, when a protected API is running, and the execution is halted, or interrupted by an interrupt handler, a software developer can observe the data in the register bank and SRAM (including stack contents).

It is also possible to use debug / frequent interrupts to try to ‘single step’ the protected firmware and guess the operations by observing the changes in register bank or memories. However, this requires significant effort, as the visibility is very limited. For example, a step that doesn’t have any register value change could be any of the following:

  • A store instruction that writes to a write-only location
  • A data processing instruction for which the result is the same as previous destination register value
  • Compare / Test instruction, with result flags unchanged
  • Conditional branch that is not taken or conditional execution that failed the required condition
  • Barrier/hint instruction

Nevertheless, such analysis can be automated, and therefore, chip designers should not rely on XOM on its own to protect critical software assets.

Design Considerations

  • Chip designers can make the XOM feature configurable. It can be made disabled when the chip is manufactured to allow software developers to debug the application easily, and enable it once the protected firmware is finalized and locked down.
  • Chip designs must use the bus transaction information to filter transactions. In the Cortex-M3 and Cortex-M4 processors, although the I-CODE bus does not have data accesses (they use D-CODE bus for data and debug accesses), it can still carry data accesses generated from exception vector accesses.
  • If the system contains cache memories, chip designers must ensure that the cached instructions cannot be read out by data accesses.  For example, if a unified cache (I+D) is used and if the cache is not XOM aware, it must not be used with XOM. Even for instruction caches, potentially cached instruction could be read out by BIST feature in the cache controller and that can bypass the protection.

Additional information

  • Arm Compiler Software Development Guide: 2.21 Execute-only memory
  • Whitepaper – Separating instructions and data with PureCode
Anonymous
  • Eric Zhang
    Eric Zhang over 5 years ago

    Great Article, It gives grate help to better understand XOM.

    Many thanks

    • Cancel
    • Up 0 Down
    • Reply
    • More
    • Cancel
  • armer junge
    armer junge over 5 years ago

    Great article, thank you.

    Can you please specify which ARM processors definately have XOM.

    Do all ARM-v8.1 based or ARM-v8.2 based have it or a certain Cortex-family?

    Or can someone list which mobile phones support XOM?

    Thank you in advance.

    • Cancel
    • Up 0 Down
    • Reply
    • More
    • Cancel
  • armer junge
    armer junge over 5 years ago

    Can you please list which ARM processors have XOM?

    Do all ARM-v8.1 have it? Or all ARM-v8.2?

    Thank you in advance.

    • Cancel
    • Up 0 Down
    • Reply
    • More
    • Cancel
Architectures and Processors blog
  • Introducing GICv5: Scalable and secure interrupt management for Arm

    Christoffer Dall
    Christoffer Dall
    Introducing Arm GICv5: a scalable, hypervisor-free interrupt controller for modern multi-core systems with improved virtualization and real-time support.
    • April 28, 2025
  • Getting started with AARCHMRS Features.json using Python

    Joh
    Joh
    A high-level introduction to the Arm Architecture Machine Readable Specification (AARCHMRS) Features.json with some examples to interpret and start to work with the available data using Python.
    • April 8, 2025
  • Advancing server manageability on Arm Neoverse Compute Subsystem (CSS) with OpenBMC

    Samer El-Haj-Mahmoud
    Samer El-Haj-Mahmoud
    Arm and 9elements Cyber Security have brought a prototype of OpenBMC to the Arm Neoverse Compute Subsystem (CSS) to advancing server manageability.
    • January 28, 2025