source: trunk/kernel/mm/ppm.h @ 654

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

This version is a major evolution: The physical memory allocators,
defined in the kmem.c, ppm.c, and kcm.c files have been modified
to support remote accesses. The RPCs that were previously user
to allocate physical memory in a remote cluster have been removed.
This has been done to cure a dead-lock in case of concurrent page-faults.

This version 2.2 has been tested on a (4 clusters / 2 cores per cluster)
TSAR architecture, for both the "sort" and the "fft" applications.

File size: 15.1 KB
RevLine 
[1]1/*
[567]2 * ppm.h - Per-cluster Physical Pages Manager definition.
[18]3 *
[1]4 * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
[623]5 *          Alain Greiner    (2016,2017,2018,2019)
[1]6 *
7 * Copyright (c) UPMC Sorbonne Universites
8 *
9 * This file is part of ALMOS-MKH.
10 *
11 * ALMOS-kernel is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2.0 of the License.
14 *
15 * ALMOS-kernel is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with ALMOS-kernel; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#ifndef _PPM_H_
26#define _PPM_H_
27
[457]28#include <hal_kernel_types.h>
[1]29#include <list.h>
[567]30#include <busylock.h>
[606]31#include <remote_queuelock.h>
[1]32#include <boot_info.h>
33#include <page.h>
34
35
36/*****************************************************************************************
[409]37 * This structure defines the Physical Pages Manager in a cluster.
38 * In each cluster, the physical memory bank starts at local physical address 0 and
[623]39 * contains an integer number of small pages, defined by the <pages_nr> field in the
[50]40 * boot_info structure. It is split in three parts:
[606]41 *
[50]42 * - the "kernel_code" section contains the kernel code, loaded by the boot-loader.
[623]43 *   It starts at local PPN = 0 and the size is defined by the <pages_offset> field
44 *   in the boot_info structure.
45 * - the local "pages_tbl" section contains the physical page descriptors array.
46 *   It starts at local PPN = pages_offset, and it contains one entry per small page.
[567]47 *   It is created and initialized by the hal_ppm_create() function.
[50]48 * - The "kernel_heap" section contains all physical pages that are are not in the
[623]49 *   "kernel_code" and "pages_tbl" sections, and that have not been reserved.
50 *   The reserved pages are defined in the boot_info structure.
[160]51 *
[50]52 * The main service provided by the PMM is the dynamic allocation of physical pages
[632]53 * from the "kernel_heap" section. This low-level allocator implements the "buddy"
[567]54 * algorithm: an allocated block is an integer number n of small pages, where n
[632]55 * is a power of 2, and ln(n) is called order. The free_pages_root[] array contains
56 * the roots ot the local lists of free pages for different sizes, as required by
57 * the "buddy" algorithm.
58 * The local threads can access these free_lists by calling the ppm_alloc_pages() and
59 * ppm_free_page() functions, but the remote threads can access the same free lists,
60 * by calling the ppm_remote_alloc_pages() and ppm_remote_free_pages functions.
61 * Therefore, these free lists are protected by a remote_busy_lock.
62 *
63 * Another service is to register the dirty pages in a specific local dirty_list,
[623]64 * also rooted in the PPM, in order to be able to synchronize all dirty pages on disk.
[606]65 * This dirty list is protected by a specific remote_queuelock, because it can be
[632]66 * modified by a remote thread.
[1]67 ****************************************************************************************/
[50]68
[1]69typedef struct ppm_s
70{
[632]71        remote_busylock_t   free_lock;          /*! lock protecting free_pages[] lists      */
[606]72        list_entry_t        free_pages_root[CONFIG_PPM_MAX_ORDER];  /*! roots of free lists */
73        uint32_t            free_pages_nr[CONFIG_PPM_MAX_ORDER];    /*! free pages number   */
74        page_t            * pages_tbl;          /*! pointer on page descriptors array       */
75        uint32_t            pages_nr;           /*! total number of small physical page     */
76    remote_queuelock_t  dirty_lock;         /*! lock protecting dirty pages list        */
77    list_entry_t        dirty_root;         /*! root of dirty pages list                */
78    void              * vaddr_base;         /*! pointer on local physical memory base   */
[1]79}
80ppm_t;
81
[567]82/************** functions to allocate / release physical pages  *************************/
83
[1]84/*****************************************************************************************
[632]85 * This local allocator must be called by a thread running in local cluster.
86 * It allocates n contiguous physical 4 Kbytes pages from the local cluster, where
87 * n is a power of 2 defined by the <order> argument.
88 * In normal use, it should not be called directly, as the recommended way to allocate
[1]89 * physical pages is to call the generic allocator defined in kmem.h.
[7]90 *****************************************************************************************
[632]91 * @ order     : ln2( number of 4 Kbytes pages)
92 * @ returns a local pointer on the page descriptor if success / NULL if error.
[611]93 ****************************************************************************************/
[1]94page_t * ppm_alloc_pages( uint32_t order );
95
96/*****************************************************************************************
[632]97 * This function must be called by a thread running in local cluster to release
98 * physical pages. It takes the lock protecting the free_lists before register the
99 * released page in the relevant free_list.
[18]100 * In normal use, you do not need to call it directly, as the recommended way to free
[1]101 * physical pages is to call the generic allocator defined in kmem.h.
[7]102 *****************************************************************************************
[632]103 * @ page   : local pointer on the page descriptor to be released
[1]104 ****************************************************************************************/
105void ppm_free_pages( page_t * page );
106
107/*****************************************************************************************
[53]108 * This function does the same as the ppm_free_page() function, without taking the lock.
109 * It is used by the hal_ppm_init() function to initialize the pages_tbl[] array, when
110 * there is no concurrent access issue.
111 *****************************************************************************************
[632]112 * @ page   : local pointer on the page descriptor to be released
[53]113 ****************************************************************************************/
114void ppm_free_pages_nolock( page_t * page );
115
116/*****************************************************************************************
[632]117 * This remote  allocator can be called by any thread running in any cluster.
118 * It allocates n contiguous physical 4 Kbytes pages from cluster identified
119 * by the <cxy> argument, where n is a power of 2 defined by the <order> argument.
120 * In normal use, it should not be called directly, as the recommended way to allocate
121 * physical pages is to call the generic allocator defined in kmem.h.
[7]122 *****************************************************************************************
[632]123 * @ cxy       : remote cluster identifier.
124 * @ order     : ln2( number of 4 Kbytes pages)
[635]125 * @ returns a local pointer on remote page descriptor if success / XPTR_NULL if error.
[1]126 ****************************************************************************************/
[635]127void *  ppm_remote_alloc_pages( cxy_t    cxy,
[632]128                                uint32_t order );
[1]129
[632]130/*****************************************************************************************
131 * This function can be called by any thread running in any cluster to release physical
132 * pages to a remote cluster. It takes the lock protecting the free_list before register
133 * the released page in the relevant free_list.
134 * In normal use, you do not need to call it directly, as the recommended way to free
135 * physical pages is to call the generic allocator defined in kmem.h.
136 *****************************************************************************************
137 * @ cxy       : remote cluster identifier.
138 * @ page      : local pointer on the page descriptor to be released in remote cluster.
139 ****************************************************************************************/
140void ppm_remote_free_pages( cxy_t    cxy,
141                            page_t * page );
[315]142
[632]143/*****************************************************************************************
144 * This debug function can be called by any thread running in any cluster to display
145 * the current PPM state of a remote cluster.
146 *****************************************************************************************
147 * @ cxy       : remote cluster identifier.
148 ****************************************************************************************/
149void ppm_remote_display( cxy_t cxy );
150
151
[567]152/************** functions to translate [ page <->  base <-> ppn ] ***********************/
[315]153
[1]154/*****************************************************************************************
[315]155 * Get extended pointer on page base from extended pointer on page descriptor.
[7]156 *****************************************************************************************
[315]157 * @ page_xp    : extended pointer to page descriptor
158 * @ returns extended pointer on page base.
[1]159 ****************************************************************************************/
[315]160inline xptr_t ppm_page2base( xptr_t page_xp );
[1]161
162/*****************************************************************************************
[315]163 * Get extended pointer on page descriptor from extended pointer on page base.
[7]164 *****************************************************************************************
[315]165 * @ base_xp   : extended pointer to page base.
166 * @ returns extended pointer on page descriptor
[1]167 ****************************************************************************************/
[315]168inline xptr_t ppm_base2page( xptr_t base_xp );
[1]169
170/*****************************************************************************************
[407]171 * Get extended pointer on page base from global PPN.
[315]172 *****************************************************************************************
173 * @ ppn    : global physical page number.
174 * @ returns extended pointer on page base.
175 ****************************************************************************************/
176inline xptr_t ppm_ppn2base( ppn_t ppn );
177
178/*****************************************************************************************
179 * Get global PPN from extended pointer on page base.
180 *****************************************************************************************
181 * @ base_xp   : extended pointer to page base.
182 * @ returns global physical page number.
183 ****************************************************************************************/
184inline ppn_t ppm_base2ppn( xptr_t base_xp );
185
186/*****************************************************************************************
187 * Get global PPN from extended pointer on page descriptor.
188 *****************************************************************************************
189 * @ page_xp   : pointer to page descriptor
190 * @ returns global physical page number.
191 ****************************************************************************************/
192inline ppn_t ppm_page2ppn( xptr_t page_xp );
193
194/*****************************************************************************************
195 * Get extended pointer on page descriptor from global PPN.
196 *****************************************************************************************
197 * @ ppn       : global physical page number
198 * @ returns extended pointer on page descriptor.
199 ****************************************************************************************/
200inline xptr_t ppm_ppn2page( ppn_t ppn );
201
202
[606]203/*********** debug  functions  **********************************************************/
[315]204
205/*****************************************************************************************
[632]206 * This function can be called by any thread running in any cluster.
207 * It displays the PPM allocator status in cluster identified by the <cxy> argument.
[611]208 *****************************************************************************************
[632]209 * @ cxy   : remote cluster
[1]210 ****************************************************************************************/
[632]211void ppm_remote_display( cxy_t cxy );
[1]212
213/*****************************************************************************************
[632]214 * This function must be called by a thread running in local cluster.
215 * It checks the consistency of the local PPM allocator.
[7]216 *****************************************************************************************
[53]217 * @ return 0 if PPM is OK / return -1 if PPM not consistent.
[1]218 ****************************************************************************************/
[632]219error_t ppm_assert_order( void );
[1]220
[567]221
222/*********** functions to handle dirty pages  *******************************************/
223
224/*****************************************************************************************
[606]225 * This function registers a page identified by the <page_xp> argument as dirty.
226 * It can be called by a thread running in any cluster.
[567]227 * - it takes the queuelock protecting the PPM dirty_list.
[610]228 * - it takes the busylock protecting the page flags.
[567]229 * - it test the PG_DIRTY flag in the page descriptor.
230 *   . if page already dirty => do nothing
231 *   . it page not dirty => set the PG_DIRTY flag and register page in PPM dirty list.
[623]232 * - it releases the busylock protecting the page flags.
[567]233 * - it releases the queuelock protecting the PPM dirty_list.
234 *****************************************************************************************
[606]235 * @ page_xp  : extended pointer on page descriptor.
[567]236 * @ returns true if page was not dirty / returns false if page was dirty
237 ****************************************************************************************/
[606]238bool_t ppm_page_do_dirty( xptr_t page_xp );
[567]239
240/*****************************************************************************************
[606]241 * This function unregisters a page identified by the <page_xp> argument as dirty.
242 * It can be called by a thread running in any cluster.
[567]243 * - it takes the queuelock protecting the PPM dirty_list.
[610]244 * - it takes the busylock protecting the page flags.
[567]245 * - it test the PG_DIRTY flag in the page descriptor.
246 *   . if page not dirty => do nothing
247 *   . it page dirty => reset the PG_DIRTY flag and remove page from PPM dirty list.
[623]248 * - it releases the busylock protecting the page flags.
[567]249 * - it releases the queuelock protecting the PPM dirty_list.
250 *****************************************************************************************
[606]251 * @ page_xp  : extended pointer on page descriptor.
[567]252 * @ returns true if page was dirty / returns false if page was not dirty
253 ****************************************************************************************/
[606]254bool_t ppm_page_undo_dirty( xptr_t page_xp );
[567]255
256/*****************************************************************************************
[606]257 * This function synchronizes (i.e. update the IOC device) all dirty pages in a cluster.
[567]258 * - it takes the queuelock protecting the PPM dirty_list.
259 * - it scans the PPM dirty list, and for each page:
260 *   . it takes the lock protecting the page.
261 *   . it removes the page from the PPM dirty_list.
262 *   . it reset the PG_DIRTY flag.
263 *   . it releases the lock protecting the page.
264 * - it releases the queuelock protecting the PPM dirty_list.
265 $ The PPM dirty_list is empty when the sync operation completes.
266 ****************************************************************************************/
[606]267void ppm_sync_dirty_pages( void );
[567]268
[1]269#endif  /* _PPM_H_ */
Note: See TracBrowser for help on using the repository browser.