source: trunk/hal/tsar_mips32/hal_gpt.c @ 1

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

First import

File size: 19.3 KB
Line 
1/*
2 * hal_gpt.c - implementation of the Generic Page Table API for TSAR-MIPS32
3 *
4 * Author   Alain Greiner (2016)
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_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// the GPT masks are derived from the TSAR MMU PTE attributes
39// in the TSAR specific hal_gpt_create() function.
40////////////////////////////////////////////////////////////////////////////////////////
41
42#define TSAR_MMU_PRESENT        0x80000000
43#define TSAR_MMU_PTD1           0x40000000
44#define TSAR_MMU_LOCAL          0x20000000
45#define TSAR_MMU_REMOTE         0x10000000
46#define TSAR_MMU_CACHABLE       0x08000000
47#define TSAR_MMU_WRITABLE       0x04000000
48#define TSAR_MMU_EXECUTABLE     0x02000000
49#define TSAR_MMU_USER           0x01000000
50#define TSAR_MMU_GLOBAL         0x00800000
51#define TSAR_MMU_DIRTY          0x00400000
52
53#define TSAR_MMU_COW            0x00000001
54#define TSAR_MMU_SWAP           0x00000004
55#define TSAR_MMU_LOCKED         0x00000008
56
57////////////////////////////////////////////////////////////////////////////////////////
58//       TSAR MMU related macros  (from the TSAR MMU specification)
59// - IX1  on 11 bits
60// - IX2  on  9 bits
61// - PPN  on 28 bits
62////////////////////////////////////////////////////////////////////////////////////////
63
64#define TSAR_MMU_IX1_WIDTH                 11
65#define TSAR_MMU_IX2_WIDTH                 9
66#define TSAR_MMU_PPN_WIDTH                 28
67
68#define TSAR_MMU_IX1_FROM_VPN( vpn )       ((vpn >> 9) & 0x7FF)
69#define TSAR_MMU_IX2_FROM_VPN( vpn )       (vpn & 0x1FF)
70
71#define TSAR_MMU_PTBA_FROM_PTE1( pte1 )    (pte1 & 0xFFFFFFF)
72#define TSAR_MMU_PPN_FROM_PTE1( pte1 )     ((pte1 & 0x7FFFF)<<9)
73#define TSAR_MMU_ATTR_FROM_PTE1( pte1 )    (pte1 & 0xFFC00000)
74
75#define TSAR_MMU_PPN_FROM_PTE2( pte2 )     (pte2 & 0x0FFFFFFF)
76#define TSAR_MMU_ATTR_FROM_PTE2( pte2 )    (pte2 & 0xFFC000FF)
77
78/****************************************************************************************
79 * These global variables defines the masks for the Generic Page Table Entry attributes,
80 * and must be defined in all GPT implementation.
81 ***************************************************************************************/
82
83uint32_t  GPT_MAPPED;
84uint32_t  GPT_SMALL;
85uint32_t  GPT_READABLE;
86uint32_t  GPT_WRITABLE; 
87uint32_t  GPT_EXECUTABLE;
88uint32_t  GPT_CACHABLE; 
89uint32_t  GPT_USER; 
90uint32_t  GPT_DIRTY;
91uint32_t  GPT_ACCESSED;
92uint32_t  GPT_GLOBAL;
93uint32_t  GPT_COW;
94uint32_t  GPT_SWAP;
95uint32_t  GPT_LOCKED;
96
97/////////////////////////////////////
98error_t hal_gpt_create( gpt_t * gpt )
99{
100        page_t   * page;
101
102    // check page size
103    if( CONFIG_PPM_PAGE_SIZE != 4096 );
104    {
105        printk("\n[PANIC] in %s : For TSAR, the page must be 4 Kbytes\n", __FUNCTION__ );
106        hal_core_sleep();
107    }
108
109    // allocates 2 physical pages for PT1
110        kmem_req_t req;
111        req.type  = KMEM_PAGE;
112        req.size  = 1;                     // 2 small pages
113        req.flags = AF_KERNEL | AF_ZERO;
114        page = (page_t *)kmem_alloc( &req );
115
116        if( page == NULL )
117    {
118                printk("\n[ERROR] in %s : cannot allocate physical memory for PT1\n", __FUNCTION__ );
119        return ENOMEM;
120        }
121
122    // initialize generic page table descriptor
123        gpt->ptr  = ppm_page2base( page );
124        gpt->ppn  = ppm_page2ppn( page );
125        gpt->page = page;
126
127    // initialize PTE entries attributes masks
128    GPT_MAPPED     = TSAR_MMU_PRESENT;
129    GPT_SMALL      = TSAR_MMU_PTD1;
130    GPT_READABLE   = TSAR_MMU_PRESENT;
131    GPT_WRITABLE   = TSAR_MMU_WRITABLE;
132    GPT_EXECUTABLE = TSAR_MMU_EXECUTABLE;
133    GPT_CACHABLE   = TSAR_MMU_CACHABLE;
134    GPT_USER       = TSAR_MMU_USER;     
135    GPT_DIRTY      = TSAR_MMU_DIRTY;   
136    GPT_ACCESSED   = TSAR_MMU_LOCAL | TSAR_MMU_REMOTE;
137    GPT_GLOBAL     = TSAR_MMU_GLOBAL; 
138    GPT_COW        = TSAR_MMU_COW;
139    GPT_SWAP       = TSAR_MMU_SWAP;
140    GPT_LOCKED     = TSAR_MMU_LOCKED;
141
142        return 0;
143} // end hal_gpt_create()
144
145
146///////////////////////////////////
147void hal_gpt_destroy( gpt_t * gpt )
148{
149        uint32_t     ix1;
150        uint32_t     ix2;
151        uint32_t   * pt1;
152    uint32_t     pte1;
153    ppn_t        pt2_ppn;
154    uint32_t   * pt2;
155    uint32_t     attr;
156    vpn_t        vpn;     
157        kmem_req_t   req;
158    bool_t       is_ref;
159
160    // get pointer on calling process
161    process_t  * process = CURRENT_THREAD->process;
162
163    // compute is_ref
164    is_ref = process->is_ref;
165
166    // get pointer on PT1
167    pt1 = (uint32_t *)gpt->ptr;
168
169    // scan the PT1
170        for( ix1 = 0 ; ix1 < 2048 ; ix1++ )
171        {
172        pte1 = pt1[ix1];
173                if( (pte1 & GPT_MAPPED) != 0 )  // PTE1 valid
174        {
175            if( (pte1 & GPT_SMALL) == 0 )   // BIG page
176            {
177                if( (pte1 & GPT_USER) != 0 ) 
178                {
179                    // warning message
180                    printk("\n[WARNING] in %s : found an USER BIG page / ix1 = %d\n", 
181                           __FUNCTION__ , ix1 );
182
183                    // release the big physical page if reference cluster
184                    if( is_ref )
185                    {
186                        vpn = (vpn_t)(ix1 << TSAR_MMU_IX2_WIDTH);
187                        hal_gpt_reset_pte( gpt , vpn );
188                    }
189                }
190            }
191            else                           // SMALL page
192            {
193                // get pointer on PT2
194                pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
195                pt2 = ppm_ppn2base( pt2_ppn );
196
197                // scan the PT2 to release all entries VALID and USER if reference cluster
198                    if( is_ref )
199                {
200                    for( ix2 = 0 ; ix2 < 512 ; ix2++ )
201                    {
202                        attr = TSAR_MMU_ATTR_FROM_PTE2( pt2[2 * ix2] );
203                                if( ((attr & GPT_MAPPED) != 0 ) && ((attr & GPT_USER) != 0) ) 
204                        {
205                            // release the physical page
206                            vpn = (vpn_t)((ix1 << TSAR_MMU_IX2_WIDTH) | ix2);
207                            hal_gpt_reset_pte( gpt , vpn );
208                        }
209                    }
210                }
211
212                // release the PT2
213                req.type = KMEM_PAGE;
214                req.ptr  = ppm_base2page( pt2 );
215                kmem_free( &req );
216            }
217        }
218        }
219
220    // release the PT1
221    req.type = KMEM_PAGE;
222    req.ptr  = ppm_base2page( pt1 );
223    kmem_free( &req );
224
225} // end hal_gpt_destroy()
226
227/////////////////////////////////
228void hal_gpt_print( gpt_t * gpt )
229{
230        uint32_t   ix1;
231        uint32_t   ix2;
232        uint32_t * pt1;
233    uint32_t   pte1;
234    ppn_t      pt2_ppn;
235    uint32_t * pt2;
236    uint32_t   pte2_attr;
237    ppn_t      pte2_ppn;
238
239    printk("*** Page Table for process %x in cluster %x ***\n",
240           CURRENT_PROCESS->pid , local_cxy );
241
242    pt1 = (uint32_t *)gpt->ptr;
243
244    // scan the PT1
245        for( ix1 = 0 ; ix1 < 2048 ; ix1++ )
246        {
247        pte1 = pt1[ix1];
248                if( (pte1 & GPT_MAPPED) != 0 )
249        {
250            if( (pte1 & GPT_SMALL) == 0 )  // BIG page
251            {
252                printk(" - BIG   : pt1[%d] = %x\n", ix1 , pte1 );
253            }
254            else                           // SMALL pages
255            {
256                pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
257                pt2 = ppm_ppn2base( pt2_ppn );
258
259                // scan the PT2
260                    for( ix2 = 0 ; ix2 < 512 ; ix2++ )
261                {
262                    pte2_attr = TSAR_MMU_ATTR_FROM_PTE2( pt2[2 * ix2] );
263                    pte2_ppn  = TSAR_MMU_PPN_FROM_PTE2( pt2[2 * ix2 + 1] );
264                            if( (pte2_attr & GPT_MAPPED) != 0 )
265                    {
266                        printk(" - SMALL   : pt1[%d] = %x / pt2[%d] / pt2[%d]\n",
267                               ix1 , pt1[ix1] , 2*ix2 , pte2_attr , 2*ix2+1 , pte2_ppn );
268                    }
269                }
270            }
271        }
272        }
273} // end hal_gpt_print()
274
275
276///////////////////////////////////////
277error_t hal_gpt_set_pte( gpt_t   * gpt,
278                         vpn_t     vpn,
279                         ppn_t     ppn,
280                         uint32_t  attr )
281{
282    uint32_t          * pt1;         // virtual base addres of PT1
283        volatile uint32_t * pte1_ptr;    // pointer on PT1 entry
284        uint32_t            pte1;        // PT1 entry value
285
286        ppn_t               pt2_ppn;     // PPN of PT2
287        uint32_t          * pt2;         // virtual base address of PT2
288
289        uint32_t            small;       // requested PTE is for a small page
290        bool_t              atomic;      //
291        page_t            * page;        // pointer on new physical page descriptor
292
293    uint32_t            ix1;         // index in PT1
294    uint32_t            ix2;         // index in PT2
295
296    // compute indexes in PT1 and PT2
297    ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
298    ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
299
300    pt1   = gpt->ptr;
301        small = (attr & GPT_SMALL);
302
303    // get PT1 entry value
304        pte1_ptr  = &pt1[ix1];
305        pte1      = *pte1_ptr;
306
307    // Big pages (PTE1) are only set for the kernel vsegs, in the kernel init phase.
308    // There is no risk of concurrent access.
309        if( small == 0 )
310        {
311                if( (pte1 != 0) || (attr & GPT_COW) )
312                {
313                        printk("\n[ERROR] in %s : set a big page in a mapped PT1 entry / PT1[%d] = %x\n",
314                   __FUNCTION__ , ix1 , pte1 );
315                        return EINVAL;
316                }
317     
318        // set the PTE1
319                *pte1_ptr = attr | (ppn >> 9);
320                hal_wbflush();
321                return 0;
322        }
323
324    // From this point, the requested PTE is a PTE2 (small page)
325
326        if( (pte1 & GPT_MAPPED) == 0 )      // the PT1 entry is not valid
327        {
328        // allocate one physical page for the PT2
329            kmem_req_t req;
330            req.type  = KMEM_PAGE;
331            req.size  = 0;                     // 1 small page
332            req.flags = AF_KERNEL | AF_ZERO;
333            page = (page_t *)kmem_alloc( &req );
334        if( page == NULL )
335        {
336                        printk("\n[ERROR] in %s : try to set a small page but cannot allocate PT2\n",
337                    __FUNCTION__ );
338            return ENOMEM;
339        }
340        pt2_ppn = ppm_page2ppn( page );
341        pt2     = ppm_page2base( page );
342
343        // try to atomicaly set a PTD1 in the PT1 entry
344                do 
345                {
346                    atomic = hal_atomic_cas( (void*)pte1, 0 , 
347                                      TSAR_MMU_PRESENT | TSAR_MMU_PTD1 | pt2_ppn );
348        } 
349        while( (atomic == false) && (*pte1_ptr == 0) );
350
351            if( atomic == false ) // the mapping has been done by another thread !!!
352        {
353            // release the allocated page
354                ppm_free_pages( page );
355
356            // read PT1 entry again
357                        pte1 = *pte1_ptr;
358
359            // compute PPN of PT2 base
360                        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
361
362            // compute pointer on PT2 base
363                        pt2 = (uint32_t*)ppm_ppn2base( pt2_ppn );
364                }
365        }
366        else                             // The PT1 entry is valid 
367        {
368        // This valid entry must be a PTD1
369        if( (pte1 & GPT_SMALL) == 0 )
370        {
371                        printk("\n[ERROR] in %s : set a small page in a big PT1 entry / PT1[%d] = %x\n",
372                    __FUNCTION__ , ix1 , pte1 );
373            return EINVAL;
374        }
375
376        // compute PPN of PT2 base
377                pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
378
379        // compute pointer on PT2 base
380            pt2 = (uint32_t*)ppm_ppn2base( pt2_ppn );
381        }
382
383    // set PTE2 in this order
384        pt2[2 * ix2 + 1] = ppn;
385        hal_wbflush();
386        pt2[2 * ix2]     = attr;
387        hal_wbflush();
388
389        return 0;
390} // end of hal_gpt_set_pte()
391
392/////////////////////////////////////
393void hal_gpt_get_pte( gpt_t    * gpt,
394                      vpn_t      vpn,
395                      uint32_t * attr,
396                      ppn_t    * ppn )
397{
398    uint32_t * pt1;
399    uint32_t   pte1;
400
401    uint32_t * pt2;
402    ppn_t      pt2_ppn;
403
404    uint32_t   ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
405    uint32_t   ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
406
407    // get PTE1 value
408        pt1  = gpt->ptr;
409    pte1 = pt1[ix1];
410
411        if( (pte1 & GPT_MAPPED) == 0 )   // PT1 entry not present
412        {
413                *attr = 0;
414                *ppn  = 0;
415        }
416
417        if( (pte1 & GPT_SMALL) == 0 )     // it's a PTE1
418        {
419                *attr = TSAR_MMU_ATTR_FROM_PTE1( pte1 );
420        *ppn  = TSAR_MMU_PPN_FROM_PTE1( pte1 ) | (vpn & ((1<<TSAR_MMU_IX2_WIDTH)-1));
421        }
422    else                              // it's a PTD1
423    {
424        // compute PT2 base address
425        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
426        pt2     = (uint32_t*)ppm_ppn2base( pt2_ppn );
427
428            *ppn  = pt2[2*ix2+1] & ((1<<TSAR_MMU_PPN_WIDTH)-1);
429            *attr = pt2[2*ix2];
430    }
431} // end hal_gpt_get_pte()
432
433////////////////////////////////////
434void hal_gpt_reset_pte( gpt_t * gpt,
435                        vpn_t   vpn )
436{
437    uint32_t * pt1;         // PT1 base address
438    uint32_t   pte1;        // PT1 entry value
439
440    ppn_t      pt2_ppn;     // PPN of PT2
441    uint32_t * pt2;         // PT2 base address
442
443    ppn_t      ppn;         // PPN of page to be released
444
445    kmem_req_t req;
446
447    uint32_t   ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
448    uint32_t   ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
449
450    // get PTE1 value
451        pt1      = gpt->ptr;
452    pte1     = pt1[ix1];
453
454        if( (pte1 & GPT_MAPPED) == 0 )   // PT1 entry not present
455        {
456                return;
457        }
458
459        if( (pte1 & GPT_SMALL) == 0 )     // it's a PTE1
460        {
461        // get PPN
462        ppn = TSAR_MMU_PPN_FROM_PTE1( pte1 );
463
464        // unmap the big page
465        pt1[ix1] = 0;
466            hal_wbflush();
467
468        // releases the big page
469        req.type  = KMEM_PAGE;
470            req.size  = 9;
471        req.ptr   = (void*)(ppn << CONFIG_PPM_PAGE_SHIFT);
472            kmem_free( &req );
473
474        return;
475        }
476    else                              // it's a PTD1
477    {
478        // compute PT2 base address
479        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
480        pt2 = (uint32_t*)ppm_ppn2base( pt2_ppn );
481       
482        // get PPN
483            ppn = TSAR_MMU_PPN_FROM_PTE2( pt2[2*ix2+1] );
484
485        // unmap the small page
486            pt2[2*ix2]   = 0;
487            hal_wbflush();
488            pt2[2*ix2+1] = 0;
489            hal_wbflush();
490
491        // releases the small page
492        req.type  = KMEM_PAGE;
493            req.size  = 0;
494        req.ptr   = (void*)(ppn << CONFIG_PPM_PAGE_SHIFT);
495            kmem_free( &req );
496
497        return;
498    }
499}  // end hal_gpt_reset_pte()
500
501//////////////////////////////////////
502error_t hal_gpt_lock_pte( gpt_t * gpt,
503                          vpn_t   vpn )
504{
505    uint32_t          * pt1;             // PT1 base address
506        volatile uint32_t * pte1_ptr;        // address of PT1 entry
507        uint32_t            pte1;            // value of PT1 entry
508
509    uint32_t          * pt2;             // PT2 base address
510        ppn_t               pt2_ppn;         // PPN of PT2 page if missing PT2
511        volatile uint32_t * pte2_ptr;        // address of PT2 entry
512
513        uint32_t            attr;
514        bool_t              atomic;
515    page_t            * page;
516
517    uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
518    uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
519
520    // get the PTE1 value
521    pt1       = gpt->ptr; 
522        pte1_ptr  = &pt1[ix1];
523        pte1      = *pte1_ptr;
524
525    // If present, the page must be small
526        if( ((pte1 & GPT_MAPPED) != 0) && ((pte1 & GPT_SMALL) == 0) )
527    {
528        printk("\n[ERROR] in %s : try to lock a big page / PT1[%d] = %x\n",
529               __FUNCTION__ , ix1 , pte1 );
530                return EINVAL;
531    }
532
533        if( (pte1 & GPT_MAPPED) == 0 )  // missing PT1 entry   
534        {
535        // allocate one physical page for PT2
536            kmem_req_t req;
537            req.type  = KMEM_PAGE;
538            req.size  = 0;                     // 1 small page
539            req.flags = AF_KERNEL | AF_ZERO;
540            page = (page_t *)kmem_alloc( &req );
541        if( page == NULL )
542        {
543                        printk("\n[ERROR] in %s : try to set a small page but cannot allocate PT2\n",
544                      __FUNCTION__ );
545            return ENOMEM;
546        }
547        pt2_ppn = ppm_page2ppn( page );
548        pt2     = ppm_page2base( page );
549
550        // try to set the PT1 entry
551                do 
552                {
553                        atomic = hal_atomic_cas( (void*)pte1_ptr , 0 , 
554                                     TSAR_MMU_PRESENT | TSAR_MMU_PTD1 | pt2_ppn );
555                } 
556        while( (atomic == false) && (*pte1_ptr == 0) );
557
558                if( atomic == false )  // missing PT2 has been allocate by another core
559                {
560            // release the allocated page
561                        ppm_free_pages( page );
562
563            // read again the PTE1     
564                        pte1 = *pte1_ptr;
565
566            // get the PT2 base address
567                        pt2_ppn = TSAR_MMU_PPN_FROM_PTE1( pte1 );
568                        pt2     = (uint32_t*)ppm_ppn2base( pt2_ppn );
569                }
570        }
571    else
572    {
573        // This valid entry must be a PTD1
574        if( (pte1 & GPT_SMALL) == 0 )
575        {
576                        printk("\n[ERROR] in %s : set a small page in a big PT1 entry / PT1[%d] = %x\n",
577                    __FUNCTION__ , ix1 , pte1 );
578            return EINVAL;
579        }
580
581        // compute PPN of PT2 base
582                pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
583
584        // compute pointer on PT2 base
585            pt2 = (uint32_t*)ppm_ppn2base( pt2_ppn );
586    }
587   
588    // from here we have the PT2 pointer
589   
590    // compute pointer on PTE2
591    pte2_ptr = &pt2[2 * ix2];
592
593    // try to atomically lock the PTE2 until success
594        do
595    {
596        // busy waiting until GPT_LOCK == 0
597        do
598                {
599                        attr = *pte2_ptr;
600                        hal_rdbar();
601                }
602        while( (attr & GPT_LOCKED) != 0 );
603
604        // try to set the GPT_LOCK wit a CAS
605                atomic = hal_atomic_cas( (void*)pte2_ptr, attr , (attr | GPT_LOCKED) );
606        }
607    while( atomic == 0 );
608
609        return 0;
610}  // end hal_gpt_lock_pte()
611
612////////////////////////////////////////
613error_t hal_gpt_unlock_pte( gpt_t * gpt,
614                            vpn_t   vpn )
615{
616    uint32_t * pt1;             // PT1 base address
617        uint32_t   pte1;            // value of PT1 entry
618
619    uint32_t * pt2;             // PT2 base address
620        ppn_t      pt2_ppn;         // PPN of PT2 page if missing PT2
621        uint32_t * pte2_ptr;        // address of PT2 entry
622
623        uint32_t   attr;            // PTE2 attribute
624
625    // compute indexes in P1 and PT2
626    uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
627    uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
628
629    // get pointer on PT1 base
630    pt1  = (uint32_t*)gpt->ptr;
631
632    // get PTE1
633    pte1 = pt1[ix1];
634
635    // check PTE1 present and small page
636    if( ((pte1 & GPT_MAPPED) == 0) || ((pte1 & GPT_SMALL) == 0) )
637    {
638        printk("\n[ERROR] in %s : try to unlock a big or undefined page / PT1[%d] = %x\n",
639                 __FUNCTION__ , ix1 , pte1 );
640        return EINVAL;
641    }
642
643    // get pointer on PT2 base
644    pt2_ppn = TSAR_MMU_PPN_FROM_PTE1( pte1 );
645    pt2     = ppm_ppn2base( pt2_ppn );
646 
647    // get pointer on PTE2
648        pte2_ptr = &pt2[2 * ix2];
649
650    // get PTE2_ATTR
651        attr = *pte2_ptr;
652
653    // check PTE2 present and locked
654    if( ((attr & GPT_MAPPED) == 0) || ((attr & GPT_LOCKED) == 0) );
655    {
656        printk("\n[ERROR] in %s : try to unlock an undefined page / PT1[%d] = %x\n",
657                 __FUNCTION__ , ix1 , pte1 );
658        return EINVAL;
659    }
660
661    // reset GPT_LOCK
662        *pte2_ptr = attr & !GPT_LOCKED;
663
664        return 0;
665}  // end hal_gpt_unlock_pte()
666
667
668
669
670
671
672
673
Note: See TracBrowser for help on using the repository browser.