source: trunk/hal/tsar_mips32/core/hal_gpt.c @ 632

Last change on this file since 632 was 632, checked in by alain, 5 years ago

This version replace the RPC by direct remote memory access
for physical pages allacation/release.
It is commited before being tested.

File size: 37.1 KB
RevLine 
[1]1/*
2 * hal_gpt.c - implementation of the Generic Page Table API for TSAR-MIPS32
3 *
[445]4 * Author   Alain Greiner (2016,2017,2018)
[1]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
[457]24#include <hal_kernel_types.h>
[1]25#include <hal_gpt.h>
26#include <hal_special.h>
27#include <printk.h>
28#include <bits.h>
29#include <process.h>
30#include <kmem.h>
31#include <thread.h>
32#include <cluster.h>
33#include <ppm.h>
34#include <page.h>
35
36////////////////////////////////////////////////////////////////////////////////////////
[401]37// This define the masks for the TSAR MMU PTE attributes (from TSAR MMU specification)
[1]38////////////////////////////////////////////////////////////////////////////////////////
39
[629]40#define TSAR_PTE_MAPPED         0x80000000
41#define TSAR_PTE_SMALL          0x40000000
42#define TSAR_PTE_LOCAL          0x20000000
43#define TSAR_PTE_REMOTE         0x10000000
44#define TSAR_PTE_CACHABLE       0x08000000
45#define TSAR_PTE_WRITABLE       0x04000000
46#define TSAR_PTE_EXECUTABLE     0x02000000
47#define TSAR_PTE_USER           0x01000000
48#define TSAR_PTE_GLOBAL         0x00800000
49#define TSAR_PTE_DIRTY          0x00400000
[1]50
[629]51#define TSAR_PTE_COW            0x00000001       // only for small pages
52#define TSAR_PTE_SWAP           0x00000004       // only for small pages
53#define TSAR_PTE_LOCKED         0x00000008       // only for small pages
[1]54
55////////////////////////////////////////////////////////////////////////////////////////
56//       TSAR MMU related macros  (from the TSAR MMU specification)
57// - IX1  on 11 bits
58// - IX2  on  9 bits
59// - PPN  on 28 bits
60////////////////////////////////////////////////////////////////////////////////////////
61
62#define TSAR_MMU_IX1_WIDTH                 11
63#define TSAR_MMU_IX2_WIDTH                 9
64#define TSAR_MMU_PPN_WIDTH                 28
65
[401]66#define TSAR_MMU_PTE1_ATTR_MASK            0xFFC00000
67#define TSAR_MMU_PTE1_PPN_MASK             0x0007FFFF
68
[1]69#define TSAR_MMU_IX1_FROM_VPN( vpn )       ((vpn >> 9) & 0x7FF)
70#define TSAR_MMU_IX2_FROM_VPN( vpn )       (vpn & 0x1FF)
71
[315]72#define TSAR_MMU_PTBA_FROM_PTE1( pte1 )    (pte1 & 0x0FFFFFFF)
73#define TSAR_MMU_PPN_FROM_PTE1( pte1 )     ((pte1 & 0x0007FFFF)<<9)
[1]74#define TSAR_MMU_ATTR_FROM_PTE1( pte1 )    (pte1 & 0xFFC00000)
75
76#define TSAR_MMU_PPN_FROM_PTE2( pte2 )     (pte2 & 0x0FFFFFFF)
77#define TSAR_MMU_ATTR_FROM_PTE2( pte2 )    (pte2 & 0xFFC000FF)
78
[401]79///////////////////////////////////////////////////////////////////////////////////////
80// This static function translates the GPT attributes to the TSAR attributes
81///////////////////////////////////////////////////////////////////////////////////////
82static inline uint32_t gpt2tsar( uint32_t gpt_attr )
83{
84    uint32_t tsar_attr = 0;
85
[629]86    if( gpt_attr & GPT_MAPPED     ) tsar_attr |= TSAR_PTE_MAPPED;
87    if( gpt_attr & GPT_SMALL      ) tsar_attr |= TSAR_PTE_SMALL;
88    if( gpt_attr & GPT_WRITABLE   ) tsar_attr |= TSAR_PTE_WRITABLE;
89    if( gpt_attr & GPT_EXECUTABLE ) tsar_attr |= TSAR_PTE_EXECUTABLE;
90    if( gpt_attr & GPT_CACHABLE   ) tsar_attr |= TSAR_PTE_CACHABLE; 
91    if( gpt_attr & GPT_USER       ) tsar_attr |= TSAR_PTE_USER;
92    if( gpt_attr & GPT_DIRTY      ) tsar_attr |= TSAR_PTE_DIRTY;
93    if( gpt_attr & GPT_ACCESSED   ) tsar_attr |= TSAR_PTE_LOCAL;
94    if( gpt_attr & GPT_GLOBAL     ) tsar_attr |= TSAR_PTE_GLOBAL;
95    if( gpt_attr & GPT_COW        ) tsar_attr |= TSAR_PTE_COW;
96    if( gpt_attr & GPT_SWAP       ) tsar_attr |= TSAR_PTE_SWAP;
97    if( gpt_attr & GPT_LOCKED     ) tsar_attr |= TSAR_PTE_LOCKED;
[401]98
99    return tsar_attr;
100}
101
102///////////////////////////////////////////////////////////////////////////////////////
103// This static function translates the TSAR attributes to the GPT attributes
104///////////////////////////////////////////////////////////////////////////////////////
105static inline uint32_t tsar2gpt( uint32_t tsar_attr )
106{
107    uint32_t gpt_attr = 0;
108
[629]109    if( tsar_attr & TSAR_PTE_MAPPED     ) gpt_attr |= GPT_MAPPED;
110    if( tsar_attr & TSAR_PTE_MAPPED     ) gpt_attr |= GPT_READABLE;
111    if( tsar_attr & TSAR_PTE_SMALL      ) gpt_attr |= GPT_SMALL;
112    if( tsar_attr & TSAR_PTE_WRITABLE   ) gpt_attr |= GPT_WRITABLE;
113    if( tsar_attr & TSAR_PTE_EXECUTABLE ) gpt_attr |= GPT_EXECUTABLE;
114    if( tsar_attr & TSAR_PTE_CACHABLE   ) gpt_attr |= GPT_CACHABLE; 
115    if( tsar_attr & TSAR_PTE_USER       ) gpt_attr |= GPT_USER;
116    if( tsar_attr & TSAR_PTE_DIRTY      ) gpt_attr |= GPT_DIRTY;
117    if( tsar_attr & TSAR_PTE_LOCAL      ) gpt_attr |= GPT_ACCESSED;
118    if( tsar_attr & TSAR_PTE_REMOTE     ) gpt_attr |= GPT_ACCESSED;
119    if( tsar_attr & TSAR_PTE_GLOBAL     ) gpt_attr |= GPT_GLOBAL;
120    if( tsar_attr & TSAR_PTE_COW        ) gpt_attr |= GPT_COW;
121    if( tsar_attr & TSAR_PTE_SWAP       ) gpt_attr |= GPT_SWAP;
122    if( tsar_attr & TSAR_PTE_LOCKED     ) gpt_attr |= GPT_LOCKED;
[401]123
124    return gpt_attr;
125}
126
[632]127///////////////////////////////////////////////////////////////////////////////////////
128// The blocking hal_gpt_lock_pte() function implements a busy-waiting policy to get
129// exclusive access to a specific GPT entry.
130// - when non zero, the following variable defines the max number of iterations
131//   in the busy waiting loop.
132// - when zero, the watchdog mechanism is deactivated.
133///////////////////////////////////////////////////////////////////////////////////////
134
135#define GPT_LOCK_WATCHDOG   100000
136
[1]137/////////////////////////////////////
138error_t hal_gpt_create( gpt_t * gpt )
139{
140        page_t   * page;
[315]141    xptr_t     page_xp;
[1]142
[587]143    thread_t * this = CURRENT_THREAD;
144
[443]145#if DEBUG_HAL_GPT_CREATE
[587]146uint32_t cycle = (uint32_t)hal_get_cycles();
[443]147if( DEBUG_HAL_GPT_CREATE < cycle )
[611]148printk("\n[%s] : thread[%x,%x] enter / cycle %d\n", 
[587]149__FUNCTION__, this->process->pid, this->trdid, cycle );
[432]150#endif
[406]151
[623]152// check page size
153assert( (CONFIG_PPM_PAGE_SIZE == 4096) , "for TSAR, the page size must be 4 Kbytes\n" );
[1]154
155    // allocates 2 physical pages for PT1
156        kmem_req_t req;
157        req.type  = KMEM_PAGE;
158        req.size  = 1;                     // 2 small pages
159        req.flags = AF_KERNEL | AF_ZERO;
160        page = (page_t *)kmem_alloc( &req );
161
[406]162        if( page == NULL ) 
[1]163    {
[587]164        printk("\n[PANIC] in %s : no memory for PT1 / process %x / cluster %x\n",
165        __FUNCTION__, this->process->pid, local_cxy );
[1]166        return ENOMEM;
[406]167    }
[1]168
169    // initialize generic page table descriptor
[315]170    page_xp   = XPTR( local_cxy , page );
171        gpt->ptr  = GET_PTR( ppm_page2base( page_xp ) );
172        gpt->ppn  = ppm_page2ppn( page_xp );
173
[443]174#if DEBUG_HAL_GPT_CREATE
[587]175cycle = (uint32_t)hal_get_cycles();
[443]176if( DEBUG_HAL_GPT_CREATE < cycle )
[611]177printk("\n[%s] : thread[%x,%x] exit / cycle %d\n", 
[587]178__FUNCTION__, this->process->pid, this->trdid, cycle );
[432]179#endif
[406]180
[1]181        return 0;
[406]182
[1]183} // end hal_gpt_create()
184
185///////////////////////////////////
186void hal_gpt_destroy( gpt_t * gpt )
187{
188        uint32_t     ix1;
189        uint32_t     ix2;
190        uint32_t   * pt1;
191    uint32_t     pte1;
192    ppn_t        pt2_ppn;
193    uint32_t   * pt2;
194    uint32_t     attr;
195        kmem_req_t   req;
196
[443]197#if DEBUG_HAL_GPT_DESTROY
[587]198uint32_t   cycle = (uint32_t)hal_get_cycles();
199thread_t * this  = CURRENT_THREAD;
[443]200if( DEBUG_HAL_GPT_DESTROY < cycle )
[611]201printk("\n[%s] : thread[%x,%x] enter / cycle %d\n", 
[587]202__FUNCTION__, this->process->pid, this->trdid, cycle );
[443]203#endif
204
[1]205    // get pointer on PT1
206    pt1 = (uint32_t *)gpt->ptr;
207
208    // scan the PT1
209        for( ix1 = 0 ; ix1 < 2048 ; ix1++ )
210        {
211        pte1 = pt1[ix1];
[629]212
213                if( (pte1 & TSAR_PTE_MAPPED) != 0 )  // PTE1 mapped
[1]214        {
[629]215            if( (pte1 & TSAR_PTE_SMALL) == 0 )   // BIG page
[1]216            {
[629]217                printk("\n[WARNING] in %s : mapped big page / ix1 %x\n", 
218                __FUNCTION__ , ix1 );
[1]219            }
[629]220            else                             // PT2 exist
[1]221            {
[315]222                // get local pointer on PT2
[1]223                pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
[315]224                xptr_t base_xp = ppm_ppn2base( pt2_ppn );
[587]225                pt2     = GET_PTR( base_xp );
[1]226
[629]227                // scan the PT2
228                for( ix2 = 0 ; ix2 < 512 ; ix2++ )
[1]229                {
[629]230                    attr = TSAR_MMU_ATTR_FROM_PTE2( pt2[2 * ix2] );
231
232                    if( (attr & TSAR_PTE_MAPPED) != 0 )  // PTE2 mapped
[1]233                    {
[629]234                        printk("\n[WARNING] in %s : mapped small page / ix1 %x / ix2 %x\n", 
235                        __FUNCTION__ , ix1, ix2 );
[1]236                    }
237                }
238
[629]239                // release the page allocated for the PT2
[1]240                req.type = KMEM_PAGE;
[315]241                req.ptr  = GET_PTR( ppm_base2page( XPTR(local_cxy , pt2 ) ) );
[1]242                kmem_free( &req );
243            }
244        }
245        }
246
247    // release the PT1
248    req.type = KMEM_PAGE;
[315]249    req.ptr  = GET_PTR( ppm_base2page( XPTR(local_cxy , pt1 ) ) );
[1]250    kmem_free( &req );
251
[443]252#if DEBUG_HAL_GPT_DESTROY
[587]253cycle = (uint32_t)hal_get_cycles();
[443]254if( DEBUG_HAL_GPT_DESTROY < cycle )
[611]255printk("\n[%s] : thread[%x,%x] exit / cycle %d\n", 
[587]256__FUNCTION__, this->process->pid, this->trdid, cycle );
[443]257#endif
258
[1]259} // end hal_gpt_destroy()
260
[629]261/*
262
263/////////////////////////////////////////////////////////////////////////////////////
264// This static function can be used for debug.
265/////////////////////////////////////////////////////////////////////////////////////
266static void hal_gpt_display( process_t * process )
[1]267{
[407]268    gpt_t    * gpt;
[1]269        uint32_t   ix1;
270        uint32_t   ix2;
271        uint32_t * pt1;
272    uint32_t   pte1;
273    ppn_t      pt2_ppn;
274    uint32_t * pt2;
275    uint32_t   pte2_attr;
276    ppn_t      pte2_ppn;
[406]277    vpn_t      vpn;
[1]278
[623]279// check argument
280assert( (process != NULL) , "NULL process pointer\n");
[1]281
[407]282    // get pointer on gpt
283    gpt = &(process->vmm.gpt);
284
285    // get pointer on PT1
[1]286    pt1 = (uint32_t *)gpt->ptr;
287
[623]288    printk("\n***** Tsar Page Table for process %x : &gpt = %x / &pt1 = %x\n\n",
[407]289    process->pid , gpt , pt1 );
[406]290
[1]291    // scan the PT1
292        for( ix1 = 0 ; ix1 < 2048 ; ix1++ )
293        {
294        pte1 = pt1[ix1];
[629]295                if( (pte1 & TSAR_PTE_MAPPED) != 0 )
[1]296        {
[629]297            if( (pte1 & TSAR_PTE_SMALL) == 0 )  // BIG page
[1]298            {
[406]299                vpn = ix1 << 9;
300                printk(" - BIG   : vpn = %x / pt1[%d] = %X\n", vpn , ix1 , pte1 );
[1]301            }
302            else                           // SMALL pages
303            {
304                pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
[315]305                xptr_t base_xp = ppm_ppn2base ( pt2_ppn );
[587]306                pt2     = GET_PTR( base_xp );
[1]307
308                // scan the PT2
309                    for( ix2 = 0 ; ix2 < 512 ; ix2++ )
310                {
311                    pte2_attr = TSAR_MMU_ATTR_FROM_PTE2( pt2[2 * ix2] );
312                    pte2_ppn  = TSAR_MMU_PPN_FROM_PTE2( pt2[2 * ix2 + 1] );
[406]313
[629]314                            if( (pte2_attr & TSAR_PTE_MAPPED) != 0 )
[1]315                    {
[406]316                        vpn = (ix1 << 9) | ix2;
[408]317                        printk(" - SMALL : vpn %X / ppn %X / attr %X\n",
318                        vpn , pte2_ppn , tsar2gpt(pte2_attr) );
[1]319                    }
320                }
321            }
322        }
323        }
[407]324} // end hal_gpt_display()
[1]325
[629]326*/
[1]327
[632]328////////////////////////////////////////////
329error_t hal_gpt_lock_pte( xptr_t     gpt_xp,
330                          vpn_t      vpn,
331                          uint32_t * attr,
332                          ppn_t    * ppn )
[1]333{
[632]334    uint32_t          * pt1_ptr;         // local pointer on PT1 base
335    xptr_t              ptd1_xp;         // extended pointer on PT1[x1] entry
336        uint32_t            ptd1;            // value of PT1[x1] entry
[629]337
[632]338    xptr_t              page_xp;
[629]339
[632]340        ppn_t               pt2_ppn;         // PPN of page containing PT2
341    uint32_t          * pt2_ptr;         // local pointer on PT2 base
342        xptr_t              pte2_xp;         // extended pointer on PT2[ix2].attr
343    uint32_t            pte2_attr;       // PT2[ix2].attr current value   
344    uint32_t            pte2_ppn;        // PT2[ix2].ppn current value   
345        bool_t              atomic;
346
347#if GPT_LOCK_WATCHDOG
348    uint32_t count;
349#endif
350
351    // get cluster and local pointer on GPT
352    cxy_t   gpt_cxy = GET_CXY( gpt_xp );
353    gpt_t * gpt_ptr = GET_PTR( gpt_xp );
354
355#if DEBUG_HAL_GPT_LOCK_PTE
356thread_t * this  = CURRENT_THREAD;
357uint32_t   cycle = (uint32_t)hal_get_cycles();
358if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
359printk("\n[%s] : thread[%x,%x] enters / vpn %x in cluster %x / cycle %d\n", 
360__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, cycle );
361#endif
362
363    // get indexes in PTI & PT2 from vpn
364    uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
365    uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
366
367    // get local pointer on PT1
368    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
369
370    // build extended pointer on PTD1 == PT1[ix1]
371        ptd1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
372
373    // get current PT1 entry value
[630]374    ptd1 = hal_remote_l32( ptd1_xp );
[629]375
[632]376    // If PTD1 is unmapped and unlocked, try to atomically lock this PT1 entry.
377    // This PTD1 lock prevent multiple concurrent PT2 allocations
378    // - only the thread that successfully locked the PTD1 allocates a new PT2
379    //   and updates the PTD1
380    // - all other threads simply wait until the missing PTD1 is mapped.
381
382    if( ptd1 == 0 ) 
[629]383        {
[632]384        // try to atomically lock the PTD1 to prevent concurrent PT2 allocations
[630]385        atomic = hal_remote_atomic_cas( ptd1_xp,
386                                        ptd1,
387                                        ptd1 | TSAR_PTE_LOCKED );
[632]388        if( atomic ) 
389                {
390            // allocate one 4 Kbytes physical page for PT2
391            page_xp = ppm_remote_alloc_pages( gpt_cxy , 0 );
[629]392
[632]393            if( page_xp == NULL )
[629]394            {
[632]395                printk("\n[ERROR] in %s : cannot allocate memory for PT2\n", __FUNCTION__ );
396                return -1;
[629]397            }
398
399            // get the PT2 PPN
400            pt2_ppn = ppm_page2ppn( page_xp );
401
[630]402            // build  PTD1
403            ptd1 = TSAR_PTE_MAPPED | TSAR_PTE_SMALL | pt2_ppn;
[629]404
405            // set the PTD1 value in PT1
[632]406            // this unlocks the PTD1
[630]407            hal_remote_s32( ptd1_xp , ptd1 );
[629]408            hal_fence();
409
[632]410#if (DEBUG_HAL_GPT_LOCK_PTE & 1)
411if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
412printk("\n[%s] : thread[%x,%x] allocates a new PT2 for vpn %x in cluster %x\n", 
413__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy );
[629]414#endif
[632]415
416        }  // end if atomic
417    }  // end if (ptd1 == 0)
418
419    // wait until PTD1 is mapped by another thread
420    while( (ptd1 & TSAR_PTE_MAPPED) == 0 )
[629]421    {
[632]422        ptd1 = hal_remote_l32( ptd1_xp );
[629]423
[632]424#if GPT_LOCK_WATCHDOG
425if( count > GPT_LOCK_WATCHDOG ) 
426{
427    thread_t * thread = CURRENT_THREAD;
428    printk("\n[PANIC] in %s : thread[%x,%x] waiting PTD1 / vpn %x / cxy %x / %d iterations\n",
429    __FUNCTION__, thread->process->pid, thread->trdid, vpn, gpt_cxy, count );
430    hal_core_sleep();
431}
432count++;
[629]433#endif
434
435    }
436
[632]437// check ptd1 because only small page can be locked
438assert( (ptd1 & TSAR_PTE_SMALL), "cannot lock a big page\n");
[629]439
[632]440#if (DEBUG_HAL_GPT_LOCK_PTE & 1)
441if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
442printk("\n[%s] : thread[%x,%x] get ptd1 %x for vpn %x in cluster %x\n", 
443__FUNCTION__, this->process->pid, this->trdid, ptd1, vpn, gpt_cxy );
444#endif
[629]445
[632]446    // get pointer on PT2 base from PTD1
447        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( ptd1 );
448        pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
[629]449
[632]450    // build extended pointers on PT2[ix2].attr 
451    pte2_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
[629]452
[632]453    // wait until PTE2 atomically set using a remote CAS
454    do
[629]455    {
456
[632]457#if GPT_LOCK_WATCHDOG
458count = 0;
459#endif
[629]460
[632]461        // wait until PTE lock released by the current owner
[629]462        do
463                {
[632]464                        pte2_attr = hal_remote_l32( pte2_xp );
465
466#if GPT_LOCK_WATCHDOG
467if( count > GPT_LOCK_WATCHDOG ) 
468{
469    thread_t * thread = CURRENT_THREAD;
470    printk("\n[PANIC] in %s : thread[%x,%x] waiting PTE2 / vpn %x / cxy %x / %d iterations\n",
471    __FUNCTION__, thread->process->pid, thread->trdid, vpn, gpt_cxy, count );
472    hal_core_sleep();
473}
474count++;
475#endif
476     
[629]477                }
478        while( (pte2_attr & TSAR_PTE_LOCKED) != 0 );
479
[632]480        // try to atomically set the TSAR_PTE_LOCKED attribute   
481                atomic = hal_remote_atomic_cas( pte2_xp,
[629]482                                        pte2_attr,
483                                        (pte2_attr | TSAR_PTE_LOCKED) );
484        }
485    while( atomic == 0 );
486
487    // get PTE2.ppn
[632]488    pte2_ppn = hal_remote_l32( pte2_xp + 4 );
[629]489
490#if DEBUG_HAL_GPT_LOCK_PTE
[632]491cycle = (uint32_t)hal_get_cycles();
[629]492if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
[632]493printk("\n[%s] : thread[%x,%x] exit / vpn %x in cluster %x / attr %x / ppn %x / cycle %d\n", 
494__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, pte2_attr, pte2_ppn, cycle );
[629]495#endif
496   
497    // return PPN and GPT attributes
[632]498    *ppn  = pte2_ppn & ((1<<TSAR_MMU_PPN_WIDTH)-1);
[629]499    *attr = tsar2gpt( pte2_attr );
500        return 0;
501
502}  // end hal_gpt_lock_pte()
503
504////////////////////////////////////////
505void hal_gpt_unlock_pte( xptr_t  gpt_xp,
506                         vpn_t   vpn )
507{
508    uint32_t * pt1_ptr;         // local pointer on PT1 base
[632]509    xptr_t     ptd1_xp;         // extended pointer on PT1[ix1]
510        uint32_t   ptd1;            // value of PT1[ix1] entry
[629]511
512        ppn_t      pt2_ppn;         // PPN of page containing PT2
513    uint32_t * pt2_ptr;         // PT2 base address
[632]514        xptr_t     pte2_xp;         // extended pointer on PT2[ix2].attr
515        uint32_t   pte2_attr;       // PTE2 attribute
[629]516
517    // get cluster and local pointer on GPT
518    cxy_t   gpt_cxy = GET_CXY( gpt_xp );
519    gpt_t * gpt_ptr = GET_PTR( gpt_xp );
520
[632]521#if DEBUG_HAL_GPT_LOCK_PTE
522thread_t * this  = CURRENT_THREAD;
523uint32_t   cycle = (uint32_t)hal_get_cycles();
524if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
525printk("\n[%s] : thread[%x,%x] enters for vpn %x in cluster %x / cycle %d\n", 
526__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, cycle );
527#endif
528
[629]529    // compute indexes in P1 and PT2
530    uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
531    uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
532
533    // get local pointer on PT1
534    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
535
[632]536    // build extended pointer on PTD1 == PT1[ix1]
537        ptd1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
[629]538
[632]539    // get current ptd1 value
540    ptd1 = hal_remote_l32( ptd1_xp );
[629]541
[632]542// check PTD1 attributes
543assert( ((ptd1 & TSAR_PTE_MAPPED) != 0), "unmapped PTE1\n");
544assert( ((ptd1 & TSAR_PTE_SMALL ) != 0), "big page PTE1\n");
[629]545
[632]546    // get pointer on PT2 base from PTD1
547        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( ptd1 );
[629]548        pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
549
550    // build extended pointers on PT2[ix2].attr 
[632]551    pte2_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
[629]552
553    // get PT2[ix2].attr
[632]554    pte2_attr = hal_remote_l32( pte2_xp );
[629]555
[632]556// check PTE2 attributes
557assert( ((pte2_attr & TSAR_PTE_MAPPED) != 0), "unmapped PTE2\n");
558assert( ((pte2_attr & TSAR_PTE_LOCKED) != 0), "unlocked PTE2\n");
[629]559
[632]560    // reset TSAR_PTE_LOCKED attribute
561    hal_remote_s32( pte2_xp , pte2_attr & ~TSAR_PTE_LOCKED );
562
[629]563#if DEBUG_HAL_GPT_LOCK_PTE
[632]564cycle = (uint32_t)hal_get_cycles();
[629]565if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
[632]566printk("\n[%s] : thread[%x,%x] unlocks vpn %x in cluster %x / cycle %d\n", 
567__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, cycle );
[629]568#endif
[632]569
[629]570}  // end hal_gpt_unlock_pte()
571
[632]572
[629]573///////////////////////////////////////
574void hal_gpt_set_pte( xptr_t    gpt_xp,
575                      vpn_t     vpn,
576                      uint32_t  attr, 
577                      ppn_t     ppn )
578{
[587]579    cxy_t               gpt_cxy;             // target GPT cluster
580    gpt_t             * gpt_ptr;             // target GPT local pointer
[629]581
582    uint32_t          * pt1_ptr;             // local pointer on PT1 base
[587]583        xptr_t              pte1_xp;             // extended pointer on PT1 entry
584        uint32_t            pte1;                // PT1 entry value if PTE1
[1]585
[401]586        ppn_t               pt2_ppn;             // PPN of PT2
[629]587        uint32_t          * pt2_ptr;             // local pointer on PT2 base
588    xptr_t              pte2_attr_xp;        // extended pointer on PT2[ix2].attr
589    xptr_t              pte2_ppn_xp;         // extended pointer on PT2[ix2].ppn
590    uint32_t            pte2_attr;           // current value of PT2[ix2].attr
[1]591
[401]592    uint32_t            ix1;                 // index in PT1
593    uint32_t            ix2;                 // index in PT2
[1]594
[401]595    uint32_t            tsar_attr;           // PTE attributes for TSAR MMU
[629]596        uint32_t            small;               // requested PTE is for a small page
[401]597
[587]598    // get cluster and local pointer on GPT
599    gpt_cxy = GET_CXY( gpt_xp );
600    gpt_ptr = GET_PTR( gpt_xp );
601
[1]602    // compute indexes in PT1 and PT2
603    ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
604    ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
605
[587]606    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
607        small   = attr & GPT_SMALL;
[1]608
[432]609    // compute tsar attributes from generic attributes
[401]610    tsar_attr = gpt2tsar( attr );
611
[587]612    // build extended pointer on PTE1 = PT1[ix1]
613        pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
[406]614
[587]615    // get current pte1 value
616    pte1 = hal_remote_l32( pte1_xp );
[1]617
[629]618        if( small == 0 )  ///////////////// map a big page in PT1
[401]619    {
[623]620
621// check PT1 entry not mapped
[629]622assert( (pte1 == 0) , "try to set a big page in an already mapped PTE1\n" );
[623]623
624// check VPN aligned
625assert( (ix2 == 0) , "illegal vpn for a big page\n" );
626
627// check PPN aligned
628assert( ((ppn & 0x1FF) == 0) , "illegal ppn for a big page\n" );
629
[587]630        // set the PTE1 value in PT1
631        pte1 = (tsar_attr  & TSAR_MMU_PTE1_ATTR_MASK) | ((ppn >> 9) & TSAR_MMU_PTE1_PPN_MASK);
632        hal_remote_s32( pte1_xp , pte1 );
[124]633                hal_fence();
[587]634
635#if DEBUG_HAL_GPT_SET_PTE
[629]636thread_t * this  = CURRENT_THREAD;
637uint32_t   cycle = (uint32_t)hal_get_cycles();
[587]638if( DEBUG_HAL_GPT_SET_PTE < cycle )
[611]639printk("\n[%s] : thread[%x,%x] map PTE1 / cxy %x / ix1 %x / pt1 %x / pte1 %x\n", 
[587]640__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1_ptr, pte1 );
641#endif
642
[1]643        }
[629]644    else      ///////////////// map a small page in PT2
[587]645    {
[1]646
[629]647// PTE1 must be mapped because PTE2 must be locked
648assert( (pte1 & TSAR_PTE_MAPPED), "PTE1 must be mapped\n" );
[1]649
[629]650        // get PT2 base from PTE1
651            pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
652            pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
[315]653
[629]654        // build extended pointers on PT2[ix2].attr and PT2[ix2].ppn
655        pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
656        pte2_ppn_xp  = XPTR( gpt_cxy , &pt2_ptr[2 * ix2 + 1] );
[1]657
[629]658        // get current value of PTE2.attr
659        pte2_attr = hal_remote_l32( pte2_attr_xp );
[587]660
[629]661// PTE2 must be locked
662assert( (pte2_attr & TSAR_PTE_LOCKED), "PTE2 must be locked\n" );
663 
[587]664        // set PTE2 in PT2 (in this order)
[629]665            hal_remote_s32( pte2_ppn_xp  , ppn );
[587]666            hal_fence();
[629]667            hal_remote_s32( pte2_attr_xp , tsar_attr );
[587]668            hal_fence();
[1]669
[587]670#if DEBUG_HAL_GPT_SET_PTE
[629]671thread_t * this  = CURRENT_THREAD;
672uint32_t   cycle = (uint32_t)hal_get_cycles();
[587]673if( DEBUG_HAL_GPT_SET_PTE < cycle )
[611]674printk("\n[%s] : thread[%x,%x] map PTE2 / cxy %x / ix2 %x / pt2 %x / attr %x / ppn %x\n", 
[587]675__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix2, pt2_ptr, tsar_attr, ppn );
[432]676#endif
677
[587]678    }
[1]679} // end of hal_gpt_set_pte()
680
[629]681///////////////////////////////////////
682void hal_gpt_reset_pte( xptr_t  gpt_xp,
683                        vpn_t   vpn )
[1]684{
[629]685    cxy_t      gpt_cxy;        // target GPT cluster
686    gpt_t    * gpt_ptr;        // target GPT local pointer
[1]687
[629]688    uint32_t   ix1;            // index in PT1
689    uint32_t   ix2;            // index in PT2
[1]690
[629]691    uint32_t * pt1_ptr;        // PT1 base address
692    xptr_t     pte1_xp;        // extended pointer on PT1[ix1]
693    uint32_t   pte1;           // PT1 entry value
[587]694
[629]695    ppn_t      pt2_ppn;        // PPN of PT2
696    uint32_t * pt2_ptr;        // PT2 base address
697    xptr_t     pte2_attr_xp;   // extended pointer on PT2[ix2].attr
698    xptr_t     pte2_ppn_xp;    // extended pointer on PT2[ix2].ppn
[1]699
[629]700    // get cluster and local pointer on GPT
701    gpt_cxy = GET_CXY( gpt_xp );
702    gpt_ptr = GET_PTR( gpt_xp );
[1]703
[629]704    // get ix1 & ix2 indexes
705    ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
706    ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
[1]707
[629]708    // get local pointer on PT1 base
709    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
[1]710
[629]711    // build extended pointer on PTE1 = PT1[ix1]
712        pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
[1]713
[629]714    // get current PTE1 value
715    pte1 = hal_remote_l32( pte1_xp );
[1]716
[629]717        if( (pte1 & TSAR_PTE_MAPPED) == 0 )     // PTE1 unmapped => do nothing
[1]718        {
719                return;
720        }
721
[629]722        if( (pte1 & TSAR_PTE_SMALL) == 0 )      // it's a PTE1 => unmap it from PT1
[1]723        {
[629]724        hal_remote_s32( pte1_xp , 0 );
[124]725            hal_fence();
[1]726
[629]727#if DEBUG_HAL_GPT_RESET_PTE
728thread_t * this  = CURRENT_THREAD;
729uint32_t   cycle = (uint32_t)hal_get_cycles();
730if( DEBUG_HAL_GPT_RESET_PTE < cycle )
731printk("\n[%s] : thread[%x,%x] unmap PTE1 / cxy %x / vpn %x / ix1 %x\n", 
732__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, vpn, ix1 );
733#endif
734
[1]735        return;
736        }
[629]737    else                                    // it's a PTE2 => unmap it from PT2
[1]738    {
739        // compute PT2 base address
740        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
[629]741        pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
[1]742       
[629]743        // build extended pointer on PT2[ix2].attr and PT2[ix2].ppn
744        pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
745        pte2_ppn_xp  = XPTR( gpt_cxy , &pt2_ptr[2 * ix2 + 1] );
746
747        // unmap the PTE2
748        hal_remote_s32( pte2_attr_xp , 0 );
[391]749            hal_fence();       
[629]750        hal_remote_s32( pte2_ppn_xp  , 0 );
751            hal_fence();       
[1]752
[629]753#if DEBUG_HAL_GPT_RESET_PTE
754thread_t * this  = CURRENT_THREAD;
755uint32_t   cycle = (uint32_t)hal_get_cycles();
756if( DEBUG_HAL_GPT_RESET_PTE < cycle )
757printk("\n[%s] : thread[%x,%x] unmap PTE2 / cxy %x / vpn %x / ix2 %x\n", 
758__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, vpn, ix2 );
759#endif
760
[1]761        return;
762    }
763}  // end hal_gpt_reset_pte()
764
[629]765////////////////////////////////////////
766void hal_gpt_get_pte( xptr_t     gpt_xp,
767                      vpn_t      vpn,
768                      uint32_t * attr,
769                      ppn_t    * ppn )
[624]770{
[629]771    uint32_t * pt1;            // local pointer on PT1 base
772    uint32_t   pte1;           // PTE1 value
[624]773
[629]774    uint32_t * pt2;            // local pointer on PT2 base
775    ppn_t      pt2_ppn;        // PPN of page containing the PT2
776    xptr_t     pte2_attr_xp;   // extended pointer on PT2[ix2].attr
777    xptr_t     pte2_ppn_xp;    // extended pointer on PT2[ix2].ppn
778    uint32_t   pte2_attr;      // current value of PT2[ix2].attr
779    ppn_t      pte2_ppn;       // current value of PT2[ix2].ppn
[624]780
[629]781    // get cluster and local pointer on GPT
782    cxy_t   gpt_cxy = GET_CXY( gpt_xp );
783    gpt_t * gpt_ptr = GET_PTR( gpt_xp );
[624]784
[629]785    // compute indexes in PT1 and PT2
786    uint32_t   ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
787    uint32_t   ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
[624]788
[629]789    // get PT1 base
790    pt1 = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
791   
792    // get pte1
793    pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
[624]794
[629]795    // check PTE1 mapped
796        if( (pte1 & TSAR_PTE_MAPPED) == 0 )   // PTE1 unmapped
[1]797        {
[629]798                *attr = 0;
799                *ppn  = 0;
800        return;
[1]801        }
802
[629]803    // access GPT
804        if( (pte1 & TSAR_PTE_SMALL) == 0 )     // it's a PTE1
805        {
806        // get PPN & ATTR from PT1
807                *attr = tsar2gpt( TSAR_MMU_ATTR_FROM_PTE1( pte1 ) );
808        *ppn  = TSAR_MMU_PPN_FROM_PTE1( pte1 ) | (vpn & ((1<<TSAR_MMU_IX2_WIDTH)-1));
[1]809        }
[629]810    else                                  // it's a PTE2
[1]811    {
[629]812        // compute PT2 base address
813        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
814        pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
[1]815
[629]816        // build extended pointer on PT2[ix2].attr and PT2[ix2].ppn
817        pte2_attr_xp = XPTR( gpt_cxy , &pt2[2 * ix2] );
818        pte2_ppn_xp  = XPTR( gpt_cxy , &pt2[2 * ix2 + 1] );
[1]819
[629]820        // get current value of PTE2.attr & PTE2.ppn
821        pte2_attr = hal_remote_l32( pte2_attr_xp );
822        pte2_ppn  = hal_remote_l32( pte2_ppn_xp );
[1]823
[629]824        // return PPN & GPT attributes
825        *ppn  = pte2_ppn & ((1<<TSAR_MMU_PPN_WIDTH)-1);
826        *attr = tsar2gpt( pte2_attr );
[1]827    }
[629]828} // end hal_gpt_get_pte()
[1]829
830
[408]831///////////////////////////////////////////
832error_t hal_gpt_pte_copy( gpt_t  * dst_gpt,
[625]833                          vpn_t    dst_vpn,
[408]834                          xptr_t   src_gpt_xp,
[625]835                          vpn_t    src_vpn,
[408]836                          bool_t   cow,
837                          ppn_t  * ppn,
838                          bool_t * mapped )
[23]839{
[625]840    uint32_t     src_ix1;   // index in SRC PT1
841    uint32_t     src_ix2;   // index in SRC PT2
[1]842
[625]843    uint32_t     dst_ix1;   // index in DST PT1
844    uint32_t     dst_ix2;   // index in DST PT2
845
[408]846    cxy_t        src_cxy;   // SRC GPT cluster
847    gpt_t      * src_gpt;   // SRC GPT local pointer
[1]848
[408]849        uint32_t   * src_pt1;   // local pointer on SRC PT1
850        uint32_t   * dst_pt1;   // local pointer on DST PT1
851    uint32_t   * src_pt2;   // local pointer on SRC PT2
852    uint32_t   * dst_pt2;   // local pointer on DST PT2
853
[587]854        kmem_req_t   req;       // for PT2 allocation
[407]855
856    uint32_t     src_pte1;
857    uint32_t     dst_pte1;
858
[408]859    uint32_t     src_pte2_attr;
860    uint32_t     src_pte2_ppn;
[1]861
[23]862    page_t     * page;
[315]863    xptr_t       page_xp;
[1]864
[23]865    ppn_t        src_pt2_ppn;
866    ppn_t        dst_pt2_ppn;
[1]867
[587]868    // get remote src_gpt cluster and local pointer
869    src_cxy = GET_CXY( src_gpt_xp );
870    src_gpt = GET_PTR( src_gpt_xp );
871
872#if DEBUG_HAL_GPT_COPY
873uint32_t   cycle = (uint32_t)hal_get_cycles();
874thread_t * this  = CURRENT_THREAD;
875if( DEBUG_HAL_GPT_COPY < cycle )
[625]876printk("\n[%s] : thread[%x,%x] enter / src_cxy %x / dst_cxy %x / cycle %d\n", 
877__FUNCTION__, this->process->pid, this->trdid, src_cxy, local_cxy, cycle );
[432]878#endif
[407]879
[408]880    // get remote src_gpt cluster and local pointer
881    src_cxy = GET_CXY( src_gpt_xp );
[587]882    src_gpt = GET_PTR( src_gpt_xp );
[407]883
[408]884    // get remote src_pt1 and local dst_pt1
885    src_pt1 = (uint32_t *)hal_remote_lpt( XPTR( src_cxy , &src_gpt->ptr ) );
[23]886    dst_pt1 = (uint32_t *)dst_gpt->ptr;
[1]887
[408]888    // check src_pt1 and dst_pt1 existence
[492]889    assert( (src_pt1 != NULL) , "src_pt1 does not exist\n");
890    assert( (dst_pt1 != NULL) , "dst_pt1 does not exist\n");
[407]891
[625]892    // compute SRC indexes
893    src_ix1 = TSAR_MMU_IX1_FROM_VPN( src_vpn );
894    src_ix2 = TSAR_MMU_IX2_FROM_VPN( src_vpn );
[407]895
[625]896    // compute DST indexes
897    dst_ix1 = TSAR_MMU_IX1_FROM_VPN( dst_vpn );
898    dst_ix2 = TSAR_MMU_IX2_FROM_VPN( dst_vpn );
899
[408]900    // get src_pte1
[625]901    src_pte1 = hal_remote_l32( XPTR( src_cxy , &src_pt1[src_ix1] ) );
[407]902
[408]903    // do nothing if src_pte1 not MAPPED or not SMALL
[629]904        if( (src_pte1 & TSAR_PTE_MAPPED) && (src_pte1 & TSAR_PTE_SMALL) )   
[408]905    {
906        // get dst_pt1 entry
[625]907        dst_pte1 = dst_pt1[dst_ix1];
[407]908
[408]909        // map dst_pte1 if required
[629]910        if( (dst_pte1 & TSAR_PTE_MAPPED) == 0 ) 
[408]911        { 
912            // allocate one physical page for a new PT2
913                req.type  = KMEM_PAGE;
914                req.size  = 0;                     // 1 small page
915                req.flags = AF_KERNEL | AF_ZERO;
916                page = (page_t *)kmem_alloc( &req );
[407]917
[408]918            if( page == NULL )
919            {
920                        printk("\n[ERROR] in %s : cannot allocate PT2\n", __FUNCTION__ );
921                return -1;
922            }
[407]923
[408]924            // build extended pointer on page descriptor
925            page_xp = XPTR( local_cxy , page );
[407]926
[408]927            // get PPN for this new PT2
928            dst_pt2_ppn = (ppn_t)ppm_page2ppn( page_xp );
[407]929
[408]930            // build the new dst_pte1
[629]931            dst_pte1 = TSAR_PTE_MAPPED | TSAR_PTE_SMALL | dst_pt2_ppn;
[407]932
[408]933            // register it in DST_GPT
[625]934            dst_pt1[dst_ix1] = dst_pte1;
[408]935        }
[407]936
[408]937        // get pointer on src_pt2
938        src_pt2_ppn = (ppn_t)TSAR_MMU_PTBA_FROM_PTE1( src_pte1 );
[587]939        src_pt2     = GET_PTR( ppm_ppn2base( src_pt2_ppn ) );
[407]940
[408]941        // get pointer on dst_pt2
942        dst_pt2_ppn = (ppn_t)TSAR_MMU_PTBA_FROM_PTE1( dst_pte1 );
[587]943        dst_pt2     = GET_PTR( ppm_ppn2base( dst_pt2_ppn ) );
[407]944
[408]945        // get attr and ppn from SRC_PT2
[625]946        src_pte2_attr = hal_remote_l32( XPTR( src_cxy , &src_pt2[2 * src_ix2]     ) );
947        src_pte2_ppn  = hal_remote_l32( XPTR( src_cxy , &src_pt2[2 * src_ix2 + 1] ) );
[407]948
[408]949        // do nothing if src_pte2 not MAPPED
[629]950        if( (src_pte2_attr & TSAR_PTE_MAPPED) != 0 ) 
[408]951        {
952            // set PPN in DST PTE2
[625]953            dst_pt2[2 * dst_ix2 + 1] = src_pte2_ppn;
[408]954                       
955            // set attributes in DST PTE2         
[629]956            if( cow && (src_pte2_attr & TSAR_PTE_WRITABLE) ) 
[407]957            {
[629]958                dst_pt2[2 * dst_ix2] = (src_pte2_attr | TSAR_PTE_COW) & (~TSAR_PTE_WRITABLE);
[408]959            } 
960            else
961            {
[625]962                dst_pt2[2 * dst_ix2] = src_pte2_attr;
[408]963            }
[407]964
[408]965            // return "successfully copied"
966            *mapped = true;
967            *ppn    = src_pte2_ppn;
968       
[587]969#if DEBUG_HAL_GPT_COPY
[432]970cycle = (uint32_t)hal_get_cycles;
[587]971if( DEBUG_HAL_GPT_COPY < cycle )
[625]972printk("\n[%s] : thread[%x,%x] exit / copy done for src_vpn %x / dst_vpn %x / cycle %d\n", 
973__FUNCTION__, this->process->pid, this->trdid, src_vpn, dst_vpn, cycle );
[432]974#endif
[407]975
[408]976            hal_fence();
[407]977
[408]978            return 0;
979        }   // end if PTE2 mapped
980    }   // end if PTE1 mapped
981
982    // return "nothing done"
983    *mapped = false;
984    *ppn    = 0;
[432]985   
[587]986#if DEBUG_HAL_GPT_COPY
[432]987cycle = (uint32_t)hal_get_cycles;
[587]988if( DEBUG_HAL_GPT_COPY < cycle )
[625]989printk("\n[%s] : thread[%x,%x] exit / nothing done / cycle %d\n", 
990__FUNCTION__, this->process->pid, this->trdid, cycle );
[432]991#endif
[408]992
[407]993    hal_fence();
994
995    return 0;
996
[408]997}  // end hal_gpt_pte_copy()
[407]998
[408]999/////////////////////////////////////////
[432]1000void hal_gpt_set_cow( xptr_t  gpt_xp,
1001                      vpn_t   vpn_base,
1002                      vpn_t   vpn_size )
[408]1003{
1004    cxy_t      gpt_cxy;
1005    gpt_t    * gpt_ptr;
[407]1006
[408]1007    vpn_t      vpn;
[407]1008
[408]1009    uint32_t   ix1;
1010    uint32_t   ix2;
[407]1011
[408]1012    uint32_t * pt1;
1013    uint32_t   pte1;
[407]1014
[408]1015    uint32_t * pt2;
1016    ppn_t      pt2_ppn;
[432]1017    uint32_t   attr;
[407]1018
[408]1019    // get GPT cluster and local pointer
1020    gpt_cxy = GET_CXY( gpt_xp );
[587]1021    gpt_ptr = GET_PTR( gpt_xp );
[407]1022
[408]1023    // get local PT1 pointer
1024    pt1 = (uint32_t *)hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
[407]1025
[408]1026    // loop on pages
1027    for( vpn = vpn_base ; vpn < (vpn_base + vpn_size) ; vpn++ )
1028    {
1029        ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
1030        ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
[407]1031
[408]1032        // get PTE1 value
[570]1033        pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
[407]1034
[408]1035        // only MAPPED & SMALL PTEs are modified
[629]1036            if( (pte1 & TSAR_PTE_MAPPED) && (pte1 & TSAR_PTE_SMALL) )
[408]1037        {
1038            // compute PT2 base address
1039            pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
[587]1040            pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
[407]1041
[492]1042            assert( (GET_CXY( ppm_ppn2base( pt2_ppn ) ) == gpt_cxy ),
[408]1043            "PT2 and PT1 must be in the same cluster\n");
1044 
1045            // get current PTE2 attributes
[570]1046            attr = hal_remote_l32( XPTR( gpt_cxy , &pt2[2*ix2] ) );
[408]1047
1048            // only MAPPED PTEs are modified       
[629]1049            if( attr & TSAR_PTE_MAPPED ) 
[23]1050            {
[629]1051                attr = (attr | TSAR_PTE_COW) & (~TSAR_PTE_WRITABLE);
[570]1052                hal_remote_s32( XPTR( gpt_cxy , &pt2[2*ix2] ) , attr );
[432]1053            } 
1054        } 
[408]1055    }   // end loop on pages
[23]1056
[432]1057}  // end hal_gpt_set_cow()
[315]1058
[408]1059//////////////////////////////////////////
1060void hal_gpt_update_pte( xptr_t    gpt_xp,
1061                         vpn_t     vpn,
1062                         uint32_t  attr,     // generic GPT attributes
1063                         ppn_t     ppn )
1064{
1065    uint32_t          * pt1;                 // PT1 base addres
1066        uint32_t            pte1;                // PT1 entry value
[23]1067
[408]1068        ppn_t               pt2_ppn;             // PPN of PT2
1069        uint32_t          * pt2;                 // PT2 base address
[632]1070    xptr_t              pte2_xp;             // exended pointer on PTE2
[23]1071
[408]1072    uint32_t            ix1;                 // index in PT1
1073    uint32_t            ix2;                 // index in PT2
[23]1074
[632]1075
[408]1076    uint32_t            tsar_attr;           // PTE attributes for TSAR MMU
[23]1077
[632]1078// check MAPPED, SMALL, and not LOCKED in attr argument
1079assert( ((attr & GPT_MAPPED) != 0), "attribute MAPPED must be set in new attributes\n" );
1080assert( ((attr & GPT_SMALL ) != 0), "attribute SMALL  must be set in new attributes\n" );
1081assert( ((attr & GPT_LOCKED) == 0), "attribute LOCKED must not be set in new attributes\n" );
[23]1082
[408]1083    // get cluster and local pointer on remote GPT
1084    cxy_t   gpt_cxy = GET_CXY( gpt_xp );
[587]1085    gpt_t * gpt_ptr = GET_PTR( gpt_xp );
[23]1086
[408]1087    // compute indexes in PT1 and PT2
1088    ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
1089    ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
[23]1090
[408]1091    // get PT1 base
1092    pt1 = (uint32_t *)hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
[23]1093
[408]1094    // compute tsar_attr from generic attributes
1095    tsar_attr = gpt2tsar( attr );
[23]1096
[408]1097    // get PTE1 value
[570]1098    pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
[23]1099
[632]1100// check MAPPED and SMALL in target PTE1
1101assert( ((pte1 & GPT_MAPPED) != 0), "attribute MAPPED must be set in target PTE1\n" );
1102assert( ((pte1 & GPT_SMALL ) != 0), "attribute SMALL  must be set in target PTE1\n" );
[408]1103
1104    // get PT2 base from PTE1
1105    pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
[587]1106    pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
[408]1107
[632]1108    // get extended pointer on PTE2
1109    pte2_xp = XPTR( gpt_cxy , &pt2[2*ix2] );
1110   
1111// check MAPPED in target PTE2
1112assert( ((hal_remote_l32(pte2_xp) & GPT_MAPPED) != 0),
1113"attribute MAPPED must be set in target PTE2\n" );
1114
[408]1115    // set PTE2 in this order
[632]1116        hal_remote_s32( pte2_xp     , ppn );
[408]1117        hal_fence();
[632]1118        hal_remote_s32( pte2_xp + 4 , tsar_attr );
[408]1119        hal_fence();
1120
1121} // end hal_gpt_update_pte()
1122
[629]1123
1124
1125
1126
Note: See TracBrowser for help on using the repository browser.