1 /*
2  * Copyright (C) 2018-2024 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <types.h>
7 #include <asm/lib/bits.h>
8 #include <asm/page.h>
9 #include <logmsg.h>
10 
11 /**
12  * @addtogroup hwmgmt_page
13  *
14  * @{
15  */
16 
17 /**
18  * @file
19  * @brief Implementation of page management.
20  *
21  * This file provides the core functionality required for allocating and freeing memory pages. It's a fundamental
22  * support to manage memory resources.
23  */
24 
alloc_page(struct page_pool * pool)25 struct page *alloc_page(struct page_pool *pool)
26 {
27 	struct page *page = NULL;
28 	uint64_t loop_idx, idx, bit;
29 
30 	spinlock_obtain(&pool->lock);
31 	for (loop_idx = pool->last_hint_id;
32 		loop_idx < (pool->last_hint_id + pool->bitmap_size); loop_idx++) {
33 		idx = loop_idx % pool->bitmap_size;
34 		if (*(pool->bitmap + idx) != ~0UL) {
35 			bit = ffz64(*(pool->bitmap + idx));
36 			bitmap_set_nolock(bit, pool->bitmap + idx);
37 			page = pool->start_page + ((idx << 6U) + bit);
38 
39 			pool->last_hint_id = idx;
40 			break;
41 		}
42 	}
43 	spinlock_release(&pool->lock);
44 
45 	ASSERT(page != NULL, "no page aviable!");
46 	page = (page != NULL) ? page : pool->dummy_page;
47 	if (page == NULL) {
48 		/* For HV MMU page-table mapping, we didn't use dummy page when there's no page
49 		 * available in the page pool. This because we only do MMU page-table mapping on
50 		 * the early boot time and we reserve enough pages for it. After that, we would
51 		 * not do any MMU page-table mapping. We would let the system boot fail when page
52 		 * allocation failed.
53 		 */
54 		panic("no dummy aviable!");
55 	}
56 	(void)memset(page, 0U, PAGE_SIZE);
57 	return page;
58 }
59 
60 /*
61  *@pre: ((page - pool->start_page) >> 6U) < pool->bitmap_size
62  */
free_page(struct page_pool * pool,struct page * page)63 void free_page(struct page_pool *pool, struct page *page)
64 {
65 	uint64_t idx, bit;
66 
67 	spinlock_obtain(&pool->lock);
68 	idx = (page - pool->start_page) >> 6U;
69 	bit = (page - pool->start_page) & 0x3fUL;
70 	bitmap_clear_nolock(bit, pool->bitmap + idx);
71 	spinlock_release(&pool->lock);
72 }
73 
74 /**
75  * @}
76  */