Channel-open policy hook -- FABRIC-3.6.md task 3.7
Added HERMES-CHANNEL-OPEN? ( req-hi req-lo -- allow? ) at capsules/ACL.4th block 4008 (default: approve everything) -- the one word policy authors edit. sk_hermes_channel_open_policy(VM*, VMUuid) (kernel_hermes.h/.c) is the C-side query that calls it via plain word-dispatch against the target VM's own dictionary/stack, never vm_interpret() (avoids task 3.4's input-buffer cursor hazard entirely) and never decides the answer itself. Fails closed: no policy word, a policy error, or stack underflow all deny, matching CLAUDE.md's posture that absence of policy must never mean "always allow." Two real bugs found and fixed before this was called done: missing current_executing_entry assignment before calling the word's func pointer (colon words silently no-op without it, vm_core.c:730 -- no crash, just a wrong answer); and a second FAIL with debug instrumentation still in place whose precise cause isn't reconstructable, since no intermediate commit exists for that attempt. Self-test proves the task's check four ways against the same unchanged C function: default approve, live redefinition to deny (zero C change), restore, and a VM with no ACL.4th loaded at all (fail closed). A fifth check wires the result into task 3.6's sk_hermes_channel_respond() end to end: a denied policy produces a NACK and no channel, ledger/stadium_conserved() holding throughout. Scope, per Captain Bob's ruling: closes with the query built and proven; sk_hermes_channel_respond() still takes a caller-supplied approved bool rather than calling the policy internally. Wiring a real channel-open call site to only this query is deferred to whichever later task first needs a live decision. dict_hash identical across amd64/aarch64/riscv64 for every VM, zero UNKNOWN WORD, mkcapsule --lint clean (38 files, 0 violations). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
205a49ecd0
commit
f37aa0fb17
+61
-1
@@ -984,9 +984,69 @@ ruling]** cannot be written precisely until Captain Bob settles the named sub-it
|
||||
task touches no capsule). Artemis's own `dict_hash` differs run-to-run as already
|
||||
documented (task 3.1's own finding) -- shared `disk/artemis.img` state accumulated across
|
||||
this session's many prior boots, not an architecture divergence.
|
||||
- [ ] **3.7** — **Channel-open policy hook** **[needs ruling 3.0b]**. Kernel-Hermes asks
|
||||
- [x] **3.7** — **Channel-open policy hook** **[needs ruling 3.0b]**. Kernel-Hermes asks
|
||||
`ACL.4th`, never decides in C, never gates on `zuse_session`. *Check:* a denied open is
|
||||
denied by FORTH policy, with the C unchanged when the policy changes.
|
||||
2026-09-22 · `logs/20260922-075138/amd64/`, `logs/20260922-075649/aarch64/`,
|
||||
`logs/20260922-080212/riscv64/` (the successful runs; `logs/20260922-074119/amd64/` and
|
||||
`logs/20260922-074628/amd64/` are two genuine prior attempts that hit real bugs, caught by
|
||||
the self-test itself before this task was called done -- kept, not deleted, per the
|
||||
never-delete-logs convention) — all three reach `[zuse@Hera] ok>`, zero `UNKNOWN WORD`,
|
||||
`mkcapsule --lint capsules/` clean (38 files, 0 violations — one block added inside the
|
||||
existing `ACL.4th`, no file added). `dict_hash` identical across all three architectures
|
||||
for every VM (Hera `0xbb2b51e7595464ce`, Hermes `0xc95ef2d92fa0781f`, Hestia
|
||||
`0xfbde9fe105fd3b3d`, Artemis `0x7f18214489036b39`).
|
||||
|
||||
Added `HERMES-CHANNEL-OPEN? ( req-hi req-lo -- allow? )` at `capsules/ACL.4th` block 4008
|
||||
(default: approve everything) — the one word policy authors edit; `sk_hermes_channel_open_policy(VM *target_vm, VMUuid requester)`
|
||||
(`kernel_hermes.h`/`.c`) is the C-side query that calls it, and never itself decides. Uses
|
||||
plain word-dispatch (`vm_find_word()` + the entry's own `func` pointer) against the
|
||||
*target* VM's own dictionary and data stack, not `vm_interpret()` — deliberately, since
|
||||
`HERMES-CHANNEL-OPEN?` is a fixed known name, and this avoids task 3.4's input-buffer
|
||||
cursor-preservation hazard entirely (this touches the target's data stack only, never its
|
||||
input buffer). **Fails closed, not open**: no policy word present (e.g. a VM that never
|
||||
loaded `ACL.4th`), a policy-word error, or stack underflow all return "denied," matching
|
||||
`.claude/CLAUDE.md`'s own posture that absence of policy must never mean "always allow."
|
||||
A broken policy word's own error state is cleared on the target VM before returning, so it
|
||||
cannot leak into whatever else that VM is doing.
|
||||
|
||||
**Two real bugs found and fixed before this was called done, not a clean first pass:**
|
||||
1. (`logs/20260922-074119/`) The first draft called `entry->func(target_vm)` directly
|
||||
without setting `target_vm->current_executing_entry` first — colon words dispatch
|
||||
through `execute_colon_word()`, which reads its own body address from that field and
|
||||
silently no-ops if it's `NULL` (`vm_core.c:730`). Every call silently did nothing,
|
||||
leaving the pushed requester args untouched on the stack rather than erroring — no
|
||||
crash, no obvious symptom, just a wrong answer, which is why it needed the self-test
|
||||
(not a crash) to catch. Fixed by setting `current_executing_entry` before the call and
|
||||
restoring the caller's own value after (in case the target VM is ever called into
|
||||
mid-dispatch elsewhere later).
|
||||
2. (`logs/20260922-074628/`) Still `FAIL`, with debug instrumentation left in from
|
||||
diagnosing bug 1 (`entry=... func=...`, `error=0 dsp=1`/`error=0 dsp=2` printed, then
|
||||
`FAIL`). **No intermediate commit exists for this attempt, so its precise defect is
|
||||
not reconstructable now** — the log records the symptom and nothing more. Debug prints
|
||||
were removed; the third attempt (`075138`/`075649`/`080212`) passed clean on all three
|
||||
architectures with no debug output.
|
||||
|
||||
Self-test in `kernel_main.c` proves the task's check four ways against the **same
|
||||
unchanged C function**: (a) Hera's default `HERMES-CHANNEL-OPEN?` approves; (b)
|
||||
redefining that same word live on Hera to deny flips the answer with zero C change; (c)
|
||||
restoring the approve-default flips it back; (d) Hermes — who never loads `ACL.4th` at
|
||||
all (grep-confirmed: only `init.4th`/`ACL.4th`/`zuse.4th`/`block-acl.4th` reference it) —
|
||||
is correctly refused closed, not silently approved, proving the fail-closed behaviour on a
|
||||
VM with no policy at all. A fifth check wires the policy result straight into task 3.6's
|
||||
`sk_hermes_channel_respond()` end to end: a denied policy really produces a NACK and no
|
||||
channel, with the ledger audit and `stadium_conserved()` holding before and after —
|
||||
exactly task 3.6's own deny-path shape, reused rather than re-derived.
|
||||
|
||||
**Not yet done, by scope**: the actual call site inside `sk_hermes_channel_respond()`'s
|
||||
caller still takes a plain `approved` bool (task 3.6's own signature, unchanged, as
|
||||
promised) — this task builds and proves the query function itself; wiring it as the
|
||||
*only* source of that bool at a real call site is deferred to whichever later task first
|
||||
needs a live (not self-test-only) channel-open decision, consistent with every other
|
||||
Phase 3 task before Stage C being self-test-only. `dict_hash` for Hermes/Hestia unmoved
|
||||
from task 3.6's values, as expected (neither VM loads `ACL.4th`'s changed block); Hera's
|
||||
own hash moved (she does) and Artemis's tracks the same disk-state artifact already
|
||||
documented at task 3.1.
|
||||
- [ ] **3.8** — **Stage C: cut over `BLK-ATTACH-EVENT` alone** (§XXXIV.3). One layer owns it;
|
||||
FORTH Hermes still routes every other type. *Check:* the real Hera↔Artemis attach path
|
||||
works end to end on all three ISAs; ledger and `stadium_conserved()` true before/after;
|
||||
|
||||
@@ -98,6 +98,16 @@ Block 4007
|
||||
( rewired: physics-style regression belongs to the kernel )
|
||||
( exclusively, and this file is deliberately host-portable. )
|
||||
|
||||
Block 4008
|
||||
( HERMES-CHANNEL-OPEN? -- FABRIC-3.6.md task 3.7 hook. )
|
||||
( Stack: req-hi req-lo -- allow? Kernel-Hermes asks )
|
||||
( this word, never decides in C, never gates on )
|
||||
( zuse_session (CLAUDE.md). Default: approve every )
|
||||
( request. Policy authors edit THIS word's body only -- )
|
||||
( kernel_hermes.c's own query function never changes. )
|
||||
: HERMES-CHANNEL-OPEN? ( req-hi req-lo -- allow? )
|
||||
2DROP 1 ;
|
||||
|
||||
Block 4015
|
||||
( Self-activation - runs after all ACL words are defined )
|
||||
ACL-BOOT
|
||||
|
||||
+12
-11
@@ -1,5 +1,5 @@
|
||||
# Capsule Block Manifest — Auto-generated
|
||||
<!-- Generated by mkcapsule --manifest 2026-09-20T09:57:21Z -->
|
||||
<!-- Generated by mkcapsule --manifest 2026-09-22T12:01:35Z -->
|
||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||
<!-- Hand-written justifications and immutability notes live -->
|
||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
| Capsule | Blocks claimed | xxHash64 | Signed |
|
||||
|---------|----------------|----------|--------|
|
||||
| `ACL.4th` | 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4015 | `0xd781d22148ff171d` | yes |
|
||||
| `ACL.4th` | 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4015 | `0xf8890c05c0d8f921` | yes |
|
||||
| `acl-std79.4th` | 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048 | `0x773bf9209df191d1` | yes |
|
||||
| `artemis:init.4th` | 4110, 4111, 4112, 4113, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4177, 4178, 4179, 4180, 4181, 4182, 4851, 4852, 4853, 4854, 4856, 4857, 4858, 4860 | `0xf55edc4e76a8c294` | yes |
|
||||
| `block-acl.4th` | 4019, 4020 | `0xf6cc2a59e3a6734e` | yes |
|
||||
@@ -101,15 +101,16 @@
|
||||
| 2160 | `workload-8.4th` | `0x56b7f2f0efa000df` | ok |
|
||||
| 2200 | `workload-0.4th` | `0x93f86f60aeba8feb` | ok |
|
||||
| 2201 | `workload-0.4th` | `0x93f86f60aeba8feb` | ok |
|
||||
| 4000 | `ACL.4th` | `0xd781d22148ff171d` | ok |
|
||||
| 4001 | `ACL.4th` | `0xd781d22148ff171d` | ok |
|
||||
| 4002 | `ACL.4th` | `0xd781d22148ff171d` | ok |
|
||||
| 4003 | `ACL.4th` | `0xd781d22148ff171d` | ok |
|
||||
| 4004 | `ACL.4th` | `0xd781d22148ff171d` | ok |
|
||||
| 4005 | `ACL.4th` | `0xd781d22148ff171d` | ok |
|
||||
| 4006 | `ACL.4th` | `0xd781d22148ff171d` | ok |
|
||||
| 4007 | `ACL.4th` | `0xd781d22148ff171d` | ok |
|
||||
| 4015 | `ACL.4th` | `0xd781d22148ff171d` | ok |
|
||||
| 4000 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4001 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4002 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4003 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4004 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4005 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4006 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4007 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4008 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4015 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
|
||||
| 4016 | `zuse.4th` | `0x490ded9be257a90b` | ok |
|
||||
| 4017 | `zuse.4th` | `0x490ded9be257a90b` | ok |
|
||||
| 4018 | `zuse.4th` | `0x490ded9be257a90b` | ok |
|
||||
|
||||
@@ -727,6 +727,49 @@ int sk_hermes_channel_respond(VMUuid target, VMUuid requester, int approved);
|
||||
* @return 0 on success, -1 on refusal. */
|
||||
int sk_hermes_channel_close(VMUuid closer, int channel_id);
|
||||
|
||||
/*
|
||||
* Channel-open policy hook (FABRIC-3.6.md task 3.7, B1, ruling 3.0b:
|
||||
* "kernel-Hermes asks ACL.4th, never decides in C, never gates on
|
||||
* zuse_session"). sk_hermes_channel_open_policy() is the CALL SITE task
|
||||
* 3.6's own doc comment named as replacing sk_hermes_channel_respond()'s
|
||||
* caller-supplied `approved` bool with a real query -- this function IS
|
||||
* that query; sk_hermes_channel_respond()'s own signature stays
|
||||
* unchanged, as promised.
|
||||
*
|
||||
* Deliberately NOT vm_interpret() (contrast task 3.4's drain, which
|
||||
* genuinely needs to run arbitrary payload text): HERMES-CHANNEL-OPEN?
|
||||
* is a FIXED, known word name, so this uses the plain-word-dispatch
|
||||
* pattern FABRIC-3.md SXX already established for Hera's own MSG-TICK
|
||||
* self-drain ("a plain word dispatch in her own dictionary, not a
|
||||
* VM-EXEC dispatch into anyone else's input buffer -- no reentrancy
|
||||
* risk") -- vm_find_word() + calling the entry's own func pointer
|
||||
* directly, with the requester passed via the target's own data stack.
|
||||
* This touches neither target_vm->input_buffer nor input_pos, so it
|
||||
* carries none of task 3.4's cursor-preservation hazard; it DOES still
|
||||
* touch target_vm's own data stack (dsp), which is the correct and
|
||||
* expected thing for a word call to do. Calling this from within a live
|
||||
* checkpoint on a VM that is itself mid-dispatch is deferred, undecided
|
||||
* territory -- this task (like every Phase 3 task before Stage C/3.8+)
|
||||
* is self-test only, not wired into any real checkpoint yet.
|
||||
*
|
||||
* Fails CLOSED, not open: if target_vm has no HERMES-CHANNEL-OPEN? word
|
||||
* (e.g. ACL.4th was never loaded into it) or the word itself sets
|
||||
* target_vm->error or leaves too few stack items, this returns 0
|
||||
* (denied) -- absence of policy must never silently mean "always
|
||||
* allow" (CLAUDE.md's own posture on ACL policy). A policy-word bug's
|
||||
* own error state is cleared on target_vm before returning, so a
|
||||
* broken policy word cannot leak an error into whatever else target_vm
|
||||
* is doing.
|
||||
*
|
||||
* @param target_vm The VM being asked -- its own dictionary is
|
||||
* consulted, its own data stack is used for the call.
|
||||
* @param requester Passed to HERMES-CHANNEL-OPEN? as (hi, lo) on
|
||||
* target_vm's own stack.
|
||||
* @return 1 if HERMES-CHANNEL-OPEN? approved (returned a nonzero top of
|
||||
* stack), 0 otherwise (denied, missing, or errored).
|
||||
*/
|
||||
int sk_hermes_channel_open_policy(VM *target_vm, VMUuid requester);
|
||||
|
||||
#endif /* __STARKERNEL__ */
|
||||
|
||||
#endif /* STARKERNEL_VM_KERNEL_HERMES_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1749,6 +1749,92 @@ static void kernel_main_deep(BootInfo *boot_info) {
|
||||
}
|
||||
}
|
||||
|
||||
/* FABRIC-3.6.md task 3.7 self-test: the channel-open policy hook.
|
||||
* Proves "a denied open is denied by FORTH policy, with the C
|
||||
* unchanged" three ways against the SAME unchanged C function
|
||||
* (sk_hermes_channel_open_policy()): Hera's default
|
||||
* HERMES-CHANNEL-OPEN? (capsules/ACL.4th block 4008, "approve
|
||||
* everything") approves; redefining that same word live on Hera to
|
||||
* deny flips the answer with no C change; and Hermes -- who never
|
||||
* loads ACL.4th at all (grep-confirmed: only init.4th/ACL.4th/
|
||||
* zuse.4th/block-acl.4th reference it) -- is correctly refused
|
||||
* closed (no policy present), not silently approved. A fourth check
|
||||
* wires the policy result straight into sk_hermes_channel_respond()
|
||||
* (task 3.6) end to end: a denied policy really produces a NACK and
|
||||
* no channel, exactly like task 3.6's own deny path. */
|
||||
{
|
||||
VMRegistryEntry hera_pol_entry, hermes_pol_entry;
|
||||
VMUuid requester_pol;
|
||||
int pol_ok = 1;
|
||||
|
||||
requester_pol.hi = 0; requester_pol.lo = 17;
|
||||
|
||||
console_puts("Kernel-Hermes channel-open policy self-test: ");
|
||||
if (capsule_vm_find_by_name_nocase("Hera", &hera_pol_entry) != 0 || !hera_pol_entry.vm_ptr ||
|
||||
capsule_vm_find_by_name_nocase("Hermes", &hermes_pol_entry) != 0 ||
|
||||
hermes_pol_entry.state != VM_STATE_LIVE || !hermes_pol_entry.vm_ptr) {
|
||||
console_println("SKIPPED (Hera/Hermes not available)");
|
||||
} else {
|
||||
VM *hera_vm = (VM *)hera_pol_entry.vm_ptr;
|
||||
VM *hermes_vm = (VM *)hermes_pol_entry.vm_ptr;
|
||||
|
||||
/* Default: approve. */
|
||||
if (sk_hermes_channel_open_policy(hera_vm, requester_pol) != 1) pol_ok = 0;
|
||||
|
||||
/* Same C function, policy redefined on Hera alone -- deny. */
|
||||
if (pol_ok) {
|
||||
vm_interpret(hera_vm, ": HERMES-CHANNEL-OPEN? ( a b -- f ) 2DROP 0 ;");
|
||||
if (hera_vm->error) { hera_vm->error = 0; pol_ok = 0; }
|
||||
}
|
||||
if (pol_ok && sk_hermes_channel_open_policy(hera_vm, requester_pol) != 0) pol_ok = 0;
|
||||
|
||||
/* Restore the default before this self-test's own later use
|
||||
* of respond()/negotiation against Hera, and for whatever
|
||||
* runs after this block. */
|
||||
if (pol_ok) {
|
||||
vm_interpret(hera_vm, ": HERMES-CHANNEL-OPEN? ( a b -- f ) 2DROP 1 ;");
|
||||
if (hera_vm->error) { hera_vm->error = 0; pol_ok = 0; }
|
||||
}
|
||||
if (pol_ok && sk_hermes_channel_open_policy(hera_vm, requester_pol) != 1) pol_ok = 0;
|
||||
|
||||
/* No policy word at all (Hermes never loads ACL.4th) --
|
||||
* fail closed, not open. */
|
||||
if (pol_ok && sk_hermes_channel_open_policy(hermes_vm, requester_pol) != 0) pol_ok = 0;
|
||||
|
||||
/* End to end with task 3.6: a denied policy really produces
|
||||
* a NACK and no channel. Funds requester/target fresh so
|
||||
* this sub-test doesn't depend on the negotiation self-test
|
||||
* above having left any particular ledger state. */
|
||||
if (pol_ok) {
|
||||
VMUuid pub_id5, sub_id5;
|
||||
int grant_rc3, grant_rc4;
|
||||
|
||||
pub_id5.hi = 0; pub_id5.lo = 19;
|
||||
sub_id5.hi = 0; sub_id5.lo = 20;
|
||||
grant_rc3 = stadium_grant_quota(pub_id5, vm_uuid_hera());
|
||||
grant_rc4 = stadium_grant_quota(sub_id5, vm_uuid_hera());
|
||||
if (grant_rc3 != 0 || grant_rc4 != 0) {
|
||||
pol_ok = 0;
|
||||
} else {
|
||||
int approved = sk_hermes_channel_open_policy(hermes_vm, pub_id5); /* Hermes: no policy -> denied */
|
||||
int ch5 = sk_hermes_channel_respond(sub_id5, pub_id5, approved);
|
||||
if (approved != 0 || ch5 != -1) pol_ok = 0;
|
||||
if (pol_ok && sk_hermes_pending_count(pub_id5) != 1) pol_ok = 0; /* NACK only */
|
||||
if (pol_ok) {
|
||||
SkHermesMessage *m5 = sk_hermes_pending_peek(pub_id5);
|
||||
if (!m5 || m5->type != SK_HERMES_MSG_TYPE_NACK) pol_ok = 0;
|
||||
if (pol_ok && sk_hermes_release(m5) != 0) pol_ok = 0;
|
||||
if (pol_ok && sk_hermes_pending_pop(pub_id5) != 0) pol_ok = 0;
|
||||
}
|
||||
if (pol_ok && !stadium_conserved(pub_id5)) pol_ok = 0;
|
||||
if (pol_ok && !stadium_conserved(sub_id5)) pol_ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
console_println(pol_ok ? "PASS" : "FAIL");
|
||||
}
|
||||
}
|
||||
|
||||
/* Decided 2026-09-05: no console for the running system unless a
|
||||
* thumbdrive is present -- headless by default (EMERGENCY_CONSOLE_
|
||||
* ENABLED off), reusing that flag's own existing "does this build
|
||||
|
||||
@@ -713,4 +713,43 @@ int sk_hermes_channel_close(VMUuid closer, int channel_id) {
|
||||
return sk_hermes_channel_destroy(channel_id);
|
||||
}
|
||||
|
||||
int sk_hermes_channel_open_policy(VM *target_vm, VMUuid requester) {
|
||||
static const char word_name[] = "HERMES-CHANNEL-OPEN?";
|
||||
DictEntry *entry;
|
||||
DictEntry *saved_entry;
|
||||
cell_t result;
|
||||
|
||||
if (!target_vm) return 0;
|
||||
|
||||
entry = vm_find_word(target_vm, word_name, sizeof(word_name) - 1);
|
||||
if (!entry || !entry->func) return 0; /* fail closed: no policy, no open */
|
||||
|
||||
/* Colon words dispatch through execute_colon_word(), which reads its
|
||||
* own body address from vm->current_executing_entry and no-ops
|
||||
* silently if it is NULL (vm_core.c:730) -- vm_interpret_word() always
|
||||
* sets this immediately before calling entry->func(); matched here
|
||||
* for the same reason (found live: without it, every call silently
|
||||
* did nothing, leaving the pushed requester untouched on the stack
|
||||
* rather than erroring, which is why this needed a debug session to
|
||||
* catch rather than showing up as an obvious crash). Saved and
|
||||
* restored, not just set, in case target_vm is ever called into
|
||||
* mid-dispatch (not exercised by this task's own self-test, but no
|
||||
* reason to assume it away). */
|
||||
saved_entry = target_vm->current_executing_entry;
|
||||
target_vm->current_executing_entry = entry;
|
||||
vm_push(target_vm, (cell_t)requester.hi);
|
||||
vm_push(target_vm, (cell_t)requester.lo);
|
||||
entry->func(target_vm);
|
||||
target_vm->current_executing_entry = saved_entry;
|
||||
|
||||
if (target_vm->error || target_vm->dsp < 0) {
|
||||
target_vm->error = 0; /* a broken policy word must not leak into
|
||||
* whatever else target_vm is doing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = vm_pop(target_vm);
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
#endif /* __STARKERNEL__ */
|
||||
|
||||
Reference in New Issue
Block a user