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)
60 ObjTableEntry *ote = table.lookup(id);
61 if (!ote || ote->hdr.id == invalid_id)
65 return ote->ptr.object;
72 ObjectHdr *IDSpace::get_local(Object *obj)
74 if (&obj->aspace->idspace == this)
77 Lock::AutoSpinLock autolock(lock);
78 ObjectPtr *ptr = *rmap.find(obj);
83 int id = alloc.alloc();
84 ptr = &table.lookup(id, true)->ptr;
98 Object *IDSpace::newobj(Mem::ProcAddrSpace *aspace)
101 Lock::AutoSpinLock autolock(lock);
102 int id = alloc.alloc();
103 Object *obj = &table.lookup(id, true)->obj;
108 obj->aspace = aspace;
115 static void copy_data(u8 *dest, u8 *vaddr, size_t bufsize,
116 ParamInfoBlock *dpib, ParamInfoBlock *spib,
117 u32 fmask, u32 flags)
121 for (uint i = 0; i < spib->num_segments; i++) {
122 if ((spib->segments[i].flags & fmask) != flags)
125 size_t len = round_up(spib->segments[i].len, 3);
127 if (len + copied > bufsize || len + copied < copied)
128 throw_idl(InvalidArgument, 0, countarray<ORBMM>("copy_data: bad size"));
130 dpib->segments[i].ptr = vaddr;
131 dpib->segments[i].len = len;
132 dpib->segments[i].reserved = 0;
133 Arch::copyin(spib->segments[i].ptr, dest, len);
141 typedef void (*KernEntry)(ParamInfoBlock *pib);
143 struct KernObject : public Object {
147 typedef Util::RadixTree<KernObject, ID, 6> KIDTable;
150 void copy_ids_to_kern(ParamInfoBlock *dpib, ParamInfoBlock *spib,
153 dpib->objlist_len = spib->objlist_len;
155 for (uint i = 0; i < spib->objlist_len; i++) {
156 Object *obj = ids->lookup(spib->objlist[i]);
159 throw_idl(InvalidReference, i, nullarray);
161 dpib->objlist[i] = reinterpret_cast<uintptr_t>(obj);
165 void invoke_method(ParamInfoBlock *user_pib, uintptr_t &stack)
167 printf("invoke_method: pib %p\n", user_pib);
169 ParamInfoBlock pib = Arch::copyin(user_pib);
170 printf("objlist len %u\n", pib.objlist_len);
172 if (pib.objlist_len == 0)
173 throw_idl(InvalidArgument, 0, countarray<ORBMM>("no objects"));
175 // FIXME: declare constants somewhere
176 if (pib.num_segments > 64)
177 throw_idl(InvalidArgument, 0, countarray<ORBMM>("too many segments"));
178 if (pib.objlist_len > 4096)
179 throw_idl(InvalidArgument, 0, countarray<ORBMM>("too many objects"));
181 printf("&pib.objlist[0] %p\n", &pib.objlist[0]);
183 IDSpace *ids = &curthread->aspace->idspace;
184 ID objid = Arch::copyin(&pib.objlist[0]);
185 Object *obj = ids->lookup(objid);
188 printf("no obj %d\n", objid);
189 throw_idl(InvalidReference, 0, nullarray);
192 printf("obj %p\n", obj);
194 if (obj->aspace == Arch::init_thread->aspace) {
195 KernObject *ko = static_cast<KernObject *>(obj);
196 int datalen = round_up(pib.buffer_size, 8);
197 int buflen = datalen + pib.objlist_len * sizeof(void *);
198 int piboff = datalen;
199 buflen += sizeof(ParamInfoBlock);
200 buflen += pib.num_segments * sizeof(ParamInfoBlock::Segment);
202 u8 *args = new(ORBMM()) u8[buflen];
203 u8 *copy = new(ORBMM()) u8[pib.copy_size];
204 ParamInfoBlock *dpib = reinterpret_cast<ParamInfoBlock *>
206 dpib->objlist = reinterpret_cast<ID *>(args + datalen);
208 copy_ids_to_kern(dpib, &pib, ids);
209 copy_data(args, args, pib.buffer_size, dpib, &pib, ~0U, Segment::In);
210 copy_data(copy, copy, pib.copy_size, dpib, &pib, ~0U,
211 Segment::In | Segment::Copy);
215 // FIXME: Copy return data
219 CallFrame *frame = new_frame(curthread);
220 frame->caller_user_pib = user_pib;
221 frame->ret_stack = stack;
223 printf("invoke_method: frame %p pib %p ret_stack %lx obj %p\n",
224 frame, frame->caller_user_pib,
225 frame->ret_stack, obj);
228 uintptr_t return_from_method(uintptr_t &exptr, size_t &exlen)
235 kernobjs = new KIDTable;