3 #include "mapping_tree.h"
8 #include "slab_cache_anon.h"
13 class Vm : public Kobject_iface, 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;
69 typedef slab_cache_anon Allocator;
73 Space *_space; // space the state is contained in
79 //-----------------------------------------------------------------------------
96 static unsigned vm_log_fmt(Tb_entry *tbe, int maxlen, char *buf)
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))
135 : _valid(true), _state(0), _space(0)
145 { return dec_ref() == 0; }
151 { return reinterpret_cast<machine_state *>(_state); };
153 // ------------------------------------------------------------------------
154 IMPLEMENTATION [arm && tz]:
159 Vm::run(Syscall_frame *f, Utcb *utcb)
161 assert(cpu_lock.test());
162 Ref_ptr<Vm> ref_ptr(this);
164 L4_msg_tag const &tag = f->tag();
166 if (tag.words() != 3)
168 WARN("tz: Invalid message length\n");
169 f->tag(commit_result(-L4_err::EInval));
173 // FIXME: use a send item (fpage) for vm_state. this implementation is wrong!
174 L4_fpage state_fpage(utcb->values[1]);
176 if (!state_fpage.is_mempage()
177 || state_fpage.order() != 12)
179 WARN("tz: Fpage invalid\n");
180 f->tag(commit_result(-L4_err::EInval));
184 _state = (Mword *)(Virt_addr(state_fpage.mem_address()).value());
188 Mem_space::Phys_addr phys;
189 Mem_space::Size size;
190 unsigned int attribs;
192 _space = current()->space();
193 Mem_space *const curr_mem_space = current()->space()->mem_space();
194 resident = curr_mem_space->v_lookup(Virt_addr(_state), &phys, &size, &attribs);
198 WARN("tz: Vm_state not mapped\n");
199 f->tag(commit_result(-L4_err::EInval));
204 // set the temporary label for this VM
205 Mword label = f->from_spec();
209 Proc::preemption_point();
211 if (current_thread()->sender_list()->head())
213 current_thread()->do_ipc(L4_msg_tag(), 0, 0, true, 0,
214 L4_timeout_pair(L4_timeout::Zero, L4_timeout::Zero), f, 7);
215 if (EXPECT_TRUE(!f->tag().has_error()))
217 WARN("tz: Receive event failed\n");
224 f->tag(commit_result(-L4_err::EInval));
228 Cpu::cpus.cpu(current()->cpu()).tz_switch_to_ns(_state);
230 assert(cpu_lock.test());
234 if ((state()->exit_reason != 1) ||
235 ((state()->exit_reason == 1) &&
236 ((state()->r[0] & 0xffff0000) == 0xffff0000)))
242 // set label as return value for this vm
244 f->tag(L4_msg_tag(L4_msg_tag::Label_task, 0, 0, 0));
248 IMPLEMENTATION [arm && tz && fpu]:
254 if (!(current()->state() & Thread_fpu_owner))
256 if (!current_thread()->switchin_fpu())
258 printf("tz: switchin_fpu failed\n");
265 // --------------------------------------------------------------------------
266 IMPLEMENTATION [arm && tz && !fpu]:
273 IMPLEMENTATION [arm && !tz]:
279 return L4_msg_tag(0, 0, 0, 0);
282 // --------------------------------------------------------------------------
287 Vm::operator new (size_t, void *p)
292 Vm::operator delete (void *_l)
294 Vm *l = reinterpret_cast<Vm*>(_l);
295 allocator()->free(l);
298 PRIVATE static inline NOEXPORT NEEDS["kmem_slab.h"]
302 static Allocator* slabs =
303 new Kmem_slab_simple (sizeof (Vm), sizeof (Mword), "Vm");
315 Vm::invoke(L4_obj_ref, Mword, Syscall_frame *f, Utcb *u)
317 switch (f->tag().proto())
320 case L4_msg_tag::Label_task:
321 run(nonull_static_cast<Syscall_frame*>(f), u);
327 f->tag(L4_msg_tag(0,0,0,-L4_err::EInval));
330 // --------------------------------------------------------------------------
331 IMPLEMENTATION [debug]:
337 Vm::jdb_get(Mword *state_ptr)
340 Jdb::peek(state_ptr, _space, v);
346 Vm::dump_machine_state()
348 machine_state *s = reinterpret_cast<machine_state*>(_state);
349 printf("pc: %08lx cpsr: %08lx exit_reason:%ld \n",
350 jdb_get(&s->pc), jdb_get(&s->cpsr), jdb_get(&s->exit_reason));
351 printf("r0: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
352 jdb_get(&s->r[0]), jdb_get(&s->r[1]), jdb_get(&s->r[2]), jdb_get(&s->r[3]),
353 jdb_get(&s->r[4]), jdb_get(&s->r[5]), jdb_get(&s->r[6]), jdb_get(&s->r[7]));
354 printf("r8: %08lx %08lx %08lx %08lx %08lx\n",
355 jdb_get(&s->r[8]), jdb_get(&s->r[9]), jdb_get(&s->r[10]), jdb_get(&s->r[11]),
358 printf("usr: sp %08lx lr %08lx\n",
359 jdb_get(&s->sp_usr), jdb_get(&s->lr_usr));
360 printf("irq: sp %08lx lr %08lx psr %08lx\n",
361 jdb_get(&s->sp_irq), jdb_get(&s->lr_irq), jdb_get(&s->spsr_irq));
362 printf("fiq: sp %08lx lr %08lx psr %08lx\n",
363 jdb_get(&s->sp_fiq), jdb_get(&s->lr_fiq), jdb_get(&s->spsr_fiq));
364 printf("r8: %08lx %08lx %08lx %08lx %08lx\n",
365 jdb_get(&s->r_fiq[8]), jdb_get(&s->r_fiq[9]), jdb_get(&s->r_fiq[10]),
366 jdb_get(&s->r_fiq[11]), jdb_get(&s->r_fiq[12]));
368 printf("abt: sp %08lx lr %08lx psr %08lx\n",
369 jdb_get(&s->sp_abt), jdb_get(&s->lr_abt), jdb_get(&s->spsr_abt));
370 printf("und: sp %08lx lr %08lx psr %08lx\n",
371 jdb_get(&s->sp_und), jdb_get(&s->lr_und), jdb_get(&s->spsr_und));
372 printf("svc: sp %08lx lr %08lx psr %08lx\n",
373 jdb_get(&s->sp_svc), jdb_get(&s->lr_svc), jdb_get(&s->spsr_svc));
374 printf("cp15_sctlr:%08lx\n", jdb_get(&s->cp15_control));
375 printf("cp15_ttbr0:%08lx\n", jdb_get(&s->cp15_ttbr0));
376 printf("cp15_ttbr1:%08lx\n", jdb_get(&s->cp15_ttbr1));
377 printf("cp15_ttbcr:%08lx\n", jdb_get(&s->cp15_ttbcr));
378 printf("dfar: %08lx dfsr: %08lx ifar: %08lx ifsr: %08lx\n",
379 jdb_get(&s->cp15_dfar), jdb_get(&s->cp15_dfsr), jdb_get(&s->cp15_ifar),
380 jdb_get(&s->cp15_ifsr));
385 Vm::show_short(char *buf, int max)
387 return snprintf(buf, max, " utcb:%lx pc:%lx ", (Mword)_state, (Mword)jdb_get(&state()->pc));
392 Vm::vm_log_fmt(Tb_entry *e, int maxlen, char *buf)
394 Vm_log *l = e->payload<Vm_log>();
396 return vm_entry_log_fmt(l, maxlen, buf);
398 return vm_exit_log_fmt(l, maxlen, buf);
403 Vm::vm_entry_log_fmt(Vm_log *l, int maxlen, char *buf)
406 return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx intack irq: %lx", l->pc, l->pending_events, l->r1);
408 return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx r0:%lx", l->pc, l->pending_events, l->r0);
413 Vm::vm_exit_log_fmt(Vm_log *l, int maxlen, char *buf)
415 if ((l->r0 & 0xffff0000) == 0xffff0000)
416 return snprintf(buf, maxlen, "=====: pc:%08lx/%03lx [%04lx]", l->pc, l->pending_events, l->r0 & 0xffff);
418 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx enable irq: %lx", l->pc, l->pending_events, l->r1);
420 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx disable irq: %lx", l->pc, l->pending_events, l->r1);
422 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx intack", l->pc, l->pending_events);
424 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx send ipi:%lx", l->pc, l->pending_events, l->r1);
426 return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx r0:%lx", l->pc, l->pending_events, l->r0);
431 Vm::log_vm(Vm *vm, bool is_entry)
433 if (vm->state()->exit_reason != 1)
435 if ((vm->state()->r[0] & 0xf000) == 0x7000)
437 if ((is_entry && (vm->state()->r[0] & 0xffff0000) == 0xffff0000))
439 LOG_TRACE("VM entry/entry", "VM", current(), __vm_log_fmt,
440 Vm::Vm_log *l = tbe->payload<Vm::Vm_log>();
441 l->is_entry = is_entry;
442 l->pc = vm->state()->pc;
443 l->cpsr = vm->state()->cpsr;
444 l->exit_reason = vm->state()->exit_reason;
445 l->pending_events = vm->state()->pending_events;
446 l->r0 = vm->state()->r[0];
447 l->r1 = vm->state()->r[1];
451 // --------------------------------------------------------------------------
452 IMPLEMENTATION [!debug]:
456 Vm::log_vm(Vm *, bool)