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

Last change on this file since 625 was 625, checked in by alain, 2 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

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