source: trunk/hal/tsar_mips32/core/hal_vmm.c @ 625

Last change on this file since 625 was 625, checked in by alain, 3 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

File size: 10.3 KB
Line 
1/*
2 * hal_vmm.c - Virtual Memory Manager Initialisation for TSAR
3 *
4 * Authors  Alain Greiner (2016,2017,2018,2019)
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 <kernel_config.h>
25#include <hal_kernel_types.h>
26#include <hal_vmm.h>
27#include <hal_gpt.h>
28#include <process.h>
29#include <thread.h>
30#include <vseg.h>
31#include <xlist.h>
32#include <vmm.h>
33#include <remote_rwlock.h>
34
35//////////////////////////////////////////////////////////////////////////////////////////
36// This file contains the TSAR specific code used to initialize the kernel process VMM,
37// or to update an user process VMM with informations related to the kernel vsegs.
38// As the TSAR architure does not use the DATA MMU, but use only the DATA extension
39// address register to access local and remote kernel data, the kernel VSL contains only
40// one "kcode" segment, and the kernel GPT contains only one big page in PT1[0] slot.
41//////////////////////////////////////////////////////////////////////////////////////////
42
43// extern global variables
44extern process_t            process_zero;
45extern chdev_directory_t    chdev_dir;
46
47//////////////////////////////////////////////////////////////////////////////////////////
48// This function is called by the process_zero_init() function during kernel_init.
49// It initializes the VMM of the kernel proces_zero (containing all kernel threads)
50// in the local cluster: For TSAR, it registers one "kcode" vseg in kernel VSL,
51// and registers one big page in slot[0] of kernel GPT.
52//////////////////////////////////////////////////////////////////////////////////////////
53error_t  hal_vmm_kernel_init( boot_info_t * info )
54{
55    error_t   error;
56
57    // get pointer on kernel GPT
58    gpt_t * gpt = &process_zero.vmm.gpt;
59
60    // get cluster identifier
61    cxy_t cxy = local_cxy;
62
63    // allocate memory for kernel GPT
64    error = hal_gpt_create( gpt );
65
66    if( error )
67    {
68        printk("\n[PANIC] in %s : cannot allocate kernel GPT in cluster %x\n",
69        __FUNCTION__ , cxy );
70        hal_core_sleep();
71    }
72
73#if DEBUG_HAL_VMM
74thread_t * this = CURRENT_THREAD;
75printk("\n[%s] thread[%x,%x] enter in cluster %x / gpt %x\n", 
76__FUNCTION__, this->process->pid, this->trdid, local_cxy, gpt );
77#endif
78
79    // compute attr and ppn for one PTE1
80    uint32_t attr = GPT_MAPPED | GPT_READABLE | GPT_CACHABLE | GPT_EXECUTABLE | GPT_GLOBAL;
81    uint32_t ppn  = cxy << 20;   
82
83    // register PTE1  in slot[0] of kernel GPT
84    error = hal_gpt_set_pte( XPTR( cxy , gpt ) , 0 , attr , ppn );
85
86    if( error )
87    {
88        printk("\n[PANIC] in %s : cannot initialize kernel GPT in cluster %x\n",
89        __FUNCTION__ , cxy );
90        hal_core_sleep();
91    }
92
93#if DEBUG_HAL_VMM
94printk("\n[%s] thread[%x,%x] created PT1[0] : ppn %x / attr %x\n", 
95__FUNCTION__, this->process->pid, this->trdid, ppn, attr );
96#endif
97
98    // create kcode vseg and register it in kernel VSL
99    vseg_t * vseg = vmm_create_vseg( &process_zero,
100                                     VSEG_TYPE_KCODE,
101                                     info->kcode_base,
102                                     info->kcode_size,
103                                     0, 0,                  // file ofset and file size (unused)
104                                     XPTR_NULL,             // no mapper
105                                     local_cxy );
106    if( vseg == NULL )
107    {
108        printk("\n[PANIC] in %s : cannot register vseg to VSL in cluster %x\n",
109        __FUNCTION__ , cxy );
110        hal_core_sleep();
111    }
112
113#if DEBUG_HAL_VMM
114printk("\n[%s] thread[%x,%x] registered kcode vseg[%x,%x]\n",
115__FUNCTION__, this->process->pid, this->trdid, info->kcode_base, info->kcode_size );
116hal_vmm_display( &process_zero , true );
117#endif
118
119    return 0;
120
121}  // end hal_vmm_kernel_init()
122
123//////////////////////////////////////////////////////////////////////////////////////////
124// This function registers in the VMM of an user process identified by the <process>
125// argument all required kernel vsegs.
126// For TSAR, it registers in the user VSL the "kcode" vseg, from the local kernel VSL,
127// and register in the user GPT the big page[0] from the local kernel GPT.
128//////////////////////////////////////////////////////////////////////////////////////////
129error_t hal_vmm_kernel_update( process_t * process )
130{
131    error_t  error;
132    uint32_t attr;
133    uint32_t ppn;
134
135    // get cluster identifier
136    cxy_t cxy = local_cxy;
137
138#if DEBUG_HAL_VMM
139thread_t * this = CURRENT_THREAD;
140printk("\n[%s] thread[%x,%x] enter in cluster %x \n", 
141__FUNCTION__, this->process->pid, this->trdid, cxy );
142hal_vmm_display( &process_zero , true );
143hal_vmm_display( process , true );
144#endif
145
146    // get extended pointer on local kernel GPT
147    xptr_t k_gpt_xp = XPTR( cxy , &process_zero.vmm.gpt );
148
149    // get ppn and attributes from slot[0] of kernel GPT
150    hal_gpt_get_pte( k_gpt_xp , 0 , &attr , &ppn );
151
152#if DEBUG_HAL_VMM
153printk("\n[%s] thread[%x,%x] get PT1[0] ( ppn %x / attr %x ) from kernel  GPT\n", 
154__FUNCTION__, this->process->pid, this->trdid, ppn, attr );
155#endif
156
157    // get extended pointer on user GPT
158    xptr_t u_gpt_xp = XPTR( cxy , &process->vmm.gpt );
159
160    // update user GPT : set PTE1 in slot[0]
161    error = hal_gpt_set_pte( u_gpt_xp , 0 , attr , ppn );
162
163    if( error )
164    {
165        printk("\n[ERROR] in %s : cannot update user GPT in cluster %x\n",
166        __FUNCTION__ , cxy );
167        return -1;
168    }
169
170#if DEBUG_HAL_VMM
171printk("\n[%s] thread[%x,%x] registered PT1[0] ( ppn %x / attr %x ) to user GPT\n", 
172__FUNCTION__, this->process->pid, this->trdid, ppn, attr );
173#endif
174
175    // get pointer on the unique vseg registered in kernel VSL
176    xptr_t   root_xp = XPTR( cxy , &process_zero.vmm.vsegs_root );
177    xptr_t   vseg_xp = XLIST_FIRST( root_xp , vseg_t , xlist );
178    vseg_t * vseg    = GET_PTR( vseg_xp );
179
180// check vsegs_nr
181assert( (process_zero.vmm.vsegs_nr == 1 ) ,
182"bad vsegs number in kernel VSL = %d\n", process_zero.vmm.vsegs_nr );
183
184    // update user VSL : register one new vseg for kcode
185    vseg_t * new = vmm_create_vseg( process,
186                                    vseg->type,
187                                    vseg->min,
188                                    vseg->max - vseg->min,
189                                    0, 0,                  // file ofset and file size (unused)
190                                    XPTR_NULL,             // no mapper
191                                    local_cxy );
192    if( new == NULL )
193    {
194        printk("\n[ERROR] in %s : cannot update user VSL in cluster %x\n",
195        __FUNCTION__ , cxy );
196        return -1;
197    }
198
199#if DEBUG_HAL_VMM
200printk("\n[%s] thread[%x,%x] created vseg %s ( base %x / size %x ) to user VSL\n", 
201__FUNCTION__, this->process->pid, this->trdid,
202vseg_type_str(vseg->type) , vseg->min, (vseg->max - vseg->min) );
203hal_vmm_display( process , true );
204#endif
205
206    return 0;
207
208}  // end hal_vmm_kernel_update()
209
210//////////////////////////////////////////
211void hal_vmm_display( process_t * process,
212                      bool_t      mapping )
213{
214    // get pointer on process VMM
215    vmm_t * vmm = &process->vmm;
216
217    // get pointers on TXT0 chdev
218    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
219    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
220    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
221
222    // build extended pointers on TXT0 lock, GPT lock and VSL lock
223    xptr_t  txt_lock_xp = XPTR( txt0_cxy  , &txt0_ptr->wait_lock );
224    xptr_t  vsl_lock_xp = XPTR( local_cxy , &vmm->vsl_lock );
225    xptr_t  gpt_lock_xp = XPTR( local_cxy , &vmm->gpt_lock );
226
227    // get root of vsegs list
228    xptr_t root_xp = XPTR( local_cxy , &vmm->vsegs_root );
229
230    // get the locks protecting TXT0, VSL, and GPT
231    remote_rwlock_rd_acquire( vsl_lock_xp );
232    remote_rwlock_rd_acquire( gpt_lock_xp );
233    remote_busylock_acquire( txt_lock_xp );
234
235    nolock_printk("\n***** VSL and GPT for process %x in cluster %x / PT1 = %x\n",
236    process->pid , local_cxy , vmm->gpt.ptr );
237
238    if( xlist_is_empty( root_xp ) )
239    {
240        nolock_printk("   ... no vsegs registered\n");
241    }
242    else  // scan the list of vsegs
243    {
244        xptr_t         iter_xp;
245        xptr_t         vseg_xp;
246        vseg_t       * vseg;
247
248        XLIST_FOREACH( root_xp , iter_xp )
249        {
250            vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
251            vseg    = GET_PTR( vseg_xp );
252
253            nolock_printk(" - %s : base = %X / size = %X / npages = %d\n",
254            vseg_type_str(vseg->type), vseg->min, vseg->max - vseg->min, vseg->vpn_size );
255
256            if( mapping ) 
257            {
258                vpn_t    vpn     = vseg->vpn_base;
259                vpn_t    vpn_max = vpn + vseg->vpn_size;
260                ppn_t    ppn;
261                uint32_t attr;
262
263                while( vpn < vpn_max )   // scan the PTEs
264                {
265                    hal_gpt_get_pte( XPTR( local_cxy , &vmm->gpt ) , vpn , &attr , &ppn );
266
267                    if( attr & GPT_MAPPED )
268                    {
269                        if( attr & GPT_SMALL )
270                        {
271                            nolock_printk("    . SMALL : vpn = %X / attr = %X / ppn = %X\n",
272                            vpn , attr , ppn );
273                            vpn++;
274                        }
275                        else
276                        {
277                            nolock_printk("    . BIG   : vpn = %X / attr = %X / ppn = %X\n",
278                            vpn , attr , ppn );
279                            vpn += 512;
280                        }
281                    }
282                    else
283                    {
284                        vpn++;
285                    }
286                }
287            }
288        }
289    }
290
291    // release locks
292    remote_busylock_release( txt_lock_xp );
293    remote_rwlock_rd_release( gpt_lock_xp );
294    remote_rwlock_rd_release( vsl_lock_xp );
295
296}  // hal_vmm_display()
297
Note: See TracBrowser for help on using the repository browser.