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

Last change on this file since 635 was 635, checked in by alain, 17 months ago

This version is a major evolution: The physical memory allocators,
defined in the kmem.c, ppm.c, and kcm.c files have been modified
to support remote accesses. The RPCs that were previously user
to allocate physical memory in a remote cluster have been removed.
This has been done to cure a dead-lock in case of concurrent page-faults.

This version 2.2 has been tested on a (4 clusters / 2 cores per cluster)
TSAR architecture, for both the "sort" and the "fft" applications.

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