source: soft/giet_vm/giet_common/vmem.c @ 751

Last change on this file since 751 was 751, checked in by alain, 8 years ago

Introduce the _v2p_add_pte1(), _v2p_add_pte2(), _v2p_del_pte1(), _v2p_del_pte2() functions
to support dynamic mapping / unmapping associated to the giet_fat_mmap() and giet_fat_munmap() system calls.

  • Property svn:executable set to *
File size: 11.0 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : vmem.c
3// Date     : 01/07/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <tty0.h>
9#include <utils.h>
10#include <vmem.h>
11#include <ctx_handler.h>
12#include <kernel_locks.h>
13#include <giet_config.h>
14
15//////////////////////////////////////////////////////////////////////////////////
16// Extern global variables (allocated in boot.c or kernel_init.c)
17//////////////////////////////////////////////////////////////////////////////////
18
19extern  spin_lock_t         _ptabs_spin_lock[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
20extern  unsigned long long  _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
21extern  unsigned int        _ptabs_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
22extern  unsigned int        _ptabs_max_pt2;
23
24///////////////////////////////////////////////////////
25unsigned long long _v2p_translate( unsigned int  vaddr,
26                                   unsigned int* flags )
27{
28    unsigned long long ptba;
29    unsigned long long pte2_paddr;
30
31    unsigned int pte2_msb;
32    unsigned int pte2_lsb;
33    unsigned int flags_value;
34    unsigned int ppn_value;
35
36    unsigned int save_sr;
37 
38    // decode the vaddr fields
39    unsigned int offset = vaddr & 0xFFF;
40    unsigned int ix1    = (vaddr >> 21) & 0x7FF;
41    unsigned int ix2    = (vaddr >> 12) & 0x1FF;
42
43    // get page table vbase address
44    page_table_t* pt = (page_table_t*)_get_context_slot(CTX_PTAB_ID);
45
46    // get PTE1
47    unsigned int pte1 = pt->pt1[ix1];
48
49    // check PTE1 mapping
50    if ( (pte1 & PTE_V) == 0 )
51    {
52        _printf("\n[VMEM ERROR] _v2p_translate() : pte1 unmapped\n"
53                "  vaddr = %x / ptab = %x / pte1_vaddr = %x / pte1_value = %x\n",
54                vaddr , (unsigned int)pt, &(pt->pt1[ix1]) , pte1 );
55        _exit();
56    }
57
58    // test big/small page
59    if ( (pte1 & PTE_T) == 0 )  // big page
60    {
61        *flags = pte1 & 0xFFC00000;
62        offset = offset | (ix2<<12);
63        return (((unsigned long long)(pte1 & 0x7FFFF)) << 21) | offset;
64    }
65    else                        // small page
66    {
67
68        // get physical addresses of pte2
69        ptba       = ((unsigned long long)(pte1 & 0x0FFFFFFF)) << 12;
70        pte2_paddr = ptba + 8*ix2;
71
72        // split physical address in two 32 bits words
73        pte2_lsb   = (unsigned int) pte2_paddr;
74        pte2_msb   = (unsigned int) (pte2_paddr >> 32);
75
76        // disable interrupts and save status register
77        _it_disable( &save_sr );
78
79        // get ppn_value and flags_value, using a physical read
80        // after temporary DTLB desactivation
81        asm volatile (
82                "mfc2    $2,     $1          \n"     /* $2 <= MMU_MODE       */
83                "andi    $3,     $2,    0xb  \n"
84                "mtc2    $3,     $1          \n"     /* DTLB off             */
85
86                "move    $4,     %3          \n"     /* $4 <= pte_lsb        */
87                "mtc2    %2,     $24         \n"     /* PADDR_EXT <= pte_msb */
88                "lw      %0,     0($4)       \n"     /* read flags           */ 
89                "lw      %1,     4($4)       \n"     /* read ppn             */
90                "mtc2    $0,     $24         \n"     /* PADDR_EXT <= 0       */
91
92                "mtc2    $2,     $1          \n"     /* restore MMU_MODE     */
93                : "=r" (flags_value), "=r" (ppn_value)
94                : "r"  (pte2_msb)   , "r"  (pte2_lsb)
95                : "$2", "$3", "$4" );
96
97        // restore saved status register
98        _it_restore( &save_sr );
99
100        // check PTE2 mapping
101        if ( (flags_value & PTE_V) == 0 )
102        {
103            _printf("\n[VMEM ERROR] _v2p_translate() : pte2 unmapped\n"
104                    "  vaddr = %x / ptab = %x / pte1_value = %x\n"
105                    "  pte2_paddr = %l / ppn = %x / flags = %x\n",
106                    vaddr , pt , pte1 , pte2_paddr ,  ppn_value , flags_value );
107            _exit();
108        }
109
110        *flags = flags_value & 0xFFC00000;
111        return (((unsigned long long)(ppn_value & 0x0FFFFFFF)) << 12) | offset;
112    }
113} // end _v2p_translate()
114
115
116////////////////////////////////////////////
117void _v2p_add_pte1( unsigned int vspace_id,
118                    unsigned int x,
119                    unsigned int y,
120                    unsigned int vpn,        // 20 bits right-justified
121                    unsigned int flags,      // 10 bits left-justified
122                    unsigned int ppn,        // 28 bits right-justified
123                    unsigned int ident )     // identity mapping if non zero
124{
125    unsigned int   pte1;     // PTE1 value
126    paddr_t        paddr;    // PTE1 physical address
127
128    // compute index in PT1
129    unsigned int    ix1 = vpn >> 9;         // 11 bits for ix1
130
131    // get PT1 physical base address
132    paddr_t  pt1_base = _ptabs_paddr[vspace_id][x][y];
133
134    if ( pt1_base == 0 )
135    {
136        _printf("\n[GIET ERROR] in _v2p_add_pte1() : no PTAB in cluster[%d,%d]"
137                    " containing processors\n", x , y );
138        _exit();
139    }
140
141    // get lock protecting PTAB[vspace_id][x][y]
142    _spin_lock_acquire( &_ptabs_spin_lock[vspace_id][x][y] );
143
144    // compute pte1 physical address
145    paddr = pt1_base + 4*ix1;
146
147    // check PTE1 not already mapped
148    if ( ident == 0 )
149    {
150        if ( _physical_read( paddr ) & PTE_V )
151        {
152            _printf("\n[GIET ERROR] in _v2p_add_pte1() : vpn %x already mapped "
153                    "in PTAB[%d,%d] for vspace %d\n", vpn , x , y , vspace_id );
154            _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
155            _exit();
156        }
157    }
158
159    // compute pte1 : 2 bits V T / 8 bits flags / 3 bits RSVD / 19 bits bppi
160    pte1 = PTE_V | (flags & 0x3FC00000) | ((ppn>>9) & 0x0007FFFF);
161
162    // write pte1 in PT1
163    _physical_write( paddr , pte1 );
164
165    // release lock protecting PTAB[vspace_id][x][y]
166    _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
167
168    asm volatile ("sync");
169
170}   // end _v2p_add_pte1()
171
172
173
174///////////////////////////////////////////
175void _v2p_add_pte2( unsigned int vspace_id,
176                    unsigned int x,
177                    unsigned int y,
178                    unsigned int vpn,        // 20 bits right-justified
179                    unsigned int flags,      // 10 bits left-justified
180                    unsigned int ppn,        // 28 bits right-justified
181                    unsigned int ident )     // identity mapping if non zero
182{
183    unsigned int ix1;
184    unsigned int ix2;
185    paddr_t      pt2_pbase;     // PT2 physical base address
186    paddr_t      pte2_paddr;    // PTE2 physical address
187    unsigned int pt2_id;        // PT2 index
188    unsigned int ptd;           // PTD : entry in PT1
189
190    ix1 = vpn >> 9;             // 11 bits for ix1
191    ix2 = vpn & 0x1FF;          //  9 bits for ix2
192
193    // get page table physical base address
194    paddr_t      pt1_pbase = _ptabs_paddr[vspace_id][x][y];
195
196    if ( pt1_pbase == 0 )
197    {
198        _printf("\n[GIET ERROR] in _v2p_add_pte2() : no PTAB for vspace %d "
199                "in cluster[%d,%d]\n", vspace_id , x , y );
200        _exit();
201    }
202
203    // get lock protecting PTAB[vspace_id][x][y]
204    _spin_lock_acquire( &_ptabs_spin_lock[vspace_id][x][y] );
205
206    // get ptd in PT1
207    ptd = _physical_read( pt1_pbase + 4 * ix1 );
208
209    if ((ptd & PTE_V) == 0)    // undefined PTD: compute PT2 base address,
210                               // and set a new PTD in PT1
211    {
212        // get a new pt2_id
213        pt2_id = _ptabs_next_pt2[vspace_id][x][y];
214        _ptabs_next_pt2[vspace_id][x][y] = pt2_id + 1;
215
216        // check overflow
217        if (pt2_id == _ptabs_max_pt2) 
218        {
219            _printf("\n[GIET ERROR] in _v2p_add_pte2() : PTAB[%d,%d,%d]"
220                    " contains not enough PT2s\n", vspace_id, x, y );
221            _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
222            _exit();
223        }
224
225        pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id;
226        ptd = PTE_V | PTE_T | (unsigned int) (pt2_pbase >> 12);
227
228        // set PTD into PT1
229        _physical_write( pt1_pbase + 4*ix1, ptd);
230    }
231    else                       // valid PTD: compute PT2 base address
232    {
233        pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
234    }
235
236    // set PTE in PT2 : flags & PPN in two 32 bits words
237    pte2_paddr  = pt2_pbase + 8 * ix2;
238    _physical_write(pte2_paddr     , (PTE_V | flags) );
239    _physical_write(pte2_paddr + 4 , ppn );
240
241    // release lock protecting PTAB[vspace_id][x][y]
242    _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
243
244    asm volatile ("sync");
245
246}   // end _v2p_add_pte2()
247
248////////////////////////////////////////////
249void _v2p_del_pte1( unsigned int vspace_id,
250                    unsigned int x,
251                    unsigned int y,
252                    unsigned int vpn )       // 20 bits right-justified
253{
254    unsigned int ix1 = vpn >> 9;             // 11 bits for ix1
255
256    // get page table physical base address
257    paddr_t pt1_pbase = _ptabs_paddr[vspace_id][x][y];
258
259    // check PTAB defined
260    if ( pt1_pbase == 0 )
261    {
262        _printf("\n[GIET ERROR] in _v2p_del_pte1() : no PTAB for vspace %d "
263                "in cluster[%d,%d]\n", vspace_id , x , y );
264        _exit();
265    }
266
267    // get ptd in PT1
268    paddr_t ptd_paddr = pt2_pbase + 4 * ix1;
269    unsigned int ptd = _physical_read( ptd_paddr );
270
271    // check ptd valid
272    if ((ptd & PTE_V) == 0)   
273    {
274        _printf("\n[GIET ERROR] in _v2p_del_pte1() : vpn %x not mapped in PT1"
275                "for vspace %d in cluster[%d,%d]\n", vpn , vspace_id , x , y );
276        _exit();
277    }
278
279    // invalidate PTD in PT1
280    _physical_write( ptd_paddr , 0 );
281
282}   // end _v2p_del_pte1()
283 
284////////////////////////////////////////////
285void _v2p_del_pte2( unsigned int vspace_id,
286                    unsigned int x,
287                    unsigned int y,
288                    unsigned int vpn )       // 20 bits right-justified
289{
290    unsigned int ix1 = vpn >> 9;             // 11 bits for ix1
291    unsigned int ix2 = vpn & 0x1FF;          //  9 bits for ix2
292
293    // get page table physical base address
294    paddr_t pt1_pbase = _ptabs_paddr[vspace_id][x][y];
295
296    // check PTAB defined
297    if ( pt1_pbase == 0 )
298    {
299        _printf("\n[GIET ERROR] in _v2p_del_pte2() : no PTAB for vspace %d "
300                "in cluster[%d,%d]\n", vspace_id , x , y );
301        _exit();
302    }
303
304    // get ptd in PT1
305    unsigned int ptd = _physical_read( pt1_pbase + 4 * ix1 );
306
307    // check ptd valid
308    if ((ptd & PTE_V) == 0)   
309    {
310        _printf("\n[GIET ERROR] in _v2p_del_pte2() : vpn %x not mapped in PT1"
311                "for vspace %d in cluster[%d,%d]\n", vpn , vspace_id , x , y );
312        _exit();
313    }
314
315    // get PT2 physical base address
316    paddr_t  pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
317
318    // invalidate PTE in PT2
319    paddr_t pte2_paddr  = pt2_pbase + 8 * ix2;
320    _physical_write( pte2_paddr , 0 );
321
322    asm volatile ("sync");
323
324}  // end _v2p_del_pte2()
325
326
327
328// Local Variables:
329// tab-width: 4
330// c-basic-offset: 4
331// c-file-offsets:((innamespace . 0)(inline-open . 0))
332// indent-tabs-mode: nil
333// End:
334// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
335
336
Note: See TracBrowser for help on using the repository browser.