Subversion Repositories HelenOS-historic

Rev

Rev 219 | Rev 368 | 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 <arch/types.h>
  30. #include <func.h>
  31.  
  32. #include <mm/heap.h>
  33. #include <mm/frame.h>
  34. #include <mm/page.h>
  35. #include <mm/vm.h>
  36. #include <arch/mm/page.h>
  37.  
  38. #include <config.h>
  39. #include <memstr.h>
  40.  
  41. #include <panic.h>
  42. #include <debug.h>
  43.  
  44. #include <synch/spinlock.h>
  45.  
  46. #include <arch/asm.h>
  47. #include <arch.h>
  48.  
  49. count_t frames = 0;
  50. count_t frames_free;
  51.  
  52. __u8 *frame_bitmap;
  53. count_t frame_bitmap_octets;
  54.  
  55. static spinlock_t framelock;
  56.  
  57. spinlock_t zone_head_lock;       /**< this lock protects zone_head list */
  58. link_t zone_head;                /**< list of all zones in the system */
  59.  
  60.  
  61. void frame_init(void)
  62. {
  63.     if (config.cpu_active == 1) {
  64.         zone_init();
  65.  
  66.         /*
  67.          * The bootstrap processor will allocate all necessary memory for frame allocation.
  68.          */
  69.  
  70.         frames = config.memory_size / FRAME_SIZE;
  71.         frame_bitmap_octets = frames / 8 + (frames % 8 > 0);
  72.         frame_bitmap = (__u8 *) malloc(frame_bitmap_octets);
  73.         if (!frame_bitmap)
  74.             panic("malloc/frame_bitmap\n");
  75.  
  76.         /*
  77.          * Mark all frames free.
  78.          */
  79.         memsetb((__address) frame_bitmap, frame_bitmap_octets, 0);
  80.         frames_free = frames;
  81.     }
  82.  
  83.     /*
  84.      * No frame allocations/reservations prior this point.
  85.      */
  86.  
  87.     frame_arch_init();
  88.  
  89.     if (config.cpu_active == 1) {
  90.         /*
  91.          * Create the memory address space map. Marked frames and frame
  92.          * regions cannot be used for allocation.
  93.          */
  94.         frame_region_not_free(config.base, config.base + config.kernel_size);
  95.     }
  96. }
  97.  
  98. /*
  99.  * Allocate a frame.
  100.  */
  101. __address frame_alloc(int flags)
  102. {
  103.     int i;
  104.     pri_t pri;
  105.    
  106. loop:
  107.     pri = cpu_priority_high();
  108.     spinlock_lock(&framelock);
  109.     if (frames_free) {
  110.         for (i=0; i < frames; i++) {
  111.             int m, n;
  112.        
  113.             m = i / 8;
  114.             n = i % 8;
  115.  
  116.             if ((frame_bitmap[m] & (1<<n)) == 0) {
  117.                 frame_bitmap[m] |= (1<<n);
  118.                 frames_free--;
  119.                 spinlock_unlock(&framelock);
  120.                 cpu_priority_restore(pri);
  121.                 if (flags & FRAME_KA) return PA2KA(i*FRAME_SIZE);
  122.                 return i*FRAME_SIZE;
  123.             }
  124.         }
  125.         panic("frames_free inconsistent (%d)\n", frames_free);
  126.     }
  127.     spinlock_unlock(&framelock);
  128.     cpu_priority_restore(pri);
  129.  
  130.     if (flags & FRAME_PANIC)
  131.         panic("unable to allocate frame\n");
  132.        
  133.     /* TODO: implement sleeping logic here */
  134.     panic("sleep not supported\n");
  135.    
  136.     goto loop;
  137. }
  138.  
  139. /*
  140.  * Free a frame.
  141.  */
  142. void frame_free(__address addr)
  143. {
  144.     pri_t pri;
  145.     __u32 frame;
  146.  
  147.     pri = cpu_priority_high();
  148.     spinlock_lock(&framelock);
  149.    
  150.     frame = IS_KA(addr) ? KA2PA(addr) : addr;
  151.     frame /= FRAME_SIZE;
  152.     if (frame < frames) {
  153.         int m, n;
  154.    
  155.         m = frame / 8;
  156.         n = frame % 8;
  157.    
  158.         if (frame_bitmap[m] & (1<<n)) {
  159.             frame_bitmap[m] &= ~(1<<n);
  160.             frames_free++;
  161.         }
  162.         else panic("frame already free\n");
  163.     }
  164.     else panic("frame number too big\n");
  165.    
  166.     spinlock_unlock(&framelock);
  167.     cpu_priority_restore(pri);
  168. }
  169.  
  170. /*
  171.  * Don't use this function for normal allocation. Use frame_alloc() instead.
  172.  * Use this function to declare that some special frame is not free.
  173.  */
  174. void frame_not_free(__address addr)
  175. {
  176.     pri_t pri;
  177.     __u32 frame;
  178.    
  179.     pri = cpu_priority_high();
  180.     spinlock_lock(&framelock);
  181.     frame = IS_KA(addr) ? KA2PA(addr) : addr;
  182.     frame /= FRAME_SIZE;
  183.     if (frame < frames) {
  184.         int m, n;
  185.  
  186.         m = frame / 8;
  187.         n = frame % 8;
  188.    
  189.         if ((frame_bitmap[m] & (1<<n)) == 0) { 
  190.             frame_bitmap[m] |= (1<<n);
  191.             frames_free--; 
  192.         }
  193.     }
  194.     spinlock_unlock(&framelock);
  195.     cpu_priority_restore(pri);
  196. }
  197.  
  198. void frame_region_not_free(__address start, __address stop)
  199. {
  200.     __address a;
  201.  
  202.     start /= FRAME_SIZE;
  203.     stop /= FRAME_SIZE;
  204.     for (a = start; a <= stop; a++)
  205.         frame_not_free(a * FRAME_SIZE);
  206. }
  207.  
  208. /** Initialize zonekeeping
  209.  *
  210.  * Initialize zonekeeping.
  211.  */
  212. void zone_init(void)
  213. {
  214.     spinlock_initialize(&zone_head_lock);
  215.     list_initialize(&zone_head);
  216. }
  217.  
  218. /** Create frame zone
  219.  *
  220.  * Create new frame zone.
  221.  *
  222.  * @param start Physical address of the first frame within the zone.
  223.  * @param size Size of the zone. Must be a multiple of FRAME_SIZE.
  224.  * @param flags Zone flags.
  225.  *
  226.  * @return Initialized zone.
  227.  */
  228. zone_t *zone_create(__address start, size_t size, int flags)
  229. {
  230.     zone_t *z;
  231.     count_t cnt;
  232.     int i;
  233.    
  234.     ASSERT(start % FRAME_SIZE == 0);
  235.     ASSERT(size % FRAME_SIZE == 0);
  236.    
  237.     cnt = size / FRAME_SIZE;
  238.    
  239.     z = (zone_t *) malloc(sizeof(zone_t));
  240.     if (z) {
  241.         link_initialize(&z->link);
  242.         spinlock_initialize(&z->lock);
  243.    
  244.         z->base = start;
  245.         z->flags = flags;
  246.  
  247.         z->free_count = cnt;
  248.         list_initialize(&z->free_head);
  249.  
  250.         z->busy_count = 0;
  251.         list_initialize(&z->busy_head);
  252.        
  253.         z->frames = (frame_t *) malloc(cnt * sizeof(frame_t));
  254.         if (!z->frames) {
  255.             free(z);
  256.             return NULL;
  257.         }
  258.        
  259.         for (i = 0; i<cnt; i++) {
  260.             frame_initialize(&z->frames[i], z);
  261.             list_append(&z->frames[i].link, &z->free_head);
  262.         }
  263.        
  264.     }
  265.    
  266.     return z;
  267. }
  268.  
  269. /** Attach frame zone
  270.  *
  271.  * Attach frame zone to zone list.
  272.  *
  273.  * @param zone Zone to be attached.
  274.  */
  275. void zone_attach(zone_t *zone)
  276. {
  277.     pri_t pri;
  278.    
  279.     pri = cpu_priority_high();
  280.     spinlock_lock(&zone_head_lock);
  281.    
  282.     list_append(&zone->link, &zone_head);
  283.    
  284.     spinlock_unlock(&zone_head_lock);
  285.     cpu_priority_restore(pri);
  286. }
  287.  
  288. /** Initialize frame structure
  289.  *
  290.  * Initialize frame structure.
  291.  *
  292.  * @param frame Frame structure to be initialized.
  293.  * @param zone Host frame zone.
  294.  */
  295. void frame_initialize(frame_t *frame, zone_t *zone)
  296. {
  297.     frame->refcount = 0;
  298.     link_initialize(&frame->link);
  299.     frame->zone = zone;
  300. }
  301.  
  302. /** Get address of physical frame from its frame structure
  303.  *
  304.  * Get address of physical frame from its frame structure.
  305.  *
  306.  * @param frame Frame structure of the queried frame address.
  307.  *
  308.  * @return Address of frame associated with the argument.
  309.  */
  310. __address frame_get_address(frame_t *frame)
  311. {
  312.     __address v;
  313.     zone_t *z;
  314.     pri_t pri;
  315.    
  316.     z = frame->zone;
  317.    
  318.     pri = cpu_priority_high();
  319.     spinlock_lock(&z->lock);
  320.  
  321.     v = z->base + (frame - z->frames) * FRAME_SIZE;
  322.    
  323.     if (z->flags & FRAME_KA)
  324.         v = PA2KA(v);
  325.  
  326.     spinlock_unlock(&z->lock);
  327.     cpu_priority_restore(pri);
  328.    
  329.     return v;
  330. }
  331.