/[hurd]/hurd-l4/libhurd-mm/map.c
ViewVC logotype

Diff of /hurd-l4/libhurd-mm/map.c

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

revision 1.2 by neal, Wed Mar 9 10:26:03 2005 UTC revision 1.3 by neal, Wed Apr 6 16:30:37 2005 UTC
# Line 37  Line 37 
37    
38  /* Initialized by the machine-specific startup-code.  */  /* Initialized by the machine-specific startup-code.  */
39  extern struct hurd_startup_data *__hurd_startup_data;  extern struct hurd_startup_data *__hurd_startup_data;
   
 /* We don't want to start mapping things at 0 as then we don't catch  
    NULL pointer dereferences.  Reserving about 16k makes sense.  */  
 #define VIRTUAL_MEMORY_START 0x4000  
   
 struct as as;  
40    
41  void  void
42  map_init (void)  map_system_init (void)
43  {  {
44      error_t err;
45    int i;    int i;
46    struct map *map;    struct map *map;
47    
48    pthread_mutex_init (&as.lock, NULL);    pthread_mutex_init (&as.lock, NULL);
49    hurd_btree_map_tree_init (&as.mappings);    hurd_btree_map_tree_init (&as.mappings);
50    
51    /* Add the startup code.  */    /* Reserve the virtual memory where the startup code lies.  */
52    map = map_alloc ();    map = map_alloc ();
53    assert (map);    assert (map);
54      err = map_init (map, (uintptr_t) HURD_STARTUP_ADDR, HURD_STARTUP_SIZE,
55                      NULL, 0, NULL);
56      assert_perror (err);
57    
58    map->store = NULL;    /* The UTCB.  */
59    map->store_offset = (uintptr_t) HURD_STARTUP_ADDR;    map = map_alloc ();
60    map->vm.start = (uintptr_t) HURD_STARTUP_ADDR;    assert (map);
61    map->vm.size = HURD_STARTUP_SIZE;    err = map_init (map, l4_address (__hurd_startup_data->utcb_area),
62                      l4_size (__hurd_startup_data->utcb_area),
63                      NULL, 0, NULL);
64      assert_perror (err);
65    
66      /* And the kip.  */
67      map = map_alloc ();
68      assert (map);
69      err = map_init (map, (uintptr_t) l4_kip (), l4_kip_area_size (),
70                      NULL, 0, NULL);
71      assert_perror (err);
72    
73    /* Add the program code, data segment, etc which can be found in the    /* Add the program code, data segment, etc which can be found in the
74       start up data.  */       start up data.  */
# Line 74  map_init (void) Line 82  map_init (void)
82        /* XXX: Wrong, wrong, wrong.  Right now we just make sure we        /* XXX: Wrong, wrong, wrong.  Right now we just make sure we
83           know about the virtual address region the mapping uses and           know about the virtual address region the mapping uses and
84           assume that there won't be any page faults.  */           assume that there won't be any page faults.  */
       map->store = NULL;  
85        // lookup store (mapv->cont.server, mapv->cont.cap_handle) add        // lookup store (mapv->cont.server, mapv->cont.cap_handle) add
86        // these frames to it (but we would need to copy them to the        // these memory to it (but we would need to copy them to the
87        // default container.        // default container.
88        map->store_offset = mapv->offset & ~0x7;        err = map_init (map, (l4_word_t) mapv->vaddr, mapv->size,
89        map->vm.start = (l4_word_t) mapv->vaddr;                        NULL, mapv->offset & ~0x7, 0);
90        map->vm.size = mapv->size;        assert_perror (err);
91    
92        /* FIXME: Do something with the access rights (in the lower        /* FIXME: Do something with the access rights (in the lower
93           three bits of offset).  */           three bits of offset).  */
   
       map_insert (map);  
94      }      }
95  }  }
96    
97  bool map_spare_integrate;  bool map_spare_integrate;
98  struct map map_spare;  struct map map_spare;
99  struct frame frame_spare;  struct hurd_memory memory_spare;
100    
101  /* This is the allocation_buffer call back for the map slab.  If this  /* This is the allocation_buffer call back for the map slab.  If this
102     is called then someone has called map_alloc and hence map_lock is     is called then someone has called map_alloc and hence map_lock is
103     locked.  */     locked.  */
104  error_t  error_t
105  mem_slab_allocate_buffer (void *hook, size_t size, void **ptr)  core_slab_allocate_buffer (void *hook, size_t size, void **ptr)
106  {  {
107    error_t err;    error_t err;
108    int i;    int i;
# Line 105  mem_slab_allocate_buffer (void *hook, si Line 110  mem_slab_allocate_buffer (void *hook, si
110    
111    assert ((size & (size - 1)) == 0);    assert ((size & (size - 1)) == 0);
112    
113    /* Find an unused offset.  */    /* Find an unused virtual memory address.  */
114    if (EXPECT_FALSE (! mm_init_done))    if (EXPECT_FALSE (! mm_init_done))
115      {      {
116        /* We are not yet initialized.  Initialize the mapping database.  */        /* We are not yet initialized.  Initialize the mapping database.  */
# Line 162  mem_slab_allocate_buffer (void *hook, si Line 167  mem_slab_allocate_buffer (void *hook, si
167            if (! vaddr_free)            if (! vaddr_free)
168              continue;              continue;
169    
170            /* We may have already allocated a map structure which            /* We may have already allocated a map structure which the
171               search would not find.  This may do some extra work but               above search would not find.  */
172               that's life.  */            map = map_find_first (vaddr, size);
           map = map_find (vaddr, size);  
173            if (map)            if (map)
174              {              {
175                vaddr_free = false;                vaddr_free = false;
# Line 176  mem_slab_allocate_buffer (void *hook, si Line 180  mem_slab_allocate_buffer (void *hook, si
180        while (! vaddr_free);        while (! vaddr_free);
181      }      }
182    else    else
183      vaddr = map_find_free (size, size);      vaddr = as_find_free (size, size);
184    
185    /* Save the mapping in the spare map.  We cannot call map_alloc as    /* Save the mapping in the spare map.  We cannot call map_alloc as
186       it is likely (indirectly) invoking us because its slab is out of       it is likely (indirectly) invoking us because its slab is out of
# Line 188  mem_slab_allocate_buffer (void *hook, si Line 192  mem_slab_allocate_buffer (void *hook, si
192    /* We allocate and map the data ourselves even in the case where the    /* We allocate and map the data ourselves even in the case where the
193       pager is already up: clearly we are going to use the memory as       pager is already up: clearly we are going to use the memory as
194       soon as we return.  */       soon as we return.  */
195    err = frame_alloc_into (&frame_spare, vaddr, size);    err = memory_alloc_into (&memory_spare, size);
196    if (err)    if (err)
197      {      {
198        debug ("frame_alloc_into failed! %d\n", err);        debug ("memory_alloc_into failed! %d\n", err);
199        return err;        return err;
200      }      }
201    
202    map_spare.store = &swap_store;    map_spare.store = &core_store;
203    map_spare.store_offset = frame_spare.dc_start;    map_spare.store_offset = memory_spare.cont_start;
204    map_spare.vm.start = vaddr;    map_spare.vm.start = vaddr;
205    map_spare.vm.size = size;    map_spare.vm.size = size;
206    map_spare_integrate = true;    map_spare_integrate = true;
207    
208    err = frame_map (&frame_spare, 0, size, vaddr);    err = hurd_memory_map (&memory_spare, 0, size, vaddr);
209    if (err)    if (err)
210      /* Hmm, failure.  Nevertheless we managed to allocate the memory.      /* Hmm, failure.  Nevertheless we managed to allocate the memory.
211         Let's just ignore it and assume that whatever went wrong will         Let's just ignore it and assume that whatever went wrong will
212         go away when the memory is eventually faulted in.  */         go away when the memory is eventually faulted in.  */
213      debug ("frame_map failed! %d\n", err);      debug ("hurd_memory_map failed! %d\n", err);
214    
215    *ptr = (void *) vaddr;    *ptr = (void *) vaddr;
216    return 0;    return 0;
217  }  }
218    
219  error_t  error_t
220  mem_slab_deallocate_buffer (void *hook, void *buffer, size_t size)  core_slab_deallocate_buffer (void *hook, void *buffer, size_t size)
221  {  {
222    error_t err = hurd_vm_deallocate ((uintptr_t) buffer, size);    error_t err = hurd_vm_release ((uintptr_t) buffer, size);
223    assert_perror (err);    assert_perror (err);
224    return 0;    return 0;
225  }  }
226    
227  struct hurd_slab_space map_slab  struct hurd_slab_space map_slab
228    = HURD_SLAB_SPACE_INITIALIZER (struct map,    = HURD_SLAB_SPACE_INITIALIZER (struct map,
229                                   mem_slab_allocate_buffer,                                   core_slab_allocate_buffer,
230                                   mem_slab_deallocate_buffer,                                   core_slab_deallocate_buffer,
231                                   NULL, NULL, NULL);                                   NULL, NULL, NULL);
232    
233  struct map *  struct map *
# Line 242  map_alloc (void) Line 246  map_alloc (void)
246       another one for the caller.  */       another one for the caller.  */
247    if (EXPECT_FALSE (map_spare_integrate))    if (EXPECT_FALSE (map_spare_integrate))
248      {      {
249        struct frame frame, *f;        struct hurd_memory memory, *f;
250    
251        memcpy (map, &map_spare, sizeof (struct map));        memcpy (map, &map_spare, sizeof (struct map));
252        map_insert (map);        map_insert (map);
253    
254        /* We can't allocate it using frame_alloc() as that might call        /* We can't allocate it using memory_alloc() as that might call
255           the slab's buffer allocation routine and overwrite           the slab's buffer allocation routine and overwrite
256           FRAME_SPARE.  Copy it here, then allocate it and only then           MEMORY_SPARE.  Copy it here, then allocate it and only then
257           copy over.  */           copy over.  */
258        memcpy (&frame, &frame_spare, sizeof (struct frame));        memcpy (&memory, &memory_spare, sizeof (struct hurd_memory));
259        map_spare_integrate = false;        map_spare_integrate = false;
260    
261        err = hurd_slab_alloc (&frame_slab, (void *) &f);        err = hurd_slab_alloc (&memory_slab, (void *) &f);
262        assert_perror (err);        assert_perror (err);
263    
264        memcpy (f, &frame, sizeof (struct frame));        memcpy (f, &memory, sizeof (struct hurd_memory));
265        frame_insert (&swap_store, map->store_offset, f);        hurd_store_cache (&core_store, map->store_offset, f);
266    
267        goto start;        goto start;
268      }      }
# Line 266  map_alloc (void) Line 270  map_alloc (void)
270    return map;    return map;
271  }  }
272    
273    error_t
274    map_init (struct map *map, uintptr_t vm_addr, size_t size,
275              hurd_store_t *store, size_t store_offset,
276              uintptr_t *vm_used_addr)
277    {
278      if (vm_addr == 0)
279        vm_addr = as_find_free (size, getpagesize ());
280      else
281        {
282          struct map *map = map_find_first (vm_addr, size);
283          if (map)
284            return EEXIST;
285        }
286    
287      map->vm.start = vm_addr;
288      map->vm.size = size;
289      map->store = store;
290      map->store_offset = store_offset;
291    
292      if (vm_used_addr)
293        *vm_used_addr = vm_addr;
294    
295      map_insert (map);
296    
297      return 0;
298    }
299    
300  void  void
301  map_insert (struct map *map)  map_insert (struct map *map)
302  {  {
# Line 281  map_detach (struct map *map) Line 312  map_detach (struct map *map)
312  }  }
313    
314  void  void
315  map_dealloc (struct map *map)  map_free (struct map *map)
316  {  {
317    map_detach (map);    map_detach (map);
318    hurd_slab_dealloc (&map_slab, (void *) map);    hurd_slab_dealloc (&map_slab, (void *) map);
319  }  }
320    
321  struct map *  struct map *
322  map_find (uintptr_t address, size_t size)  map_find_first (uintptr_t address, size_t size)
323  {  {
324    struct region region = { address, size };    struct region region = { address, size };
325    struct map *map = hurd_btree_map_find (&as.mappings, &region);    struct map *map = hurd_btree_map_find (&as.mappings, &region);
# Line 298  map_find (uintptr_t address, size_t size Line 329  map_find (uintptr_t address, size_t size
329    
330    for (;;)    for (;;)
331      {      {
332        struct map *prev = hurd_btree_map_prev (map);        if (map->vm.start <= address)
333            return map;
334    
335          struct map *prev = hurd_btree_map_prev (map);
336        if (prev && overlap (address, size, prev->vm.start, prev->vm.size))        if (prev && overlap (address, size, prev->vm.start, prev->vm.size))
337          map = prev;          map = prev;
338        else        else
339          return map;          return map;
340      }      }
341  }  }
   
 /* Find a free region of the virtual address space for a region of  
    size SIZE with alignment ALIGN.  Must be called with the map lock.  
    The lock msut not be dropped until the virtual address is entered  
    into the mapping database (and this function should not be called  
    again until that has happened).  */  
 uintptr_t  
 map_find_free (size_t size, size_t align)  
 {  
   /* Start the probe at the lowest address aligned address after  
      VIRTUAL_MEMORY_START.  FIXME: We should use a hint.  But then, we  
      shouldn't use linked lists either.  */  
   l4_word_t start = (VIRTUAL_MEMORY_START + align - 1) & ~(align - 1);  
   bool ok;  
   struct map *map;  
   
   do  
     {  
       /* The proposed start is free unless proven not to be.  */  
       ok = true;  
   
       /* Iterate over all of the maps and see if any intersect.  If  
          none do, then we have a good address.  */  
       for (map = hurd_btree_map_first (&as.mappings); map;  
            map = hurd_btree_map_next (map))  
         if (overlap (start, size, map->vm.start, map->vm.size))  
           {  
             ok = false;  
             /* Use the next aligned virtual address after MAP.  */  
             /* FIXME: We need to check that we don't overflow.  */  
             start = (map->vm.start + map->vm.size + align - 1) & ~(align - 1);  
             break;  
           }  
     }  
   while (! ok);  
   
   return start;  
 }  
   
 /* Find a free region in a container for a region of size SIZE with  
    alignment ALIGN.  Must be called with the map lock.  The lock must  
    not be dropped until the virtual address is entered into the  
    mapping database (and this function should not be called again  
    until that has happened).  */  
 uintptr_t  
 store_find_free (struct store *store, size_t size, size_t align)  
 {  
   /* FIXME: Optimize this search!  */  
   l4_word_t offset = 0;  
   bool ok;  
   struct frame *frame;  
   
   assert (! map_spare_integrate);  
   
   do  
     {  
       /* The proposed offset is free unless proven not to be.  */  
       ok = true;  
   
       for (frame = hurd_btree_frame_first (&store->frames); frame;  
            frame = hurd_btree_frame_next (frame))  
         if (overlap (offset, size, frame->dc_start, frame->store.size))  
           {  
             ok = false;  
             /* FIXME: Check for overflow.  */  
             offset = (frame->dc_start + frame->store.size + align - 1)  
               & ~(align - 1);  
             break;  
           }  
     }  
   while (! ok);  
   
   debug ("Sought range covering %x bytes with alignment %x.  Using %x\n",  
          size, align, offset);  
   
   return offset;  
 }  

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

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