switcher: docs for library functions
diff --git a/sdk/core/switcher/entry.S b/sdk/core/switcher/entry.S index ea6ea19..f0ceb04 100644 --- a/sdk/core/switcher/entry.S +++ b/sdk/core/switcher/entry.S
@@ -77,6 +77,7 @@ * * - "LIVE IN:", a list of live (in) registers at this point of the code and/or * - "*": the entire general purpose register file (no CSRs or SCRs implied) + * - "callee-save": the psABI callee-save registers * - "mcause" * - "mtdc" * - "mtval" @@ -1824,10 +1825,14 @@ .type __Z23trusted_stack_has_spacei,@function __Z23trusted_stack_has_spacei: /* - * LIVE IN: mtdc, a0 + * FROM: malice + * IRQ ASSUME: deferred + * LIVE IN: mtdc, callee-save, ra, a0 * * Atlas: * mtdc: pointer to TrustedStack (or nullptr if from buggy scheduler) + * ra: return pointer (guaranteed because this symbol is reachable only + * through an interrupt-disabling forward-arc sentry) * a0: requested number of trusted stack frames */ li a2, TrustedStackFrame_size @@ -1855,15 +1860,20 @@ // LIVE OUT: mtdc, a0 cret +// Reveal the stack pointer given to this compartment invocation .section .text, "ax", @progbits .p2align 2 .type __Z22switcher_recover_stackv,@function __Z22switcher_recover_stackv: /* - * LIVE IN: mtdc + * FROM: malice + * IRQ ASSUME: deferred + * LIVE IN: mtdc, callee-save, ra * * Atlas: * mtdc: pointer to TrustedStack (or nullptr if buggy scheduler) + * ra: return pointer (guaranteed because this symbol is reachable only + * through an interrupt-disabling forward-arc sentry) */ /* * Load the trusted stack pointer into a register that we will clobber after @@ -1884,6 +1894,7 @@ * on entry, and can be returned directly. */ li a2, TrustedStack_offset_frames + // Atlas update: a2: dead but exposed: TrustedStack_offset_frames beq a1, a2, 0f /* @@ -1897,6 +1908,11 @@ sub a1, a1, a2 csetaddr ca0, ca0, a2 csetboundsexact ca0, ca0, a1 + /* + * Atlas update: + * a1: dead but exposed: the length of the stack + * a2: dead but exposed: base address of the stack + */ 0: // LIVE OUT: mtdc, a0 cret @@ -1905,14 +1921,30 @@ .p2align 2 .type __Z30trusted_stack_interrupt_threadPv,@function __Z25switcher_interrupt_threadPv: - // Load the unsealing key into a register that we will clobber two - // instructions later. + /* + * FROM: malice + * IRQ ASSUME: deferred + * LIVE IN: mtdc, callee-save, ra, a0 + * + * Atlas: + * mtdc: pointer to TrustedStack (or nullptr if buggy scheduler) + * a0: sealed pointer to target thread TrustedStack + * ra: return pointer (guaranteed because this symbol is reachable only + * through an interrupt-disabling forward-arc sentry) + */ + /* + * Because this function involves looking across two threads' states, it + * needs to run with preemption prohibited, and that means IRQs deferred. + */ + + // Load the unsealing key LoadCapPCC ca1, .Lsealing_key_trusted_stacks /* - * The target capability is in ca0. Unseal, check tag and load the entry - * point offset. + * The target capability is in ca0. Unseal, clobbering our authority; + * check tag; and load the entry point offset. */ cunseal ca1, ca0, ca1 + // Atlas update: a1: unsealed pointer to target thread TrustedStack /* * LOCAL SEAL: Nothing herein depends on a1 being GL(obal). */ @@ -1926,12 +1958,14 @@ cspecialr ca2, mtdc li a0, 0 beq a2, a1, .Lswitcher_interrupt_thread_return + // Atlas update: a2: unsealed pointer to current thread TrustedStack - // ca1 now contains the unsealed capability for the target thread. We - // allow the target thread to be interrupted if (and only if) the caller is - // in the same compartment as the interrupted thread. We will determine - // this by checking if the base of the two export table entries from the - // top of the trusted stack frames match. + /* + * We allow the target thread to be interrupted if (and only if) the caller + * is in the same compartment as the interrupted thread. We will determine + * this by checking if the base of the two export table entries from the + * top of the trusted stack frames match. + */ // Helper macro that loads the export table from the register containing the // trusted stack. The two arguments must be different registers. @@ -1954,10 +1988,13 @@ // If the two export table entries differ, return. bne a2, a3, .Lswitcher_interrupt_thread_return - // After this point, we no longer care about the values in a0, a2, and a3. + // Atlas update: a1, a2, a3: dead (to be zeroed) - // Mark the thread as interrupted. - // Store a magic value in mcause + /* + * Mark the thread as interrupted. Store a magic value in mcause. This + * value will not be overwritten by a trap before the scheduler sees the + * target thread, since we are on core and it isn't. + */ li a2, MCAUSE_THREAD_INTERRUPT csw a2, TrustedStack_offset_mcause(ca1) // Return success @@ -1966,67 +2003,130 @@ zeroRegisters a1, a2, a3 cret +// Get a sealed pointer to the current thread's TrustedStack .section .text, "ax", @progbits .p2align 2 .type __Z23switcher_current_threadv,@function __Z23switcher_current_threadv: + /* + * FROM: malice + * IRQ ASSUME: deferred + * LIVE IN: mtdc, callee-save, ra + * + * Atlas: + * mtdc: pointer to TrustedStack (or nullptr if buggy scheduler) + * ra: return pointer (guaranteed because this symbol is reachable only + * through an interrupt-disabling forward-arc sentry) + */ + LoadCapPCC ca0, .Lsealing_key_trusted_stacks + // Atlas update: a0: sealing authority for trusted stacks cspecialr ca1, mtdc + // Atlas update: a1: copy of mtdc cseal ca0, ca1, ca0 li a1, 0 + /* + * Atlas update: + * a0: sealed copy of mtdc, this thread's TrustedStack + * a1: zero + */ cret +// Get a pointer to this thread's hazard pointers array .section .text, "ax", @progbits .p2align 2 .type __Z28switcher_thread_hazard_slotsv,@function __Z28switcher_thread_hazard_slotsv: - // Load the trusted stack pointer into a register that we will clobber in - // two instructions. + /* + * FROM: malice + * IRQ ASSUME: deferred + * LIVE IN: mtdc, callee-save, ra + * + * Atlas: + * mtdc: pointer to TrustedStack (or nullptr if buggy scheduler) + * ra: return pointer (guaranteed because this symbol is reachable only + * through an interrupt-disabling forward-arc sentry) + */ + cspecialr ca0, mtdc + + // If this traps (from null mtdc, say), we'll forcibly unwind. clc ca0, TrustedStack_offset_hazardPointers(ca0) + // Atlas update: a0: pointer to hazard pointers + cret +// Get the current thread's integer ID .section .text, "ax", @progbits .p2align 2 .type __Z13thread_id_getv,@function __Z13thread_id_getv: - // Load the trusted stack pointer into a register that we will clobber in - // the next instruction when we load the thread ID. + /* + * FROM: malice + * IRQ ASSUME: deferred + * LIVE IN: mtdc, callee-save, ra + * + * Atlas: + * mtdc: pointer to TrustedStack (or nullptr if buggy scheduler) + * ra: return pointer (guaranteed because this symbol is reachable only + * through an interrupt-disabling forward-arc sentry) + */ + cspecialr ca0, mtdc + /* + * If this is a null pointer, don't try to dereference it and report that + * we are thread 0. This permits the debug code to work even from things + * that are not real threads. + */ cgettag a1, ca0 - // If this is a null pointer, don't try to dereference it and report that - // we are thread 0. This permits the debug code to work even from things - // that are not real threads. + // Atlas update: a1: tag of a0/mtdc beqz a1, 0f clh a0, TrustedStack_offset_threadID(ca0) + // Atlas update: a0: integer ID of current thread 0: cret +// Return the stack high-water mark .section .text, "ax", @progbits .p2align 2 .type __Z25stack_lowest_used_addressv,@function __Z25stack_lowest_used_addressv: - // Read the stack high-water mark into the return register. csrr a0, CSR_MSHWM cret +// Reset the count of error handler invocations in this compartment invocation .section .text, "ax", @progbits .p2align 2 .type __Z39switcher_handler_invocation_count_resetv,@function __Z39switcher_handler_invocation_count_resetv: - // Trusted stack pointer in ca1 + /* + * FROM: malice + * IRQ ASSUME: deferred + * LIVE IN: mtdc, callee-save, ra + * + * Atlas: + * mtdc: pointer to TrustedStack (or nullptr if buggy scheduler) + * ra: return pointer (guaranteed because this symbol is reachable only + * through an interrupt-disabling forward-arc sentry) + */ + cspecialr ca1, mtdc - // Offset of the current trusted stack frame to a1 + // Atlas update: a1: copy of mtdc clhu a0, TrustedStack_offset_frameoffset(ca1) addi a0, a0, -TrustedStackFrame_size - // Current trusted stack frame to ca1, a0 is dead + // Atlas update: a0: offset of the current trusted stack frame cincoffset ca1, ca1, a0 - // Current invocation count (for return) in a0 + /* + * Atlas update: + * a0: dead + * a1: pointer to current TrustedStack::frame + */ clh a0, TrustedStackFrame_offset_errorHandlerCount(ca1) + // Atlas update: a0: current invocation count (for return) // Reset invocation count csh zero, TrustedStackFrame_offset_errorHandlerCount(ca1) - // Zero trusted stack frame pointer register + // Atlas update: a1: dead (to be zeroed) li a1, 0 cret