.section .text.user_handle,"ax" .balign 4 .global __user_task_blob_start __user_task_blob_start: // Same user VA, different private root and data/stack pages for A/B. 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 .Lhandle_a movz x9, #0xb22b cmp x19, x9 b.ne .Lhandle_fail .Lhandle_b: mov x7, #1 // A's live handle 1 must be invisible to B. mov x0, #1 mov x8, #9 svc #0x42 movn x9, #8 cmp x0, x9 b.ne .Lhandle_fail // B owns handle 2 (clock resource). mov x0, #2 mov x8, #8 svc #0x42 cmp x0, #2 b.ne .Lhandle_fail mov x22, x0 // Both slots occupied; no third descriptor is issued. mov x0, #1 mov x8, #8 svc #0x42 movn x9, #23 cmp x0, x9 b.ne .Lhandle_fail mov x8, #6 svc #0x42 cbnz x0, .Lhandle_fail cmp x22, #2 b.ne .Lhandle_fail cmp x21, #0x55 b.ne .Lhandle_fail ldr x9, [x20] cmp x9, x19 b.ne .Lhandle_fail ldr x9, [sp] cmp x9, x19 b.ne .Lhandle_fail // A has closed 1. It must stay stale after A exits. mov x0, #1 mov x8, #9 svc #0x42 movn x9, #8 cmp x0, x9 b.ne .Lhandle_fail mov x0, x22 mov x8, #9 svc #0x42 cmp x0, #2 b.ne .Lhandle_fail mov x0, x22 mov x8, #10 svc #0x42 cbnz x0, .Lhandle_fail mov x0, x19 mov x8, #2 svc #0x42 b .Lhandle_fail .Lhandle_a: mov x7, #1 mov x0, #1 mov x8, #8 svc #0x42 cmp x0, #1 b.ne .Lhandle_fail mov x22, x0 mov x8, #6 svc #0x42 cbnz x0, .Lhandle_fail cmp x22, #1 b.ne .Lhandle_fail cmp x21, #0x55 b.ne .Lhandle_fail ldr x9, [x20] cmp x9, x19 b.ne .Lhandle_fail ldr x9, [sp] cmp x9, x19 b.ne .Lhandle_fail // A still owns 1; B's live handle 2 is foreign to A. mov x0, x22 mov x8, #9 svc #0x42 cmp x0, #1 b.ne .Lhandle_fail mov x0, #2 mov x8, #9 svc #0x42 movn x9, #8 cmp x0, x9 b.ne .Lhandle_fail mov x0, x22 mov x8, #10 svc #0x42 cbnz x0, .Lhandle_fail mov x0, x19 mov x8, #2 svc #0x42 .Lhandle_fail: brk #0xbad b .Lhandle_fail .global __user_task_blob_end __user_task_blob_end: