On traditional 32-bit and 64-bit architectures, uint64_t can be abused to hold a uintptr_t and be cast back to a valid pointer. However, on CHERI, and thus Arm's Morello prototype, pointers are capabilities, which contain a traditional address alongside additional metadata, including a tag bit that ensures it cannot be forged (the only way to get a capability with the tag bit set is by using instructions that take in another valid capability with sufficient bounds/permissions/etc for the request, and any other operation, like overwriting individual bytes in memory, will give a capability whose tag is clear). Casting a pointer to a uintptr_t is fine as uintptr_t is represented as a capability, but casting to a uint64_t yields just the address, losing the metadata and tag. Thus, when cast back to a uintptr_t, the capability remains invalid and faults on any attempt to dereference.
As with various other places in the tree, address this by searching for the pointer in a list so that we no longer rely on this undefined behaviour.
As part of this, a bunch of cleanup is done to reduce the number of places that have to convert from event_id back to event in the first place.
A more invasive change would be to pass the vblank itself through the callbacks, or have some kind of arbitrary data field in the vblank that's a pointer to whatever the present implementation wants (which could also allow xwayland to stop extending present_vblank_rec), but this is the simplest change to make it work and seems consistent with other places like the modesetting vblank sequence number handling and scmd.