]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/orb/invoke.cc
Move some freestanding libc functions from the kernel into
[polintos/scott/priv.git] / kernel / orb / invoke.cc
1 // orb/invoke.cc -- Method Invocation
2 //
3 // This software is copyright (c) 2007 Scott Wood <scott@buserror.net>.
4 // 
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.
8 // 
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.
14
15 #include <kern/types.h>
16 #include <kern/orb.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>
23
24 #include <arch/usercopy.h>
25
26 #include <util/misc.h>
27 #include <orb.h>
28
29 using System::RunTime::ParamInfoBlock;
30 typedef ParamInfoBlock::Segment Segment;
31 using namespace ORB;
32 using Threads::Thread;
33 using Util::round_up;
34
35 namespace ORB {
36         static CallFrame *new_frame(Thread *thread)
37         {
38                 CallStackHeader *hdr = thread->orbstack_top_hdr;
39                 
40                 if (unlikely(thread->orbstack_top == hdr->num_frames - 1)) {
41                         hdr = static_cast<CallStackHeader *>(Mem::alloc_pages(1));
42                         new(hdr) CallStackHeader;
43                         hdr->thread = thread;
44                         hdr->num_frames = (Arch::page_size - sizeof(CallStackHeader)) /
45                                           sizeof(CallFrame);
46
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];
51                 }
52                 
53                 return &hdr->frames[++thread->orbstack_top];
54         }
55         
56         Object *IDSpace::lookup(ID id)
57         {
58                 // FIXME: refcounting
59                 ObjTableEntry *ote = table.lookup(id);
60                 if (!ote || !ote->hdr.Valid)
61                         return NULL;
62                 
63                 if (ote->hdr.Pointer)
64                         return ote->ptr.object;
65
66                 return &ote->obj;
67         }
68
69         ObjectHdr *IDSpace::get_local(Object *obj)
70         {
71                 if (&obj->aspace->idspace == this)
72                         return obj;
73         
74                 Lock::AutoSpinLock autolock(lock);
75                 ObjectPtr *ptr = *rmap.find(obj);
76                 if (ptr)
77                         return ptr;
78                 
79                 int id = alloc.alloc();
80                 ptr = &table.lookup(id, true)->ptr;
81
82                 ptr->id = id;
83                 ptr->flags = 0;
84                 ptr->Valid = 1;
85                 ptr->Pointer = 1;
86                 ptr->object = obj;
87
88                 rmap.add(obj, ptr);
89                 return ptr;
90         }
91
92         Object *IDSpace::newobj(Mem::ProcAddrSpace *aspace)
93         {
94                 Lock::AutoSpinLock autolock(lock);
95                 int id = alloc.alloc();
96                 Object *obj = &table.lookup(id, true)->obj;
97
98                 obj->id = id;
99                 obj->flags = 0;
100                 obj->Valid = 1;
101                 obj->aspace = aspace;
102                 
103                 return obj;
104         }
105         
106         static void copy_data(u8 *dest, u8 *vaddr, size_t bufsize,
107                               ParamInfoBlock *dpib, ParamInfoBlock *spib,
108                               u32 fmask, u32 flags)
109         {
110                 size_t copied = 0;
111         
112                 for (uint i = 0; i < spib->num_segments; i++) {
113                         if ((spib->segments[i].flags & fmask) != flags)
114                                 continue;
115                         
116                         size_t len = round_up(spib->segments[i].len, 3);
117
118                         if (len + copied > bufsize || len + copied < copied)
119                                 throw_idl(InvalidArgument, 0, countarray("copy_data: bad size"));
120                         
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);
125
126                         copied += len;
127                         dest += len;
128                         vaddr += len;
129                 }
130         }
131
132         typedef void (*KernEntry)(ParamInfoBlock *pib);
133
134         struct KernObject : public Object {
135                 KernEntry entry;
136         };
137
138         typedef Util::RadixTree<KernObject, ID, 6> KIDTable;
139         KIDTable *kernobjs;
140         
141         void copy_ids_to_kern(ParamInfoBlock *dpib, ParamInfoBlock *spib,
142                               IDSpace *ids)
143         {
144                 dpib->objlist_len = spib->objlist_len;
145         
146                 for (uint i = 0; i < spib->objlist_len; i++) {
147                         Object *obj = ids->lookup(spib->objlist[i]);
148                         
149                         if (!obj)
150                                 throw_idl(InvalidReference, i, nullarray);
151                         
152                         dpib->objlist[i] = reinterpret_cast<uintptr_t>(obj);
153                 }
154         }
155
156         void invoke_method(ParamInfoBlock *user_pib, uintptr_t &stack)
157         {
158                 printf("invoke_method: pib %p\n", user_pib);
159         
160                 ParamInfoBlock pib = Arch::copyin(user_pib);
161                 printf("objlist len %u\n", pib.objlist_len);
162                 
163                 if (pib.objlist_len == 0)
164                         throw_idl(InvalidArgument, 0, countarray("no objects"));
165                 
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"));
171                 
172                 printf("&pib.objlist[0] %p\n", &pib.objlist[0]);
173                 
174                 IDSpace *ids = &curthread->aspace->idspace;
175                 ID objid = Arch::copyin(&pib.objlist[0]);
176                 Object *obj = ids->lookup(objid);
177                 
178                 if (!obj) {
179                         printf("no obj %d\n", objid);
180                         throw_idl(InvalidReference, 0, nullarray);
181                 }
182                 
183                 printf("obj %p\n", obj);
184                 
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);
192                         
193                         u8 *args = new(orbmm) u8[buflen];
194                         u8 *copy = new(orbmm) u8[pib.copy_size];
195                         ParamInfoBlock *dpib = reinterpret_cast<ParamInfoBlock *>
196                                                (args + piboff);
197                         dpib->objlist = reinterpret_cast<ID *>(args + datalen);
198                         
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);
203                         
204                         ko->entry(dpib);
205                         
206                         // FIXME: Copy return data
207                         return;
208                 }
209                 
210                 CallFrame *frame = new_frame(curthread);
211                 frame->caller_user_pib = user_pib;
212                 frame->ret_stack = stack;
213                 
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);
217         }
218         
219         uintptr_t return_from_method(uintptr_t &exptr, size_t &exlen)
220         {
221                 return 0;
222         }
223         
224         void init()
225         {
226                 kernobjs = new KIDTable;
227         }
228 }