3 #include "mapping_tree.h"
8 #include "slab_cache.h"
13 class Vm : public Kobject, public Ref_cnt_obj
15 FIASCO_DECLARE_KOBJ();
28 Mword r_fiq[5]; // r8 - r12
53 Mword cp15_vector_base;
59 Mword cp15_prim_region_remap;
60 Mword cp15_norm_region_remap;
71 typedef Slab_cache Allocator;
74 Space *_space; // space the state is contained in
77 //-----------------------------------------------------------------------------
85 struct Vm_log : public Tb_entry
94 unsigned print(int maxlen, char *buf) const;
95 unsigned vm_entry_log_fmt(int maxlen, char *buf) const;
96 unsigned vm_exit_log_fmt(int maxlen, char *buf) const;
100 //-----------------------------------------------------------------------------
105 #include "cpu_lock.h"
106 #include "entry_frame.h"
107 #include "ipc_timeout.h"
109 #include "mem_space.h"
110 #include "thread_state.h"
114 FIASCO_DEFINE_KOBJ(Vm);
119 Vm::create(Ram_quota *quota)
121 if (void *a = allocator()->q_alloc(quota))
131 Vm::Vm() : _state(0), _space(0)
137 { return dec_ref() == 0; }
143 { return reinterpret_cast<machine_state *>(_state); };
145 // ------------------------------------------------------------------------
146 IMPLEMENTATION [arm && tz]:
151 Vm::run(Syscall_frame *f, Utcb *utcb)
153 assert(cpu_lock.test());
154 Ref_ptr<Vm> ref_ptr(this);
156 L4_msg_tag const &tag = f->tag();
158 if (tag.words() != 3)
160 WARN("tz: Invalid message length\n");
161 f->tag(commit_result(-L4_err::EInval));
165 // FIXME: use a send item (fpage) for vm_state. this implementation is wrong!
166 L4_fpage state_fpage(utcb->values[1]);
168 if (!state_fpage.is_mempage()
169 || state_fpage.order() != 12)
171 WARN("tz: Fpage invalid\n");
172 f->tag(commit_result(-L4_err::EInval));
176 _state = (Mword *)(Virt_addr(state_fpage.mem_address()).value());
180 Mem_space::Phys_addr phys;
181 Mem_space::Size size;
182 unsigned int attribs;
184 _space = current()->space();
186 Mem_space *const curr_mem_space = _space;
187 resident = curr_mem_space->v_lookup(Virt_addr(_state), &phys, &size, &attribs);
191 WARN("tz: Vm_state not mapped\n");
192 f->tag(commit_result(-L4_err::EInval));
197 // set the temporary label for this VM
198 Mword label = f->from_spec();
202 Proc::preemption_point();
204 if (current_thread()->sender_list()->first())
206 current_thread()->do_ipc(L4_msg_tag(), 0, 0, true, 0,
207 L4_timeout_pair(L4_timeout::Zero, L4_timeout::Zero), f, 7);
208 if (EXPECT_TRUE(!f->tag().has_error()))
210 WARN("tz: Receive event failed\n");
217 f->tag(commit_result(-L4_err::EInval));
221 Cpu::cpus.cpu(current()->cpu()).tz_switch_to_ns(_state);
223 assert(cpu_lock.test());
227 if ((state()->exit_reason != 1) ||
228 ((state()->exit_reason == 1) &&
229 ((state()->r[0] & 0xffff0000) == 0xffff0000)))
235 // set label as return value for this vm
237 f->tag(L4_msg_tag(L4_msg_tag::Label_task, 0, 0, 0));
241 IMPLEMENTATION [arm && tz && fpu]:
247 if (!(current()->state() & Thread_fpu_owner))
249 if (!current_thread()->switchin_fpu())
251 printf("tz: switchin_fpu failed\n");
258 // --------------------------------------------------------------------------
259 IMPLEMENTATION [arm && tz && !fpu]:
266 IMPLEMENTATION [arm && !tz]:
272 return L4_msg_tag(0, 0, 0, 0);
275 // --------------------------------------------------------------------------
280 Vm::operator new (size_t, void *p) throw()
285 Vm::operator delete (void *_l)
287 Vm *l = reinterpret_cast<Vm*>(_l);
288 allocator()->free(l);
291 static Kmem_slab_t<Vm> _vm_allocator("Vm");
296 { return &_vm_allocator; }
300 Vm::invoke(L4_obj_ref, Mword, Syscall_frame *f, Utcb *u)
302 switch (f->tag().proto())
305 case L4_msg_tag::Label_task:
306 run(nonull_static_cast<Syscall_frame*>(f), u);
312 f->tag(L4_msg_tag(0,0,0,-L4_err::EInval));
315 // --------------------------------------------------------------------------
316 IMPLEMENTATION [debug]:
322 Vm::jdb_get(Mword *state_ptr)
325 Jdb::peek(state_ptr, _space, v);
331 Vm::dump_machine_state()
333 machine_state *s = reinterpret_cast<machine_state*>(_state);
334 printf("pc: %08lx cpsr: %08lx exit_reason:%ld \n",
335 jdb_get(&s->pc), jdb_get(&s->cpsr), jdb_get(&s->exit_reason));
336 printf("r0: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
337 jdb_get(&s->r[0]), jdb_get(&s->r[1]), jdb_get(&s->r[2]), jdb_get(&s->r[3]),
338 jdb_get(&s->r[4]), jdb_get(&s->r[5]), jdb_get(&s->r[6]), jdb_get(&s->r[7]));
339 printf("r8: %08lx %08lx %08lx %08lx %08lx\n",
340 jdb_get(&s->r[8]), jdb_get(&s->r[9]), jdb_get(&s->r[10]), jdb_get(&s->r[11]),
343 printf("usr: sp %08lx lr %08lx\n",
344 jdb_get(&s->sp_usr), jdb_get(&s->lr_usr));
345 printf("irq: sp %08lx lr %08lx psr %08lx\n",
346 jdb_get(&s->sp_irq), jdb_get(&s->lr_irq), jdb_get(&s->spsr_irq));
347 printf("fiq: sp %08lx lr %08lx psr %08lx\n",
348 jdb_get(&s->sp_fiq), jdb_get(&s->lr_fiq), jdb_get(&s->spsr_fiq));
349 printf("r8: %08lx %08lx %08lx %08lx %08lx\n",
350 jdb_get(&s->r_fiq[0]), jdb_get(&s->r_fiq[1]), jdb_get(&s->r_fiq[2]),
351 jdb_get(&s->r_fiq[3]), jdb_get(&s->r_fiq[4]));
353 printf("abt: sp %08lx lr %08lx psr %08lx\n",
354 jdb_get(&s->sp_abt), jdb_get(&s->lr_abt), jdb_get(&s->spsr_abt));
355 printf("und: sp %08lx lr %08lx psr %08lx\n",
356 jdb_get(&s->sp_und), jdb_get(&s->lr_und), jdb_get(&s->spsr_und));
357 printf("svc: sp %08lx lr %08lx psr %08lx\n",
358 jdb_get(&s->sp_svc), jdb_get(&s->lr_svc), jdb_get(&s->spsr_svc));
359 printf("cp15_sctlr:%08lx\n", jdb_get(&s->cp15_control));
360 printf("cp15_ttbr0:%08lx\n", jdb_get(&s->cp15_ttbr0));
361 printf("cp15_ttbr1:%08lx\n", jdb_get(&s->cp15_ttbr1));
362 printf("cp15_ttbcr:%08lx\n", jdb_get(&s->cp15_ttbcr));
363 printf("dfar: %08lx dfsr: %08lx ifar: %08lx ifsr: %08lx\n",
364 jdb_get(&s->cp15_dfar), jdb_get(&s->cp15_dfsr), jdb_get(&s->cp15_ifar),
365 jdb_get(&s->cp15_ifsr));
370 Vm::show_short(char *buf, int max)
372 return snprintf(buf, max, " utcb:%lx pc:%lx ", (Mword)_state, (Mword)jdb_get(&state()->pc));
377 Vm::Vm_log::print(int maxlen, char *buf) const
380 return vm_entry_log_fmt(maxlen, buf);
382 return vm_exit_log_fmt(maxlen, buf);
387 Vm::Vm_log::vm_entry_log_fmt(int maxlen, char *buf) const
390 return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx intack irq: %lx", pc, pending_events, r1);
392 return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx r0:%lx", pc, pending_events, r0);
397 Vm::Vm_log::vm_exit_log_fmt(int maxlen, char *buf) const
399 if ((r0 & 0xffff0000) == 0xffff0000)
400 return snprintf(buf, maxlen, "=====: pc:%08lx/%03lx [%04lx]", pc, pending_events, r0 & 0xffff);
402 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx enable irq: %lx", pc, pending_events, r1);
404 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx disable irq: %lx", pc, pending_events, r1);
406 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx intack", pc, pending_events);
408 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx send ipi:%lx", pc, pending_events, r1);
410 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx r0:%lx", pc, pending_events, r0);
415 Vm::log_vm(Vm *vm, bool is_entry)
417 if (vm->state()->exit_reason != 1)
419 if ((vm->state()->r[0] & 0xf000) == 0x7000)
421 if ((is_entry && (vm->state()->r[0] & 0xffff0000) == 0xffff0000))
423 LOG_TRACE("VM entry/entry", "VM", current(), Vm_log,
424 l->is_entry = is_entry;
425 l->pc = vm->state()->pc;
426 l->cpsr = vm->state()->cpsr;
427 l->exit_reason = vm->state()->exit_reason;
428 l->pending_events = vm->state()->pending_events;
429 l->r0 = vm->state()->r[0];
430 l->r1 = vm->state()->r[1];
434 // --------------------------------------------------------------------------
435 IMPLEMENTATION [!debug]:
439 Vm::log_vm(Vm *, bool)