Fault reflection and blocking page faults (XCC)
[akaros.git] / kern / include / trap.h
1 /* See COPYRIGHT for copyright information. */
2
3 #ifndef ROS_KERN_TRAP_H
4 #define ROS_KERN_TRAP_H
5
6 #include <ros/trapframe.h>
7 #include <arch/arch.h>
8 #include <arch/mmu.h>
9 #include <sys/queue.h>
10 #include <arch/trap.h>
11
12 // func ptr for interrupt service routines
13 typedef void (*isr_t)(struct hw_trapframe *hw_tf, void *data);
14 struct irq_handler {
15         isr_t isr;
16         void *data;
17         struct irq_handler *next;
18 };
19
20 void idt_init(void);
21 void register_raw_irq(unsigned int vector, isr_t handler, void *data);
22 void unregister_raw_irq(unsigned int vector, isr_t handler, void *data);
23 int register_dev_irq(int irq, isr_t handler, void *irq_arg);
24 void print_trapframe(struct hw_trapframe *hw_tf);
25 void print_user_ctx(struct user_context *ctx);
26 /* Generic per-core timer interrupt handler.  set_percore_timer() will fire the
27  * timer_interrupt(). */
28 void set_core_timer(uint32_t usec, bool periodic);
29 void timer_interrupt(struct hw_trapframe *hw_tf, void *data);
30
31 extern inline void save_fp_state(struct ancillary_state *silly);
32 extern inline void restore_fp_state(struct ancillary_state *silly);
33 extern inline void init_fp_state(void);
34 /* Set stacktop for the current core to be the stack the kernel will start on
35  * when trapping/interrupting from userspace */
36 void set_stack_top(uintptr_t stacktop);
37 uintptr_t get_stack_top(void);
38
39 /* It's important that this is inline and that ctx is not a stack variable */
40 static inline void save_kernel_ctx(struct kernel_ctx *ctx)
41                    __attribute__((always_inline, returns_twice));
42 void pop_kernel_ctx(struct kernel_ctx *ctx) __attribute__((noreturn));
43 void send_nmi(uint32_t os_coreid);
44 void reflect_unhandled_trap(unsigned int trap_nr, unsigned int err,
45                             unsigned long aux);
46 void __arch_reflect_trap_hwtf(struct hw_trapframe *hw_tf, unsigned int trap_nr,
47                               unsigned int err, unsigned long aux);
48
49 /* Kernel messages.  This is an in-order 'active message' style messaging
50  * subsystem, where you can instruct other cores (including your own) to execute
51  * a function (with arguments), either immediately or whenever the kernel is
52  * able to abandon its context/stack (permanent swap).
53  *
54  * These are different (for now) than the smp_calls in smp.h, since
55  * they will be executed immediately (for urgent messages), and in the order in
56  * which they are sent.  smp_calls are currently not run in order, and they must
57  * return (possibly passing the work to a workqueue, which is really just a
58  * routine message, so they really need to just return).
59  *
60  * Eventually, smp_call will be replaced by these.
61  *
62  * Also, a big difference is that smp_calls can use the same message (registered
63  * in the interrupt_handlers[] for x86) for every recipient, but the kernel
64  * messages require a unique message.  Also for now, but it might be like that
65  * for a while on x86 (til we have a broadcast). */
66
67 #define KMSG_IMMEDIATE                  1
68 #define KMSG_ROUTINE                    2
69
70 typedef void (*amr_t)(uint32_t srcid, long a0, long a1, long a2);
71
72 struct kernel_message
73 {
74         STAILQ_ENTRY(kernel_message) link;
75         uint32_t srcid;
76         uint32_t dstid;
77         amr_t pc;
78         long arg0;
79         long arg1;
80         long arg2;
81 }__attribute__((aligned(8)));
82
83 STAILQ_HEAD(kernel_msg_list, kernel_message);
84 typedef struct kernel_message kernel_message_t;
85
86 void kernel_msg_init(void);
87 uint32_t send_kernel_message(uint32_t dst, amr_t pc, long arg0, long arg1,
88                              long arg2, int type);
89 void handle_kmsg_ipi(struct hw_trapframe *hw_tf, void *data);
90 void process_routine_kmsg(void);
91 void print_kmsgs(uint32_t coreid);
92
93 /* Kernel context depths.  IRQ depth is how many nested IRQ stacks/contexts we
94  * are working on.  Kernel trap depth is how many nested kernel traps (not
95  * user-space traps) we have.
96  *
97  * Some examples:
98  *              (original context in parens, +(x, y) is the change to IRQ and ktrap
99  *              depth):
100  * - syscall (user): +(0, 0)
101  * - trap (user): +(0, 0)
102  * - irq (user): +(1, 0)
103  * - irq (kernel, handling syscall): +(1, 0)
104  * - trap (kernel, regardless of context): +(0, 1)
105  * - NMI (kernel): it's actually a kernel trap, even though it is
106  *   sent by IPI.  +(0, 1)
107  * - NMI (user): just a trap.  +(0, 0)
108  *
109  * So if the user traps in for a syscall (0, 0), then the kernel takes an IRQ
110  * (1, 0), and then another IRQ (2, 0), and then the kernel page faults (a
111  * trap), we're at (2, 1).
112  *
113  * Or if we're in userspace, then an IRQ arrives, we're in the kernel at (1, 0).
114  * Note that regardless of whether or not we are in userspace or the kernel when
115  * an irq arrives, we still are only at level 1 irq depth.  We don't care if we
116  * have one or 0 kernel contexts under us.  (The reason for this is that I care
117  * if it is *possible* for us to interrupt the kernel, not whether or not it
118  * actually happened). */
119
120 /* uint32_t __ctx_depth is laid out like so:
121  *
122  * +------8------+------8------+------8------+------8------+
123  * |    Flags    |    Unused   | Kernel Trap |  IRQ Depth  |
124  * |             |             |    Depth    |             |
125  * +-------------+-------------+-------------+-------------+
126  *
127  */
128 #define __CTX_IRQ_D_SHIFT                       0
129 #define __CTX_KTRAP_D_SHIFT                     8
130 #define __CTX_FLAG_SHIFT                        24
131 #define __CTX_IRQ_D_MASK                        ((1 << 8) - 1)
132 #define __CTX_KTRAP_D_MASK                      ((1 << 8) - 1)
133 #define __CTX_NESTED_CTX_MASK           ((1 << 16) - 1)
134 #define __CTX_EARLY_RKM                         (1 << __CTX_FLAG_SHIFT)
135
136 /* Basic functions to get or change depths */
137
138 #define irq_depth(pcpui)                                                       \
139         (((pcpui)->__ctx_depth >> __CTX_IRQ_D_SHIFT) & __CTX_IRQ_D_MASK)
140
141 #define ktrap_depth(pcpui)                                                     \
142         (((pcpui)->__ctx_depth >> __CTX_KTRAP_D_SHIFT) & __CTX_KTRAP_D_MASK)
143
144 #define inc_irq_depth(pcpui)                                                   \
145         ((pcpui)->__ctx_depth += 1 << __CTX_IRQ_D_SHIFT)
146
147 #define dec_irq_depth(pcpui)                                                   \
148         ((pcpui)->__ctx_depth -= 1 << __CTX_IRQ_D_SHIFT)
149
150 #define inc_ktrap_depth(pcpui)                                                 \
151         ((pcpui)->__ctx_depth += 1 << __CTX_KTRAP_D_SHIFT)
152
153 #define dec_ktrap_depth(pcpui)                                                 \
154         ((pcpui)->__ctx_depth -= 1 << __CTX_KTRAP_D_SHIFT)
155
156 #define set_rkmsg(pcpui)                                                       \
157         ((pcpui)->__ctx_depth |= __CTX_EARLY_RKM)
158
159 #define clear_rkmsg(pcpui)                                                     \
160         ((pcpui)->__ctx_depth &= ~__CTX_EARLY_RKM)
161
162 /* Functions to query the kernel context depth/state.  I haven't fully decided
163  * on whether or not 'default' context includes RKMs or not.  Will depend on
164  * how we use it.  Check the code below to see what the latest is. */
165
166 #define in_irq_ctx(pcpui)                                                      \
167         (irq_depth(pcpui))
168
169 #define in_early_rkmsg_ctx(pcpui)                                              \
170         ((pcpui)->__ctx_depth & __CTX_EARLY_RKM)
171
172 /* Right now, anything (KTRAP, IRQ, or RKM) makes us not 'default' */
173 #define in_default_ctx(pcpui)                                                  \
174         (!(pcpui)->__ctx_depth)
175
176 /* Can block only if we have no nested contexts (ktraps or irqs, (which are
177  * potentially nested contexts)) */
178 #define can_block(pcpui)                                                       \
179         (!((pcpui)->__ctx_depth & __CTX_NESTED_CTX_MASK))
180
181 /* TRUE if we are allowed to spin, given that the 'lock' was declared as not
182  * grabbable from IRQ context.  Meaning, we can't grab the lock from any nested
183  * context.  (And for most locks, we can never grab them from a kernel trap
184  * handler). 
185  *
186  * Example is a lock that is not declared as irqsave, but we later grab it from
187  * irq context.  This could deadlock the system, even if it doesn't do it this
188  * time.  This function will catch that. */
189 #define can_spinwait_noirq(pcpui)                                              \
190         (!((pcpui)->__ctx_depth & __CTX_NESTED_CTX_MASK))
191
192 /* TRUE if we are allowed to spin, given that the 'lock' was declared as
193  * potentially grabbable by IRQ context (such as with an irqsave lock).  We can
194  * never grab from a ktrap, since there is no way to prevent that.  And we must
195  * have IRQs disabled, since an IRQ handler could attempt to grab the lock. */
196 #define can_spinwait_irq(pcpui)                                                \
197         ((!ktrap_depth(pcpui) && !irq_is_enabled()))
198
199 /* Debugging */
200 void print_kctx_depths(const char *str);
201  
202 #endif /* ROS_KERN_TRAP_H */