Changeset 7 for trunk/kernel/mm
- Timestamp:
- Apr 26, 2017, 2:15:50 PM (8 years ago)
- Location:
- trunk/kernel/mm
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/mm/kcm.c
r1 r7 33 33 #include <page.h> 34 34 #include <cluster.h> 35 #include <kmem.h> 35 36 #include <kcm.h> 36 37 37 /////////////////////////////////////////////////////////////////////////////////////38 // Extern global variable (defined in kmem.c file)39 /////////////////////////////////////////////////////////////////////////////////////40 41 extern uint32_t kmem_size_tbl[KMEM_TYPES_NR];42 43 44 /////////////////////////////////////////////////////////////////////////////////////45 // This function allocates one page from local PPM.46 /////////////////////////////////////////////////////////////////////////////////////47 static page_t * kcm_page_alloc( kcm_t * kcm )48 {49 page_t * page;50 kmem_req_t req;51 52 req.type = KMEM_PAGE;53 req.size = 0;54 req.flags = AF_KERNEL;55 page = kmem_alloc( &req );56 57 if( page == NULL )58 {59 printk("\n[ERROR] in %s failed to allocate page in cluster %d\n",60 __FUNCTION__ , local_cxy );61 }62 63 return page;64 }65 66 38 ////////////////////////////////////////////////////////////////////////////////////// 67 // This static function returns pointer on a llocated block from an active page.39 // This static function returns pointer on an allocated block from an active page. 68 40 // It returns NULL if no block available in selected page. 69 41 // It changes the page status if required. 70 42 ////////////////////////////////////////////////////////////////////////////////////// 71 static void * get_block( kcm_t * kcm, 72 kcm_page_t * page ) 73 { 74 int32_t index = bitmap_ffs( page->bitmap , sizeof(page->bitmap) ); 75 76 // the page should be active 77 if( page->active == 0 ) 78 { 79 printk("\n[PANIC] in %s : kcm page should be active\n", __FUNCTION__ ); 80 hal_core_sleep(); 81 } 82 83 // the page should not be full 84 if( index == -1 ) 85 { 86 printk("\n[PANIC] in %s : kcm page should be active\n", __FUNCTION__ ); 87 hal_core_sleep(); 88 } 43 // @ kcm : pointer on kcm allocator. 44 // @ ptr : pointer on active kcm page to use. 45 ///////////////////////////////////////////////////////////////////////////////////// 46 static void * kcm_get_block( kcm_t * kcm, 47 kcm_page_t * page ) 48 { 49 assert( page->active , __FUNCTION__ , "kcm page should be active" ); 50 51 // get first block available 52 int32_t index = bitmap_ffs( page->bitmap , kcm->blocks_nr ); 53 54 assert( (index != -1) , __FUNCTION__ , "kcm page should not be full" ); 89 55 56 // allocate block 90 57 bitmap_clear( page->bitmap , index ); 58 59 // increase page refcount 91 60 page->refcount ++; 92 61 93 // change the page to busy if lastblock in page62 // change the page to busy no more free block in page 94 63 if( page->refcount >= kcm->blocks_nr ) 95 64 { … … 103 72 } 104 73 105 return (page->blk_tbl + index * kcm->block_size ); 106 } 74 return (page->base + index * kcm->block_size ); 75 76 } // kcm_get_block() 107 77 108 78 ///////////////////////////////////////////////////////////////////////////////////// … … 110 80 // It changes the page status if required. 111 81 ///////////////////////////////////////////////////////////////////////////////////// 112 static void put_block ( kcm_t * kcm, 113 void * ptr ) 82 // @ kcm : pointer on kcm allocator. 83 // @ ptr : pointer on block to be released. 84 ///////////////////////////////////////////////////////////////////////////////////// 85 static void kcm_put_block ( kcm_t * kcm, 86 void * ptr ) 114 87 { 115 88 kcm_page_t * page; … … 117 90 118 91 page = (kcm_page_t*)((intptr_t)ptr & CONFIG_PPM_PAGE_MASK); 119 index = ((uint8_t*)ptr - page->b lk_tbl) / kcm->block_size;92 index = ((uint8_t*)ptr - page->base) / kcm->block_size; 120 93 121 94 bitmap_set( page->bitmap , index ); … … 144 117 kcm->free_pages_nr ++; 145 118 } 146 } 147 148 ///////////////////////////////////////////////////////////////////////////////////// 149 // This static function tries to allocateone page from PPM. It initializes119 } // kcm_put_block() 120 121 ///////////////////////////////////////////////////////////////////////////////////// 122 // This static function allocates one page from PPM. It initializes 150 123 // the KCM-page descriptor, and introduces the new page into freelist. 151 124 ///////////////////////////////////////////////////////////////////////////////////// … … 154 127 page_t * page; 155 128 kcm_page_t * ptr; 129 kmem_req_t req; 156 130 157 131 // get one page from local PPM 158 page = kcm_page_alloc( kcm ); 159 if( page == NULL ) return ENOMEM; 160 161 // get physical page base address 132 req.type = KMEM_PAGE; 133 req.size = 0; 134 req.flags = AF_KERNEL; 135 page = kmem_alloc( &req ); 136 137 if( page == NULL ) 138 { 139 printk("\n[ERROR] in %s : failed to allocate page in cluster %d\n", 140 __FUNCTION__ , local_cxy ); 141 return ENOMEM; 142 } 143 144 // get page base address 162 145 ptr = ppm_page2base( page ); 163 146 … … 168 151 ptr->active = 0; 169 152 ptr->refcount = 0; 170 ptr->b lk_tbl= (uint8_t*)ptr + kcm->block_size;153 ptr->base = (uint8_t*)ptr + kcm->block_size; 171 154 ptr->kcm = kcm; 172 155 ptr->page = page; … … 177 160 178 161 return 0; 179 } 162 163 } // freelist_populate() 180 164 181 165 ///////////////////////////////////////////////////////////////////////////////////// … … 185 169 static kcm_page_t * freelist_get( kcm_t * kcm ) 186 170 { 187 error_t err ;171 error_t error; 188 172 kcm_page_t * page; 189 173 … … 191 175 if( kcm->free_pages_nr == 0 ) 192 176 { 193 err = freelist_populate( kcm );194 if( err ) return NULL;177 error = freelist_populate( kcm ); 178 if( error ) return NULL; 195 179 } 196 180 … … 199 183 list_unlink( &page->list ); 200 184 kcm->free_pages_nr --; 201 page->active = 1;202 203 list_add_first( &kcm->active_root , &page->list);204 kcm->active_pages_nr ++;205 page->active = 1;206 185 207 186 return page; 208 } 209 210 211 //////////////////////////////////// 212 error_t kcm_init( kcm_t * kcm, 213 uint32_t type ) 187 188 } // freelist_get() 189 190 191 ////////////////////////////// 192 void kcm_init( kcm_t * kcm, 193 uint32_t type ) 214 194 { 215 195 uint32_t blocks_nr; 216 196 uint32_t block_size; 217 197 uint32_t remaining; 218 kcm_page_t * page; 219 198 199 // initialize lock 220 200 spinlock_init( &kcm->lock ); 221 201 … … 231 211 list_root_init( &kcm->active_root ); 232 212 233 // initialize block size and number of blocks per page, 234 // using the global kmem_size_tbl[] array 235 block_size = ARROUND_UP( kmem_size_tbl[type] , 64 ); 213 // initialize block size and number of blocks per page 214 block_size = ARROUND_UP( kmem_type_size( type ) , 64 ); 236 215 blocks_nr = CONFIG_PPM_PAGE_SIZE / block_size; 237 216 remaining = CONFIG_PPM_PAGE_SIZE % block_size; … … 240 219 kcm->blocks_nr = blocks_nr; 241 220 kcm->block_size = block_size; 242 243 // get one page from free_list244 page = freelist_get( kcm );245 if( page == NULL ) return ENOMEM;246 221 247 // register page in active list 248 list_add_first( &kcm->active_root , &page->list ); 249 page->active = 1; 250 kcm->active_pages_nr ++; 251 252 return 0; 253 } 222 kcm_dmsg("\n[INFO] %s : KCM %s initialised / block_size = %d / blocks_nr = %d\n", 223 __FUNCTION__ , kmem_type_str( type ) , block_size , blocks_nr ); 224 225 } // kcm_init() 254 226 255 227 /////////////////////////////// … … 292 264 spinlock_unlock( &kcm->lock ); 293 265 294 295 } 266 } // kcm_destroy() 296 267 297 268 /////////////////////////////// … … 304 275 spinlock_lock( &kcm->lock ); 305 276 306 // get block307 if( list_is_empty( &kcm->active_root ) ) // no active page 277 // get an active page 278 if( list_is_empty( &kcm->active_root ) ) // no active page => get one 308 279 { 280 kcm_dmsg("\n[INFO] %s : enters for type %s but no active page => get one\n", 281 __FUNCTION__ , kmem_type_str( kcm->type ) ); 282 283 // get a page from free list 284 page = freelist_get( kcm ); 285 if( page == NULL ) return NULL; 286 287 // insert page in active list 288 list_add_first( &kcm->active_root , &page->list ); 289 kcm->active_pages_nr ++; 290 page->active = 1; 291 } 292 else // get first page from active list 293 { 294 kcm_dmsg("\n[INFO] %s : enters for type %s with an active page\n", 295 __FUNCTION__ , kmem_type_str( kcm->type ) ); 296 297 // get page pointer from active list 309 298 page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list ); 310 ptr = get_block( kcm , page );311 299 } 312 else // active page cannot be full 313 { 314 page = LIST_FIRST( &kcm->active_root , kcm_page_t , list ); 315 ptr = get_block( kcm , page ); 316 } 300 301 // get a block from selected active page 302 // cannot fail, as an active page cannot be full... 303 ptr = kcm_get_block( kcm , page ); 317 304 318 305 // release lock 319 306 spinlock_unlock(&kcm->lock); 320 307 308 kcm_dmsg("\n[INFO] %s : allocated one block of type %s / ptr = %x\n", 309 __FUNCTION__ , kmem_type_str( kcm->type ) , (uint32_t)ptr ); 310 321 311 return ptr; 322 } 312 313 } // kcm_alloc() 323 314 324 315 /////////////////////////// … … 337 328 338 329 // release block 339 put_block( kcm , ptr );330 kcm_put_block( kcm , ptr ); 340 331 341 332 // release lock … … 346 337 void kcm_print (kcm_t * kcm) 347 338 { 348 printk("*** KCM type = % d/ free_pages = %d / busy_pages = %d / active_pages = %d\n",349 k cm->type,339 printk("*** KCM type = %s / free_pages = %d / busy_pages = %d / active_pages = %d\n", 340 kmem_type_str( kcm->type ) , 350 341 kcm->free_pages_nr , 351 342 kcm->busy_pages_nr , -
trunk/kernel/mm/kcm.h
r1 r7 39 39 * contain one single object. 40 40 * The various KCM allocators themselves are not statically allocated in the cluster 41 * manager, but are dynamically allocated when required, using the specificKCM41 * manager, but are dynamically allocated when required, using the embedded KCM 42 42 * allocator defined in the cluster manager, to allocate the other ones... 43 43 ***************************************************************************************/ … … 64 64 /**************************************************************************************** 65 65 * This structure defines a KCM-page descriptor. 66 * A KCM-page can contain severalblocks.67 * This descriptor is stored in the first block slot.66 * A KCM-page can contain up to (CONFIG_PPM_PAGE_SIZE / CONFIG_CACHE_LINE_SIZE) blocks. 67 * This kcm page descriptor is stored in the first slot of the page. 68 68 ***************************************************************************************/ 69 69 70 70 typedef struct kcm_page_s 71 71 { 72 BITMAP ( bitmap , 16 ); /*! at most 16 blocks in a page (1 if free) */73 uint8_t * b lk_tbl; /*! pointer on first free block in page*/72 BITMAP ( bitmap , CONFIG_KCM_BLOCKS_MAX ); 73 uint8_t * base; /*! pointer on first block in page */ 74 74 kcm_t * kcm; /*! owner KCM allocator */ 75 uint8_t unused; /*! first free block index in page */ 75 list_entry_t list; /*! [active / busy / free] list member */ 76 page_t * page; /*! pointer on the physical page descriptor */ 76 77 uint8_t refcount; /*! number of allocated blocks */ 77 78 uint8_t busy; /*! page busy if non zero */ 78 79 uint8_t active; /*! page active if non zero */ 79 list_entry_t list; /*! [active / busy / free] list member */ 80 page_t * page; /*! pointer on the physical page descriptor */ 80 uint8_t unused; /*! */ 81 81 } 82 82 kcm_page_t; … … 88 88 * @ type : KCM allocator type. 89 89 ***************************************************************************************/ 90 error_t kcm_init( kcm_t* kcm,91 uint32_ttype );90 void kcm_init( kcm_t * kcm, 91 uint32_t type ); 92 92 93 93 /**************************************************************************************** … … 96 96 * @ kcm : pointer on KCM manager to destroy. 97 97 ***************************************************************************************/ 98 void kcm_destroy( kcm_t 98 void kcm_destroy( kcm_t * kcm ); 99 99 100 100 /**************************************************************************************** … … 102 102 * The object size must be smaller than one page size. 103 103 **************************************************************************************** 104 * @ kcm : pointer on the selected KCM allocator 104 * @ kcm : pointer on the selected KCM allocator 105 * @ return pointer on allocated block if success / return NULL if failure 105 106 ***************************************************************************************/ 106 107 void * kcm_alloc( kcm_t * kcm ); -
trunk/kernel/mm/khm.c
r1 r7 40 40 { 41 41 // check config parameters 42 if( (CONFIG_PPM_PAGE_SHIFT + CONFIG_PPM_HEAP_ORDER) >= 32 ) 43 { 44 printk("\n[PANIC] in %s : CONFIG_PPM_HEAP_ORDER too large\n", __FUNCTION__ ); 45 hal_core_sleep(); 46 } 42 assert( ((CONFIG_PPM_PAGE_SHIFT + CONFIG_PPM_HEAP_ORDER) < 32 ) , __FUNCTION__ , 43 "CONFIG_PPM_HEAP_ORDER too large" ); 47 44 48 45 // initialize lock … … 65 62 khm->size = heap_size; 66 63 khm->next = (intptr_t)heap_base; 64 65 kinit_dmsg("\n[INFO] %s done in cluster %x at cycle %d\n", 66 __FUNCTION__ , local_cxy , hal_time_stamp() ); 67 67 } 68 68 -
trunk/kernel/mm/kmem.c
r1 r7 37 37 #include <thread.h> 38 38 #include <process.h> 39 #include < device.h>39 #include <chdev.h> 40 40 #include <mapper.h> 41 41 #include <vfs.h> … … 49 49 #include <kmem.h> 50 50 51 ///////////////////////////////////////////////////////////////////////////////////////////// 52 // This global array is indexed by the Kernel Memory Object Type (defined in kmem.h) 53 // It contains the size of fixed size objects type dynamically allocated by the KCMs. 54 // This array should be consistent with the enum defined kmem.h. 55 ///////////////////////////////////////////////////////////////////////////////////////////// 56 57 uint32_t kmem_size_tbl[KMEM_TYPES_NR] = 58 { 59 0, // 0 KMEM_PAGE is not a fixed size object 60 0, // 1 KMEM_GENERIC 61 sizeof( kcm_t ), // 2 KMEM_KCM 62 sizeof( vseg_t ), // 3 KMEM_VSEG 63 sizeof( device_t ), // 4 KMEM_DEVICE 64 sizeof( mapper_t ), // 5 KMEM_MAPPER 65 sizeof( process_t ), // 6 KMEM_PROCESS 66 0, // 7 67 0, // 8 68 0, // 9 69 70 sizeof( fatfs_inode_t ), // 10 KMEM_FATFS_INODE 71 sizeof( fatfs_ctx_t ), // 11 KMEM_FATFS_CTX 72 sizeof( ramfs_inode_t ), // 12 KMEM_RAMFS_INODE 73 sizeof( ramfs_ctx_t ), // 13 KMEM_RAMFS_CTX 74 sizeof( vfs_ctx_t ), // 14 KMEM_VFS_CTX 75 sizeof( vfs_inode_t ), // 15 KMEM_VFS_INODE 76 sizeof( vfs_dentry_t ), // 16 KMEM_VFS_DENTRY 77 sizeof( vfs_file_t ), // 17 KMEM_VFS_FILE 78 sizeof( remote_sem_t ), // 18 KMEM_SEM 79 0, // 19 80 81 64, // 20 KMEM_64_BYTES 82 128, // 21 KMEM_128_BYTES 83 256, // 22 KMEM_256_BYTES 84 512, // 23 KMEM_512_BYTES 85 1024, // 24 KMEM_1024_BYTES 86 2048, // 25 KMEM_2048_BYTES 87 }; 51 /////////////////////////// 52 void kmem_print_kcm_table() 53 { 54 uint32_t index; 55 kcm_t * kcm; 56 cluster_t * cluster = LOCAL_CLUSTER; 57 58 printk("\n *** KCM Pointers Table ***\n"); 59 60 for( index = 0 ; index < KMEM_TYPES_NR ; index++ ) 61 { 62 kcm = cluster->kcm_tbl[index]; 63 if( kcm != NULL ) 64 { 65 if( index == kcm->type ) 66 { 67 printk(" - KCM[%s] (at address %x) is OK\n", 68 kmem_type_str( index ) , (intptr_t)kcm ); 69 } 70 else 71 { 72 printk(" - KCM[%s] (at address %x) is KO : has type %s\n", 73 kmem_type_str( index ) , (intptr_t)kcm , kmem_type_str( kcm->type ) ); 74 } 75 } 76 } 77 } // end kmem_print_kcm_table() 78 79 ///////////////////////////////////////// 80 uint32_t kmem_type_size( uint32_t type ) 81 { 82 if ( type == KMEM_PAGE ) return CONFIG_PPM_PAGE_SIZE; 83 else if( type == KMEM_GENERIC ) return 0; 84 else if( type == KMEM_KCM ) return sizeof( kcm_t ); 85 else if( type == KMEM_VSEG ) return sizeof( vseg_t ); 86 else if( type == KMEM_DEVICE ) return sizeof( chdev_t ); 87 else if( type == KMEM_MAPPER ) return sizeof( mapper_t ); 88 else if( type == KMEM_PROCESS ) return sizeof( process_t ); 89 else if( type == KMEM_CPU_CTX ) return sizeof( hal_cpu_context_t ); 90 else if( type == KMEM_FPU_CTX ) return sizeof( hal_fpu_context_t ); 91 92 else if( type == KMEM_FATFS_INODE ) return sizeof( fatfs_inode_t ); 93 else if( type == KMEM_FATFS_CTX ) return sizeof( fatfs_ctx_t ); 94 else if( type == KMEM_RAMFS_INODE ) return sizeof( ramfs_inode_t ); 95 else if( type == KMEM_RAMFS_CTX ) return sizeof( ramfs_ctx_t ); 96 else if( type == KMEM_VFS_CTX ) return sizeof( vfs_ctx_t ); 97 else if( type == KMEM_VFS_INODE ) return sizeof( vfs_inode_t ); 98 else if( type == KMEM_VFS_DENTRY ) return sizeof( vfs_dentry_t ); 99 else if( type == KMEM_VFS_FILE ) return sizeof( vfs_file_t ); 100 else if( type == KMEM_SEM ) return sizeof( remote_sem_t ); 101 else return 0; 102 } 103 104 ///////////////////////////////////// 105 char * kmem_type_str( uint32_t type ) 106 { 107 if ( type == KMEM_PAGE ) return "KMEM_PAGE"; 108 else if( type == KMEM_GENERIC ) return "KMEM_GENERIC"; 109 else if( type == KMEM_KCM ) return "KMEM_KCM"; 110 else if( type == KMEM_VSEG ) return "KMEM_VSEG"; 111 else if( type == KMEM_DEVICE ) return "KMEM_DEVICE"; 112 else if( type == KMEM_MAPPER ) return "KMEM_MAPPER"; 113 else if( type == KMEM_PROCESS ) return "KMEM_PROCESS"; 114 else if( type == KMEM_CPU_CTX ) return "KMEM_CPU_CTX"; 115 else if( type == KMEM_FPU_CTX ) return "KMEM_FPU_CTX"; 116 117 else if( type == KMEM_FATFS_INODE ) return "KMEM_FATFS_INODE"; 118 else if( type == KMEM_FATFS_CTX ) return "KMEM_FATFS_CTX"; 119 else if( type == KMEM_RAMFS_INODE ) return "KMEM_RAMFS_INODE"; 120 else if( type == KMEM_RAMFS_CTX ) return "KMEM_RAMFS_CTX"; 121 else if( type == KMEM_VFS_CTX ) return "KMEM_VFS_CTX"; 122 else if( type == KMEM_VFS_INODE ) return "KMEM_VFS_INODE"; 123 else if( type == KMEM_VFS_DENTRY ) return "KMEM_VFS_DENTRY"; 124 else if( type == KMEM_VFS_FILE ) return "KMEM_VFS_FILE"; 125 else if( type == KMEM_SEM ) return "KMEM_SEM"; 126 else return "undefined"; 127 } 88 128 89 129 ///////////////////////////////////////////////////////////////////////////////////////////// … … 91 131 // It uses the KCM allocator embedded in cluster manager, initialized by cluster_init(). 92 132 ///////////////////////////////////////////////////////////////////////////////////////////// 93 static error_t kmem_ get_kcm( uint32_t type )133 static error_t kmem_create_kcm( uint32_t type ) 94 134 { 95 135 kcm_t * kcm; 96 error_t error; 97 98 // check kmem object type 99 if( (type < 2) || (type >= KMEM_TYPES_NR) ) 100 { 101 printk("\n[PANIC] in %s illegal request type\n", __FUNCTION__ ); 102 hal_core_sleep(); 103 } 136 137 assert( ((type > 1) && (type < KMEM_TYPES_NR) ) , __FUNCTION__ , "illegal KCM type" ); 138 139 kmem_dmsg("\n[INFO] %s : enters / KCM type %s missing in cluster %x\n", 140 __FUNCTION__ , kmem_type_str( type ) , local_cxy ); 104 141 105 142 cluster_t * cluster = LOCAL_CLUSTER; 106 143 107 144 // allocates memory for the requested KCM allocator 145 // from the KCM allocator embedded in cluster descriptor 108 146 kcm = kcm_alloc( &cluster->kcm ); 147 109 148 if( kcm == NULL ) 110 149 { … … 115 154 116 155 // initializes the new KCM allocator 117 error = kcm_init( kcm , type ); 118 119 if( error ) 120 { 121 printk("\n[ERROR] in %s : failed to init KCM type %d\n", 122 __FUNCTION__ , type , local_cxy ); 123 return error; 124 } 125 156 kcm_init( kcm , type ); 157 158 // register it if the KCM pointers Table 126 159 cluster->kcm_tbl[type] = kcm; 160 127 161 hal_wbflush(); 128 162 163 kmem_dmsg("\n[INFO] %s : exit / KCM type %s created in cluster %x\n", 164 __FUNCTION__ , kmem_type_str( type ) , local_cxy ); 165 129 166 return 0; 130 } 167 168 } // end kmem_create_kcm() 169 131 170 132 171 … … 137 176 138 177 uint32_t type; 139 uint32_t size; // ln( pages ) if PPM / bytes if KHM or BKM / unused if KCM140 178 uint32_t flags; 141 void * ptr; // local pointer on allocated memory buffer 179 uint32_t size; // ln( pages ) if PPM / bytes if KHM / unused if KCM 180 void * ptr; // memory buffer if KHM or KCM / page descriptor if PPM 181 142 182 143 183 type = req->type; … … 145 185 flags = req->flags; 146 186 147 kmem_dmsg("\n[INFO] %s in cluster %x : type %d, size %d, flags %x at cycle %d \n", 148 __FUNCTION__, local_cxy , type, size, flags , hal_time_stamp() ); 149 150 if( type >= KMEM_TYPES_NR ) 151 { 152 printk("\n[PANIC] in %s illegal request type\n", __FUNCTION__ ); 153 hal_core_sleep(); 154 } 187 assert( (type < KMEM_TYPES_NR) , __FUNCTION__ , "illegal KMEM request type" ); 155 188 189 kmem_dmsg("\n[INFO] %s : enters in cluster %x for type %s / size %d\n", 190 __FUNCTION__ , local_cxy , kmem_type_str( type ) , size ); 191 156 192 // analyse request type 157 193 if( type == KMEM_PAGE ) // PPM allocator 158 194 { 159 195 // allocate the number of requested pages 160 ptr = (void *)ppm_alloc_pages( size );196 ptr = (void *)ppm_alloc_pages( size ); 161 197 162 198 // reset page if required 163 if( flags & AF_ZERO ) page_zero( (page_t*)ptr ); 199 if( flags & AF_ZERO ) page_zero( (page_t *)ptr ); 200 201 kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / page = %x / base = %x\n", 202 __FUNCTION__, local_cxy , kmem_type_str( type ) , 203 (intptr_t)ptr , (intptr_t)ppm_page2base( ptr ) ); 164 204 } 165 205 else if( type == KMEM_GENERIC ) // KHM allocator … … 170 210 // reset memory if requested 171 211 if( flags & AF_ZERO ) memset( ptr , 0 , size ); 212 213 kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x\n", 214 __FUNCTION__, local_cxy , kmem_type_str( type ) , (intptr_t)ptr ); 172 215 } 173 216 else // KCM allocator 174 217 { 175 uint32_t error = 0;176 177 218 // initialize the KCM allocator if not already done 178 219 if( cluster->kcm_tbl[type] == NULL ) 179 220 { 180 221 spinlock_lock( &cluster->kcm_lock ); 181 error = kmem_get_kcm( type );222 error_t error = kmem_create_kcm( type ); 182 223 spinlock_unlock( &cluster->kcm_lock ); 224 if ( error ) return NULL; 183 225 } 184 226 185 // allocate memory from KCM if success 186 if( error ) ptr = NULL; 187 else ptr = kcm_alloc( cluster->kcm_tbl[type] ); 227 // allocate memory from KCM 228 ptr = kcm_alloc( cluster->kcm_tbl[type] ); 229 230 // reset memory if requested 231 if( flags & AF_ZERO ) memset( ptr , 0 , kmem_type_size( type ) ); 232 233 kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x\n", 234 __FUNCTION__, local_cxy , kmem_type_str( type ) , (intptr_t)ptr ); 188 235 } 189 236 190 237 if( ptr == NULL ) 191 238 { 192 printk("\n[ERROR] in %s : failed for type %d , size %d, flags %xin cluster %x\n",193 __FUNCTION__ , type , size , flags ,local_cxy );239 printk("\n[ERROR] in %s : failed for type %d / size %d in cluster %x\n", 240 __FUNCTION__ , type , size , local_cxy ); 194 241 195 242 return NULL; 196 243 } 197 244 198 kmem_dmsg("\n[INFO] %s got ptr = %x in cluster %x at cycle %d\n",199 __FUNCTION__, (intptr_t)ptr , local_cxy , hal_time_stamp() );200 201 245 return ptr; 202 246 -
trunk/kernel/mm/kmem.h
r1 r7 31 31 32 32 /************************************************************************************* 33 * This enum defines the Kernel Memory Types for dynamically allocated objects .33 * This enum defines the Kernel Memory Types for dynamically allocated objectsn. 34 34 ************************************************************************************/ 35 35 … … 43 43 KMEM_MAPPER = 5, /*! mapper_t */ 44 44 KMEM_PROCESS = 6, /*! process_t */ 45 KMEM_ TBD_7 = 7,46 KMEM_ TBD_8 = 8,45 KMEM_CPU_CTX = 7, /*! hal_cpu_context_t */ 46 KMEM_FPU_CTX = 8, /*! hal_fpu_context_t */ 47 47 KMEM_TBD_9 = 9, 48 48 … … 58 58 KMEM_TBD_19 = 19, 59 59 60 KMEM_64_BYTES = 20, /*! fixed size buffer */ 61 KMEM_128_BYTES = 21, /*! fixed size buffer */ 62 KMEM_256_BYTES = 22, /*! fixed size buffer */ 63 KMEM_512_BYTES = 23, /*! fixed size buffer */ 64 KMEM_1024_BYTES = 24, /*! fixed size buffer */ 65 KMEM_2048_BYTES = 25, /*! fixed size buffer */ 66 67 KMEM_TYPES_NR = 26, 60 KMEM_TYPES_NR = 20, 68 61 }; 69 62 … … 93 86 * This generic function allocates physical memory in the local cluster 94 87 * as specified by the request descriptor. 95 * It uses three specialised physical memory allocators :88 * It uses three specialised physical memory allocators, depending on request type: 96 89 * - PPM (Physical Pages Manager) allocates N contiguous physical pages, 97 90 * N must be a power of 2. … … 101 94 * handling a dedicated cache for each object type. 102 95 ************************************************************************************* 103 * @ req : local pointer to allocation request 104 * @ return a local pointer to allocated buffer / NULL otherwise 96 * @ req : local pointer to allocation request. 97 * @ return a local pointer on page descriptor if PPM (i.e. type KMEM_PAGE). 98 * return a local pointer to allocated buffer if KCM or KHM. 99 * return NULL if no physical memory available. 105 100 ************************************************************************************/ 106 101 void * kmem_alloc( kmem_req_t * req ); … … 114 109 void kmem_free ( kmem_req_t * req ); 115 110 111 /************************************************************************************* 112 * This function returns a printable string for a kmem object type. 113 ************************************************************************************* 114 * @ type : kmem object type. 115 ************************************************************************************/ 116 char * kmem_type_str( uint32_t type ); 117 118 /************************************************************************************* 119 * This function returns the size (bytes) for a kmem object type. 120 ************************************************************************************* 121 * @ type : kmem object type. 122 ************************************************************************************/ 123 uint32_t kmem_type_size( uint32_t type ); 124 125 /************************************************************************************* 126 * This functions display the content of the KCM pointers Table 127 ************************************************************************************/ 128 void kmem_print_kcm_table(); 129 116 130 117 131 #endif /* _KMEM_H_ */ -
trunk/kernel/mm/page.c
r1 r7 265 265 266 266 size = (1 << page->order) * CONFIG_PPM_PAGE_SIZE; 267 base = ppm_page2base(page); 267 base = ppm_page2base( page ); 268 269 // kmem_print_kcm_table(); 270 271 // printk("\n@@@ in page_zero : size = %x / base = %x / kcm_tbl = %x\n", 272 // size , (uint32_t)base , (uint32_t)(&LOCAL_CLUSTER->kcm_tbl[0] ) ); 268 273 269 274 memset( base , 0 , size ); 275 276 // kmem_print_kcm_table(); 277 270 278 } 271 279 … … 285 293 286 294 287 /* 288 ///////////////////////////////////////// 289 static void page_to_free( page_t * page ) 290 { 291 assert((page->state == PGINVALID) || 292 (page->state == PGVALID) || 293 (page->state == PGINIT)); 294 295 if(page_refcount_get(page) != 0) 296 { 297 printk(ERROR, "ERROR: %s: cpu %d, pid %d, tid %x, page %x, state %x, count %d [%d]\n", 298 __FUNCTION__, 299 cpu_get_id(), 300 current_task->pid, 301 current_thread, 302 page, 303 page->state, 304 page_refcount_get(page), 305 cpu_time_stamp()); 306 } 307 page->state = PGFREE; 308 } 309 310 //////////////////////////////////////////// 311 static void page_to_invalid( page_t * page ) 312 { 313 assert((page->state == PGFREE) || 314 (page->state == PGVALID) || 315 (page->state == PGLOCKEDIO)); 316 317 if(page->state == PGLOCKEDIO) 318 { 319 page->state = PGINVALID; 320 page_unlock(page); 321 return; 322 } 323 324 page->state = PGINVALID; 325 } 326 327 ////////////////////////////////////////// 328 static void page_to_valid( page_t * page ) 329 { 330 assert((page->state == PGINVALID) || 331 (page->state == PGLOCKED) || 332 (page->state == PGLOCKEDIO)); 333 334 if(page->state == PGINVALID) 335 { 336 page->state = PGVALID; 337 return; 338 } 339 340 page->state = PGVALID; 341 page_unlock(page); 342 } 343 344 ////////////////////////////////////////////// 345 static void page_to_locked_io( page_t * page ) 346 { 347 assert((page->state == PGINVALID) || 348 (page->state == PGVALID)); 349 350 page_lock(page); 351 page->state = PGLOCKEDIO; 352 } 353 354 /////////////////////////////////////////// 355 static void page_to_locked( page_t * page ) 356 { 357 assert(page->state == PGVALID); 358 page_lock(page); 359 page->state = PGLOCKED; 360 } 361 362 ///////////////////////////////////////// 363 void page_state_set( page_t * page, 364 page_state_t state ) 365 { 366 switch( state ) 367 { 368 case PGFREE: 369 page_to_free(page); 370 return; 371 372 case PGINVALID: 373 page_to_invalid(page); 374 return; 375 376 case PGVALID: 377 page_to_valid(page); 378 return; 379 380 case PGLOCKEDIO: 381 page_to_locked_io(page); 382 return; 383 384 case PGLOCKED: 385 page_to_locked(page); 386 return; 387 388 case PGRESERVED: 389 refcount_set(&page->count,1); 390 391 case PGINIT: 392 page->state = new_state; 393 return; 394 395 default: 396 printk(ERROR, "ERROR: %s: Unknown Asked State %d\n", new_state); 397 return; 398 } 399 } 400 */ 401 402 295 -
trunk/kernel/mm/ppm.c
r1 r7 91 91 static void ppm_free_pages_nolock( page_t * page ) 92 92 { 93 page_t * buddy; // searched buddy page descriptor 94 uint32_t buddy_index; // buddy page index 95 page_t * current; // current (merged) page descriptor 96 uint32_t current_index; // current (merged) page index 97 uint32_t current_order; // current (merget) page order 98 93 99 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 94 100 page_t * pages_tbl = ppm->pages_tbl; 95 uint32_t page_order = page->order; 96 uint32_t page_index = (uint32_t)(page - ppm->pages_tbl); 97 98 page_t * block; 99 uint32_t block_index; 100 uint32_t current_order; 101 102 // update page descriptor flag 101 102 // update released page descriptor flags 103 103 page_set_flag( page , PG_FREE ); 104 104 105 // update free_lists 106 for( current_order = page_order ; current_order < CONFIG_PPM_MAX_ORDER ; current_order++ ) 105 // search the buddy page descriptor 106 // - merge with current page descriptor if found 107 // - exit to release the current page descriptor if not found 108 current = page , 109 current_index = (uint32_t)(page - ppm->pages_tbl); 110 for( current_order = page->order ; 111 current_order < CONFIG_PPM_MAX_ORDER ; 112 current_order++ ) 107 113 { 108 block_index = page_index ^ (1 << current_order); 109 block = pages_tbl + block_index; 110 111 if( page_is_flag( block , PG_FREE ) || (block->order != current_order) ) break; 112 113 list_unlink( &block->list ); 114 buddy_index = current_index ^ (1 << current_order); 115 buddy = pages_tbl + buddy_index; 116 117 if( !page_is_flag( buddy , PG_FREE ) || (buddy->order != current_order) ) break; 118 119 // remove buddy from free list 120 list_unlink( &buddy->list ); 114 121 ppm->free_pages_nr[current_order] --; 115 122 ppm->total_free_pages -= (1 << current_order); 116 123 117 block->order = 0; 118 page_index &= block_index; 119 } 120 121 block = pages_tbl + page_index; 122 block->order = current_order; 123 124 list_add_first( &ppm->free_pages_root[current_order] , &block->list ); 124 // merge buddy with current 125 buddy->order = 0; 126 current_index &= buddy_index; 127 } 128 129 // update merged page descriptor order 130 current = pages_tbl + current_index; 131 current->order = current_order; 132 133 // insert current in free list 134 list_add_first( &ppm->free_pages_root[current_order] , ¤t->list ); 125 135 ppm->free_pages_nr[current_order] ++; 126 136 ppm->total_free_pages += (1 << current_order); … … 128 138 } // end ppm_free_pages_nolock() 129 139 130 ////////////////////////////// ///140 ////////////////////////////// 131 141 void ppm_init( ppm_t * ppm, 132 142 uint32_t pages_nr, // total pages number … … 148 158 ppm->free_pages_nr[i] = 0; 149 159 } 160 161 #if( CONFIG_PPM_DEBUG ) 162 ppm_print( ppm , "after reset" ); 163 #endif 150 164 151 165 // initialize dirty_list as empty … … 166 180 // set pages numbers 167 181 ppm->pages_nr = pages_nr; 168 ppm->pages_offset = pages_offset;182 ppm->pages_offset = reserved_pages; 169 183 170 184 // initialises all page descriptors in pages_tbl[] 171 // TODO Peut-on accélérer ces monstrueuses boucle ? [AG]172 185 for( i = 0 ; i < pages_nr ; i++ ) 173 186 { 174 187 page_init( &ppm->pages_tbl[i] ); 188 189 // TODO optimisation : make only a partial init [AG] 190 // complete the initialisation when page is allocated [AG] 191 // ppm->pages_tbl[i].flags = 0; 175 192 } 176 193 177 // set PG_RESERVED flag for reserved pages (kernel code & pages_tbl[]) 194 // - set PG_RESERVED flag for reserved pages (kernel code & pages_tbl[]) 195 // - release all other pages to populate the free lists 178 196 for( i = 0 ; i < reserved_pages ; i++) 179 197 { 180 198 page_set_flag( &ppm->pages_tbl[i] , PG_RESERVED ); 181 199 } 182 183 // initialise the free lists by releasing all non reserved pages 184 for( i = 0 ; i < pages_nr ; i++ ) 185 { 186 page_t * page = &ppm->pages_tbl[i]; 187 if( page_is_flag( page , PG_RESERVED) ) ppm_free_pages_nolock( page ); 188 } 200 for( i = reserved_pages ; i < pages_nr ; i++ ) 201 { 202 ppm_free_pages_nolock( &ppm->pages_tbl[i] ); 203 204 // TODO optimisation : decompose this enormous set of small pages 205 // to a set big pages with various order values 206 } 207 208 // check consistency 209 ppm_assert_order( ppm ); 210 211 kinit_dmsg("\n[INFO] %s : done in cluster %x at cycle %d\n", 212 __FUNCTION__ , local_cxy , hal_time_stamp() ); 213 214 #if( CONFIG_PPM_DEBUG ) 215 ppm_print( ppm , "after init" ); 216 #endif 217 189 218 } // end ppm_init() 190 219 … … 198 227 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 199 228 200 if( ppm->signature != PPM_SIGNATURE ) 201 { 202 printk("\n[PANIC] in %s : PPM non initialised in cluster %x\n", 203 __FUNCTION__ , local_cxy ); 204 hal_core_sleep(); 205 } 206 207 if( order >= CONFIG_PPM_MAX_ORDER ) 208 { 209 printk("\n[PANIC] in %s : illegal order argument in cluster %x\n", 210 __FUNCTION__ , local_cxy ); 211 hal_core_sleep(); 212 } 229 assert( (ppm->signature == PPM_SIGNATURE) , __FUNCTION__ , "PPM non initialised" ); 230 231 assert( (order < CONFIG_PPM_MAX_ORDER) , __FUNCTION__ , "illegal order argument" ); 213 232 214 233 page_t * block = NULL; 234 235 ppm_dmsg("\n[INFO] %s : enters / order = %d\n", 236 __FUNCTION__ , order ); 237 238 #if( CONFIG_PPM_DEBUG ) 239 ppm_print( ppm , "before allocation" ); 240 #endif 215 241 216 242 // take lock protecting free lists 217 243 spinlock_lock( &ppm->free_lock ); 218 244 219 // find a block larger or equalto requested size245 // find a free block equal or larger to requested size 220 246 for( current_order = order ; current_order < CONFIG_PPM_MAX_ORDER ; current_order ++ ) 221 247 { … … 264 290 spinlock_unlock( &ppm->free_lock ); 265 291 292 ppm_dmsg("\n[INFO] %s : base = %x / order = %d\n", 293 __FUNCTION__ , (uint32_t)ppm_page2base( block ) , order ); 294 295 #if CONFIG_PPM_DEBUG 296 ppm_print( ppm , "after allocation" ); 297 #endif 298 266 299 return block; 267 300 } // end pmm_alloc-pages() … … 282 315 } 283 316 284 ///////////////////////////// 285 void ppm_print( ppm_t * ppm ) 317 //////////////////////////// 318 void ppm_print( ppm_t * ppm, 319 char * string ) 286 320 { 287 321 uint32_t order; … … 292 326 spinlock_lock( &ppm->free_lock ); 293 327 294 printk(" *** PPM state in cluster %x: pages = %d / offset = %d / free = %d ***\n",295 local_cxy , ppm->pages_nr , ppm->pages_offset , ppm->total_free_pages );328 printk("\n*** PPM state in cluster %x %s : pages = %d / offset = %d / free = %d ***\n", 329 local_cxy , string , ppm->pages_nr , ppm->pages_offset , ppm->total_free_pages ); 296 330 297 331 for( order = 0 ; order < CONFIG_PPM_MAX_ORDER ; order++ ) 298 332 { 299 printk("- order = %d / free_pages = %d [ \n",333 printk("- order = %d / free_pages = %d [", 300 334 order , ppm->free_pages_nr[order] ); 301 335 … … 311 345 // release lock protecting free lists 312 346 spinlock_unlock( &ppm->free_lock ); 313 } 314 315 //////////////////////////////////////// 316 void ppm_assert_order(struct ppm_s *ppm) 347 348 } // end ppm_print() 349 350 //////////////////////////u///////// 351 void ppm_assert_order( ppm_t * ppm ) 317 352 { 318 353 uint32_t order; … … 328 363 page = LIST_ELEMENT( iter , page_t , list ); 329 364 330 if( page->order != order ) 331 { 332 printk("%s detected inconsistency at order %d, page %d\n", 333 __FUNCTION__, order , page - ppm->pages_tbl ); 334 } 365 assert( (page->order == order) , __FUNCTION__ , "PPM inconsistency" ); 335 366 } 336 367 } 337 return; 338 } 339 368 369 } // end ppm_assert_order() 370 -
trunk/kernel/mm/ppm.h
r1 r7 35 35 36 36 /***************************************************************************************** 37 * This structure defines the list of blocks of a given size for the "buddy"38 * allocation algorithm implemented by the ppm_t manager.39 ****************************************************************************************/40 typedef struct buddy_list_s41 {42 list_entry_t root; // root of the list43 uint32_t pages_nr; // number of blocks44 }45 buddy_list_t;46 47 /*****************************************************************************************48 37 * This structure defines the Physical Memory Manager in a cluster. 49 38 * In all clusters, the physical memory bank starts at address 0. … … 51 40 * The physical page descriptors array is implemented just after this offset zone. 52 41 * The main service provided by the PMM is the dynamic allocation of physical pages. 53 * This low-level allocator implements the buddy algorithm. 42 * This low-level allocator implements the buddy algorithm: an allocated block is 43 * is an integer number n of 4 Kbytes pages, and n (called order) is a power of 2. 54 44 ****************************************************************************************/ 55 45 typedef struct ppm_s … … 71 61 /***************************************************************************************** 72 62 * This function initializes a PPM (Physical Pages Manager) in a cluster. 73 * The physical memory base address in all cluster is zero.63 * The physical memory base address in all clusters is zero. 74 64 * The physical memory size is NOT constrained to be smaller than 4 Gbytes. 65 ***************************************************************************************** 75 66 * @ ppm : pointer on physical pages manager. 76 67 * @ pages_nr : total physical memory size (number of 4 Kbytes pages). … … 86 77 * In normal use, you don't need to call it directly, as the recommanded way to get 87 78 * physical pages is to call the generic allocator defined in kmem.h. 79 ***************************************************************************************** 88 80 * @ order : ln2( number of 4 Kbytes pages) 89 81 * @ returns a pointer on the page descriptor if success / NULL otherwise … … 95 87 * In normal use, you do not need to call it directly, as the recommanded way to free 96 88 * physical pages is to call the generic allocator defined in kmem.h. 89 ***************************************************************************************** 97 90 * @ page : pointer to the page descriptor to be released 98 91 ****************************************************************************************/ … … 101 94 /***************************************************************************************** 102 95 * This function check if a page descriptor is valid. 96 ***************************************************************************************** 103 97 * @ page : pointer on a page descriptor 104 98 * @ returns true if valid / false otherwise. … … 108 102 /***************************************************************************************** 109 103 * Get the page base address from the page descriptor pointer. 104 ***************************************************************************************** 110 105 * @ page : pointer to page descriptor 111 106 * @ returns page base address … … 115 110 /***************************************************************************************** 116 111 * Get the page descriptor pointer from the page base address. 112 ***************************************************************************************** 117 113 * @ vaddr : page base address 118 114 * @ returns pointer on page descriptor … … 122 118 /***************************************************************************************** 123 119 * Get the PPN from the page descriptor pointer. 120 ***************************************************************************************** 124 121 * @ page : pointer to page descriptor 125 122 * @ returns physical page number … … 129 126 /***************************************************************************************** 130 127 * Get the page descriptor pointer from the PPN. 128 ***************************************************************************************** 131 129 * @ ppn : physical page number 132 130 * @ returns pointer on page descriptor … … 136 134 /***************************************************************************************** 137 135 * Get the page base address from the PPN. 136 ***************************************************************************************** 138 137 * @ ppn : physical page number 139 138 * @ returns page base address … … 143 142 /***************************************************************************************** 144 143 * Get the PPN from the page base address. 144 ***************************************************************************************** 145 145 * @ vaddr : page base address 146 146 * @ returns physical page number … … 150 150 /***************************************************************************************** 151 151 * This function prints the PPM allocator status. 152 ***************************************************************************************** 152 153 * @ ppm : pointer on PPM allocator. 154 * @ string : define context of display. 153 155 ****************************************************************************************/ 154 void ppm_print( ppm_t * ppm ); 156 void ppm_print( ppm_t * ppm, 157 char * string ); 155 158 156 159 /***************************************************************************************** 157 160 * This function checks PPM allocator consistency. 161 ***************************************************************************************** 158 162 * @ ppm : pointer on PPM allocator. 159 163 ****************************************************************************************/
Note: See TracChangeset
for help on using the changeset viewer.