Skip to content

Support Direct Physical Memory Mapping to TA Address Space #7786

Description

@yemiaobing

Background

In secure media processing scenarios, we have hardware-protected memory regions (enforced by hardware firewall) that need to be accessed by Trusted Applications (TAs). The typical use case is:

  1. Hardware demux writes audio/video data directly to a secure memory buffer
  2. REE (Normal World) CPU cannot access this memory due to hardware firewall protection
  3. REE only knows the physical address and passes it to the TA
  4. TA needs to access this memory for decoding/processing

Current Limitations

Currently, OP-TEE's mobj mechanism has strict restrictions on memory types:

1. mobj_phys_alloc() only supports 4 predefined memory types:

enum buf_is_attr {
    CORE_MEM_TEE_RAM,
    CORE_MEM_TA_RAM,
    CORE_MEM_NSEC_SHM,
    CORE_MEM_SDP_MEM,
};

For arbitrary hardware-protected physical memory regions (e.g., secure audio/video buffers allocated by hardware), none of these types apply.

2. mobj_reg_shm_alloc() only accepts non-secure memory:

/* Only Non-secure memory can be mapped there */
if (!core_pbuf_is(CORE_MEM_NON_SEC, mobj_reg_shm->pages[i],
                  SMALL_PAGE_SIZE))
    goto err;

This prevents mapping secure physical memory regions.

3. Cannot use shared memory approach:

  • REE cannot access the memory (hardware firewall)
  • Even if mapped as non-cacheable, REE's CPU cache might leak sensitive data
  • Violates the security model

Current Workaround

We currently work around this by implementing a PTA-based proxy:

// PTA maps physical memory in kernel space
static TEE_Result xdev_map_phys_region(uint32_t instance_id, ...) {
    kva = (vaddr_t)core_mmu_add_mapping(MEM_AREA_RAM_SEC, pa, len);
    // Store kva, TA accesses via PTA read/write calls
}

// TA calls PTA for each read/write operation
utee_xdev_read_phys_region(handle, offset, buf, len);
utee_xdev_write_phys_region(handle, offset, buf, len);

Drawbacks:

  • Every memory access requires a trap to secure world (performance overhead)
  • Cannot directly access memory from TA
  • More complex code structure

Proposed Solution

Add support for mapping arbitrary physical memory regions directly to TA address space, with proper security controls.

Option 1: Extend mobj_phys_alloc() with a new memory type

enum buf_is_attr {
    CORE_MEM_TEE_RAM,
    CORE_MEM_TA_RAM,
    CORE_MEM_NSEC_SHM,
    CORE_MEM_SDP_MEM,
    CORE_MEM_SECURE_DEVICE,  // New: for hardware-protected regions
};

Option 2: Add a new API for arbitrary physical memory mapping

/**
 * mobj_phys_alloc_unchecked() - Create mobj for arbitrary physical memory
 * @pa:         Physical address
 * @size:       Size in bytes
 * @mem_type:   Memory type attributes (cache, etc.)
 * 
 * This function creates an mobj for arbitrary physical memory without
 * security checks. Caller (PTA) is responsible for ensuring the physical
 * address is valid and accessible in secure world.
 */
struct mobj *mobj_phys_alloc_unchecked(paddr_t pa, size_t size, 
                                       uint32_t mem_type);

Option 3: Add PTA helper for mapping to TA address space

/**
 * pta_map_phys_to_ta() - Map physical memory to calling TA's address space
 * @pa:         Physical address
 * @size:       Size in bytes
 * @prot:       Protection flags (TEE_MATTR_UR, TEE_MATTR_UW)
 * @flags:      Mapping flags (cached/non-cached)
 * @va:         [out] Virtual address in TA's address space
 * 
 * Returns TEE_SUCCESS or error code
 */
TEE_Result pta_map_phys_to_ta(paddr_t pa, size_t size, uint32_t prot,
                               uint32_t flags, vaddr_t *va);

Use Case Example

// In TA:
TEE_Result decode_audio(uint64_t secure_audio_pa, uint32_t size) {
    void *audio_buffer;
    
    // Map physical memory directly to TA address space
    TEE_Result res = map_secure_phys_region(secure_audio_pa, size,
                                             TEE_MATTR_UR,
                                             &audio_buffer);
    if (res != TEE_SUCCESS)
        return res;
    
    // Direct access - no PTA calls needed
    uint8_t *data = (uint8_t *)audio_buffer;
    parse_audio_frame(data, size);
    decode_audio_frame(data, size);
    
    unmap_secure_phys_region(audio_buffer);
    return TEE_SUCCESS;
}

Security Considerations

  1. Access Control: Only PTAs should be able to create such mappings, not TAs directly
  2. Validation: PTA should validate that the physical address is within allowed ranges
  3. Isolation: Each TA session should only access its own mapped regions
  4. Cleanup: Automatic cleanup when TA session closes

Benefits

  1. Performance: Zero-copy, direct memory access from TA
  2. Simplicity: Cleaner code, no PTA proxy needed for every access
  3. Flexibility: Supports various hardware-protected memory scenarios (DRM, secure camera, etc.)
  4. Standard: Aligns with how other TEE implementations handle secure memory

Questions

  1. Is there a security reason why arbitrary physical memory mapping is not supported?
  2. Would any of the proposed solutions be acceptable?
  3. Are there alternative approaches we should consider?

Environment

  • OP-TEE Version: 4.1.0
  • Platform: ARM64
  • Use Case: Secure audio/video processing with hardware firewall protection

Thank you for considering this feature request!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions