source: trunk/hal/x86_64/core/hal_ppm.c @ 116

Last change on this file since 116 was 116, checked in by max@…, 5 years ago

complete hal_ppm_init, to take into account the reserved areas

File size: 3.5 KB
Line 
1/*
2 * hal_ppm.c - Generic Physical Page Manager API implementation for x86
3 *
4 * Copyright (c) 2017 Maxime Villard
5 *
6 * This file is part of ALMOS-MKH.
7 *
8 * ALMOS-MKH is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.0 of the License.
11 *
12 * ALMOS-MKH is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <kernel_config.h>
23#include <hal_types.h>
24#include <hal_ppm.h>
25#include <hal_special.h>
26#include <printk.h>
27#include <spinlock.h>
28#include <process.h>
29#include <ppm.h>
30#include <thread.h>
31#include <cluster.h>
32#include <page.h>
33
34#include <hal_boot.h>
35#include <hal_internal.h>
36
37error_t hal_ppm_init(boot_info_t *info)
38{
39        boot_rsvd_t *rsvd;
40        size_t i, j;
41
42        // get relevant info from boot_info structure
43        uint32_t pages_nr         = info->pages_nr;
44        uint32_t pages_tbl_offset = info->pages_offset;
45        uint32_t rsvd_nr          = info->rsvd_nr;
46
47        // get pointer on local Physical Page Manager
48        ppm_t * ppm = &LOCAL_CLUSTER->ppm;
49
50        // initialize lock protecting the free_pages[] lists
51        spinlock_init( &ppm->free_lock );
52
53        // initialize lock protecting the dirty_pages list
54        spinlock_init( &ppm->dirty_lock );
55
56        // initialize all free_pages[] lists as empty
57        for( i = 0 ; i < CONFIG_PPM_MAX_ORDER ; i++ )
58        {
59                list_root_init( &ppm->free_pages_root[i] );
60                ppm->free_pages_nr[i] = 0;
61        }
62
63        // initialize dirty_list as empty
64        list_root_init( &ppm->dirty_root );
65
66        // compute size of pages_tbl[] array rounded to an integer number of pages
67        uint32_t bytes = ARROUND_UP( pages_nr * sizeof(page_t), CONFIG_PPM_PAGE_SIZE );
68
69        // compute number of pages required to store page descriptor array
70        uint32_t pages_tbl_nr = bytes >> CONFIG_PPM_PAGE_SHIFT;
71
72        // compute total number of reserved pages (kernel code & pages_tbl[])
73        uint32_t reserved_pages = pages_tbl_offset + pages_tbl_nr;
74
75        // initialize pages_nr, pages_tbl, and vaddr_base pointers
76        ppm->pages_nr   = pages_nr;
77        ppm->vaddr_base = (void *)CLUSTER_MIN_VA(0);
78        ppm->pages_tbl  = (page_t *)hal_gpt_bootstrap_valloc(pages_tbl_nr);
79
80        // make sure we respect the rule [VA = PA + constant_offset]
81        XASSERT(ppm->pages_tbl == ppm->vaddr_base + pages_tbl_offset * PAGE_SIZE);
82
83        // initialize all page descriptors in pages_tbl[]
84        for( i = 0 ; i < pages_nr ; i++ )
85        {
86                page_init( &ppm->pages_tbl[i] );
87
88                // TODO optimisation for this enormous loop on small pages:
89                // make only a partial init with a memset, and complete the
90                // initialisation when page is allocated [AG]
91        }
92
93        /*
94         * Set the PG_RESERVED flag for reserved pages (kernel, pages_tbl[] and
95         * memory holes).
96         */
97        for (i = 0; i < reserved_pages; i++) {
98                page_set_flag(&ppm->pages_tbl[i], PG_RESERVED);
99        }
100        for (i = 0; i < rsvd_nr; i++) {
101                rsvd = &info->rsvd[i];
102                for (j = 0; j < rsvd->npages; j++) {
103                        page_set_flag(&ppm->pages_tbl[rsvd->first_page + j], PG_RESERVED);
104                }
105        }
106
107        /* Release all other pages to populate the free lists */
108        for (i = reserved_pages; i < pages_nr; i++) {
109                if (!page_is_flag(&ppm->pages_tbl[i], PG_RESERVED))
110                        ppm_free_pages_nolock(&ppm->pages_tbl[i]);
111        }
112
113        /* Check consistency */
114        return ppm_assert_order(ppm);
115}
116
Note: See TracBrowser for help on using the repository browser.