]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/orb/invoke.cc
888cff13cf5f6c0dc8a9d0da95cb77594c2493b3
[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 #if 0
59                 // FIXME: refcounting
60                 ObjTableEntry *ote = table.lookup(id);
61                 if (!ote || ote->hdr.id == invalid_id)
62                         return NULL;
63                 
64                 if (ote->hdr.Pointer)
65                         return ote->ptr.object;
66
67                 return &ote->obj;
68 #endif
69                 return NULL;
70         }
71
72         ObjectHdr *IDSpace::get_local(Object *obj)
73         {
74                 if (&obj->aspace->idspace == this)
75                         return obj;
76         
77                 Lock::AutoSpinLock autolock(lock);
78                 ObjectPtr *ptr = *rmap.find(obj);
79                 if (ptr)
80                         return ptr;
81
82 #if 0           
83                 int id = alloc.alloc();
84                 ptr = &table.lookup(id, true)->ptr;
85
86                 ptr->id = id;
87                 ptr->flags = 0;
88                 ptr->Valid = 1;
89                 ptr->Pointer = 1;
90                 ptr->object = obj;
91
92                 rmap.add(obj, ptr);
93 #endif
94                 return ptr;
95
96         }
97
98         Object *IDSpace::newobj(Mem::ProcAddrSpace *aspace)
99         {
100 #if 0
101                 Lock::AutoSpinLock autolock(lock);
102                 int id = alloc.alloc();
103                 Object *obj = &table.lookup(id, true)->obj;
104
105                 obj->id = id;
106                 obj->flags = 0;
107                 obj->Valid = 1;
108                 obj->aspace = aspace;
109                 
110                 return obj;
111 #endif
112                 return NULL;
113         }
114         
115         static void copy_data(u8 *dest, u8 *vaddr, size_t bufsize,
116                               ParamInfoBlock *dpib, ParamInfoBlock *spib,
117                               u32 fmask, u32 flags)
118         {
119                 size_t copied = 0;
120         
121                 for (uint i = 0; i < spib->num_segments; i++) {
122                         if ((spib->segments[i].flags & fmask) != flags)
123                                 continue;
124                         
125                         size_t len = round_up(spib->segments[i].len, 3);
126
127                         if (len + copied > bufsize || len + copied < copied)
128                                 throw_idl(InvalidArgument, 0, countarray<ORBMM>("copy_data: bad size"));
129                         
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);
134
135                         copied += len;
136                         dest += len;
137                         vaddr += len;
138                 }
139         }
140
141         typedef void (*KernEntry)(ParamInfoBlock *pib);
142
143         struct KernObject : public Object {
144                 KernEntry entry;
145         };
146
147         typedef Util::RadixTree<KernObject, ID, 6> KIDTable;
148         KIDTable *kernobjs;
149         
150         void copy_ids_to_kern(ParamInfoBlock *dpib, ParamInfoBlock *spib,
151                               IDSpace *ids)
152         {
153                 dpib->objlist_len = spib->objlist_len;
154         
155                 for (uint i = 0; i < spib->objlist_len; i++) {
156                         Object *obj = ids->lookup(spib->objlist[i]);
157                         
158                         if (!obj)
159                                 throw_idl(InvalidReference, i, nullarray);
160                         
161                         dpib->objlist[i] = reinterpret_cast<uintptr_t>(obj);
162                 }
163         }
164
165         void invoke_method(ParamInfoBlock *user_pib, uintptr_t &stack)
166         {
167                 printf("invoke_method: pib %p\n", user_pib);
168         
169                 ParamInfoBlock pib = Arch::copyin(user_pib);
170                 printf("objlist len %u\n", pib.objlist_len);
171                 
172                 if (pib.objlist_len == 0)
173                         throw_idl(InvalidArgument, 0, countarray<ORBMM>("no objects"));
174                 
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"));
180                 
181                 printf("&pib.objlist[0] %p\n", &pib.objlist[0]);
182                 
183                 IDSpace *ids = &curthread->aspace->idspace;
184                 ID objid = Arch::copyin(&pib.objlist[0]);
185                 Object *obj = ids->lookup(objid);
186                 
187                 if (!obj) {
188                         printf("no obj %d\n", objid);
189                         throw_idl(InvalidReference, 0, nullarray);
190                 }
191                 
192                 printf("obj %p\n", obj);
193                 
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);
201                         
202                         u8 *args = new(ORBMM()) u8[buflen];
203                         u8 *copy = new(ORBMM()) u8[pib.copy_size];
204                         ParamInfoBlock *dpib = reinterpret_cast<ParamInfoBlock *>
205                                                (args + piboff);
206                         dpib->objlist = reinterpret_cast<ID *>(args + datalen);
207                         
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);
212                         
213                         ko->entry(dpib);
214                         
215                         // FIXME: Copy return data
216                         return;
217                 }
218                 
219                 CallFrame *frame = new_frame(curthread);
220                 frame->caller_user_pib = user_pib;
221                 frame->ret_stack = stack;
222                 
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);
226         }
227         
228         uintptr_t return_from_method(uintptr_t &exptr, size_t &exlen)
229         {
230                 return 0;
231         }
232         
233         void init()
234         {
235                 kernobjs = new KIDTable;
236         }
237 }