10 static int (*int3_handler)(Trap_state*);
17 #include "boot_info.h"
18 #include "config.h" // for page sizes
19 #include "emulation.h"
21 #include "lock_guard.h"
23 #include "per_cpu_data.h"
24 #include "utcb_init.h"
26 int (*Thread::int3_handler)(Trap_state*);
27 Per_cpu<Thread::Dbg_stack> DEFINE_PER_CPU Thread::dbg_stack;
30 IMPLEMENT static inline NEEDS ["emulation.h"]
32 Thread::exception_cs()
34 return Emulation::kernel_cs();
38 * The ux specific part of the thread constructor.
44 // Allocate FPU state now because it indirectly calls current()
45 // save_state runs on a signal stack and current() doesn't work there.
47 // FIXME, space()==0 for sigma0 (or even more)
48 Fpu_alloc::alloc_state(space()->ram_quota(), fpu_state());
50 Fpu_alloc::alloc_state(Ram_quota::root, fpu_state());
52 // clear out user regs that can be returned from the thread_ex_regs
53 // system call to prevent covert channel
54 Entry_frame *r = regs();
57 r->cs(Emulation::kernel_cs() & ~1); // force iret trap
58 r->ss(Emulation::kernel_ss());
60 if(Config::enable_io_protection)
61 r->flags(EFLAGS_IOPL_K | EFLAGS_IF | 2);
63 r->flags(EFLAGS_IOPL_U | EFLAGS_IF | 2); // XXX iopl=kernel
68 Thread::set_int3_handler(int (*handler)(Trap_state *ts))
70 int3_handler = handler;
73 PRIVATE inline bool Thread::check_trap13_kernel (Trap_state *)
76 PRIVATE inline void Thread::check_f00f_bug (Trap_state *)
81 Thread::check_io_bitmap_delimiter_fault(Trap_state *)
84 PRIVATE inline bool Thread::handle_sysenter_trap (Trap_state *, Address, bool)
87 PRIVATE inline bool Thread::trap_is_privileged (Trap_state *)
92 Thread::do_wrmsr_in_kernel (Trap_state *)
94 // do "wrmsr (msr[ecx], edx:eax)" in kernel
95 kdb_ke("wrmsr not supported");
100 Thread::do_rdmsr_in_kernel (Trap_state *)
102 // do "rdmsr (msr[ecx], edx:eax)" in kernel
103 kdb_ke("rdmsr not supported");
108 Thread::handle_not_nested_trap (Trap_state *)
113 Thread::call_nested_trap_handler (Trap_state *ts)
115 // run the nested trap handler on a separate stack
116 // equiv of: return nested_trap_handler(ts) == 0 ? true : false;
118 //static char nested_handler_stack [Config::PAGE_SIZE];
119 unsigned phys_cpu = Cpu::phys_id_direct();
120 unsigned log_cpu = Cpu::p2l(phys_cpu);
124 printf("Trap on unknown CPU host-thread=%x\n", phys_cpu);
128 unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
130 //printf("%s: lcpu%u sp=%p t=%lu nested_trap_recover=%ld handler=%p\n",
131 // __func__, log_cpu, (void*)Proc::stack_pointer(), ts->_trapno,
132 // ntr, nested_trap_handler);
138 stack = dbg_stack.cpu(log_cpu).stack_top;
140 unsigned dummy1, dummy2, dummy3;
143 ("movl %%esp,%[d2] \n\t"
144 "cmpl $0, (%[ntrp]) \n\t"
146 "movl %[stack],%%esp \n\t"
148 "incl (%[ntrp]) \n\t"
151 "call *%[handler] \n\t"
154 "cmpl $0,(%[ntrp]) \n\t"
156 "decl (%[ntrp]) \n\t"
166 [handler] "m" (nested_trap_handler)
169 assert (_magic == magic);
171 // Do shutdown by switching to idle loop, unless we're already there
172 if (!running && current() != kernel_thread)
173 current()->switch_to_locked (kernel_thread);
175 return ret == 0 ? 0 : -1;
184 // The "FPU not available" trap entry point
185 extern "C" void thread_handle_fputrap (void) { panic ("fpu trap"); }
187 extern "C" void thread_timer_interrupt_stop() {}
188 extern "C" void thread_timer_interrupt_slow() {}
192 Thread::user_invoke()
197 (" movl %%ds , %0 \n\t"
198 " movl %0, %%es \n\t"
202 Cpu::set_gs(Utcb_init::gs_value());
204 user_invoke_generic();
207 (" movl %%eax , %%esp \n\t"
208 " xorl %%ebx , %%ebx \n\t"
209 " xorl %%edx , %%edx \n\t"
210 " xorl %%esi , %%esi \n\t" // clean out user regs
211 " xorl %%edi , %%edi \n\t"
212 " xorl %%ebp , %%ebp \n\t"
213 " xorl %%eax , %%eax \n\t"
216 : "a" (nonull_static_cast<Return_frame*>(current()->regs())),
217 "c" (current()->space() == sigma0_task // only Sigma0 gets the KIP
218 ? Kmem::virt_to_phys(Kip::k()) : 0));
223 Thread::sys_control_arch(Utcb *utcb)
225 if (utcb->values[0] & Ctl_ux_native)
226 _is_native = utcb->values[4] & Ctl_ux_native;
230 //---------------------------------------------------------------------------
236 KIP_KERNEL_FEATURE("segments");
240 Thread::invoke_arch(L4_msg_tag &tag, Utcb *utcb)
242 #ifndef GDT_ENTRY_TLS_MIN
243 #define GDT_ENTRY_TLS_MIN 6
245 switch (utcb->values[0] & Opcode_mask)
247 case Op_gdt_x86: // Gdt operation
249 // if no words given then return the first gdt entry
250 if (tag.words() == 1)
252 utcb->values[0] = GDT_ENTRY_TLS_MIN;
253 tag = commit_result(0, 1);
258 unsigned entry_number = utcb->values[1];
260 Mword *trampoline_page = (Mword *) Kmem::phys_to_virt
261 (Mem_layout::Trampoline_frame);
264 for (; entry_number < Gdt_user_entries
266 ; idx += 2, ++entry_number)
268 Gdt_entry *d = (Gdt_entry *)&utcb->values[idx];
273 info.entry_number = entry_number + GDT_ENTRY_TLS_MIN;
274 info.base_addr = d->base();
275 info.limit = d->limit();
276 info.seg_32bit = d->seg32();
277 info.contents = d->contents();
278 info.read_exec_only = !d->writable();
279 info.limit_in_pages = d->granularity();
280 info.seg_not_present = !d->present();
281 info.useable = d->avl();
283 // Remember descriptor for reload on thread switch
284 memcpy(&_gdt_user_entries[entry_number], &info,
285 sizeof(_gdt_user_entries[0]));
287 // Set up data on trampoline
288 memcpy(trampoline_page + 1, &info, sizeof(info));
290 // Call set_thread_area for given user process
291 Trampoline::syscall(space()->pid(), 243 /* __NR_set_thread_area */,
292 Mem_layout::Trampoline_page + sizeof(Mword));
294 // Also set this for the fiasco kernel so that
295 // segment registers can be set, this is necessary for signal
296 // handling, esp. for sigreturn to work in the Fiasco kernel
297 // with the context of the client (gs/fs values).
298 Emulation::thread_area_host(entry_number + GDT_ENTRY_TLS_MIN);
302 if (this == current_thread())
303 switch_gdt_user_entries(this);
305 tag = commit_result(0);