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

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

Remove all RPCs in page-fault handling.

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