1 //----------------------------------------------------------------------------
2 IMPLEMENTATION [amd64]:
7 Thread::fast_return_to_user(Mword ip, Mword sp)
15 : "r" (static_cast<Return_frame*>(regs()))
22 Thread::invoke_arch(L4_msg_tag & /*tag*/, Utcb * /*utcb*/)
29 Thread::user_sp() const
30 { return exception_triggered()?_exc_cont.sp(regs()):regs()->sp(); }
34 Thread::user_sp(Mword sp)
36 if (exception_triggered())
37 _exc_cont.sp(regs(), sp);
44 Thread::do_trigger_exception(Entry_frame *r, void *ret_handler)
46 if (!exception_triggered())
48 _exc_cont.activate(r, ret_handler);
51 // else ignore change of IP because triggered exception already pending
57 Thread::restore_exc_state()
59 _exc_cont.restore(regs());
64 Thread::trap_state_to_rf(Trap_state *ts)
66 char *im = reinterpret_cast<char*>(ts + 1);
67 return reinterpret_cast<Return_frame*>(im)-1;
70 PRIVATE static inline NEEDS[Thread::trap_is_privileged,
71 Thread::trap_state_to_rf]
72 bool FIASCO_WARN_RESULT
73 Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
76 Trap_state *ts = (Trap_state*)rcv->_utcb_handler;
77 Mword s = tag.words();
78 Unsigned32 cs = ts->cs();
79 Utcb *snd_utcb = snd->access_utcb();
81 if (EXPECT_FALSE(rcv->exception_triggered()))
83 // triggered exception pending
84 Mem::memcpy_mwords (ts, snd_utcb->values, s > 19 ? 19 : s);
85 if (EXPECT_TRUE(s > 22))
87 Continuation::User_return_frame const *s
88 = reinterpret_cast<Continuation::User_return_frame const *>((char*)&snd_utcb->values[19]);
90 rcv->_exc_cont.set(trap_state_to_rf(ts), s);
94 Mem::memcpy_mwords (ts, snd_utcb->values, s > 23 ? 23 : s);
96 if (tag.transfer_fpu() && (rights & L4_fpage::W))
97 snd->transfer_fpu(rcv);
100 // XXX: ia32 in here!
101 if (!rcv->trap_is_privileged(0))
102 ts->flags((ts->flags() & ~(EFLAGS_IOPL | EFLAGS_NT)) | EFLAGS_IF);
104 // don't allow to overwrite the code selector!
107 bool ret = transfer_msg_items(tag, snd, snd_utcb,
108 rcv, rcv->access_utcb(), rights);
110 rcv->state_del(Thread_in_exception);
114 PRIVATE static inline NEEDS[Thread::trap_state_to_rf]
115 bool FIASCO_WARN_RESULT
116 Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv,
117 unsigned char rights)
119 Trap_state *ts = (Trap_state*)snd->_utcb_handler;
120 Utcb *rcv_utcb = rcv->utcb();
122 Lock_guard <Cpu_lock> guard (&cpu_lock);
123 if (EXPECT_FALSE(snd->exception_triggered()))
125 Mem::memcpy_mwords (rcv_utcb->values, ts, 19);
126 Continuation::User_return_frame *d
127 = reinterpret_cast<Continuation::User_return_frame *>((char*)&rcv_utcb->values[19]);
129 snd->_exc_cont.get(d, trap_state_to_rf(ts));
132 Mem::memcpy_mwords (rcv_utcb->values, ts, 23);
134 if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::W))
135 snd->transfer_fpu(rcv);
143 Thread::user_invoke()
145 user_invoke_generic();
148 (" mov %%rax,%%rsp \n" // set stack pointer to regs structure
151 " xor %%rax,%%rax \n"
152 " xor %%rcx,%%rcx \n" // clean out user regs
153 " xor %%rdx,%%rdx \n"
154 " xor %%rsi,%%rsi \n"
155 " xor %%rdi,%%rdi \n"
156 " xor %%rbx,%%rbx \n"
157 " xor %%rbp,%%rbp \n"
160 " xor %%r10,%%r10 \n"
161 " xor %%r11,%%r11 \n"
162 " xor %%r12,%%r12 \n"
163 " xor %%r13,%%r13 \n"
164 " xor %%r14,%%r14 \n"
165 " xor %%r15,%%r15 \n"
169 : "a" (nonull_static_cast<Return_frame*>(current()->regs())),
170 "c" (Gdt::gdt_data_user | Gdt::Selector_user)
173 // never returns here
178 Thread::check_trap13_kernel (Trap_state * /*ts*/)
182 //----------------------------------------------------------------------------
183 IMPLEMENTATION [amd64 & (debug | kdb)]:
185 #include "kernel_task.h"
187 /** Call the nested trap handler (either Jdb::enter_kdebugger() or the
188 * gdb stub. Setup our own stack frame */
191 Thread::call_nested_trap_handler(Trap_state *ts)
195 unsigned long phys_cpu = Cpu::phys_id_direct();
196 unsigned log_cpu = Cpu::p2l(phys_cpu);
199 printf("Trap on unknown CPU phys_id=%lx\n", phys_cpu);
203 unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
206 printf("%s: lcpu%u sp=%p t=%u nested_trap_recover=%ld\n",
207 __func__, log_cpu, (void*)Proc::stack_pointer(), ts->_trapno,
214 stack = dbg_stack.cpu(log_cpu).stack_top;
216 Unsigned64 dummy1, dummy2, dummy3;
218 // don't set %esp if gdb fault recovery to ensure that exceptions inside
219 // kdb/jdb don't overwrite the stack
221 ("mov %%rsp,%[d2] \n\t" // save old stack pointer
222 "cmpq $0,%[recover] \n\t"
223 "jne 1f \n\t" // check trap within trap handler
224 "mov %[stack],%%rsp \n\t" // setup clean stack pointer
226 "incq %[recover] \n\t"
227 "mov %%cr3, %[d1] \n\t"
228 "push %[d2] \n\t" // save old stack pointer on new stack
229 "push %[d1] \n\t" // save old pdbr
230 "mov %[pdbr], %%cr3 \n\t"
231 "callq *%[handler] \n\t"
233 "mov %[d1], %%cr3 \n\t"
234 "pop %%rsp \n\t" // restore old stack pointer
235 "cmpq $0,%[recover] \n\t" // check trap within trap handler
237 "decq %[recover] \n\t"
239 : [ret] "=a"(ret), [d2] "=&r"(dummy2), [d1] "=&r"(dummy1), "=D"(dummy3),
242 [pdbr] "r" (Kernel_task::kernel_task()->mem_space()->virt_to_phys((Address)Kmem::dir())),
245 [handler] "m" (nested_trap_handler)
246 : "rdx", "rcx", "r8", "r9", "memory");
248 return ret == 0 ? 0 : -1;