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

Last change on this file was 686, checked in by alain, 3 years ago

cosmetic

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