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

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

Remove the "giant" rwlock protecting the GPT, and
use the GPT_LOCKED attribute in each PTE to prevent
concurrent modifications of one GPT entry.
The version number has been incremented to 2.1.

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