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 DEFINE_PER_CPU Per_cpu<Thread::Dbg_stack> 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());
59 r->flags(EFLAGS_IOPL_K | EFLAGS_IF | 2);
64 Thread::set_int3_handler(int (*handler)(Trap_state *ts))
66 int3_handler = handler;
69 PRIVATE inline bool Thread::check_trap13_kernel(Trap_state *)
72 PRIVATE inline void Thread::check_f00f_bug(Trap_state *)
77 Thread::check_io_bitmap_delimiter_fault(Trap_state *)
80 PRIVATE inline bool Thread::handle_sysenter_trap(Trap_state *, Address, bool)
85 Thread::handle_not_nested_trap(Trap_state *)
90 Thread::call_nested_trap_handler(Trap_state *ts)
92 // run the nested trap handler on a separate stack
93 // equiv of: return nested_trap_handler(ts) == 0 ? true : false;
95 //static char nested_handler_stack [Config::PAGE_SIZE];
96 unsigned phys_cpu = Cpu::phys_id_direct();
97 unsigned log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
101 printf("Trap on unknown CPU host-thread=%x\n", phys_cpu);
105 unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
107 //printf("%s: lcpu%u sp=%p t=%lu nested_trap_recover=%ld handler=%p\n",
108 // __func__, log_cpu, (void*)Proc::stack_pointer(), ts->_trapno,
109 // ntr, nested_trap_handler);
115 stack = dbg_stack.cpu(log_cpu).stack_top;
117 unsigned dummy1, dummy2, dummy3;
120 ("movl %%esp,%[d2] \n\t"
121 "cmpl $0, (%[ntrp]) \n\t"
123 "movl %[stack],%%esp \n\t"
125 "incl (%[ntrp]) \n\t"
128 "call *%[handler] \n\t"
131 "cmpl $0,(%[ntrp]) \n\t"
133 "decl (%[ntrp]) \n\t"
143 [handler] "m" (nested_trap_handler)
146 assert (_magic == magic);
148 return ret == 0 ? 0 : -1;
151 // The "FPU not available" trap entry point
152 extern "C" void thread_handle_fputrap (void) { panic ("fpu trap"); }
154 extern "C" void thread_timer_interrupt_slow() {}
158 Thread::user_invoke()
163 (" movl %%ds , %0 \n\t"
164 " movl %0, %%es \n\t"
168 Cpu::set_gs(Utcb_init::utcb_segment());
169 Cpu::set_fs(Utcb_init::utcb_segment());
171 user_invoke_generic();
174 (" movl %%eax , %%esp \n\t"
175 " xorl %%ebx , %%ebx \n\t"
176 " xorl %%edx , %%edx \n\t"
177 " xorl %%esi , %%esi \n\t" // clean out user regs
178 " xorl %%edi , %%edi \n\t"
179 " xorl %%ebp , %%ebp \n\t"
180 " xorl %%eax , %%eax \n\t"
183 : "a" (nonull_static_cast<Return_frame*>(current()->regs())),
184 "c" (current()->space()->is_sigma0() // only Sigma0 gets the KIP
185 ? Kmem::virt_to_phys(Kip::k()) : 0));
190 Thread::sys_control_arch(Utcb *utcb)
192 if (utcb->values[0] & Ctl_ux_native)
193 _is_native = utcb->values[4] & Ctl_ux_native;
197 //---------------------------------------------------------------------------
203 KIP_KERNEL_FEATURE("segments");
207 Thread::invoke_arch(L4_msg_tag tag, Utcb *utcb)
209 switch (utcb->values[0] & Opcode_mask)
211 case Op_gdt_x86: // Gdt operation
213 // if no words given then return the first gdt entry
214 if (tag.words() == 1)
216 utcb->values[0] = Emulation::host_tls_base();
217 return commit_result(0, 1);
221 unsigned entry_number = utcb->values[1];
223 Mword *trampoline_page = (Mword *) Kmem::phys_to_virt
224 (Mem_layout::Trampoline_frame);
227 for (; entry_number < Gdt_user_entries
229 ; idx += 2, ++entry_number)
231 Gdt_entry *d = (Gdt_entry *)&utcb->values[idx];
236 info.entry_number = entry_number + Emulation::host_tls_base();
237 info.base_addr = d->base();
238 info.limit = d->limit();
239 info.seg_32bit = d->seg32();
240 info.contents = d->contents();
241 info.read_exec_only = !d->writable();
242 info.limit_in_pages = d->granularity();
243 info.seg_not_present = !d->present();
244 info.useable = d->avl();
246 // Remember descriptor for reload on thread switch
247 memcpy(&_gdt_user_entries[entry_number], &info,
248 sizeof(_gdt_user_entries[0]));
250 // Set up data on trampoline
251 memcpy(trampoline_page + 1, &info, sizeof(info));
253 // Call set_thread_area for given user process
254 Trampoline::syscall(space()->pid(), 243 /* __NR_set_thread_area */,
255 Mem_layout::Trampoline_page + sizeof(Mword));
257 // Also set this for the fiasco kernel so that
258 // segment registers can be set, this is necessary for signal
259 // handling, esp. for sigreturn to work in the Fiasco kernel
260 // with the context of the client (gs/fs values).
261 Emulation::thread_area_host(entry_number + Emulation::host_tls_base());
264 if (this == current_thread())
265 switch_gdt_user_entries(this);
267 return commit_result(((utcb->values[1] + Emulation::host_tls_base()) << 3) + 3);
271 return commit_result(-L4_err::ENosys);