Subversion Repositories HelenOS-historic

Rev

Rev 367 | Rev 373 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2001-2004 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. #include <typedefs.h>
  30. #include <arch/types.h>
  31. #include <mm/heap.h>
  32. #include <mm/frame.h>
  33. #include <mm/vm.h>
  34. #include <panic.h>
  35. #include <debug.h>
  36. #include <list.h>
  37. #include <synch/spinlock.h>
  38. #include <arch/asm.h>
  39. #include <arch.h>
  40.  
  41. spinlock_t zone_head_lock;       /**< this lock protects zone_head list */
  42. link_t zone_head;                /**< list of all zones in the system */
  43.  
  44. /** Initialize physical memory management
  45.  *
  46.  * Initialize physical memory managemnt.
  47.  */
  48. void frame_init(void)
  49. {
  50.     if (config.cpu_active == 1) {
  51.         zone_init();
  52.     }
  53.  
  54.     frame_arch_init();
  55.    
  56.     if (config.cpu_active == 1) {
  57.                 frame_region_not_free(config.base, config.base + config.kernel_size + CONFIG_STACK_SIZE);
  58.         }  
  59. }
  60.  
  61. /** Allocate a frame
  62.  *
  63.  * Allocate a frame of physical memory.
  64.  *
  65.  * @param flags Flags for host zone selection and address processing.
  66.  *
  67.  * @return Allocated frame.
  68.  */
  69. __address frame_alloc(int flags)
  70. {
  71.     pri_t pri;
  72.     link_t *cur, *tmp;
  73.     zone_t *z;
  74.     zone_t *zone = NULL;
  75.     frame_t *frame = NULL;
  76.     __address v;
  77.    
  78. loop:
  79.     pri = cpu_priority_high();
  80.     spinlock_lock(&zone_head_lock);
  81.    
  82.     /*
  83.      * First, find suitable frame zone.
  84.      */
  85.     for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
  86.         z = list_get_instance(cur, zone_t, link);
  87.        
  88.         spinlock_lock(&z->lock);
  89.         /*
  90.          * Check if the zone has any free frames.
  91.          */
  92.         if (z->free_count) {
  93.             zone = z;
  94.             break;
  95.         }
  96.         spinlock_unlock(&z->lock);
  97.     }
  98.    
  99.     if (!zone) {
  100.         if (flags & FRAME_PANIC)
  101.             panic("Can't allocate frame.\n");
  102.        
  103.         /*
  104.          * TODO: Sleep until frames are available again.
  105.          */
  106.         spinlock_unlock(&zone_head_lock);
  107.         cpu_priority_restore(pri);
  108.  
  109.         panic("Sleep not implemented.\n");
  110.         goto loop;
  111.     }
  112.        
  113.     tmp = zone->free_head.next;
  114.     frame = list_get_instance(tmp, frame_t, link);
  115.  
  116.     frame->refcount++;
  117.     list_remove(tmp);           /* remove frame from free_head */
  118.     list_append(tmp, &zone->busy_head); /* append frame to busy_head */
  119.     zone->free_count--;
  120.     zone->busy_count++;
  121.    
  122.     v = zone->base + (frame - zone->frames) * FRAME_SIZE;
  123.    
  124.     if (flags & FRAME_KA)
  125.         v = PA2KA(v);
  126.    
  127.     spinlock_unlock(&zone->lock);
  128.    
  129.     spinlock_unlock(&zone_head_lock);
  130.     cpu_priority_restore(pri);
  131.    
  132.     return v;
  133. }
  134.  
  135. /** Free a frame.
  136.  *
  137.  * Find respective frame structrue for supplied addr.
  138.  * Decrement frame reference count.
  139.  * If it drops to zero, move the frame structure to free list.
  140.  *
  141.  * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE.
  142.  */
  143. void frame_free(__address addr)
  144. {
  145.     pri_t pri;
  146.     link_t *cur;
  147.     zone_t *z;
  148.     zone_t *zone = NULL;
  149.     frame_t *frame;
  150.    
  151.     ASSERT(addr % FRAME_SIZE == 0);
  152.    
  153.     pri = cpu_priority_high();
  154.     spinlock_lock(&zone_head_lock);
  155.    
  156.     /*
  157.      * First, find host frame zone for addr.
  158.      */
  159.     for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
  160.         z = list_get_instance(cur, zone_t, link);
  161.        
  162.         spinlock_lock(&z->lock);
  163.        
  164.         if (IS_KA(addr))
  165.             addr = KA2PA(addr);
  166.        
  167.         /*
  168.          * Check if addr belongs to z.
  169.          */
  170.         if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
  171.             zone = z;
  172.             break;
  173.         }
  174.         spinlock_unlock(&z->lock);
  175.     }
  176.    
  177.     ASSERT(zone != NULL);
  178.    
  179.     frame = &zone->frames[(addr - zone->base)/FRAME_SIZE];
  180.     ASSERT(frame->refcount);
  181.  
  182.     if (!--frame->refcount) {
  183.         list_remove(&frame->link);          /* remove frame from busy_head */
  184.         list_append(&frame->link, &zone->free_head);    /* append frame to free_head */
  185.         zone->free_count++;
  186.         zone->busy_count--;
  187.     }
  188.    
  189.     spinlock_unlock(&zone->lock);  
  190.    
  191.     spinlock_unlock(&zone_head_lock);
  192.     cpu_priority_restore(pri);
  193. }
  194.  
  195. /** Mark frame not free.
  196.  *
  197.  * Find respective frame structrue for supplied addr.
  198.  * Increment frame reference count and move the frame structure to busy list.
  199.  *
  200.  * @param addr Address of the frame to be marked. It must be a multiple of FRAME_SIZE.
  201.  */
  202. void frame_not_free(__address addr)
  203. {
  204.     pri_t pri;
  205.     link_t *cur;
  206.     zone_t *z;
  207.     zone_t *zone = NULL;
  208.     frame_t *frame;
  209.    
  210.     ASSERT(addr % FRAME_SIZE == 0);
  211.    
  212.     pri = cpu_priority_high();
  213.     spinlock_lock(&zone_head_lock);
  214.    
  215.     /*
  216.      * First, find host frame zone for addr.
  217.      */
  218.     for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
  219.         z = list_get_instance(cur, zone_t, link);
  220.        
  221.         spinlock_lock(&z->lock);
  222.        
  223.         if (IS_KA(addr))
  224.             addr = KA2PA(addr);
  225.        
  226.         /*
  227.          * Check if addr belongs to z.
  228.          */
  229.         if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
  230.             zone = z;
  231.             break;
  232.         }
  233.         spinlock_unlock(&z->lock);
  234.     }
  235.    
  236.     ASSERT(zone != NULL);
  237.    
  238.     frame = &zone->frames[(addr - zone->base)/FRAME_SIZE];
  239.  
  240.     if (!frame->refcount) {
  241.         frame->refcount++;
  242.  
  243.         list_remove(&frame->link);          /* remove frame from free_head */
  244.         list_append(&frame->link, &zone->busy_head);    /* append frame to busy_head */
  245.         zone->free_count--;
  246.         zone->busy_count++;
  247.     }
  248.    
  249.     spinlock_unlock(&zone->lock);  
  250.    
  251.     spinlock_unlock(&zone_head_lock);
  252.     cpu_priority_restore(pri);
  253. }
  254.  
  255. /** Mark frame region not free.
  256.  *
  257.  * Mark frame region not free.
  258.  *
  259.  * @param start First address.
  260.  * @param stop Last address.
  261.  */
  262. void frame_region_not_free(__address start, __address stop)
  263. {
  264.         __address a;
  265.  
  266.         start /= FRAME_SIZE;
  267.         stop /= FRAME_SIZE;
  268.         for (a = start; a <= stop; a++)
  269.                 frame_not_free(a * FRAME_SIZE);
  270. }
  271.  
  272.  
  273. /** Initialize zonekeeping
  274.  *
  275.  * Initialize zonekeeping.
  276.  */
  277. void zone_init(void)
  278. {
  279.     spinlock_initialize(&zone_head_lock);
  280.     list_initialize(&zone_head);
  281. }
  282.  
  283. /** Create frame zone
  284.  *
  285.  * Create new frame zone.
  286.  *
  287.  * @param start Physical address of the first frame within the zone.
  288.  * @param size Size of the zone. Must be a multiple of FRAME_SIZE.
  289.  * @param flags Zone flags.
  290.  *
  291.  * @return Initialized zone.
  292.  */
  293. zone_t *zone_create(__address start, size_t size, int flags)
  294. {
  295.     zone_t *z;
  296.     count_t cnt;
  297.     int i;
  298.    
  299.     ASSERT(start % FRAME_SIZE == 0);
  300.     ASSERT(size % FRAME_SIZE == 0);
  301.    
  302.     cnt = size / FRAME_SIZE;
  303.    
  304.     z = (zone_t *) malloc(sizeof(zone_t));
  305.     if (z) {
  306.         link_initialize(&z->link);
  307.         spinlock_initialize(&z->lock);
  308.    
  309.         z->base = start;
  310.         z->flags = flags;
  311.  
  312.         z->free_count = cnt;
  313.         list_initialize(&z->free_head);
  314.  
  315.         z->busy_count = 0;
  316.         list_initialize(&z->busy_head);
  317.        
  318.         z->frames = (frame_t *) malloc(cnt * sizeof(frame_t));
  319.         if (!z->frames) {
  320.             free(z);
  321.             return NULL;
  322.         }
  323.        
  324.         for (i = 0; i<cnt; i++) {
  325.             frame_initialize(&z->frames[i], z);
  326.             list_append(&z->frames[i].link, &z->free_head);
  327.         }
  328.        
  329.     }
  330.    
  331.     return z;
  332. }
  333.  
  334. /** Attach frame zone
  335.  *
  336.  * Attach frame zone to zone list.
  337.  *
  338.  * @param zone Zone to be attached.
  339.  */
  340. void zone_attach(zone_t *zone)
  341. {
  342.     pri_t pri;
  343.    
  344.     pri = cpu_priority_high();
  345.     spinlock_lock(&zone_head_lock);
  346.    
  347.     list_append(&zone->link, &zone_head);
  348.    
  349.     spinlock_unlock(&zone_head_lock);
  350.     cpu_priority_restore(pri);
  351. }
  352.  
  353. /** Initialize frame structure
  354.  *
  355.  * Initialize frame structure.
  356.  *
  357.  * @param frame Frame structure to be initialized.
  358.  * @param zone Host frame zone.
  359.  */
  360. void frame_initialize(frame_t *frame, zone_t *zone)
  361. {
  362.     frame->refcount = 0;
  363.     link_initialize(&frame->link);
  364. }
  365.