4 #include "kobject_helper.h"
6 class Factory : public Ram_quota, public Kobject_h<Factory>
11 typedef slab_cache_anon Self_alloc;
14 //---------------------------------------------------------------------------
18 #include "kmem_slab.h"
20 #include "thread_object.h"
21 #include "static_init.h"
22 #include "l4_buf_iter.h"
24 #include "u_semaphore.h"
28 #include "entry_frame.h"
30 static Factory _root_factory INIT_PRIORITY(ROOT_FACTORY_INIT_PRIO);
31 FIASCO_DEFINE_KOBJ(Factory);
39 Factory::Factory(Ram_quota *q, unsigned long max)
44 static Kmem_slab_t<Factory> _factory_allocator("Factory");
49 { return &_factory_allocator; }
54 { return static_cast<Factory*>(Ram_quota::root); }
59 Factory::create_factory(unsigned long max)
62 if (alloc(sizeof(Factory) + max) && (nq = allocator()->alloc()))
63 return new (nq) Factory(this, max);
69 void Factory::operator delete (void *_f)
71 Factory *f = (Factory*)_f;
72 LOG_TRACE("Factory delete", "fa del", ::current(), 0, {});
77 Ram_quota *p = f->parent();
79 p->free(sizeof(Factory) + f->limit());
86 Factory::map_obj(Kobject_iface *o, Mword cap, Space *c_space,
91 case 0: return commit_result(-L4_err::ENomem);
92 case -L4_err::EInval: return commit_result(-L4_err::EInval);
93 case -L4_err::EPerm: return commit_result(-L4_err::EPerm);
99 if (!map(o, o_space, c_space, cap, rl.list()))
102 // FIXME: reap stuff if needed
103 return commit_result(-L4_err::ENomem);
106 // FIXME: reap stuff if needed
107 return commit_result(0, 0, 1);
112 PRIVATE inline NOEXPORT
114 Factory::new_factory(Utcb const *u)
116 // XXX: should check for type tag in new call
117 return create_factory(u->values[2]);
121 PRIVATE inline NOEXPORT
123 Factory::new_task(Utcb const *u)
125 L4_fpage utcb_area(0);
126 // XXX: should check for type tag in new call
127 utcb_area = L4_fpage(u->values[2]);
129 Task *new_t = Task::create(Space::Default_factory(), this, utcb_area);
134 if (!new_t->valid() || !new_t->initialize())
143 PRIVATE inline NOEXPORT
145 Factory::new_thread(Utcb const *)
147 Thread_object *t = new (this) Thread_object();
151 PRIVATE inline NOEXPORT
153 Factory::new_gate(L4_msg_tag const &tag, Utcb const *utcb, Obj_space *o_space)
155 L4_snd_item_iter snd_items(utcb, tag.words());
158 if (tag.items() && snd_items.next())
160 L4_fpage bind_thread(snd_items.get()->d);
161 if (EXPECT_FALSE(!bind_thread.is_objpage()))
162 return reinterpret_cast<Kobject_iface*>(-L4_err::EInval);
164 unsigned char thread_rights = 0;
165 thread = Kobject::dcast<Thread_object*>(o_space->lookup_local(bind_thread.obj_index(), &thread_rights));
167 if (EXPECT_FALSE(!(thread_rights & L4_fpage::W)))
168 return reinterpret_cast<Kobject_iface*>(-L4_err::EPerm);
172 return reinterpret_cast<Kobject_iface*>(-L4_err::EInval);
174 // should check type tag of varg
175 return static_cast<Ipc_gate_ctl*>(Ipc_gate::create(this, thread, utcb->values[2]));
179 PRIVATE inline NOEXPORT
181 Factory::new_semaphore(Utcb const *)
183 return U_semaphore::alloc(this);
186 PRIVATE inline NOEXPORT
188 Factory::new_irq(unsigned w, Utcb const *utcb)
190 if (w >= 3 && utcb->values[2])
191 return Irq::allocate<Irq_muxer>(this);
193 return Irq::allocate<Irq_sender>(this);
198 Factory::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f,
199 Utcb const *utcb, Utcb *)
201 register Context *const c_thread = ::current();
202 register Space *const c_space = c_thread->space();
203 register Obj_space *const o_space = c_space->obj_space();
205 if (EXPECT_FALSE(f->tag().proto() != L4_msg_tag::Label_factory))
206 return commit_result(-L4_err::EBadproto);
208 if (EXPECT_FALSE(!(rights & L4_fpage::W)))
209 return commit_result(-L4_err::EPerm);
211 if (EXPECT_FALSE(!ref.have_recv()))
212 return commit_result(0);
214 if (f->tag().words() < 1)
215 return commit_result(-L4_err::EInval);
220 L4_buf_iter buf(utcb, utcb->buf_desc.obj());
221 L4_buf_iter::Item const *const b = buf.get();
222 if (EXPECT_FALSE(b->b.is_void()
223 || b->b.type() != L4_msg_item::Map))
224 return commit_error(utcb, L4_error(L4_error::Overflow, L4_error::Rcv));
226 buffer = L4_fpage(b->d);
229 if (EXPECT_FALSE(!buffer.is_objpage()))
230 return commit_error(utcb, L4_error(L4_error::Overflow, L4_error::Rcv));
232 Kobject_iface *new_o;
234 switch ((long)utcb->values[0])
236 case 0: // new IPC Gate
237 new_o = new_gate(f->tag(), utcb, o_space);
240 case L4_msg_tag::Label_factory:
241 new_o = new_factory(utcb);
244 case L4_msg_tag::Label_task:
245 new_o = new_task(utcb);
248 case L4_msg_tag::Label_thread:
249 new_o = new_thread(utcb);
252 case L4_msg_tag::Label_semaphore:
253 new_o = new_semaphore(utcb);
256 case L4_msg_tag::Label_irq:
257 new_o = new_irq(f->tag().words(), utcb);
260 case L4_msg_tag::Label_vm:
261 new_o = new_vm(utcb);
265 return commit_result(-L4_err::ENodev);
268 LOG_TRACE("Kobject create", "new", ::current(), __factory_log_fmt,
269 Log_entry *le = tbe->payload<Log_entry>();
270 le->op = utcb->values[0];
271 le->buffer = buffer.obj_index();
272 le->id = dbg_info()->dbg_id();
274 le->newo = new_o ? new_o->dbg_info()->dbg_id() : ~0);
276 return map_obj(new_o, buffer.obj_index(), c_space, o_space);
281 //----------------------------------------------------------------------------
282 IMPLEMENTATION [svm || vmx]:
284 #include "vm_factory.h"
286 PRIVATE inline NOEXPORT
288 Factory::new_vm(Utcb const *)
290 Vm *new_t = Vm_factory::create(this);
295 if (!new_t->valid() || !new_t->initialize())
308 PRIVATE inline NOEXPORT
310 Factory::new_vm(Utcb const *)
312 return Vm::create(this);
315 //----------------------------------------------------------------------------
316 IMPLEMENTATION [!svm && !tz && !vmx]:
318 PRIVATE inline NOEXPORT
320 Factory::new_vm(Utcb const *)
321 { return (Kobject_iface*)(-L4_err::EInval); }
323 // ------------------------------------------------------------------------
326 #include "tb_entry.h"
328 EXTENSION class Factory
339 static unsigned log_fmt(Tb_entry *, int, char *) asm ("__factory_log_fmt");
342 // ------------------------------------------------------------------------
343 IMPLEMENTATION [debug]:
347 Factory::log_fmt(Tb_entry *e, int maxlen, char *buf)
349 static char const *const ops[] =
350 { /* 0 */ "gate", "irq", 0, 0, 0, 0, 0, 0,
351 /* -8 */ 0, 0, 0, "task", "thread", 0, 0, "factory",
352 /* -16 */ "vm", 0, 0, 0, "sem" };
353 Log_entry *le = e->payload<Log_entry>();
354 char const *op = -le->op <= (int)(sizeof(ops)/sizeof(ops[0]))
355 ? ops[-le->op] : "invalid op";
359 return snprintf(buf, maxlen, "factory=%lx [%s] new=%lx cap=[C:%lx] ram=%lx", le->id, op, le->newo, le->buffer, le->ram);