kernel 6.12.57-ti-arm64-r64: sa2ul crypto driver oopses on iwd

I’m working with Claude to get Bone AI64 C7x working with my project: GitHub - jonreal/openWearable · GitHub

Lot’s of progress and I think we’re close but ran into this and wanted to share in case anyone else has seen the issue. We upgraded the kernel to linux-image-6.12.57-ti-arm64-r64 then iwctl stopped working – here is the summary:

Title: kernel 6.12.57-ti-arm64-r64: sa2ul crypto driver oopses on iwd
startup
(AF_ALG), kills WiFi — root cause + workaround

Board: BeagleBone AI-64 (TDA4VM/J721E), Debian Bookworm (2024-09-04 minimal
image)
Kernel: linux-image-6.12.57-ti-arm64-r64 (also expected on any build
carrying
TI’s sa2ul rework)
Works fine on: 6.12.17-ti-arm64-r33

Symptom

After upgrading from r33 to r64, iwd segfaults in a restart loop at boot
and WiFi
(USB mt7601u dongle) never comes up:

iwd.service: Main process exited, code=killed, status=11/SEGV
iwd.service: Start request repeated too quickly.

But it’s not an iwd bug — dmesg shows the kernel itself oopses (and is left
tainted G D )
every time iwd starts:

[    8.275200] Unable to handle kernel paging request at virtual address

ffffffff80000140
[ 8.275244] Internal error: Oops: 0000000096000145 [#1] PREEMPT_RT SMP
[ 8.275294] CPU: 0 UID: 0 PID: 583 Comm: iwd Not tainted 6.12.57-ti-
arm64-r64 #1
[ 8.275299] Hardware name: BeagleBoard.org BeagleBone AI-64 … (DT)
[ 8.275306] pc : dcache_inval_poc+0x28/0x58
[ 8.275317] lr : arch_sync_dma_for_cpu+0x34/0x50
[ 8.275373] Call trace:
[ 8.275376] dcache_inval_poc+0x28/0x58
[ 8.275380] dma_unmap_page_attrs+0x230/0x258
[ 8.275386] sa_free_ctx_info+0xa8/0xd8
[ 8.275393] sa_sha_cra_exit+0xe8/0xf8
[ 8.275396] crypto_destroy_tfm+0xe8/0x110
[ 8.275402] hash_release+0x1c/0x30
[ 8.275407] alg_bind+0xe0/0x150
[ 8.275409] __sys_bind+0x104/0x118
[ 8.275414] __arm64_sys_bind+0x28/0x40

Register dump shows the fault address is phys_to_virt(0) + offset, size
0x160
( SA_CTX_MAX_SZ ) — i.e. a DMA unmap of handle 0.

Root cause (ti-linux-6.12.y drivers/crypto/sa2ul.c )

The TI BSP tree carries a heavily reworked sa2ul driver (~3600 lines vs
~2500
upstream). Upstream allocates the security-context buffer from a coherent
dma_pool (no streaming DMA anywhere). The TI rework switched to a mempool
+
streaming DMA, and broke the map/unmap pairing:

• sa_init_ctx_info() (tfm init): ctx->sc = mempool_alloc(…) — no
dma_map_single() , so ctx->sc_phys stays 0.
• dma_map_single() only happens later, in sa_init_sc() — reached from
the
setkey paths.
• sa_free_ctx_info() (tfm destroy) unconditionally does
dma_unmap_single(dev, ctx->sc_phys, SA_CTX_MAX_SZ, DMA_BIDIRECTIONAL)
whenever ctx->sc != NULL .

So any hash tfm that is allocated and freed without ever being keyed/used
unmaps DMA handle 0 → dcache_inval_poc on phys_to_virt(0) → fatal paging
fault. That’s exactly what iwd does at startup: it probes kernel crypto
capabilities via AF_ALG bind() / close() . Since sa2ul registers its hash
algos
at priority 400–1000 (above the ARMv8-CE software implementations), every
AF_ALG
hash user on the board lands on the buggy driver.

(Secondary issue while in there: sa_init_sc() calls dma_map_single() on
every
setkey without unmapping a previous mapping, so re-keying a live tfm leaks
DMA
mappings.)

Repro

On an affected kernel, either systemctl start iwd , or directly:

python3 -c "
import socket
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
s.bind(('hash', 'hmac(sha256)'))   # alloc tfm, no setkey
s.close()                          # destroy tfm -> kernel oops
"

Workaround

Disable the SA2UL node in the device tree — crypto falls back to the A72’s
ARMv8-CE implementations:

&main_crypto {
    status = "disabled";                                                     
};

(Verified: with this, r64 boots clean and iwd/WiFi work normally.)

Candidate fix

 static void sa_free_ctx_info(struct sa_ctx_info *ctx,
                         struct sa_crypto_data *data)                        
 {
    ...
    if (ctx->sc) {
            memzero_explicit(ctx->sc, SA_CTX_MAX_SZ);                        
-           dma_unmap_single(dev, ctx->sc_phys, SA_CTX_MAX_SZ, DMA_BIDIRECTIONAL);
+           if (ctx->sc_phys) {                                              
+                   dma_unmap_single(dev, ctx->sc_phys, SA_CTX_MAX_SZ,       
+                                    DMA_BIDIRECTIONAL);                     
+                   ctx->sc_phys = 0;                                        
+           }                                                                
            mempool_free(ctx->sc, data->sc_pool);                            
            ctx->sc = NULL;                                                  
    }
 }

(The rekey-leak in sa_init_sc() deserves a matching unmap-before-remap,
but
the
guard above is the boot-breaking one.)

Since the rework comes from TI’s BSP tree, this probably also wants to go to
TI —
happy to file it on E2E as well if that’s the right route.

I am hitting the same issue.

Here is what grok has to say on my debug uart log/paste https://grok.com/share/bGVnYWN5_84dc8387-d348-465e-ac16-4e883bb367b6