1 // orb/invoke.cc -- Method Invocation
3 // This software is copyright (c) 2007 Scott Wood <scott@buserror.net>.
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
15 #include <kern/types.h>
17 #include <kern/pagealloc.h>
18 #include <kern/compiler.h>
19 #include <kern/thread.h>
20 #include <kern/process.h>
21 #include <kern/arch.h>
22 #include <kern/lock.h>
24 #include <arch/usercopy.h>
26 #include <util/misc.h>
29 using System::RunTime::ParamInfoBlock;
30 typedef ParamInfoBlock::Segment Segment;
32 using Threads::Thread;
36 static CallFrame *new_frame(Thread *thread)
38 CallStackHeader *hdr = thread->orbstack_top_hdr;
40 if (unlikely(thread->orbstack_top == hdr->num_frames - 1)) {
41 hdr = static_cast<CallStackHeader *>(Mem::alloc_pages(1));
42 new(hdr) CallStackHeader;
44 hdr->num_frames = (Arch::page_size - sizeof(CallStackHeader)) /
47 thread->orbstack_top_hdr->node.add_front(&hdr->node);
48 thread->orbstack_top_hdr = hdr;
49 thread->orbstack_top = 0;
50 return &hdr->frames[0];
53 return &hdr->frames[++thread->orbstack_top];
56 Object *IDSpace::lookup(ID id)
59 ObjTableEntry *ote = table.lookup(id);
60 if (!ote || !ote->hdr.Valid)
64 return ote->ptr.object;
69 ObjectHdr *IDSpace::get_local(Object *obj)
71 if (&obj->aspace->idspace == this)
74 Lock::AutoSpinLock autolock(lock);
75 ObjectPtr *ptr = *rmap.find(obj);
79 int id = alloc.alloc();
80 ptr = &table.lookup(id, true)->ptr;
92 Object *IDSpace::newobj(Mem::ProcAddrSpace *aspace)
94 Lock::AutoSpinLock autolock(lock);
95 int id = alloc.alloc();
96 Object *obj = &table.lookup(id, true)->obj;
101 obj->aspace = aspace;
106 static void copy_data(u8 *dest, u8 *vaddr, size_t bufsize,
107 ParamInfoBlock *dpib, ParamInfoBlock *spib,
108 u32 fmask, u32 flags)
112 for (uint i = 0; i < spib->num_segments; i++) {
113 if ((spib->segments[i].flags & fmask) != flags)
116 size_t len = round_up(spib->segments[i].len, 3);
118 if (len + copied > bufsize || len + copied < copied)
119 throw_idl(InvalidArgument, 0, countarray("copy_data: bad size"));
121 dpib->segments[i].ptr = vaddr;
122 dpib->segments[i].len = len;
123 dpib->segments[i].reserved = 0;
124 Arch::copyin(spib->segments[i].ptr, dest, len);
132 typedef void (*KernEntry)(ParamInfoBlock *pib);
134 struct KernObject : public Object {
138 typedef Util::RadixTree<KernObject, ID, 6> KIDTable;
141 void copy_ids_to_kern(ParamInfoBlock *dpib, ParamInfoBlock *spib,
144 dpib->objlist_len = spib->objlist_len;
146 for (uint i = 0; i < spib->objlist_len; i++) {
147 Object *obj = ids->lookup(spib->objlist[i]);
150 throw_idl(InvalidReference, i, nullarray);
152 dpib->objlist[i] = reinterpret_cast<uintptr_t>(obj);
156 void invoke_method(ParamInfoBlock *user_pib, uintptr_t &stack)
158 printf("invoke_method: pib %p\n", user_pib);
160 ParamInfoBlock pib = Arch::copyin(user_pib);
161 printf("objlist len %u\n", pib.objlist_len);
163 if (pib.objlist_len == 0)
164 throw_idl(InvalidArgument, 0, countarray("no objects"));
166 // FIXME: declare constants somewhere
167 if (pib.num_segments > 64)
168 throw_idl(InvalidArgument, 0, countarray("too many segments"));
169 if (pib.objlist_len > 4096)
170 throw_idl(InvalidArgument, 0, countarray("too many objects"));
172 printf("&pib.objlist[0] %p\n", &pib.objlist[0]);
174 IDSpace *ids = &curthread->aspace->idspace;
175 ID objid = Arch::copyin(&pib.objlist[0]);
176 Object *obj = ids->lookup(objid);
179 printf("no obj %d\n", objid);
180 throw_idl(InvalidReference, 0, nullarray);
183 printf("obj %p\n", obj);
185 if (obj->aspace == Arch::init_thread->aspace) {
186 KernObject *ko = static_cast<KernObject *>(obj);
187 int datalen = round_up(pib.buffer_size, 8);
188 int buflen = datalen + pib.objlist_len * sizeof(void *);
189 int piboff = datalen;
190 buflen += sizeof(ParamInfoBlock);
191 buflen += pib.num_segments * sizeof(ParamInfoBlock::Segment);
193 u8 *args = new(orbmm) u8[buflen];
194 u8 *copy = new(orbmm) u8[pib.copy_size];
195 ParamInfoBlock *dpib = reinterpret_cast<ParamInfoBlock *>
197 dpib->objlist = reinterpret_cast<ID *>(args + datalen);
199 copy_ids_to_kern(dpib, &pib, ids);
200 copy_data(args, args, pib.buffer_size, dpib, &pib, ~0U, Segment::In);
201 copy_data(copy, copy, pib.copy_size, dpib, &pib, ~0U,
202 Segment::In | Segment::Copy);
206 // FIXME: Copy return data
210 CallFrame *frame = new_frame(curthread);
211 frame->caller_user_pib = user_pib;
212 frame->ret_stack = stack;
214 printf("invoke_method: frame %p pib %p ret_stack %lx obj %p\n",
215 frame, frame->caller_user_pib,
216 frame->ret_stack, obj);
219 uintptr_t return_from_method(uintptr_t &exptr, size_t &exlen)
226 kernobjs = new KIDTable;