akaros/kern/include/trap.h
<<
>>
Prefs
   1/* See COPYRIGHT for copyright information. */
   2
   3#pragma once
   4
   5#define ROS_KERN_TRAP_H
   6
   7#include <ros/trapframe.h>
   8#include <arch/arch.h>
   9#include <arch/mmu.h>
  10#include <sys/queue.h>
  11#include <arch/trap.h>
  12
  13// func ptr for interrupt service routines
  14typedef void (*isr_t)(struct hw_trapframe *hw_tf, void *data);
  15
  16void idt_init(void);
  17struct irq_handler *register_irq(int irq, isr_t handler, void *irq_arg,
  18                                 uint32_t tbdf);
  19int deregister_irq(int vector, uint32_t tbdf);
  20int route_irqs(int cpu_vec, int coreid);
  21int get_irq_vector(void);
  22void put_irq_vector(int vec);
  23
  24void print_trapframe(struct hw_trapframe *hw_tf);
  25void print_swtrapframe(struct sw_trapframe *sw_tf);
  26void print_vmtrapframe(struct vm_trapframe *vm_tf);
  27void print_user_ctx(struct user_context *ctx);
  28/* Generic per-core timer interrupt handler.  set_percore_timer() will fire the
  29 * timer_interrupt(). */
  30void set_core_timer(uint32_t usec, bool periodic);
  31void timer_interrupt(struct hw_trapframe *hw_tf, void *data);
  32
  33extern inline void save_fp_state(struct ancillary_state *silly);
  34extern inline void restore_fp_state(struct ancillary_state *silly);
  35extern inline void init_fp_state(void);
  36/* Set stacktop for the current core to be the stack the kernel will start on
  37 * when trapping/interrupting from userspace */
  38void set_stack_top(uintptr_t stacktop);
  39uintptr_t get_stack_top(void);
  40
  41void send_nmi(uint32_t os_coreid);
  42int reflect_current_context(void);
  43void reflect_unhandled_trap(unsigned int trap_nr, unsigned int err,
  44                            unsigned long aux);
  45void __arch_reflect_trap_hwtf(struct hw_trapframe *hw_tf, unsigned int trap_nr,
  46                              unsigned int err, unsigned long aux);
  47
  48uintptr_t get_user_ctx_pc(struct user_context *ctx);
  49uintptr_t get_user_ctx_fp(struct user_context *ctx);
  50uintptr_t get_user_ctx_sp(struct user_context *ctx);
  51
  52/* Partial contexts are those where the full context is split between the parts
  53 * in the struct and the parts still loaded in hardware.
  54 *
  55 * Finalizing a context ensures that the full context is saved in the struct and
  56 * nothing remains in hardware.  Finalize does two things: makes sure the
  57 * context can be run again on another core and makes sure the core can run
  58 * another context.
  59 *
  60 * arch_finalize_ctx() must be idempotent and have no effect on a full context.
  61 * It is up to the architecture to keep track of whether or not a context is
  62 * full or partial and handle finalize calls on a context that might not be
  63 * partial.  They can do so in the ctx itself, in their own arch-dependent
  64 * manner.
  65 *
  66 * The kernel's guarantee to the arches is that:
  67 * - finalize will be called after proc_pop_ctx (i.e. after it runs) at least
  68 * once, before that context is used again on another core or before another
  69 * context is used on this core.
  70 * - the arches can store the partial status and anything else it wants in the
  71 * *ctx without fear of it being tampered with.
  72 * - user-provided contexts will be passed to proc_secure_ctx, and those
  73 * contexts are full/finalized already.  Anything else is a user bug.  The
  74 * arches enforce this.
  75 * - an arch will never be asked to pop a partial context that was not already
  76 * loaded onto the current core.
  77 * - contexts will be finalized before handing them back to the user. */
  78extern inline void arch_finalize_ctx(struct user_context *ctx);
  79extern inline bool arch_ctx_is_partial(struct user_context *ctx);
  80void copy_current_ctx_to(struct user_context *to_ctx);
  81
  82/* Kernel messages.  This is an in-order 'active message' style messaging
  83 * subsystem, where you can instruct other cores (including your own) to execute
  84 * a function (with arguments), either immediately or whenever the kernel is
  85 * able to abandon its context/stack (permanent swap).
  86 *
  87 * These are different (for now) than the smp_calls in smp.h, since
  88 * they will be executed immediately (for urgent messages), and in the order in
  89 * which they are sent.  smp_calls are currently not run in order, and they must
  90 * return (possibly passing the work to a workqueue, which is really just a
  91 * routine message, so they really need to just return).
  92 *
  93 * Eventually, smp_call will be replaced by these.
  94 *
  95 * Also, a big difference is that smp_calls can use the same message (registered
  96 * in the interrupt_handlers[] for x86) for every recipient, but the kernel
  97 * messages require a unique message.  Also for now, but it might be like that
  98 * for a while on x86 (til we have a broadcast). */
  99
 100#define KMSG_IMMEDIATE                  1
 101#define KMSG_ROUTINE                    2
 102
 103typedef void (*amr_t)(uint32_t srcid, long a0, long a1, long a2);
 104
 105struct kernel_message
 106{
 107        STAILQ_ENTRY(kernel_message) link;
 108        uint32_t srcid;
 109        uint32_t dstid;
 110        amr_t pc;
 111        long arg0;
 112        long arg1;
 113        long arg2;
 114}__attribute__((aligned(8)));
 115
 116STAILQ_HEAD(kernel_msg_list, kernel_message);
 117typedef struct kernel_message kernel_message_t;
 118
 119void kernel_msg_init(void);
 120uint32_t send_kernel_message(uint32_t dst, amr_t pc, long arg0, long arg1,
 121                             long arg2, int type);
 122void handle_kmsg_ipi(struct hw_trapframe *hw_tf, void *data);
 123bool has_routine_kmsg(void);
 124void process_routine_kmsg(void);
 125void print_kmsgs(uint32_t coreid);
 126
 127/* Runs a function with up to two arguments as a routine kernel message.  Kernel
 128 * messages can have three arguments, but the deferred function pointer counts
 129 * as one.  Note the arguments to the function will be treated as longs. */
 130#define run_as_rkm(f, ...) do {                                                \
 131        static_assert(MACRO_NR_ARGS(__VA_ARGS__) <= 2);                        \
 132        PASTE(__run_as_rkm_, MACRO_NR_ARGS(__VA_ARGS__))(f, ##__VA_ARGS__);    \
 133} while (0)
 134
 135#define __run_as_rkm_0(f) \
 136        send_kernel_message(core_id(), __kmsg_trampoline, (long)f, 0xcafebabe, \
 137                            0xcafebabe, KMSG_ROUTINE)
 138#define __run_as_rkm_1(f, a1) \
 139        send_kernel_message(core_id(), __kmsg_trampoline, (long)f, (long)a1, \
 140                            0xcafebabe, KMSG_ROUTINE)
 141#define __run_as_rkm_2(f, a1, a2) \
 142        send_kernel_message(core_id(), __kmsg_trampoline, (long)f, (long)a1, \
 143                            (long)a2, KMSG_ROUTINE)
 144void __kmsg_trampoline(uint32_t srcid, long a0, long a1, long a2);
 145
 146/* Kernel context depths.  IRQ depth is how many nested IRQ stacks/contexts we
 147 * are working on.  Kernel trap depth is how many nested kernel traps (not
 148 * user-space traps) we have.
 149 *
 150 * Some examples:
 151 *      (original context in parens, +(x, y) is the change to IRQ and ktrap
 152 *      depth):
 153 * - syscall (user): +(0, 0)
 154 * - trap (user): +(0, 0)
 155 * - irq (user): +(1, 0)
 156 * - irq (kernel, handling syscall): +(1, 0)
 157 * - trap (kernel, regardless of context): +(0, 1)
 158 * - NMI (kernel): it's actually a kernel trap, even though it is
 159 *   sent by IPI.  +(0, 1)
 160 * - NMI (user): just a trap.  +(0, 0)
 161 *
 162 * So if the user traps in for a syscall (0, 0), then the kernel takes an IRQ
 163 * (1, 0), and then another IRQ (2, 0), and then the kernel page faults (a
 164 * trap), we're at (2, 1).
 165 *
 166 * Or if we're in userspace, then an IRQ arrives, we're in the kernel at (1, 0).
 167 * Note that regardless of whether or not we are in userspace or the kernel when
 168 * an irq arrives, we still are only at level 1 irq depth.  We don't care if we
 169 * have one or 0 kernel contexts under us.  (The reason for this is that I care
 170 * if it is *possible* for us to interrupt the kernel, not whether or not it
 171 * actually happened). */
 172
 173/* uint32_t __ctx_depth is laid out like so:
 174 *
 175 * +------8------+------8------+------8------+------8------+
 176 * |    Flags    |    Unused   | Kernel Trap |  IRQ Depth  |
 177 * |             |             |    Depth    |             |
 178 * +-------------+-------------+-------------+-------------+
 179 *
 180 */
 181#define __CTX_IRQ_D_SHIFT               0
 182#define __CTX_KTRAP_D_SHIFT             8
 183#define __CTX_FLAG_SHIFT                24
 184#define __CTX_IRQ_D_MASK                ((1 << 8) - 1)
 185#define __CTX_KTRAP_D_MASK              ((1 << 8) - 1)
 186#define __CTX_NESTED_CTX_MASK           ((1 << 16) - 1)
 187#define __CTX_CANNOT_BLOCK              (1 << (__CTX_FLAG_SHIFT + 0))
 188
 189/* Basic functions to get or change depths */
 190
 191#define irq_depth(pcpui)                                                       \
 192        (((pcpui)->__ctx_depth >> __CTX_IRQ_D_SHIFT) & __CTX_IRQ_D_MASK)
 193
 194#define ktrap_depth(pcpui)                                                     \
 195        (((pcpui)->__ctx_depth >> __CTX_KTRAP_D_SHIFT) & __CTX_KTRAP_D_MASK)
 196
 197#define inc_irq_depth(pcpui)                                                   \
 198        ((pcpui)->__ctx_depth += 1 << __CTX_IRQ_D_SHIFT)
 199
 200#define dec_irq_depth(pcpui)                                                   \
 201        ((pcpui)->__ctx_depth -= 1 << __CTX_IRQ_D_SHIFT)
 202
 203#define inc_ktrap_depth(pcpui)                                                 \
 204        ((pcpui)->__ctx_depth += 1 << __CTX_KTRAP_D_SHIFT)
 205
 206#define dec_ktrap_depth(pcpui)                                                 \
 207        ((pcpui)->__ctx_depth -= 1 << __CTX_KTRAP_D_SHIFT)
 208
 209#define set_cannot_block(pcpui)                                                \
 210        ((pcpui)->__ctx_depth |= __CTX_CANNOT_BLOCK)
 211
 212#define clear_cannot_block(pcpui)                                              \
 213        ((pcpui)->__ctx_depth &= ~__CTX_CANNOT_BLOCK)
 214
 215/* Functions to query the kernel context depth/state.  I haven't fully decided
 216 * on whether or not 'default' context includes RKMs or not.  Will depend on
 217 * how we use it.  Check the code below to see what the latest is. */
 218
 219#define in_irq_ctx(pcpui)                                                      \
 220        (irq_depth(pcpui))
 221
 222/* Right now, anything (KTRAP, IRQ, or RKM) makes us not 'default' */
 223#define in_default_ctx(pcpui)                                                  \
 224        (!(pcpui)->__ctx_depth)
 225
 226/* Can block only if we have no nested contexts (ktraps or irqs, (which are
 227 * potentially nested contexts)) and not in an explicit CANNOT_BLOCK. */
 228#define can_block(pcpui)                                                       \
 229        (!((pcpui)->__ctx_depth & (__CTX_NESTED_CTX_MASK | __CTX_CANNOT_BLOCK)))
 230
 231/* TRUE if we are allowed to spin, given that the 'lock' was declared as not
 232 * grabbable from IRQ context.  Meaning, we can't grab the lock from any nested
 233 * context.  (And for most locks, we can never grab them from a kernel trap
 234 * handler).
 235 *
 236 * Example is a lock that is not declared as irqsave, but we later grab it from
 237 * irq context.  This could deadlock the system, even if it doesn't do it this
 238 * time.  This function will catch that. */
 239#define can_spinwait_noirq(pcpui)                                              \
 240        (!((pcpui)->__ctx_depth & __CTX_NESTED_CTX_MASK))
 241
 242/* TRUE if we are allowed to spin, given that the 'lock' was declared as
 243 * potentially grabbable by IRQ context (such as with an irqsave lock).  We can
 244 * never grab from a ktrap, since there is no way to prevent that.  And we must
 245 * have IRQs disabled, since an IRQ handler could attempt to grab the lock. */
 246#define can_spinwait_irq(pcpui)                                                \
 247        ((!ktrap_depth(pcpui) && !irq_is_enabled()))
 248
 249/* Debugging */
 250void print_kctx_depths(const char *str);
 251