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

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

Introduce the non-standard pthread_parallel_create() system call
and re-write the <fft> and <sort> applications to improve the
intrinsic paralelism in applications.

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