Changeset 50 for trunk/kernel/mm
- Timestamp:
- Jun 26, 2017, 3:15:11 PM (7 years ago)
- Location:
- trunk/kernel/mm
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/mm/kcm.c
r20 r50 3 3 * 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016 )5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 41 41 // It changes the page status if required. 42 42 ////////////////////////////////////////////////////////////////////////////////////// 43 // @ kcm : pointer on kcm allocator.44 // @ ptr: pointer on active kcm page to use.43 // @ kcm : pointer on kcm allocator. 44 // @ kcm_page : pointer on active kcm page to use. 45 45 ///////////////////////////////////////////////////////////////////////////////////// 46 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" ); 47 kcm_page_t * kcm_page ) 48 { 49 kcm_dmsg("\n[INFO] %s : enters for %s / page %x / count = %d / active = %d\n", 50 __FUNCTION__ , kmem_type_str( kcm->type ) , 51 (intptr_t)kcm_page , kcm_page->count , kcm_page->active ); 52 53 assert( kcm_page->active , __FUNCTION__ , "kcm_page should be active" ); 50 54 51 55 // get first block available 52 int32_t index = bitmap_ffs( page->bitmap , kcm->blocks_nr );53 54 assert( (index != -1) , __FUNCTION__ , "kcm 56 int32_t index = bitmap_ffs( kcm_page->bitmap , kcm->blocks_nr ); 57 58 assert( (index != -1) , __FUNCTION__ , "kcm_page should not be full" ); 55 59 56 60 // allocate block 57 bitmap_clear( page->bitmap , index );58 59 // increase page refcount60 page->refcount ++;61 62 // change the page to busyno more free block in page63 if( page->refcount >= kcm->blocks_nr )64 { 65 66 list_unlink( & page->list);61 bitmap_clear( kcm_page->bitmap , index ); 62 63 // increase kcm_page count 64 kcm_page->count ++; 65 66 // change the kcm_page to busy if no more free block in page 67 if( kcm_page->count >= kcm->blocks_nr ) 68 { 69 kcm_page->active = 0; 70 list_unlink( &kcm_page->list); 67 71 kcm->active_pages_nr --; 68 72 69 list_add_first( &kcm->busy_root , & page->list);73 list_add_first( &kcm->busy_root , &kcm_page->list); 70 74 kcm->busy_pages_nr ++; 71 page->busy = 1; 72 } 73 74 return (page->base + index * kcm->block_size ); 75 kcm_page->busy = 1; 76 } 77 78 // compute return pointer 79 void * ptr = (void *)((intptr_t)kcm_page + CONFIG_KCM_SLOT_SIZE 80 + (index * kcm->block_size) ); 81 82 kcm_dmsg("\n[INFO] %s : allocated one block %s / ptr = %x / page = %x / count = %d\n", 83 __FUNCTION__ , kmem_type_str( kcm->type ) , (uint32_t)ptr , 84 (intptr_t)kcm_page , kcm_page->count ); 85 86 return ptr; 75 87 76 88 } // kcm_get_block() … … 78 90 ///////////////////////////////////////////////////////////////////////////////////// 79 91 // This static function releases a previously allocated block. 80 // It changes the page status if required.92 // It changes the kcm_page status if required. 81 93 ///////////////////////////////////////////////////////////////////////////////////// 82 94 // @ kcm : pointer on kcm allocator. … … 86 98 void * ptr ) 87 99 { 88 kcm_page_t * page;100 kcm_page_t * kcm_page; 89 101 uint32_t index; 90 102 91 page = (kcm_page_t*)((intptr_t)ptr & CONFIG_PPM_PAGE_MASK); 92 index = ((uint8_t*)ptr - page->base) / kcm->block_size; 93 94 bitmap_set( page->bitmap , index ); 95 page->refcount --; 103 // compute pointer on kcm_page from block pointer 104 kcm_page = (kcm_page_t*)((intptr_t)ptr & ~CONFIG_PPM_PAGE_MASK); 105 106 // compute block index from block pointer 107 index = ((uint8_t *)ptr - (uint8_t *)kcm_page - CONFIG_KCM_SLOT_SIZE) / kcm->block_size; 108 109 bitmap_set( kcm_page->bitmap , index ); 110 kcm_page->count --; 96 111 97 112 // change the page to active if it was busy 98 if( page->busy )99 { 100 page->busy = 0;101 list_unlink( & page->list );113 if( kcm_page->busy ) 114 { 115 kcm_page->busy = 0; 116 list_unlink( &kcm_page->list ); 102 117 kcm->busy_pages_nr --; 103 118 104 list_add_last( &kcm->active_root, & page->list );119 list_add_last( &kcm->active_root, &kcm_page->list ); 105 120 kcm->active_pages_nr ++; 106 page->active = 1;107 } 108 109 // change the page to free if last block in active page110 if( ( page->active) && (page->refcount == 0) )111 { 112 page->active = 0;113 list_unlink( & page->list);121 kcm_page->active = 1; 122 } 123 124 // change the kcm_page to free if last block in active page 125 if( (kcm_page->active) && (kcm_page->count == 0) ) 126 { 127 kcm_page->active = 0; 128 list_unlink( &kcm_page->list); 114 129 kcm->active_pages_nr --; 115 130 116 list_add_first( &kcm->free_root , & page->list);131 list_add_first( &kcm->free_root , &kcm_page->list); 117 132 kcm->free_pages_nr ++; 118 133 } … … 121 136 ///////////////////////////////////////////////////////////////////////////////////// 122 137 // This static function allocates one page from PPM. It initializes 123 // the KCM-page descriptor, and introduces the newpage into freelist.138 // the kcm_page descriptor, and introduces the new kcm_page into freelist. 124 139 ///////////////////////////////////////////////////////////////////////////////////// 125 140 static error_t freelist_populate( kcm_t * kcm ) 126 141 { 127 142 page_t * page; 128 kcm_page_t * ptr;143 kcm_page_t * kcm_page; 129 144 kmem_req_t req; 130 145 … … 143 158 144 159 // get page base address 145 ptr =ppm_page2base( page );160 kcm_page = (kcm_page_t *)ppm_page2base( page ); 146 161 147 162 // initialize KCM-page descriptor 148 bitmap_set_range( ptr->bitmap , 0 , kcm->blocks_nr ); 149 150 ptr->busy = 0; 151 ptr->active = 0; 152 ptr->refcount = 0; 153 ptr->base = (uint8_t*)ptr + kcm->block_size; 154 ptr->kcm = kcm; 155 ptr->page = page; 163 bitmap_set_range( kcm_page->bitmap , 0 , kcm->blocks_nr ); 164 165 kcm_page->busy = 0; 166 kcm_page->active = 0; 167 kcm_page->count = 0; 168 kcm_page->kcm = kcm; 169 kcm_page->page = page; 156 170 157 171 // introduce new page in free-list 158 list_add_first( &kcm->free_root , & ptr->list );172 list_add_first( &kcm->free_root , &kcm_page->list ); 159 173 kcm->free_pages_nr ++; 160 174 … … 170 184 { 171 185 error_t error; 172 kcm_page_t * page;186 kcm_page_t * kcm_page; 173 187 174 188 // get a new page from PPM if freelist empty … … 179 193 } 180 194 181 // get first KCM page from freelist and change its status to active182 page = LIST_FIRST( &kcm->free_root, kcm_page_t , list );183 list_unlink( & page->list );195 // get first KCM page from freelist and unlink it 196 kcm_page = LIST_FIRST( &kcm->free_root, kcm_page_t , list ); 197 list_unlink( &kcm_page->list ); 184 198 kcm->free_pages_nr --; 185 199 186 return page;200 return kcm_page; 187 201 188 202 } // freelist_get() … … 193 207 uint32_t type ) 194 208 { 195 uint32_t blocks_nr; 196 uint32_t block_size; 197 uint32_t remaining;209 // the kcm_page descriptor mut fit in the KCM slot 210 assert( (sizeof(kcm_page_t) <= CONFIG_KCM_SLOT_SIZE) , 211 __FUNCTION__ , "KCM slot too small\n" ); 198 212 199 213 // initialize lock … … 211 225 list_root_init( &kcm->active_root ); 212 226 213 // initialize block size and number of blocks per page 214 block_size = ARROUND_UP( kmem_type_size( type ) , 64 ); 215 blocks_nr = CONFIG_PPM_PAGE_SIZE / block_size; 216 remaining = CONFIG_PPM_PAGE_SIZE % block_size; 217 blocks_nr = (remaining >= sizeof(kcm_page_t)) ? blocks_nr : blocks_nr - 1; 218 219 kcm->blocks_nr = blocks_nr; 227 // initialize block size 228 uint32_t block_size = ARROUND_UP( kmem_type_size( type ) , CONFIG_KCM_SLOT_SIZE ); 220 229 kcm->block_size = block_size; 221 230 231 // initialize number of blocks per page 232 uint32_t blocks_nr = (CONFIG_PPM_PAGE_SIZE - CONFIG_KCM_SLOT_SIZE) / block_size; 233 kcm->blocks_nr = blocks_nr; 234 222 235 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 );236 __FUNCTION__ , kmem_type_str( type ) , kcm->block_size , kcm->blocks_nr ); 224 237 225 238 } // kcm_init() … … 228 241 void kcm_destroy( kcm_t * kcm ) 229 242 { 230 kcm_page_t * page;243 kcm_page_t * kcm_page; 231 244 list_entry_t * iter; 232 245 … … 237 250 LIST_FOREACH( &kcm->free_root , iter ) 238 251 { 239 page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );252 kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list ); 240 253 list_unlink( iter ); 241 254 kcm->free_pages_nr --; 242 ppm_free_pages( page->page );255 ppm_free_pages( kcm_page->page ); 243 256 } 244 257 … … 246 259 LIST_FOREACH( &kcm->active_root , iter ) 247 260 { 248 page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );261 kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list ); 249 262 list_unlink( iter ); 250 263 kcm->free_pages_nr --; 251 ppm_free_pages( page->page );264 ppm_free_pages( kcm_page->page ); 252 265 } 253 266 … … 255 268 LIST_FOREACH( &kcm->busy_root , iter ) 256 269 { 257 page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );270 kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list ); 258 271 list_unlink( iter ); 259 272 kcm->free_pages_nr --; 260 ppm_free_pages( page->page );273 ppm_free_pages( kcm_page->page ); 261 274 } 262 275 … … 269 282 void * kcm_alloc( kcm_t * kcm ) 270 283 { 271 kcm_page_t * page;284 kcm_page_t * kcm_page; 272 285 void * ptr = NULL; // pointer on block 273 286 … … 278 291 if( list_is_empty( &kcm->active_root ) ) // no active page => get one 279 292 { 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 293 // get a page from free list 284 page = freelist_get( kcm ); 285 if( page == NULL ) return NULL; 294 kcm_page = freelist_get( kcm ); 295 296 if( kcm_page == NULL ) return NULL; 286 297 287 298 // insert page in active list 288 list_add_first( &kcm->active_root , & page->list );299 list_add_first( &kcm->active_root , &kcm_page->list ); 289 300 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 301 kcm_page->active = 1; 302 303 kcm_dmsg("\n[INFO] %s : enters for type %s at cycle %d / new page = %x / count = %d\n", 304 __FUNCTION__ , kmem_type_str( kcm->type ) , hal_time_stamp() , 305 (intptr_t)kcm_page , kcm_page->count ); 306 307 } 308 else // get first page from active list 309 { 297 310 // get page pointer from active list 298 page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list ); 311 kcm_page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list ); 312 313 kcm_dmsg("\n[INFO] %s : enters for type %s at cycle %d / page = %x / count = %d\n", 314 __FUNCTION__ , kmem_type_str( kcm->type ) , hal_time_stamp() , 315 (intptr_t)kcm_page , kcm_page->count ); 299 316 } 300 317 301 318 // get a block from selected active page 302 319 // cannot fail, as an active page cannot be full... 303 ptr = kcm_get_block( kcm , page );320 ptr = kcm_get_block( kcm , kcm_page ); 304 321 305 322 // release lock 306 spinlock_unlock(&kcm->lock); 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 ); 323 spinlock_unlock( &kcm->lock ); 310 324 311 325 return ptr; 312 326 313 } // kcm_alloc()327 } // end kcm_allo() 314 328 315 329 /////////////////////////// 316 330 void kcm_free( void * ptr ) 317 331 { 318 kcm_page_t * page;332 kcm_page_t * kcm_page; 319 333 kcm_t * kcm; 320 334 321 if( ptr == NULL ) return;322 323 page = (kcm_page_t *)((intptr_t)ptr &CONFIG_PPM_PAGE_MASK);324 kcm =page->kcm;335 assert( (ptr != NULL) , __FUNCTION__ , "pointer cannot be NULL" ); 336 337 kcm_page = (kcm_page_t *)((intptr_t)ptr & ~CONFIG_PPM_PAGE_MASK); 338 kcm = kcm_page->kcm; 325 339 326 340 // get lock … … 332 346 // release lock 333 347 spinlock_unlock( &kcm->lock ); 334 } 348 349 } // end kcm_free() 335 350 336 351 //////////////////////////// -
trunk/kernel/mm/kcm.h
r23 r50 36 36 * This structure defines a generic Kernel Cache Manager, that is a block allocator, 37 37 * for fixed size objects. It exists a specific KCM allocator for each object type. 38 * The actual allocated block size is the smallest multiple of 64 bytes that can 39 * contain one single object. 38 * The actual allocated block size is the smallest multiple of the KCM slot, that 39 * contain one single object. The KCM slot is typically 64 bytes, as it must be large 40 * enough to store the kcm_page descriptor, defined below. 40 41 * The various KCM allocators themselves are not statically allocated in the cluster 41 42 * manager, but are dynamically allocated when required, using the embedded KCM … … 46 47 { 47 48 spinlock_t lock; /*! protect exclusive access to allocator */ 48 uint32_t block_size; /*! actual block size (bytes)*/49 uint32_t blocks_nr; /*! number of blocks per page*/49 uint32_t block_size; /*! rounded block size (bytes) */ 50 uint32_t blocks_nr; /*! max number of blocks per page */ 50 51 51 52 list_entry_t active_root; /*! root of active pages list */ … … 64 65 /**************************************************************************************** 65 66 * This structure defines a KCM-page descriptor. 66 * A KCM-page c an contain up to (CONFIG_PPM_PAGE_SIZE / CONFIG_CACHE_LINE_SIZE) blocks.67 * A KCM-page contains at most (CONFIG_PPM_PAGE_SIZE / CONFIG_KCM_SLOT_SIZE) blocks. 67 68 * This kcm page descriptor is stored in the first slot of the page. 68 69 ***************************************************************************************/ … … 70 71 typedef struct kcm_page_s 71 72 { 72 uint32_t bitmap[BITMAP_SIZE(CONFIG_KCM_BLOCKS_MAX)]; 73 uint8_t * base; /*! pointer on first block in page */ 74 kcm_t * kcm; /*! owner KCM allocator */ 73 uint32_t bitmap[2]; /*! at most 64 blocks in a single page */ 75 74 list_entry_t list; /*! [active / busy / free] list member */ 75 kcm_t * kcm; /*! pointer on kcm allocator */ 76 76 page_t * page; /*! pointer on the physical page descriptor */ 77 uint8_t refcount; /*! number of allocated blocks */ 78 uint8_t busy; /*! page busy if non zero */ 79 uint8_t active; /*! page active if non zero */ 80 uint8_t unused; /*! */ 77 uint32_t count; /*! number of allocated blocks */ 78 uint32_t busy; /*! page busy if non zero */ 79 uint32_t active; /*! page active if non zero */ 81 80 } 82 81 kcm_page_t; -
trunk/kernel/mm/kmem.c
r23 r50 103 103 else if( type == KMEM_SEM ) return sizeof( remote_sem_t ); 104 104 else if( type == KMEM_CONDVAR ) return sizeof( remote_condvar_t ); 105 106 else if( type == KMEM_512_BYTES ) return 512; 107 105 108 else return 0; 106 109 } … … 130 133 else if( type == KMEM_SEM ) return "KMEM_SEM"; 131 134 else if( type == KMEM_SEM ) return "KMEM_CONDVAR"; 135 136 else if( type == KMEM_512_BYTES ) return "KMEM_512_BYTES"; 137 132 138 else return "undefined"; 133 139 } … … 193 199 assert( (type < KMEM_TYPES_NR) , __FUNCTION__ , "illegal KMEM request type" ); 194 200 195 kmem_dmsg("\n[INFO] %s : enters in cluster %x for type %s / size %d\n",196 __FUNCTION__ , local_cxy , kmem_type_str( type ) , size);201 kmem_dmsg("\n[INFO] %s : enters in cluster %x for type %s\n", 202 __FUNCTION__ , local_cxy , kmem_type_str( type ) ); 197 203 198 204 // analyse request type … … 202 208 ptr = (void *)ppm_alloc_pages( size ); 203 209 204 // reset page if requ ired210 // reset page if requested 205 211 if( flags & AF_ZERO ) page_zero( (page_t *)ptr ); 206 212 … … 217 223 if( flags & AF_ZERO ) memset( ptr , 0 , size ); 218 224 219 kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x\n", 220 __FUNCTION__, local_cxy , kmem_type_str( type ) , (intptr_t)ptr ); 225 kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x / size = %d\n", 226 __FUNCTION__, local_cxy , kmem_type_str( type ) , 227 (intptr_t)ptr , req->size ); 221 228 } 222 229 else // KCM allocator … … 237 244 if( flags & AF_ZERO ) memset( ptr , 0 , kmem_type_size( type ) ); 238 245 239 kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x\n", 240 __FUNCTION__, local_cxy , kmem_type_str( type ) , (intptr_t)ptr ); 246 kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x / size = %d\n", 247 __FUNCTION__, local_cxy , kmem_type_str( type ) , 248 (intptr_t)ptr , kmem_type_size( type ) ); 241 249 } 242 250 -
trunk/kernel/mm/kmem.h
r23 r50 59 59 KMEM_CONDVAR = 19, /*! remote_condvar_t */ 60 60 61 KMEM_TYPES_NR = 19, 61 KMEM_512_BYTES = 20, /*! 512 bytes aligned */ 62 63 KMEM_TYPES_NR = 21, 62 64 }; 63 65 -
trunk/kernel/mm/ppm.c
r18 r50 3 3 * 4 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016 )5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 48 48 } 49 49 50 //////////////////////////////////////////// 51 inline void * ppm_page2base( page_t * page ) 50 51 52 ///////////////////////////////////////////// 53 inline void * ppm_page2vaddr( page_t * page ) 52 54 { 53 55 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 54 return (void*)((page - ppm->pages_tbl) << CONFIG_PPM_PAGE_SHIFT);55 } 56 57 //////////////////////////////////////////// 58 inline page_t * ppm_ base2page( void * base)56 return ppm->vaddr_base + ((page - ppm->pages_tbl) << CONFIG_PPM_PAGE_SHIFT); 57 } 58 59 ////////////////////////////////////////////// 60 inline page_t * ppm_vaddr2page( void * vaddr ) 59 61 { 60 62 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 61 return (ppm->pages_tbl + (((uint32_t)base ) >> CONFIG_PPM_PAGE_SHIFT)); 62 } 63 return ppm->pages_tbl + (vaddr - ppm->vaddr_base); 64 } 65 66 63 67 64 68 ////////////////////////////////////////// … … 76 80 } 77 81 82 83 78 84 /////////////////////////////////////// 79 inline void * ppm_ppn2base( ppn_t ppn ) 80 { 81 return (void*)( ppn << CONFIG_PPM_PAGE_SHIFT ); 82 } 83 84 //////////////////////////////////////// 85 inline ppn_t ppm_base2ppn( void * base ) 86 { 87 return (ppn_t)( (uint32_t)base >> CONFIG_PPM_PAGE_SHIFT ); 88 } 89 90 ////////////////////////////////////////////////// 91 static void ppm_free_pages_nolock( page_t * page ) 85 inline void * ppm_ppn2vaddr( ppn_t ppn ) 86 { 87 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 88 return ppm->vaddr_base + (ppn << CONFIG_PPM_PAGE_SHIFT); 89 } 90 91 ////////////////////////////////////////// 92 inline ppn_t ppm_vaddr2ppn( void * vaddr ) 93 { 94 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 95 return ( (ppm->vaddr_base - vaddr) >> CONFIG_PPM_PAGE_SHIFT ); 96 } 97 98 99 100 /////////////////////////////////////////// 101 void ppm_free_pages_nolock( page_t * page ) 92 102 { 93 103 page_t * buddy; // searched buddy page descriptor … … 95 105 page_t * current; // current (merged) page descriptor 96 106 uint32_t current_index; // current (merged) page index 97 uint32_t current_order; // current (merge t) page order107 uint32_t current_order; // current (merged) page order 98 108 99 109 ppm_t * ppm = &LOCAL_CLUSTER->ppm; … … 120 130 list_unlink( &buddy->list ); 121 131 ppm->free_pages_nr[current_order] --; 122 ppm->total_free_pages -= (1 << current_order);123 132 124 133 // merge buddy with current … … 134 143 list_add_first( &ppm->free_pages_root[current_order] , ¤t->list ); 135 144 ppm->free_pages_nr[current_order] ++; 136 ppm->total_free_pages += (1 << current_order);137 145 138 146 } // end ppm_free_pages_nolock() 139 140 //////////////////////////////141 void ppm_init( ppm_t * ppm,142 uint32_t pages_nr, // total pages number143 uint32_t pages_offset ) // occupied pages144 {145 uint32_t i;146 147 // set signature148 ppm->signature = PPM_SIGNATURE;149 150 // initialize lock protecting the free_pages[] array151 spinlock_init( &ppm->free_lock );152 153 // initialize free_pages[] array as empty154 ppm->total_free_pages = 0;155 for( i = 0 ; i < CONFIG_PPM_MAX_ORDER ; i++ )156 {157 list_root_init( &ppm->free_pages_root[i] );158 ppm->free_pages_nr[i] = 0;159 }160 161 // initialize dirty_list as empty162 list_root_init( &ppm->dirty_root );163 164 // initialize pointer on page descriptors array165 ppm->pages_tbl = (page_t*)( pages_offset << CONFIG_PPM_PAGE_SHIFT );166 167 // compute size of pages descriptor array rounded to an integer number of pages168 uint32_t bytes = ARROUND_UP( pages_nr * sizeof(page_t), CONFIG_PPM_PAGE_SIZE );169 170 // compute number of pages required to store page descriptor array171 uint32_t pages_array = bytes >> CONFIG_PPM_PAGE_SHIFT;172 173 // compute total number of reserved pages (kernel code & pages_tbl[])174 uint32_t reserved_pages = pages_offset + pages_array;175 176 // set pages numbers177 ppm->pages_nr = pages_nr;178 ppm->pages_offset = reserved_pages;179 180 // initialises all page descriptors in pages_tbl[]181 for( i = 0 ; i < pages_nr ; i++ )182 {183 page_init( &ppm->pages_tbl[i] );184 185 // TODO optimisation : make only a partial init [AG]186 // complete the initialisation when page is allocated [AG]187 // ppm->pages_tbl[i].flags = 0;188 }189 190 // - set PG_RESERVED flag for reserved pages (kernel code & pages_tbl[])191 // - release all other pages to populate the free lists192 for( i = 0 ; i < reserved_pages ; i++)193 {194 page_set_flag( &ppm->pages_tbl[i] , PG_RESERVED );195 }196 for( i = reserved_pages ; i < pages_nr ; i++ )197 {198 ppm_free_pages_nolock( &ppm->pages_tbl[i] );199 200 // TODO optimisation : decompose this enormous set of small pages201 // to a set big pages with various order values202 }203 204 // check consistency205 ppm_assert_order( ppm );206 207 } // end ppm_init()208 147 209 148 //////////////////////////////////////////// … … 216 155 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 217 156 218 assert( (ppm->signature == PPM_SIGNATURE) , __FUNCTION__ , "PPM non initialised" );219 220 157 assert( (order < CONFIG_PPM_MAX_ORDER) , __FUNCTION__ , "illegal order argument" ); 221 158 … … 224 161 ppm_dmsg("\n[INFO] %s : enters / order = %d\n", 225 162 __FUNCTION__ , order ); 226 227 #if( CONFIG_PPM_DEBUG )228 ppm_print( ppm , "before allocation" );229 #endif230 163 231 164 // take lock protecting free lists … … 252 185 253 186 // update free-lists after removing a block 254 ppm->total_free_pages -= (1 << current_order);255 187 ppm->free_pages_nr[current_order] --; 256 188 current_size = (1 << current_order); … … 268 200 list_add_first( &ppm->free_pages_root[current_order] , &remaining_block->list ); 269 201 ppm->free_pages_nr[current_order] ++; 270 ppm->total_free_pages += (1 << current_order);271 202 } 272 203 … … 282 213 __FUNCTION__ , (uint32_t)ppm_page2base( block ) , order ); 283 214 284 #if CONFIG_PPM_DEBUG285 ppm_print( ppm , "after allocation" );286 #endif287 288 215 return block; 289 216 } // end pmm_alloc-pages() … … 315 242 spinlock_lock( &ppm->free_lock ); 316 243 317 printk("\n*** PPM state in cluster %x %s : pages = %d / offset = %d / free = %d***\n",318 local_cxy , string , ppm->pages_nr , ppm->pages_offset , ppm->total_free_pages);244 printk("\n*** PPM in cluster %x : %d pages / &pages_tbl = %x / vaddr_base = %x ***\n", 245 local_cxy , ppm->pages_nr , (intptr_t)ppm->pages_tbl , (intptr_t)ppm->vaddr_base ); 319 246 320 247 for( order = 0 ; order < CONFIG_PPM_MAX_ORDER ; order++ ) -
trunk/kernel/mm/ppm.h
r18 r50 32 32 #include <page.h> 33 33 34 #define PPM_SIGNATURE 0xBABEF00D35 34 36 35 /***************************************************************************************** 37 36 * This structure defines the Physical Memory Manager in a cluster. 38 * In all clusters, the physical memory bank starts at address 0. 39 * The segments kcode and kdata are mapped in the first "offset" pages. 40 * The physical page descriptors array is implemented just after this offset zone. 41 * The main service provided by the PMM is the dynamic allocation of physical pages. 37 * In all clusters, the physical memory bank starts at local physical address 0. 38 * The size of this local physical memory is defined by the <pages_nr> field in the 39 * boot_info structure. It is split in three parts: 40 * - the "kernel_code" section contains the kernel code, loaded by the boot-loader. 41 * It starts at PPN = 0 and the size is defined by the <pages_offset> field in the 42 * boot_info structure. 43 * - the "pages_tbl" section contains the physical page descriptors array. It starts 44 * at PPN = pages_offset, and it contains one entry per small physical page in cluster. 45 * It is created and initialized by the hal_ppm_create() function. "the 46 * - The "kernel_heap" section contains all physical pages that are are not in the 47 * in the kernel_code and pages_tbl sections, and that have not been reserved by the 48 * architecture specific bootloader. The reserved pages are defined in the boot_info 49 * structure. 50 * 51 * The main service provided by the PMM is the dynamic allocation of physical pages 52 * from the "kernel_heap" section. 42 53 * This low-level allocator implements the buddy algorithm: an allocated block is 43 * isan integer number n of 4 Kbytes pages, and n (called order) is a power of 2.54 * an integer number n of 4 Kbytes pages, and n (called order) is a power of 2. 44 55 ****************************************************************************************/ 56 45 57 typedef struct ppm_s 46 58 { 47 uint32_t signature; /*! set when initialised */ 48 spinlock_t free_lock; /*! lock protecting free_pages[] array */ 59 spinlock_t free_lock; /*! lock protecting free_pages[] lists */ 49 60 list_entry_t free_pages_root[CONFIG_PPM_MAX_ORDER]; /*! roots of free lists */ 50 61 uint32_t free_pages_nr[CONFIG_PPM_MAX_ORDER]; /*! numbers of free pages */ 51 uint32_t total_free_pages; /*! total number of free pages */52 62 page_t * pages_tbl; /*! pointer on page descriptors array */ 53 uint32_t pages_nr; /*! total number of 4 Kbytes physical page */ 54 uint32_t pages_offset; /*! allocated pages for kcode & kdata */ 55 uint32_t pages_desc; /*! allocated pages for pages_tbl[] array */ 56 spinlock_t dirty_lock; /*! lock protecting the dirty list */ 63 uint32_t pages_nr; /*! total number of small physical page */ 64 spinlock_t dirty_lock; /*! lock protecting the dirty pages list */ 57 65 list_entry_t dirty_root; /*! root of dirty pages list */ 66 void * vaddr_base; /*! pointer on local physical memory base */ 58 67 } 59 68 ppm_t; … … 80 89 * @ order : ln2( number of 4 Kbytes pages) 81 90 * @ returns a pointer on the page descriptor if success / NULL otherwise 82 ************************************************************************************** **/91 **************************************************************************************à))**/ 83 92 page_t * ppm_alloc_pages( uint32_t order ); 84 93 … … 93 102 94 103 /***************************************************************************************** 95 * This function check if a page descriptor is valid.104 * This function check if a page descriptor pointer is valid. 96 105 ***************************************************************************************** 97 106 * @ page : pointer on a page descriptor … … 101 110 102 111 /***************************************************************************************** 103 * Get the page baseaddress from the page descriptor pointer.112 * Get the page virtual address from the page descriptor pointer. 104 113 ***************************************************************************************** 105 114 * @ page : pointer to page descriptor 106 * @ returns page base address115 * @ returns virtual address of page itself. 107 116 ****************************************************************************************/ 108 inline void* ppm_page2 base( page_t * page );117 inline void* ppm_page2vaddr( page_t * page ); 109 118 110 119 /***************************************************************************************** 111 * Get the page descriptor pointer from the page baseaddress.120 * Get the page descriptor pointer from the page virtual address. 112 121 ***************************************************************************************** 113 * @ vaddr : page baseaddress122 * @ vaddr : page virtual address 114 123 * @ returns pointer on page descriptor 115 124 ****************************************************************************************/ 116 inline page_t * ppm_ base2page( void * vaddr );125 inline page_t * ppm_vaddr2page( void * vaddr ); 117 126 118 127 /***************************************************************************************** … … 133 142 134 143 /***************************************************************************************** 135 * Get the page baseaddress from the PPN.144 * Get the page virtual address from the PPN. 136 145 ***************************************************************************************** 137 146 * @ ppn : physical page number 138 * @ returns page base address147 * @ returns page virtual address. 139 148 ****************************************************************************************/ 140 inline void* ppm_ppn2 base( ppn_t ppn );149 inline void* ppm_ppn2vaddr( ppn_t ppn ); 141 150 142 151 /***************************************************************************************** 143 * Get the PPN from the page baseaddress.152 * Get the PPN from the page virtual address. 144 153 ***************************************************************************************** 145 * @ vaddr : page baseaddress146 * @ returns physical page number 154 * @ vaddr : page virtual address 155 * @ returns physical page number. 147 156 ****************************************************************************************/ 148 inline ppn_t ppm_ base2ppn( void * base );157 inline ppn_t ppm_vaddr2ppn( void * base ); 149 158 150 159 /***************************************************************************************** -
trunk/kernel/mm/vmm.c
r23 r50 936 936 offset = (uint32_t)( ((intptr_t)ptr) & CONFIG_PPM_PAGE_MASK ); 937 937 938 if( local_cxy == GET_CXY( process->ref_xp) ) 938 if( local_cxy == GET_CXY( process->ref_xp) ) // calling process is reference process 939 939 { 940 940 error = vmm_get_pte( process, vpn , &attr , &ppn ); 941 941 } 942 else // use a RPC942 else // calling process is not reference process 943 943 { 944 944 cxy_t ref_cxy = GET_CXY( process->ref_xp );
Note: See TracChangeset
for help on using the changeset viewer.