/[hurd]/hurd-l4/wortel/wortel.c
ViewVC logotype

Diff of /hurd-l4/wortel/wortel.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.8 by marcus, Mon Sep 15 19:24:01 2003 UTC revision 1.9 by marcus, Tue Sep 16 00:42:17 2003 UTC
# Line 21  Line 21 
21  #include <config.h>  #include <config.h>
22  #endif  #endif
23    
24    #include <unistd.h>
25  #include <alloca.h>  #include <alloca.h>
26    
27  #include "wortel.h"  #include "wortel.h"
28    
29    
30  /* The program name.  */  /* The program name.  */
31  char *program_name = "wortel";  const char program_name[] = "wortel";
32    
33    /* The region of wortel itself.  */
34    l4_word_t wortel_start;
35    l4_word_t wortel_end;
36    
37    
38    /* Room for the arguments.  1 KB is a cramped half-screen full, which
39       should be more than enough.  */
40    char mods_args[1024];
41    
42    /* The number of bytes in mods_args already consumed.  */
43    unsigned mods_args_len;
44    
45  const char *mod_names[] = { "physmem-mod", "task-mod", "root-fs-mod" };  const char *mod_names[] = { "physmem-mod", "task-mod", "root-fs-mod" };
46    
# Line 39  struct wortel_module mods[MOD_NUMBER]; Line 52  struct wortel_module mods[MOD_NUMBER];
52  unsigned int mods_count;  unsigned int mods_count;
53    
54    
55    /* The maximum number of tasks allowed to use the rootserver.  */
56    #define MAX_USERS 16
57    
58    /* FIXME: Needs to be somewhere else.  */
59    typedef l4_word_t hurd_task_id_t;
60    #define HURD_TASK_ID_NULL 0
61    
62    /* The allowed user tasks.  */
63    static hurd_task_id_t cap_list[MAX_USERS];
64    
65    /* Register TASK as allowed user and return the capability ID, or -1
66       if there is no space.  */
67    static int
68    wortel_add_user (hurd_task_id_t task)
69    {
70      unsigned int i;
71    
72      for (i = 0; i < MAX_USERS; i++)
73        if (cap_list[i] == HURD_TASK_ID_NULL)
74          break;
75    
76      if (i == MAX_USERS)
77        return -1;
78    
79      cap_list[i] = task;
80      return i;
81    }
82    
83    #define WORTEL_CAP_VALID(capnr, task) \
84      (capnr >= 0 && capnr < MAX_USERS && cap_list[capnr] == task)
85    
86    
87  /* Return the number of memory descriptors.  */  /* Return the number of memory descriptors.  */
88  l4_word_t  l4_word_t
89  loader_get_num_memory_desc (void)  loader_get_num_memory_desc (void)
# Line 56  loader_get_memory_desc (l4_word_t nr) Line 101  loader_get_memory_desc (l4_word_t nr)
101  }  }
102    
103    
 static void  
 load_components (void)  
 {  
   unsigned int i;  
   
   for (i = 0; i < mods_count; i++)  
     loader_add_region (mods[i].name, mods[i].start, mods[i].end);  
   
   if (!mods[MOD_PHYSMEM].start)  
     panic ("No physical memory server found");  
   
   loader_elf_load ("physmem-server", mods[MOD_PHYSMEM].start,  
                    mods[MOD_PHYSMEM].end,  
                    &mods[MOD_PHYSMEM].start, &mods[MOD_PHYSMEM].end,  
                    &mods[MOD_PHYSMEM].ip);  
   loader_remove_region ("physmem-mod");  
 }  
   
   
