source: trunk/kernel/mm/kcm.c

Last change on this file was 683, checked in by alain, 11 months ago

All modifications required to support the <tcp_chat> application
including error recovery in case of packet loss.A

File size: 26.1 KB
Line 
1/*
2 * kcm.c -  Kernel Cache Manager implementation.
3 *
4 * Author  Alain Greiner    (2016,2017,2018,2019,2020)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <kernel_config.h>
25#include <hal_kernel_types.h>
26#include <hal_special.h>
27#include <busylock.h>
28#include <list.h>
29#include <printk.h>
30#include <bits.h>
31#include <ppm.h>
32#include <thread.h>
33#include <page.h>
34#include <cluster.h>
35#include <kmem.h>
36#include <kcm.h>
37
38///////////////////////////////////////////////////////////////////////////////////////////
39//         global variables
40///////////////////////////////////////////////////////////////////////////////////////////
41
42extern chdev_directory_t    chdev_dir;          // allocated in kernel_init.c
43
44
45/////////////////////////////////////////////////////////////////////////////////////
46//        Local access functions
47/////////////////////////////////////////////////////////////////////////////////////
48
49//////////////////////////////////////////////////////////////////////////////////////
50// This static function is called by the kcm_alloc() function.
51// It returns a pointer on a block allocated from an active kcm_page.
52// It makes a panic if no block is available in the selected page.
53// It changes the page status as required.
54//////////////////////////////////////////////////////////////////////////////////////
55// @ kcm      : pointer on KCM allocator.
56// @ kcm_page : pointer on an active kcm_page.
57// @ return pointer on allocated block.
58/////////////////////////////////////////////////////////////////////////////////////
59static void * __attribute__((noinline)) kcm_get_block( kcm_t      * kcm,
60                                                       kcm_page_t * kcm_page )
61{
62    // initialise variables
63    uint32_t order  = kcm->order;
64    uint32_t count  = kcm_page->count;
65    uint64_t status = kcm_page->status;
66
67// check kcm page not full
68assert( __FUNCTION__, (count < 63) ,
69"kcm_page should not be full / cxy %x / order %d / count %d", local_cxy, order, count );
70
71    uint32_t index  = 1;
72    uint64_t mask   = (uint64_t)0x2;
73
74        // allocate first free block in kcm_page, update status,
75    // and count , compute index of allocated block in kcm_page
76    while( index <= 63 )
77    {
78        if( (status & mask) == 0 )   // block found
79        {
80            // update page count and status
81            kcm_page->status = status | mask;
82            kcm_page->count  = count + 1;
83            break;     
84        }
85       
86        index++;
87        mask <<= 1;
88    }
89
90    // switch page to full if last block
91    if( (count + 1) == 63 )
92    {
93                list_unlink( &kcm_page->list);
94                kcm->active_pages_nr--;
95
96        list_add_first( &kcm->full_root , &kcm_page->list );
97                kcm->full_pages_nr ++;
98    }
99
100        // compute return pointer
101        void * ptr = (void *)((intptr_t)kcm_page + (index << order));
102
103        return ptr;
104
105}  // end kcm_get_block()
106
107/////////////////////////////////////////////////////////////////////////////////////
108// This static function is called by the kcm_free() function.
109// It releases a previously allocated block to the relevant kcm_page.
110// It makes a panic if the released block is not allocated in this page.
111// It changes the kcm_page status as required.
112/////////////////////////////////////////////////////////////////////////////////////
113// @ kcm        : pointer on kcm allocator.
114// @ kcm_page   : pointer on kcm_page.
115// @ block_ptr  : pointer on block to be released.
116/////////////////////////////////////////////////////////////////////////////////////
117static void __attribute__((noinline)) kcm_put_block ( kcm_t      * kcm,
118                                                      kcm_page_t * kcm_page,
119                                                      void       * block_ptr )
120{
121    // initialise variables
122    uint32_t order  = kcm->order;
123    uint32_t count  = kcm_page->count;
124    uint64_t status = kcm_page->status;
125   
126        // compute block index from block pointer and kcm_page pointer
127        uint32_t index = ((intptr_t)block_ptr - (intptr_t)kcm_page) >> order;
128
129    // compute mask in bit vector
130    uint64_t mask = ((uint64_t)0x1) << index;
131
132    if( (status & mask) == 0 )
133    {
134        printk("\n[WARNING] in %s : block[%x,%x] not allocated / kcm %x / kcm_page %x\n",
135        __FUNCTION__, local_cxy, block_ptr, kcm, kcm_page );
136        kcm_remote_display( local_cxy , kcm );
137        return;
138    }
139
140    // update status & count in kcm_page
141        kcm_page->status = status & ~mask;
142        kcm_page->count  = count - 1;
143
144        // switch page to active if it was full
145        if( count == 63 )
146        {
147                list_unlink( &kcm_page->list );
148                kcm->full_pages_nr --;
149
150                list_add_last( &kcm->active_root, &kcm_page->list );
151                kcm->active_pages_nr ++;
152        }
153
154}  // kcm_put_block()
155
156/////////////////////////////////////////////////////////////////////////////////////
157// This static function  returns one non-full kcm_page with the following policy :
158// - if the "active_list" is non empty, it returns the first "active" page,
159//   without modifying the KCM state.
160// - if the "active_list" is empty, it allocates a new page from PPM, inserts
161//   this page in the active_list, and returns it.
162/////////////////////////////////////////////////////////////////////////////////////
163// @ kcm      : local pointer on local KCM allocator.
164// @ return pointer on a non-full kcm page if success / returns NULL if no memory.
165/////////////////////////////////////////////////////////////////////////////////////
166static kcm_page_t * __attribute__((noinline)) kcm_get_page( kcm_t * kcm )
167{
168    kcm_page_t * kcm_page;
169
170    uint32_t active_pages_nr = kcm->active_pages_nr;
171
172    if( active_pages_nr > 0 )       // return first active page
173    {
174        kcm_page = LIST_FIRST( &kcm->active_root , kcm_page_t , list );
175    }
176    else                            // allocate a new page from PPM
177        {
178        // get KCM order
179        uint32_t order = kcm->order;
180
181        // get one kcm_page from  PPM
182        page_t * page = ppm_alloc_pages( order + 6 - CONFIG_PPM_PAGE_ORDER );
183
184            if( page == NULL )
185            {
186
187#if DEBUG_KCM_ERROR
188printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n",
189__FUNCTION__ , local_cxy );
190#endif
191                    return NULL;
192        }
193
194            // get page base address
195            xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) );
196
197        // get local pointer on kcm_page
198            kcm_page = GET_PTR( base_xp );
199
200            // initialize kcm_page descriptor
201            kcm_page->status = 0;
202            kcm_page->count  = 0;
203            kcm_page->kcm    = kcm;
204            kcm_page->page   = page;
205
206            // introduce new page in KCM active_list
207            list_add_first( &kcm->active_root , &kcm_page->list );
208            kcm->active_pages_nr ++;
209        }
210
211        return kcm_page;
212
213}  // end kcm_get_page()
214
215//////////////////////////////
216void kcm_init( kcm_t    * kcm,
217                   uint32_t   order)
218{
219
220// check argument
221assert( __FUNCTION__, (order < CONFIG_PPM_PAGE_ORDER),
222"order argument %d too large", order );
223
224assert( __FUNCTION__, (order >= CONFIG_CACHE_LINE_ORDER),
225"order argument %d too small", order );
226
227        // initialize lock
228        remote_busylock_init( XPTR( local_cxy , &kcm->lock ) , LOCK_KCM_STATE );
229
230        // initialize KCM page lists
231        kcm->full_pages_nr   = 0;
232        kcm->active_pages_nr = 0;
233        list_root_init( &kcm->full_root );
234        list_root_init( &kcm->active_root );
235
236        // initialize order
237        kcm->order = order;
238 
239#if DEBUG_KCM
240if( (DEBUG_KCM_ORDER == order) && (DEBUG_KCM_CXY == local_cxy) )
241printk("\n[%s] cxy %x / order %d\n",
242__FUNCTION__, local_cxy, order );
243#endif
244
245}  // end kcm_init()
246
247///////////////////////////////
248void kcm_destroy( kcm_t * kcm )
249{
250        kcm_page_t   * kcm_page;
251
252    // build extended pointer on  KCM lock
253    xptr_t lock_xp = XPTR( local_cxy , &kcm->lock );
254
255        // get KCM lock
256        remote_busylock_acquire( lock_xp );
257
258        // release all full pages
259        while( list_is_empty( &kcm->full_root ) == false )
260        {
261                kcm_page = LIST_FIRST( &kcm->full_root , kcm_page_t , list );
262                list_unlink( &kcm_page->list );
263                ppm_free_pages( kcm_page->page );
264        }
265
266    // release all empty pages
267    while( list_is_empty( &kcm->active_root ) == false )
268        {
269                kcm_page = LIST_FIRST( &kcm->active_root , kcm_page_t , list );
270                list_unlink( &kcm_page->list );
271                ppm_free_pages( kcm_page->page );
272        }
273
274        // release KCM lock
275        remote_busylock_release( lock_xp );
276
277}  // end kcm_destroy()
278
279//////////////////////////////////
280void * kcm_alloc( uint32_t order )
281{
282    kcm_t      * kcm;
283        kcm_page_t * kcm_page;
284        void       * block;
285
286// check argument
287assert( __FUNCTION__, (order < CONFIG_PPM_PAGE_ORDER),
288"order argument %d too large", order );
289
290#if DEBUG_KCM
291uint32_t cycle = (uint32_t)hal_get_cycles();
292#endif
293
294    // smallest block size is a cache line
295    if (order < CONFIG_CACHE_LINE_ORDER) order = CONFIG_CACHE_LINE_ORDER;
296
297    // get local pointer on relevant KCM allocator
298    kcm = &LOCAL_CLUSTER->kcm[order - CONFIG_CACHE_LINE_ORDER];
299
300    // build extended pointer on local KCM lock
301    xptr_t lock_xp = XPTR( local_cxy , &kcm->lock );
302
303        // get KCM lock
304        remote_busylock_acquire( lock_xp );
305
306    // get a non-full kcm_page
307    kcm_page = kcm_get_page( kcm );
308
309    if( kcm_page == NULL )
310        {
311                remote_busylock_release( lock_xp );
312                return NULL;
313        }
314
315#if DEBUG_KCM
316if( (DEBUG_KCM_ORDER == order) && (DEBUG_KCM_CXY == local_cxy) && (DEBUG_KCM < cycle) )
317printk("\n[%s] enter / order %d / kcm[%x,%x] / nb_full %d / nb_active %d\n"
318"    page %x / status [%x,%x] / count %d\n",
319__FUNCTION__, order, local_cxy, kcm, kcm->full_pages_nr, kcm->active_pages_nr,
320kcm_page, (uint32_t)(kcm_page->status>>32), (uint32_t)(kcm_page->status), kcm_page->count );
321#endif
322
323        // allocate a block from selected active page
324        block = kcm_get_block( kcm , kcm_page );
325
326#if DEBUG_KCM
327if( (DEBUG_KCM_ORDER == order) && (DEBUG_KCM_CXY == local_cxy) && (DEBUG_KCM < cycle) )
328printk("\n[%s] exit  / order %d / kcm[%x,%x] / nb_full %d / nb_active %d\n"
329"    page %x / status [%x,%x] / count %d\n",
330__FUNCTION__, order, local_cxy, kcm, kcm->full_pages_nr, kcm->active_pages_nr,
331kcm_page, (uint32_t)(kcm_page->status>>32), (uint32_t)(kcm_page->status), kcm_page->count );
332#endif
333
334        // release lock
335        remote_busylock_release( lock_xp );
336
337        return block;
338
339}  // end kcm_alloc()
340
341///////////////////////////////
342void kcm_free( void    * block,
343               uint32_t  order )
344{
345    kcm_t      * kcm;
346        kcm_page_t * kcm_page;
347
348// check argument
349assert( __FUNCTION__, (block != NULL), 
350"block pointer cannot be NULL" );
351
352#if DEBUG_KCM
353uint32_t cycle = (uint32_t)hal_get_cycles();
354#endif
355
356    // smallest block size is a cache line
357    if (order < CONFIG_CACHE_LINE_ORDER) order = CONFIG_CACHE_LINE_ORDER;
358
359    // get local pointer on relevant KCM allocator
360    kcm = &LOCAL_CLUSTER->kcm[order - CONFIG_CACHE_LINE_ORDER];
361
362    // get local pointer on KCM page
363    intptr_t kcm_page_mask = (1 << (order + 6)) - 1; 
364        kcm_page = (kcm_page_t *)((intptr_t)block & ~kcm_page_mask);
365
366    // build extended pointer on local KCM lock
367    xptr_t lock_xp = XPTR( local_cxy , &kcm->lock );
368
369        // get lock
370        remote_busylock_acquire( lock_xp );
371
372#if DEBUG_KCM
373if( (DEBUG_KCM_ORDER == order) && (DEBUG_KCM_CXY == local_cxy) && (DEBUG_KCM < cycle) )
374printk("\n[%s] exit  / order %d / kcm[%x,%x] / nb_full %d / nb_active %d\n"
375"    page %x / status [%x,%x] / count %d\n",
376__FUNCTION__, order, local_cxy, kcm, kcm->full_pages_nr, kcm->active_pages_nr,
377kcm_page, (uint32_t)(kcm_page->status>>32), (uint32_t)(kcm_page->status), kcm_page->count );
378#endif
379
380        // release the block to the relevant page
381        kcm_put_block( kcm , kcm_page , block );
382
383#if DEBUG_KCM
384if( (DEBUG_KCM_ORDER == order) && (DEBUG_KCM_CXY == local_cxy) && (DEBUG_KCM < cycle) )
385printk("\n[%s] exit  / order %d / kcm[%x,%x] / nb_full %d / nb_active %d\n"
386"    page %x / status [%x,%x] / count %d\n",
387__FUNCTION__, order, local_cxy, kcm, kcm->full_pages_nr, kcm->active_pages_nr,
388kcm_page, (uint32_t)(kcm_page->status>>32), (uint32_t)(kcm_page->status), kcm_page->count );
389#endif
390
391        // release lock
392        remote_busylock_release( lock_xp );
393
394}  // end kcm_free()
395
396
397/////////////////////////////////////////////////////////////////////////////////////
398//        Remote access functions
399/////////////////////////////////////////////////////////////////////////////////////
400
401/////////////////////////////////////////////////////////////////////////////////////
402// This static function is called by the kcm_remote_alloc() function.
403// It can be called by any thread running in any cluster.
404// It returns a local pointer on a block allocated from an active kcm_page.
405// It makes a panic if no block available in the selected kcm_page.
406// It changes the page status as required.
407/////////////////////////////////////////////////////////////////////////////////////
408// @ kcm_cxy  : remote KCM cluster identifier.
409// @ kcm_ptr  : local pointer on remote KCM allocator.
410// @ kcm_page : local pointer on remote active kcm_page to use.
411// @ return a local pointer on the allocated block.
412/////////////////////////////////////////////////////////////////////////////////////
413static void * __attribute__((noinline)) kcm_remote_get_block( cxy_t        kcm_cxy,
414                                                              kcm_t      * kcm_ptr,
415                                                              kcm_page_t * kcm_page )
416{
417    uint32_t order  = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
418    uint32_t count  = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
419    uint64_t status = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
420
421// check kcm_page not full
422assert( __FUNCTION__, (count < 63) , 
423"kcm_page should not be full / cxy %x / order %d / count %d", kcm_cxy, order, count );
424
425    uint32_t index  = 1;
426    uint64_t mask   = (uint64_t)0x2;
427   
428        // allocate first free block in kcm_page, update status,
429    // and count , compute index of allocated block in kcm_page
430    while( index <= 63 )
431    {
432        if( (status & mask) == 0 )   // block found
433        {
434            hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , status | mask );
435            hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count  ) , count + 1 );
436            break;     
437        }
438       
439        index++;
440        mask <<= 1;
441    }
442
443        // swich the page to full if last block
444        if( (count + 1) == 63 )
445        {
446                list_remote_unlink( kcm_cxy , &kcm_page->list );
447                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , -1 );
448
449                list_remote_add_first( kcm_cxy , &kcm_ptr->full_root , &kcm_page->list );
450                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) , 1 );
451        }
452
453        // compute return pointer
454        void * ptr = (void *)((intptr_t)kcm_page + (index << order));
455
456        return ptr;
457
458}  // end kcm_remote_get_block()
459
460/////////////////////////////////////////////////////////////////////////////////////
461// This static function is called by the kcm_remote_free() function.
462// It can be called by any thread running in any cluster.
463// It releases a previously allocated block to the relevant kcm_page.
464// It changes the kcm_page status as required.
465/////////////////////////////////////////////////////////////////////////////////////
466// @ kcm_cxy   : remote KCM cluster identifier
467// @ kcm_ptr   : local pointer on remote KCM.
468// @ kcm_page  : local pointer on kcm_page.
469// @ block_ptr : pointer on block to be released.
470/////////////////////////////////////////////////////////////////////////////////////
471static void __attribute__((noinline)) kcm_remote_put_block ( cxy_t        kcm_cxy,
472                                                             kcm_t      * kcm_ptr,
473                                                             kcm_page_t * kcm_page,
474                                                             void       * block_ptr )
475{
476    uint32_t order  = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
477    uint32_t count  = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
478    uint64_t status = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
479   
480        // compute block index from block pointer and kcm_page pointer
481        uint32_t index = ((intptr_t)block_ptr - (intptr_t)kcm_page) >> order;
482
483    // compute mask in bit vector
484    uint64_t mask = ((uint64_t)0x1) << index;
485
486    if( (status & mask) == 0 )
487    {
488        printk("\n[WARNING] in %s : block[%x,%x] not allocated / kcm %x / kcm_page %x\n",
489        __FUNCTION__, kcm_cxy, block_ptr, kcm_ptr, kcm_page );
490        kcm_remote_display( kcm_cxy , kcm_ptr );
491        return;
492    }
493
494    // update status & count in kcm_page
495        hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , status & ~mask );
496        hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count  ) , count - 1 );
497
498        // switch the page to active if page was full
499        if( count == 63 )
500        {
501                list_remote_unlink( kcm_cxy , &kcm_page->list );
502                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) , -1 );
503
504                list_remote_add_last( kcm_cxy , &kcm_ptr->active_root, &kcm_page->list );
505                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , 1 );
506        }
507
508}  // end kcm_remote_put_block()
509
510/////////////////////////////////////////////////////////////////////////////////////
511// This static function can be called by any thread running in any cluster.
512// It gets one non-full KCM page from the remote KCM.
513// It allocates a page from remote PPM to populate the freelist, and initialises
514// the kcm_page descriptor when required.
515/////////////////////////////////////////////////////////////////////////////////////
516static kcm_page_t * __attribute__((noinline)) kcm_remote_get_page( cxy_t    kcm_cxy,
517                                                                   kcm_t  * kcm_ptr )
518{
519    kcm_page_t * kcm_page;    // local pointer on remote KCM page
520
521    uint32_t active_pages_nr = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) );
522
523    if( active_pages_nr > 0 )       // return first active page
524    {
525        kcm_page = LIST_REMOTE_FIRST( kcm_cxy , &kcm_ptr->active_root , kcm_page_t , list );
526    }
527    else                            // allocate a new page from PPM
528        {
529        // get KCM order
530        uint32_t order = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ));
531
532        // get one kcm_page from PPM
533        xptr_t page_xp = ppm_remote_alloc_pages( kcm_cxy,
534                                                 order + 6 - CONFIG_PPM_PAGE_ORDER );
535            if( page_xp == XPTR_NULL )
536            {
537
538#if DEBUG_KCM_ERROR
539printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n",
540__FUNCTION__ , kcm_cxy );
541#endif
542                    return NULL;
543        }
544
545            // get extended pointer on allocated buffer
546            xptr_t base_xp = ppm_page2base( page_xp );
547
548        // get local pointer on kcm_page
549            kcm_page = GET_PTR( base_xp );
550
551            // initialize kcm_page descriptor
552            hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count )  , 0 );
553            hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , 0 );
554            hal_remote_spt( XPTR( kcm_cxy , &kcm_page->kcm )    , kcm_ptr );
555            hal_remote_spt( XPTR( kcm_cxy , &kcm_page->page )   , GET_PTR( page_xp ) );
556
557            // introduce new page in remote KCM active_list
558            list_remote_add_first( kcm_cxy , &kcm_ptr->active_root , &kcm_page->list );
559            hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , 1 );
560        }
561
562        return kcm_page;
563
564}  // end kcm_remote_get_page()
565
566//////////////////////////////////////////
567void * kcm_remote_alloc( cxy_t    kcm_cxy,
568                         uint32_t order )
569{
570    kcm_t      * kcm_ptr;
571    kcm_page_t * kcm_page;
572    void       * block_ptr;
573
574// check kcm_cxy argument
575assert( __FUNCTION__, cluster_is_active( kcm_cxy ),
576"cluster %x not active", kcm_cxy );
577
578// check order argument
579assert( __FUNCTION__, (order < CONFIG_PPM_PAGE_ORDER) ,
580"order argument %d too large", order );
581
582    // smallest size is a cache line
583    if( order < CONFIG_CACHE_LINE_ORDER ) order = CONFIG_CACHE_LINE_ORDER;
584
585    // get local pointer on relevant KCM allocator (same in all clusters)
586    kcm_ptr = &LOCAL_CLUSTER->kcm[order - 6];
587
588    // build extended pointer on remote KCM lock
589    xptr_t lock_xp = XPTR( kcm_cxy , &kcm_ptr->lock );
590
591        // get lock
592        remote_busylock_acquire( lock_xp );
593
594    // get a non-full kcm_page
595    kcm_page = kcm_remote_get_page( kcm_cxy , kcm_ptr );
596
597    if( kcm_page == NULL )
598        {
599                remote_busylock_release( lock_xp );
600                return NULL;
601        }
602
603#if DEBUG_KCM
604uint32_t cycle     = (uint32_t)hal_get_cycles();
605uint32_t nb_full   = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ));
606uint32_t nb_active = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ));
607uint64_t status    = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ));
608uint32_t count     = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ));
609#endif
610
611
612#if DEBUG_KCM
613if( (DEBUG_KCM_ORDER == order) && (DEBUG_KCM_CXY == local_cxy) && (DEBUG_KCM < cycle) )
614printk("\n[%s] enter / order %d / kcm[%x,%x] / nb_full %d / nb_active %d\n"
615"    page %x / status [%x,%x] / count %d\n",
616__FUNCTION__, order, kcm_cxy, kcm_ptr, nb_full, nb_active,
617kcm_page, (uint32_t)(status>>32), (uint32_t)(status), kcm_page->count );
618#endif
619
620        // get a block from selected active page
621        block_ptr = kcm_remote_get_block( kcm_cxy , kcm_ptr , kcm_page );
622
623#if DEBUG_KCM
624if( (DEBUG_KCM_ORDER == order) && (DEBUG_KCM_CXY == local_cxy) && (DEBUG_KCM < cycle) )
625printk("\n[%s] exit  / order %d / kcm[%x,%x] / nb_full %d / nb_active %d\n"
626"    page %x / status [%x,%x] / count %d\n",
627__FUNCTION__, order, kcm_cxy, kcm_ptr, nb_full, nb_active,
628kcm_page, (uint32_t)(status>>32), (uint32_t)(status), kcm_page->count );
629#endif
630
631        // release lock
632        remote_busylock_release( lock_xp );
633
634        return block_ptr;
635
636}  // end kcm_remote_alloc()
637
638////////////////////////////////////////
639void kcm_remote_free( cxy_t     kcm_cxy,
640                      void    * block_ptr,
641                      uint32_t  order )
642{
643        kcm_t      * kcm_ptr;
644        kcm_page_t * kcm_page;
645
646// check kcm_cxy argument
647assert( __FUNCTION__, cluster_is_active( kcm_cxy ),
648"cluster %x not active", kcm_cxy );
649
650// check block_ptr argument
651assert( __FUNCTION__, (block_ptr != NULL),
652"block pointer cannot be NULL" );
653
654// check order argument
655assert( __FUNCTION__, (order < CONFIG_PPM_PAGE_ORDER) ,
656"order argument %d too large", order );
657
658    // smallest block size is a cache line
659    if (order < CONFIG_CACHE_LINE_ORDER) order = CONFIG_CACHE_LINE_ORDER;
660
661    // get local pointer on relevant KCM allocator (same in all clusters)
662    kcm_ptr = &LOCAL_CLUSTER->kcm[order - CONFIG_CACHE_LINE_ORDER];
663
664    // get local pointer on KCM page
665    intptr_t kcm_page_mask = (1 << (order + 6)) - 1; 
666        kcm_page = (kcm_page_t *)((intptr_t)block_ptr & ~kcm_page_mask);
667
668#if DEBUG_KCM
669uint32_t cycle     = (uint32_t)hal_get_cycles();
670uint32_t nb_full   = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ));
671uint32_t nb_active = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ));
672uint64_t status    = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ));
673uint32_t count     = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ));
674#endif
675
676    // build extended pointer on remote KCM lock
677    xptr_t lock_xp = XPTR( kcm_cxy , &kcm_ptr->lock );
678
679        // get lock
680        remote_busylock_acquire( lock_xp );
681
682#if DEBUG_KCM
683if( (DEBUG_KCM_ORDER == order) && (DEBUG_KCM_CXY == local_cxy) && (DEBUG_KCM < cycle) )
684printk("\n[%s] enter / order %d / kcm[%x,%x] / nb_full %d / nb_active %d\n"
685"    page %x / status [%x,%x] / count %d\n",
686__FUNCTION__, order, kcm_cxy, kcm_ptr, nb_full, nb_active,
687kcm_page, (uint32_t)(status>>32), (uint32_t)(status), kcm_page->count );
688#endif
689
690        // release the block to the relevant page
691        kcm_remote_put_block( kcm_cxy , kcm_ptr , kcm_page , block_ptr );
692
693#if DEBUG_KCM
694if( (DEBUG_KCM_ORDER == order) && (DEBUG_KCM_CXY == local_cxy) && (DEBUG_KCM < cycle) )
695printk("\n[%s] exit  / order %d / kcm[%x,%x] / nb_full %d / nb_active %d\n"
696"    page %x / status [%x,%x] / count %d\n",
697__FUNCTION__, order, kcm_cxy, kcm_ptr, nb_full, nb_active,
698kcm_page, (uint32_t)(status>>32), (uint32_t)(status), kcm_page->count );
699#endif
700
701        // release lock
702        remote_busylock_release( lock_xp );
703
704}  // end kcm_remote_free
705
706/////////////////////////////////////////
707void kcm_remote_display( cxy_t   kcm_cxy,
708                         kcm_t * kcm_ptr )
709{
710    list_entry_t * iter;
711    kcm_page_t   * kcm_page;
712    uint64_t       status;
713    uint32_t       count;
714
715    // get pointers on TXT0 chdev
716    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
717    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
718    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
719
720    // get extended pointer on remote TXT0 chdev lock
721    xptr_t    txt0_lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
722
723    // get TXT0 lock
724    remote_busylock_acquire( txt0_lock_xp );
725
726    uint32_t order           = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order) );
727    uint32_t full_pages_nr   = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) );
728    uint32_t active_pages_nr = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) );
729
730        nolock_printk("*** KCM : cxy %x / order %d / full_pages_nr %d / active_pages_nr %d\n",
731        kcm_cxy, order, full_pages_nr, active_pages_nr );
732
733    if( active_pages_nr )
734    {
735        LIST_REMOTE_FOREACH( kcm_cxy , &kcm_ptr->active_root , iter )
736        {
737            kcm_page = LIST_ELEMENT( iter , kcm_page_t , list );
738            status   = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
739            count    = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
740
741            nolock_printk("- active page %x / status (%x,%x) / count %d\n",
742            kcm_page, (uint32_t)( status<< 32 ), (uint32_t)( status ), count );
743        }
744    }
745
746    if( full_pages_nr )
747    {
748        LIST_REMOTE_FOREACH( kcm_cxy , &kcm_ptr->full_root , iter )
749        {
750            kcm_page = LIST_ELEMENT( iter , kcm_page_t , list );
751            status   = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
752            count    = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
753
754            nolock_printk("- full page %x / status (%x,%x) / count %d\n",
755            kcm_page, (uint32_t)( status<< 32 ), (uint32_t)( status ), count );
756        }
757    }
758
759    // release TXT0 lock
760    remote_busylock_release( txt0_lock_xp );
761
762}  // end kcm remote_display()
Note: See TracBrowser for help on using the repository browser.