1 /*
2  * Copyright (C) 2018-2024 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef PAGE_H
8 #define PAGE_H
9 
10 #include <asm/lib/spinlock.h>
11 #include <board_info.h>
12 
13 /**
14  * @defgroup hwmgmt_page hwmgmt.page
15  * @ingroup hwmgmt
16  * @brief Support the basic paging mechanism.
17  *
18  * This module mainly provides the interfaces to manipulate the paging structures.
19  * These operations are commonly used by:
20  * 1. hypervisor's MMU (Memory Management Unit) to manage the host page tables;
21  * 2. EPT to manage the extended page tables for guest.
22  * It also provides the interfaces to conduct the address translation between Host Physical Address and Host Virtual
23  * Address.
24  *
25  * @{
26  */
27 
28 /**
29  * @file
30  * @brief All APIs to support page management.
31  *
32  * This file defines macros, structures and function declarations for managing memory pages.
33  */
34 
35 #define PAGE_SHIFT	12U
36 #define PAGE_SIZE	(1U << PAGE_SHIFT)
37 #define PAGE_MASK	0xFFFFFFFFFFFFF000UL
38 
39 #define MAX_PHY_ADDRESS_SPACE	(1UL << MAXIMUM_PA_WIDTH)
40 
41 /* size of the low MMIO address space: 2GB */
42 #define PLATFORM_LO_MMIO_SIZE	0x80000000UL
43 
44 /* size of the high MMIO address space: 1GB */
45 #define PLATFORM_HI_MMIO_SIZE	0x40000000UL
46 
47 /**
48  * @brief Calculate the number of page map level-4(PML4) that is requested to control the memory region with the
49  *        specified size.
50  *
51  * Page map level-4(PML4) table is the top-level table in the x86-64 paging hierarchy. Each entry in the PML4 table can
52  * potentially map a 512 GiB region, with the entire PML4 table capable of addressing up to 256 TiB. So 1 PML4 table is
53  * enough to control the entire physical address space.
54  */
55 #define PML4_PAGE_NUM(size)	1UL
56 /**
57  * @brief Calculate the number of page directory pointer tables(PDPT) that is requested to control the memory region
58  *        with the specified size.
59  *
60  * A page directory pointer table(PDPT) can be referenced by a PML4E and each PML4E controls access to a 512-GByte
61  * region. It is supposed to be called when hypervisor allocates the page-directory-pointer tables for hypervisor and
62  * all VMs.
63  */
64 #define PDPT_PAGE_NUM(size)	(((size) + PML4E_SIZE - 1UL) >> PML4E_SHIFT)
65 /**
66  * @brief Calculate the number of page directories(PD) that is requested to control the memory region with the specified
67  *        size.
68  *
69  * A page directory(PD) can be referenced by a PDPTE and each PDPTE controls access to a 1-GByte region. It is supposed
70  * to be called when hypervisor allocates the page directories for hypervisor and all VMs.
71  */
72 #define PD_PAGE_NUM(size)	(((size) + PDPTE_SIZE - 1UL) >> PDPTE_SHIFT)
73 /**
74  * @brief Calculate the number of page tables(PT) that is requested to control the memory region with the specified
75  *        size.
76  *
77  * A page table(PT) can be referenced by a PDE and each PDE controls access to a 2-MByte region. It is supposed to be
78  * called when hypervisor allocates the page tables for hypervisor and all VMs.
79  */
80 #define PT_PAGE_NUM(size)	(((size) + PDE_SIZE - 1UL) >> PDE_SHIFT)
81 
82 /**
83  * @brief Data structure to illustrate a 4-KByte memory region with an alignment of 4-KByte.
84  *
85  * This data structure is used to illustrate a 4-KByte memory region with an alignment of 4-KByte, calling it a 4-KByte
86  * page. It can be used to support the memory management in hypervisor and the extended page-table mechanism for VMs. It
87  * can also be used when hypervisor accesses the 4-KByte aligned memory region whose size is a multiple of 4-KByte.
88  *
89  * @consistency N/A
90  * @alignment 4096
91  *
92  * @remark N/A
93  */
94 struct page {
95 	uint8_t contents[PAGE_SIZE]; /**< A 4-KByte page in the memory. */
96 } __aligned(PAGE_SIZE);
97 
98 /**
99  * @brief Data structure that contains a pool of memory pages.
100  *
101  * This structure is designed to manage a collection of memory pages, facilitating efficient allocation,
102  * deallocation, and reuse of pages. It is typically used in scenarios where memory allocation performance
103  * is critical, such as in operating systems or high-performance applications. The page pool aims to minimize
104  * the overhead associated with frequent memory page allocations by maintaining a ready-to-use pool of pages.
105  * It is used to support the memory management in hypervisor and the extended page-table mechanism for VMs.
106  *
107  * @consistency N/A
108  * @alignment N/A
109  *
110  * @remark N/A
111  */
112 struct page_pool {
113         struct page *start_page; /**< The first page in the pool. */
114         spinlock_t lock; /**< The spinlock to protect simultaneous access of the page pool. */
115         /**
116          * @brief A pointer to the bitmap that represents the allocation status of each page in the pool.
117          *
118          * The bitmap is a data structure that represents the allocation status of each page in the pool. Each bit in
119          * the bitmap corresponds to a page in the pool. If the bit is set to 1, the page is allocated; otherwise, the
120          * page is free. The bitmap is used to track the allocation status of each page in the pool.
121          */
122         uint64_t *bitmap;
123         uint64_t bitmap_size; /**< The number of bitmap. */
124         uint64_t last_hint_id; /**< The last bitmap ID that is used to allocate a page. */
125         /**
126          * @brief A pointer to the dummy page
127          *
128          * This is used when there's no page available in the pool.
129          */
130         struct page *dummy_page;
131 };
132 
133 struct page *alloc_page(struct page_pool *pool);
134 void free_page(struct page_pool *pool, struct page *page);
135 #endif /* PAGE_H */
136 
137 /**
138  * @}
139  */