kernel: record who gave each device away

One field, and the rest of the run follows from it. A device that was given
to someone is delegated hardware: it may be handed on, never taken, and when
its holder dies it goes back to whoever lent it instead of becoming free for
anyone to grab.

It also settles the framebuffer without mentioning it. Nobody delegates the
loader's framebuffer, so it has no giver, so the display service claims it
exactly as it always has — no exemption and no reference to display anywhere
in the rule.

No behaviour changes here; the field is recorded and read by nothing yet.

The test found a real bug on its first run, before the discrimination check.
The sentinel for "nobody gave this" was 0 — and task 0 is a real task, the
kernel's own, so a device given away by task 0 read back as belonging to
nobody. Both giver and registrar are optionals now. The second was a latent
bug from D9: the per-registrar allowance would have miscounted every device
task 0 registered.

Suite 118/118.
This commit is contained in:
Daniel Samson
2026-08-08 22:12:01 +01:00
parent ca1126537d
commit 4ca57fc37e
3 changed files with 46 additions and 7 deletions
+12
View File
@@ -4121,6 +4121,10 @@ fn deviceTransferTest(boot_information: *const boot_handoff.BootInformation) voi
const unheld = if (devices_broker.transfer(0, me, child)) |_| false else |e| e == error.NotHeld;
check("an unheld device cannot be transferred", unheld);
// A second device this test never hands over, so the "no giver" half below is a
// real observation rather than a restatement of the first.
const parentless: u64 = 1;
check("claimed device 0", claimOk(0, me));
// The move itself.
@@ -4139,6 +4143,14 @@ fn deviceTransferTest(boot_information: *const boot_handoff.BootInformation) voi
const stranger = if (devices_broker.transfer(0, 9999, me)) |_| false else |e| e == error.NotHeld;
check("a stranger cannot transfer another task's device", stranger);
// The giver is recorded. One field, and the authority rule follows from it: a
// device that was *given* to someone is delegated hardware, so it may be handed on
// but never taken, and when its holder dies it returns to whoever lent it instead
// of becoming free for anyone. Nothing has a giver until it is handed over —
// which is why the loader's framebuffer needs no exemption from either rule.
check("the giver is recorded on a transfer", devices_broker.giverOf(0) == me);
check("a device nobody handed over has no giver", devices_broker.giverOf(parentless) == null);
const absent = if (devices_broker.transfer(9999, me, child)) |_| false else |e| e == error.NoSuchDevice;
check("a device that does not exist is refused", absent);