.section .text.user_handle_transfer,"ax" .balign 4 .global __user_task_blob_start __user_task_blob_start: // Private A/B roots share this code. x19 is the preserved task token; // x20 and x21 prove data/stack ownership across every SVC/ERET. mov x19, x0 movz x20, #0x1000 movk x20, #0x8000, lsl #16 mov x21, #0x55 str x19, [x20] sub sp, sp, #16 str x19, [sp] movz x9, #0xa11a cmp x19, x9 b.eq .Ltransfer_a movz x9, #0xb22b cmp x19, x9 b.ne .Ltransfer_fail b .Ltransfer_b .Ltransfer_a: mov x7, #1 mov x0, #3 mov x8, #8 svc #0x42 cmp x0, #1 b.ne .Ltransfer_fail mov x22, x0 movz x9, #0x4241 movk x9, #0x4443, lsl #16 str w9, [x20, #16] mov x0, x22 add x1, x20, #16 mov x2, #4 mov x8, #12 svc #0x42 cmp x0, #4 b.ne .Ltransfer_fail mov x8, #6 svc #0x42 cbnz x0, .Ltransfer_fail cmp x22, #1 b.ne .Ltransfer_fail cmp x21, #0x55 b.ne .Ltransfer_fail ldr x9, [x20] cmp x9, x19 b.ne .Ltransfer_fail ldr x9, [sp] cmp x9, x19 b.ne .Ltransfer_fail // Unknown recipient must not consume ID 3 or move handle 1. mov x0, x22 mov x1, #0 mov x8, #14 svc #0x42 movn x9, #21 cmp x0, x9 b.ne .Ltransfer_fail // Move A/1 to the live B task; the new opaque number is 3. mov x0, x22 movz x1, #0xb22b mov x8, #14 svc #0x42 cmp x0, #3 b.ne .Ltransfer_fail mov x23, x0 mov x0, x22 mov x8, #9 svc #0x42 movn x9, #8 cmp x0, x9 b.ne .Ltransfer_fail mov x0, x23 mov x8, #9 svc #0x42 movn x9, #8 cmp x0, x9 b.ne .Ltransfer_fail mov x0, x19 mov x8, #2 svc #0x42 b .Ltransfer_fail .Ltransfer_b: mov x7, #1 // Before transfer, A/1 is foreign to B. mov x0, #1 mov x8, #9 svc #0x42 movn x9, #8 cmp x0, x9 b.ne .Ltransfer_fail mov x0, #2 mov x8, #8 svc #0x42 cmp x0, #2 b.ne .Ltransfer_fail mov x22, x0 // B cannot transfer A/1 to A even with a valid recipient token. mov x0, #1 movz x1, #0xa11a mov x8, #14 svc #0x42 movn x9, #8 cmp x0, x9 b.ne .Ltransfer_fail mov x8, #6 svc #0x42 cbnz x0, .Ltransfer_fail cmp x22, #2 b.ne .Ltransfer_fail cmp x21, #0x55 b.ne .Ltransfer_fail ldr x9, [x20] cmp x9, x19 b.ne .Ltransfer_fail ldr x9, [sp] cmp x9, x19 b.ne .Ltransfer_fail // After A transfers and exits, B alone owns number 3. mov x0, #3 mov x8, #9 svc #0x42 cmp x0, #3 b.ne .Ltransfer_fail mov x0, #1 mov x8, #9 svc #0x42 movn x9, #8 cmp x0, x9 b.ne .Ltransfer_fail mov x0, #3 add x1, x20, #16 mov x2, #4 mov x8, #15 svc #0x42 cmp x0, #4 b.ne .Ltransfer_fail ldr w9, [x20, #16] movz x10, #0x4241 movk x10, #0x4443, lsl #16 cmp w9, w10 b.ne .Ltransfer_fail mov x0, x22 mov x8, #9 svc #0x42 cmp x0, #2 b.ne .Ltransfer_fail mov x0, #3 mov x8, #10 svc #0x42 cbnz x0, .Ltransfer_fail mov x0, x22 mov x8, #10 svc #0x42 cbnz x0, .Ltransfer_fail mov x0, x19 mov x8, #2 svc #0x42 .Ltransfer_fail: brk #0xbad b .Ltransfer_fail .global __user_task_blob_end __user_task_blob_end: