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

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

Introduce three new types of vsegs (KCODE,KDATA,KDEV)
to map the kernel vsegs in the process VSL and GPT.
This now used by both the TSAR and the I86 architectures.

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