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

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

1) Fix a bug in the vfs_add_special_dentries() function:
The <.> and <..> dentries must not be created on IOC and on the mapper
for the VFS root directory.
2) Fix a bug in the hal_gpt_allocate_pt2 function, related to the
use of the TSAR_LOCKED attribute to avoid concurrent mapping of the PTD1.

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