Re: [PATCH v9 00/10] arm64: Unmap FF-A lent memory from direct map

From: Vincent Donnefort

Date: Wed Sep 02 2026 - 09:35:10 EST


This is of course v1, not v9...

On Wed, Sep 02, 2026 at 11:47:02AM +0100, Vincent Donnefort wrote:
> This series is a follow-up to the discussion that has started here [1].
> While standalone, it also provides primitives reusable for the VPR DMA
> heap.
>
> When memory is lent to the Secure world via FF-A, CPU speculative
> accesses from NS to the lent pages can still occur as long as it retains
> a cacheable mapping to it.
>
> Ideally, lent memory would be "no-map" but that would mean giving up
> MiBs of useful memory, so let's try to do better with the help of a CMA
> pool.
>
> On arm64, modifying the direct map at runtime is generally restricted
> because the linear map defaults to block mapping and splitting blocks at
> runtime may trigger fatal page fault, unless the CPU implements BBML3
> or the entire direct map was mapped at page granularity from boot.
> Forcing last-level mappings system-wide incurs a severe penalty we want
> to avoid. Instead, this series introduces targeted last-level mappings
> for designated memory regions, along with the "arm,ffa-lend-pool" CMA
> driver to manage unmapping and remapping on lend/reclaim transitions:
>
> 1. memblock & OF reserved memory ("ll-map"):
> - Introduce MEMBLOCK_LLMAP and the DT "ll-map" property for reserved-memory
> nodes to force last-level (PTE) mappings only for a specific region.
>
> 2. set_memory infrastructure:
> - Introduce can_set_direct_map_range() to check if a specific address
> range is mapped with last-level entries and can be modified safely.
> - Introduce __set_direct_map_*() variants that bypass redundant checks
> when the caller has already validated the range.
>
> 3. "arm,ffa-lend-pool" driver
> - Introduce the "arm,ffa-lend-pool" CMA reserved-memory driver, which
> unmaps pages prior to lending (ffa_prepare_lend()) and restores them
> when reclaimed (ffa_lend_reclaimed()).
>
> 4. Optee support
> - Hook OP-TEE dynamic protected memory pools to "arm,ffa-lend-pool" for
> both SMC (via DT memory-region phandle) and FF-A (via
> ffa_lend_pool_attach()) transports.
>
> Testing:
> ========
>
> Tested with QEMU v8 using OP-TEE OS (built with CFG_CORE_DYN_PROTMEM=y)
> under both SMC and FF-A transports [2]
>
> static void dump_direct_map(const char *label)
> {
> printf("\n=== %s ===\n", label);
> fflush(stdout);
> system("sed -n '/Linear Mapping start/,/Linear Mapping end/p' /sys/kernel/debug/kernel_page_tables");
> fflush(stdout);
> }
>
> int main(int argc, char *argv[])
> {
> int heap_fd;
> int dmabuf_fd;
> struct dma_heap_allocation_data data = { 0 };
> size_t size = 1024 * 1024; /* 1MB */
>
> if (argc > 1)
> size = strtoul(argv[1], NULL, 0);
>
> dump_direct_map("BEFORE ALLOCATION");
>
> heap_fd = open("/dev/dma_heap/protected,secure-video", O_RDWR);
> if (heap_fd < 0) {
> perror("open /dev/dma_heap/protected,secure-video");
> return 1;
> }
>
> printf("\nOpened /dev/dma_heap/protected,secure-video\n");
> printf("Allocating %zu bytes of protected memory via DMA heap...\n", size);
>
> data.len = size;
> data.fd_flags = O_RDWR | O_CLOEXEC;
> if (ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &data) < 0) {
> perror("ioctl DMA_HEAP_IOCTL_ALLOC");
> close(heap_fd);
> return 1;
> }
>
> dmabuf_fd = data.fd;
> printf("Successfully allocated %zu bytes! dmabuf_fd = %d\n", size, dmabuf_fd);
>
> dump_direct_map("DURING LEND (EXPECT HOLE IN DIRECT MAP)");
>
> printf("\nReleasing dmabuf_fd...\n");
> close(dmabuf_fd);
> close(heap_fd);
>
> dump_direct_map("AFTER RECLAIM (RESTORED DIRECT MAP)");
>
> return 0;
> }
>
> [1] https://lore.kernel.org/all/20260807-tegra-vpr-v4-7-5510d16af89e@xxxxxxxxxx/
> [2] https://optee.readthedocs.io/en/latest/building/gits/build.html#qemu-v8
>
> Vincent Donnefort (10):
> memblock: Introduce MEMBLOCK_LLMAP
> of: reserved_mem: Introduce "ll-map" property
> set_memory.h: Introduce can_set_direct_map_range()
> set_memory.h: Introduce __set_direct_map*()
> arm64: can_set_direct_map() if BBML3
> arm64: Implement can_set_direct_map_range()
> arm64: Implement __set_direct_map*()
> arm64: Add support for MEMBLOCK_LLMAP
> firmware: arm_ffa: Introduce ffa-lend-pool
> optee: Add support for arm,ffa-lend-pool
>
> arch/arm64/include/asm/set_memory.h | 7 +
> arch/arm64/mm/mmu.c | 23 ++-
> arch/arm64/mm/pageattr.c | 67 +++++++-
> drivers/firmware/arm_ffa/Kconfig | 5 +
> drivers/firmware/arm_ffa/Makefile | 1 +
> drivers/firmware/arm_ffa/lend_pool.c | 223 +++++++++++++++++++++++++++
> drivers/of/of_reserved_mem.c | 104 ++++++++++---
> drivers/tee/optee/ffa_abi.c | 13 +-
> drivers/tee/optee/protmem.c | 8 -
> drivers/tee/optee/smc_abi.c | 17 +-
> drivers/tee/tee_shm.c | 11 +-
> include/linux/arm_ffa.h | 21 +++
> include/linux/memblock.h | 9 ++
> include/linux/set_memory.h | 39 +++++
> mm/memblock.c | 50 ++++++
> 15 files changed, 545 insertions(+), 53 deletions(-)
> create mode 100644 drivers/firmware/arm_ffa/lend_pool.c
>
>
> base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
> --
> 2.55.0.970.g62bdec98f9-goog
>

--
Vincent