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

Last change on this file since 658 was 658, checked in by alain, 4 years ago

Improve the TSAR NIC driver.

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