104  /* The maximum number of fpages required to cover a page aligned range  /* The maximum number of fpages required to cover a page aligned range
105     of memory.  This is k if the maximum memory range size to cover is     of memory.  This is k if the maximum memory range size to cover is
106     2^(k + min_page_size_log2), which can be easily proved by     2^(k + min_page_size_log2), which can be easily proved by
# Line 82  load_components (void) Line 108  load_components (void)
108  #define MAX_FPAGES (sizeof (l4_word_t) * 8 - 10)  #define MAX_FPAGES (sizeof (l4_word_t) * 8 - 10)
109    
110    
111  /* Determine the fpages required to cover the bytes from START to END,  /* Determine the fpages required to cover the bytes from START to END
112     which must be aligned to the minimal page size supported by the     (exclusive).  START must be aligned to the minimal page size
113     system.  Returns the number of fpages required to cover the range,     supported by the system.  Returns the number of fpages required to
114     and returns that many fpages (with maximum accessibility) in     cover the range, and returns that many fpages (with maximum
115     FPAGES.  At most MAX_FPAGES fpages will be returned.  */     accessibility) in FPAGES.  At most MAX_FPAGES fpages will be
116  unsigned int     returned.  */
117  make_fpages (l4_word_t start, l4_word_t size, l4_fpage_t *fpages)  static unsigned int
118    make_fpages (l4_word_t start, l4_word_t end, l4_fpage_t *fpages)
119  {  {
120    l4_word_t min_page_size = getpagesize ();    l4_word_t min_page_size = getpagesize ();
   l4_word_t end = start + size;  
121    unsigned int nr_fpages = 0;    unsigned int nr_fpages = 0;
122    if (!size)  
123      if (start >= end)
124      return 0;      return 0;
125    
126    if (start & (min_page_size - 1))    if (start & (min_page_size - 1))
127      panic ("make_fpages: START is not aligned to minimum page size");      panic ("make_fpages: START is not aligned to minimum page size");
   if (size & (min_page_size - 1))  
     panic ("make_fpages: SIZE is not aligned to minimum page size");  
128    
129    debug ("Make fpages from 0x%x (size 0x%x): ", start, size);    end = (end + min_page_size - 1) & ~(min_page_size - 1);
130    /* END is at least one MIN_PAGE_SIZE larger than START.  */    /* END is now at least one MIN_PAGE_SIZE larger than START.  */
131    nr_fpages = 0;    nr_fpages = 0;
132    while (start < end)    while (start < end)
133      {      {
134        fpages[nr_fpages] = l4_fpage (start, end - start);        fpages[nr_fpages] = l4_fpage_add_rights (l4_fpage (start, end - start),
135        debug ("0x%x/%u ", start, l4_size_log2 (fpages[nr_fpages]));                                                 l4_fully_accessible);
136        start += l4_size (fpages[nr_fpages]);        start += l4_size (fpages[nr_fpages]);
137        nr_fpages++;        nr_fpages++;
138      }      }
   debug ("\n");  
139    return nr_fpages;    return nr_fpages;
140  }  }
141    
142    
143    /* Request the fpage FPAGE from sigma0.  */
144  static void  static void
145  start_components (void)  sigma0_get_fpage (l4_fpage_t fpage)
146  {  {
147      l4_msg_t msg;
148      l4_msg_tag_t msg_tag;
149      l4_map_item_t map_item;
150    
151      l4_accept (l4_map_grant_items (l4_complete_address_space));
152      l4_msg_clear (&msg);
153      l4_set_msg_label (&msg, 0xffa0);
154      l4_msg_append_word (&msg, fpage.raw);
155      l4_msg_append_word (&msg, L4_DEFAULT_MEMORY);
156      l4_msg_load (&msg);
157      msg_tag = l4_call (l4_global_id (l4_thread_user_base (), 1));
158      if (l4_ipc_failed (msg_tag))
159        panic ("sigma0 request failed during %s: %u",
160               l4_error_code () & 1 ? "receive" : "send",
161               (l4_error_code () >> 1) & 0x7);
162      if (l4_untyped_words (msg_tag) != 0
163          || l4_typed_words (msg_tag) != 2)
164        panic ("Invalid format of sigma0 reply");
165      l4_msg_store (msg_tag, &msg);
166      l4_msg_get_map_item (&msg, 0, &map_item);
167      if (map_item.send_fpage.raw == l4_nilpage.raw)
168        panic ("sigma0 rejected mapping");
169    }
170    
171    /* Request an fpage of the size 2^SIZE from sigma0.  */
172    static l4_fpage_t
173    sigma0_get_any (unsigned int size)
174    {
175      l4_msg_t msg;
176      l4_msg_tag_t msg_tag;
177      l4_map_item_t map_item;
178      l4_fpage_t fpage = l4_fpage_add_rights (l4_fpage_log2 (-1, size),
179                                              l4_fully_accessible);
180    
181      l4_accept (l4_map_grant_items (l4_complete_address_space));
182      l4_msg_clear (&msg);
183      l4_set_msg_label (&msg, 0xffa0);
184      debug ("Request 0x%x\n", fpage.raw);
185      l4_msg_append_word (&msg, fpage.raw);
186      l4_msg_append_word (&msg, L4_DEFAULT_MEMORY);
187      l4_msg_load (&msg);
188      msg_tag = l4_call (l4_global_id (l4_thread_user_base (), 1));
189      if (l4_ipc_failed (msg_tag))
190        panic ("sigma0 request failed during %s: %u",
191               l4_error_code () & 1 ? "receive" : "send",
192               (l4_error_code () >> 1) & 0x7);
193      if (l4_untyped_words (msg_tag) != 0
194          || l4_typed_words (msg_tag) != 2)
195        panic ("Invalid format of sigma0 reply");
196      l4_msg_store (msg_tag, &msg);
197      l4_msg_get_map_item (&msg, 0, &map_item);
198      debug ("Got 0x%x\n", map_item.send_fpage.raw);
199      return map_item.send_fpage;
200    }
201    
202    
203    static void
204    load_components (void)
205    {
206      l4_fpage_t fpages[MAX_FPAGES];
207      unsigned int nr_fpages;
208    l4_word_t min_page_size = getpagesize ();    l4_word_t min_page_size = getpagesize ();
209    l4_word_t ret;    unsigned int i;
210    l4_word_t control;  
211      /* One issue we have to solve is to make sure that when the physical
212         memory server requests all the available physical pages, we know
213         which pages we can give to it, and which we can't.  This can be
214         left to sigma0, as long as we request all pages from sigma0 we
215         can't give to the physical memory server up-front.
216    
217         We do this in several steps: First, we copy all of the startup
218         information to memory that is part of the wortel binary image
219         itself.  This is done by the architecture dependant
220         find_components function.  Then we request all of our own memory,
221         and all the memory needed for the physical memory server image
222         (at its destination address), and all the memory for each module
223         (at their corresponding load addresses).  */
224    
225      if (wortel_start & (min_page_size - 1))
226        panic ("%s does not start on a page boundary", program_name);
227      loader_add_region (program_name, wortel_start, wortel_end);
228      nr_fpages = make_fpages (wortel_start, wortel_end, fpages);
229      while (nr_fpages--)
230        sigma0_get_fpage (fpages[nr_fpages]);
231    
232      /* First protect all pages covered by the modules.  This will also
233         show if each module starts (and ends) on its own page.  */
234      for (i = 0; i < mods_count; i++)
235        {
236          if (mods[i].start & (min_page_size - 1))
237            panic ("Module %s does not start on a page boundary", mods[i].name);
238          loader_add_region (mods[i].name, mods[i].start, mods[i].end);
239        }
240    
241      /* Now load the physical memory server to its destination
242         address.  */
243      if (!mods[MOD_PHYSMEM].start)
244        panic ("No physical memory server found");
245      loader_elf_load ("physmem-server", mods[MOD_PHYSMEM].start,
246                       mods[MOD_PHYSMEM].end,
247                       &mods[MOD_PHYSMEM].start, &mods[MOD_PHYSMEM].end,
248                       &mods[MOD_PHYSMEM].ip);
249      loader_remove_region ("physmem-mod");
250    
251      /* Finally we can request all the memory for the physical memory
252         server and all other modules from sigma0.  This will register the
253         memory as taken by us, and the memory will not be returned by any
254         future request.  */
255      for (i = 0; i < mods_count; i++)
256        {
257          nr_fpages = make_fpages (mods[i].start, mods[i].end, fpages);
258          while (nr_fpages--)
259            sigma0_get_fpage (fpages[nr_fpages]);
260        }
261    }
262    
263    
264    static void
265    start_components (void)
266    {
267    l4_msg_t msg;    l4_msg_t msg;
268    l4_msg_tag_t msg_tag;    l4_msg_tag_t msg_tag;
269      l4_word_t ret;
270      l4_word_t control;
271      int cap_id;
272        
   if (mods[MOD_PHYSMEM].start & (min_page_size - 1))  
     panic ("physmem is not page aligned on this architecture");  
273    if (mods[MOD_PHYSMEM].start > mods[MOD_PHYSMEM].end)    if (mods[MOD_PHYSMEM].start > mods[MOD_PHYSMEM].end)
274      panic ("physmem has invalid memory range");      panic ("physmem has invalid memory range");
275    if (mods[MOD_PHYSMEM].ip < mods[MOD_PHYSMEM].start    if (mods[MOD_PHYSMEM].ip < mods[MOD_PHYSMEM].start
276        || mods[MOD_PHYSMEM].ip > mods[MOD_PHYSMEM].end)        || mods[MOD_PHYSMEM].ip > mods[MOD_PHYSMEM].end)
277      panic ("physmem has invalid IP");      panic ("physmem has invalid IP");
278    
279    
280      cap_id = wortel_add_user (2);
281      /* FIXME: Pass cap_id to physmem.  */
282    /* Thread nr is next available after rootserver thread nr,    /* Thread nr is next available after rootserver thread nr,
283       version part is 2 (rootserver is 1).  */       version part is 2 (rootserver is 1).  */
284    l4_thread_id_t physmem_server    l4_thread_id_t physmem_server
# Line 174  start_components (void) Line 320  start_components (void)
320    {    {
321      l4_fpage_t fpages[MAX_FPAGES];      l4_fpage_t fpages[MAX_FPAGES];
322      unsigned int nr_fpages;      unsigned int nr_fpages;
     l4_word_t size = (mods[MOD_PHYSMEM].end - mods[MOD_PHYSMEM].start  
                       + min_page_size - 1) & ~(min_page_size - 1);  
323    
324      /* We want to grant all the memory for the physmem binary image      /* We want to grant all the memory for the physmem binary image
325         with the first page fault, but we might have to send several         with the first page fault, but we might have to send several
326         fpages.  So we first create a list of all fpages we need, then         fpages.  So we first create a list of all fpages we need, then
327         we serve one after another, providing the one containing the         we serve one after another, providing the one containing the
328         fault address last.  */         fault address last.  */
329      nr_fpages = make_fpages (mods[MOD_PHYSMEM].start, size,      nr_fpages = make_fpages (mods[MOD_PHYSMEM].start, mods[MOD_PHYSMEM].end,
330                               fpages);                               fpages);
331    
332      /* Now serve page requests.  */      /* Now serve page requests.  */
# Line 217  start_components (void) Line 361  start_components (void)
361          if (i == nr_fpages)          if (i == nr_fpages)
362            panic ("Could not find suitable fpage");            panic ("Could not find suitable fpage");
363    
364          fpage = l4_fpage_add_rights (fpages[i], l4_fully_accessible);          fpage = fpages[i];
         debug ("Granting Fpage: 0x%x/%u\n", l4_address (fpage),  
                l4_size_log2 (fpage));  
   
365          if (i != 0)          if (i != 0)
366            fpages[i] = fpages[nr_fpages - 1];            fpages[i] = fpages[nr_fpages - 1];
367          nr_fpages--;          nr_fpages--;
368    
369          /* First we have to request the fpage from sigma0.  */          /* The memory was already requested from sigma0 by
370          l4_accept (l4_map_grant_items (l4_complete_address_space));             load_components, so grant it right away.  */
371          l4_msg_clear (&msg);          debug ("Granting fpage: 0x%x/%u\n", l4_address (fpage),
372          l4_set_msg_label (&msg, 0xffa0);                 l4_size_log2 (fpage));
         l4_msg_append_word (&msg, fpage.raw);  
         l4_msg_append_word (&msg, L4_DEFAULT_MEMORY);  
         l4_msg_load (&msg);  
         msg_tag = l4_call (l4_global_id (l4_thread_user_base (), 1));  
         if (l4_ipc_failed (msg_tag))  
           panic ("sigma0 request failed during %s: %u",  
                  l4_error_code () & 1 ? "receive" : "send",  
                  (l4_error_code () >> 1) & 0x7);  
         if (l4_untyped_words (msg_tag) != 0  
             || l4_typed_words (msg_tag) != 2)  
           panic ("Invalid format of sigma0 reply");  
         l4_msg_store (msg_tag, &msg);  
         if (l4_msg_word (&msg, 1) == l4_nilpage.raw)  
           panic ("sigma0 rejected mapping");  
   
         /* Now we can grant the mapping to the physmem server.  
            FIXME: Should use the fpage returned by sigma0.  */  
373          l4_msg_clear (&msg);          l4_msg_clear (&msg);
374          l4_set_msg_label (&msg, 0);          l4_set_msg_label (&msg, 0);
375          /* FIXME: Keep track of mappings already provided.  Possibly          /* FIXME: Keep track of mappings already provided.  Possibly
# Line 257  start_components (void) Line 381  start_components (void)
381        }        }
382    }    }
383    
384      /* Now we have kicked off the boot process.  The rest will be done
385         in the normal server loop.  */
386    }
387    
388    
389    /* Serve rootserver bootstrap requests.  */
390    static void
391    serve_bootstrap_requests (void)
392    {
393      /* The size of the region that we are currently trying to allocate
394         for GET_MEM requests.  If this is smaller than 2^10, no more
395         memory is available.  */
396      unsigned int get_mem_size = 12;
397    
398    do    do
399      {      {
400          l4_thread_id_t from;
401        l4_word_t label;        l4_word_t label;
402          l4_msg_t msg;
403          l4_msg_tag_t msg_tag;
404    
405        msg_tag = l4_receive (physmem_server);        msg_tag = l4_wait (&from);
406        if (l4_ipc_failed (msg_tag))        if (l4_ipc_failed (msg_tag))
407          panic ("Receiving messages from physmemserver thread failed: %u",          panic ("Receiving message failed: %u", (l4_error_code () >> 1) & 0x7);
                (l4_error_code () >> 1) & 0x7);  
408    
409        label = l4_label (msg_tag);        label = l4_label (msg_tag);
410        l4_msg_store (msg_tag, &msg);        l4_msg_store (msg_tag, &msg);
411          /* We don't do any access control in the bootstrap loop.  */
412    
413  #define WORTEL_MSG_PUTCHAR 1  #define WORTEL_MSG_PUTCHAR 1
414    #define WORTEL_MSG_GET_MEM 2
415        if (label == WORTEL_MSG_PUTCHAR)        if (label == WORTEL_MSG_PUTCHAR)
416          {          {
417            int chr;            int chr;
418    
419            /* This is a putchar() message.  */            /* This is a putchar() message.  */
420              if (l4_untyped_words (msg_tag) != 2
421                  || l4_typed_words (msg_tag) != 0)
422                panic ("Invalid format of putchar msg");
423    
424              chr = (int) l4_msg_word (&msg, 1);
425              putchar (chr);
426              /* No reply needed.  */
427              continue;
428            }
429          else if (WORTEL_MSG_GET_MEM)
430            {
431              l4_fpage_t fpage;
432              l4_grant_item_t grant_item;
433    
434            if (l4_untyped_words (msg_tag) != 1            if (l4_untyped_words (msg_tag) != 1
435                || l4_typed_words (msg_tag) != 0)                || l4_typed_words (msg_tag) != 0)
436                panic ("Invalid format of get_mem msg");
437    
438              if (get_mem_size < 10)
439                panic ("physmem server does not stop requesting memory");
440    
441              do
442                {
443                  fpage = sigma0_get_any (get_mem_size);
444                  if (fpage.raw == l4_nilpage.raw)
445                    get_mem_size--;
446                }
447              while (fpage.raw == l4_nilpage.raw && get_mem_size >= 10);
448    
449              grant_item = l4_grant_item (fpage, l4_address (fpage));
450              l4_msg_clear (&msg);
451              l4_msg_append_grant_item (&msg, grant_item);
452              l4_msg_load (&msg);
453              l4_reply (from);
454            }
455          else
456            panic ("Invalid message with tag 0x%x", msg_tag.raw);
457        }
458      while (1);
459    }
460    
461    
462    /* Serve rootserver requests.  */
463    static void
464    serve_requests (void)
465    {
466      do
467        {
468          l4_thread_id_t from;
469          l4_word_t label;
470          l4_msg_t msg;
471          l4_msg_tag_t msg_tag;
472    
473          msg_tag = l4_wait (&from);
474          if (l4_ipc_failed (msg_tag))
475            panic ("Receiving message failed: %u", (l4_error_code () >> 1) & 0x7);
476    
477          label = l4_label (msg_tag);
478          /* FIXME: Shouldn't store the whole msg before checking access
479             rights.  */
480          l4_msg_store (msg_tag, &msg);
481          if (!WORTEL_CAP_VALID (l4_msg_word (&msg, 0), l4_version (from)))
482            /* FIXME: Shouldn't be a panic of course.  */
483            panic ("Unprivileged user attemps to access wortel rootserver");
484    
485    #define WORTEL_MSG_PUTCHAR 1
486          if (label == WORTEL_MSG_PUTCHAR)
487            {
488              int chr;
489    
490              /* This is a putchar() message.  */
491              if (l4_untyped_words (msg_tag) != 2
492                  || l4_typed_words (msg_tag) != 0)
493              panic ("Invalid format of putchar msg");              panic ("Invalid format of putchar msg");
494    
495            chr = (int) l4_msg_word (&msg, 0);            chr = (int) l4_msg_word (&msg, 1);
496            putchar (chr);            putchar (chr);
497            /* No reply needed.  */            /* No reply needed.  */
498            continue;            continue;
499          }          }
500        else        else
501          panic ("Invalid message with tag 0x%x", msg_tag);          panic ("Invalid message with tag 0x%x", msg_tag.raw);
502      }      }
503    while (1);    while (1);
504  }  }
# Line 339  parse_args (int argc, char *argv[]) Line 552  parse_args (int argc, char *argv[])
552                  printf (".\n\n");                  printf (".\n\n");
553              }              }
554    
555            printf ("Report bugs to " BUG_ADDRESS ".\n", argv[0]);            printf ("Report bugs to " BUG_ADDRESS ".\n");
556            shutdown ();                shutdown ();    
557          }          }
558        else if (!strcmp (argv[i], "--version"))        else if (!strcmp (argv[i], "--version"))
# Line 395  exception_handler (void) Line 608  exception_handler (void)
608    
609        tag = l4_wait (&from);        tag = l4_wait (&from);
610        debug ("EXCEPTION HANDLER: Received message from: ");        debug ("EXCEPTION HANDLER: Received message from: ");
611        debug ("0x%x", from);        debug ("0x%x", from.raw);
612        debug ("\n");        debug ("\n");
613        debug ("Tag: 0x%x", tag.raw);        debug ("Tag: 0x%x", tag.raw);
614        debug ("Label: %u  Untyped: %u  Typed: %u\n",        debug ("Label: %u  Untyped: %u  Typed: %u\n",
# Line 417  exception_handler (void) Line 630  exception_handler (void)
630    debug ("EXCEPTION HANDLER: Too many exceptions.\n");    debug ("EXCEPTION HANDLER: Too many exceptions.\n");
631    
632    while (1)    while (1)
633      l4_yield ();      l4_sleep (l4_never);
634  }  }
635    
636    
# Line 466  main (int argc, char *argv[]) Line 679  main (int argc, char *argv[])
679    
680    start_components ();    start_components ();
681    
682    while (1)    serve_bootstrap_requests ();
     l4_yield ();  
683    
684    return 0;    return 0;
685  }  }

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.9

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26