Merge xobj-stashhandle/p0-canary-mirror
This commit is contained in:
@@ -3094,6 +3094,12 @@ fn ensure_dispatcher_object(state: &mut KernelState, mem: &GuestMemory, ptr: u32
|
|||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
state.objects.insert(ptr, obj);
|
state.objects.insert(ptr, obj);
|
||||||
|
// Mirror canary `XObject::StashHandle` (xobject.h:253-256): on first
|
||||||
|
// adoption, stamp the X_DISPATCH_HEADER's wait_list with the kXObjSignature
|
||||||
|
// fourcc 'X','E','N','\0' (flink_ptr) and the stash handle (blink_ptr).
|
||||||
|
// Game code reads these to recognize already-adopted dispatchers.
|
||||||
|
mem.write_u32(ptr + 0x08, 0x58454E00);
|
||||||
|
mem.write_u32(ptr + 0x0C, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set `gpr[3]` on a just-woken HW thread to reflect which handle in its
|
/// Set `gpr[3]` on a just-woken HW thread to reflect which handle in its
|
||||||
@@ -4601,6 +4607,35 @@ mod tests {
|
|||||||
write_dispatcher_header(&mut mem, ptr, 2, 0); // Mutant — unsupported
|
write_dispatcher_header(&mut mem, ptr, 2, 0); // Mutant — unsupported
|
||||||
ensure_dispatcher_object(&mut state, &mem, ptr);
|
ensure_dispatcher_object(&mut state, &mem, ptr);
|
||||||
assert!(!state.objects.contains_key(&ptr), "no shadow for unknown type");
|
assert!(!state.objects.contains_key(&ptr), "no shadow for unknown type");
|
||||||
|
// No StashHandle stamp on an ignored dispatcher.
|
||||||
|
assert_eq!(mem.read_u32(ptr + 0x08), 0);
|
||||||
|
assert_eq!(mem.read_u32(ptr + 0x0C), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mirror canary `XObject::StashHandle` (xobject.h:253-256): on first
|
||||||
|
/// adoption of a guest dispatcher, +0x08 must hold the 'X','E','N','\0'
|
||||||
|
/// fourcc and +0x0C must hold the stash handle.
|
||||||
|
#[test]
|
||||||
|
fn ensure_dispatcher_object_stamps_xen_signature_and_handle() {
|
||||||
|
let (mut ctx, mut mem, mut state) = fresh();
|
||||||
|
let kevent_ptr = SCRATCH_BASE + 0x700;
|
||||||
|
write_dispatcher_header(&mut mem, kevent_ptr, 1, 0); // synchronization
|
||||||
|
// Pre-condition: zeros at +0x08 / +0x0C.
|
||||||
|
assert_eq!(mem.read_u32(kevent_ptr + 0x08), 0);
|
||||||
|
assert_eq!(mem.read_u32(kevent_ptr + 0x0C), 0);
|
||||||
|
ctx.gpr[3] = kevent_ptr as u64;
|
||||||
|
ke_set_event(&mut ctx, &mut mem, &mut state);
|
||||||
|
// Post-condition: kXObjSignature ('X','E','N','\0') + stash handle.
|
||||||
|
assert_eq!(
|
||||||
|
mem.read_u32(kevent_ptr + 0x08),
|
||||||
|
0x58454E00,
|
||||||
|
"wait_list.flink_ptr must hold kXObjSignature 'XEN\\0'"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
mem.read_u32(kevent_ptr + 0x0C),
|
||||||
|
kevent_ptr,
|
||||||
|
"wait_list.blink_ptr must hold stash handle (== guest dispatcher ptr)"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `KePulseEvent` on a manual-reset event must wake every parked waiter
|
/// `KePulseEvent` on a manual-reset event must wake every parked waiter
|
||||||
|
|||||||
Reference in New Issue
Block a user