|
1 | 1 | #pragma once |
2 | 2 |
|
3 | | -#define MAX_ORDER 20 |
| 3 | +#define MAX_ORDER 31 |
| 4 | +#define MIN_ORDER 12 // 4KB = 2^12 |
| 5 | +#define ORDER_COUNT (MAX_ORDER - MIN_ORDER) |
4 | 6 |
|
5 | | -// Zone 边界(物理地址) |
6 | | -#define ZONE_DMA_END (16UL << 20) // 16MB |
7 | | -#define ZONE_DMA32_END (4UL << 30) // 4GB |
| 7 | +// Zone 边界 |
| 8 | +#define ZONE_DMA_END (16UL << 20) // 16MB |
| 9 | +#define ZONE_DMA32_END (4UL << 30) // 4GB |
8 | 10 |
|
9 | | -#define GFP_DMA (1 << 0) // 必须从 ZONE_DMA 分配 |
10 | | -#define GFP_DMA32 (1 << 1) // 可以从 ZONE_DMA32 分配 |
11 | | -#define GFP_KERNEL (1 << 2) // 内核普通分配 |
12 | | -#define GFP_ATOMIC (1 << 3) // 原子分配,不能睡眠 |
13 | | -#define GFP_NOWAIT (1 << 4) // 不等待,快速失败 |
| 11 | +// GFP 标志 |
| 12 | +#define GFP_DMA (1 << 0) |
| 13 | +#define GFP_DMA32 (1 << 1) |
| 14 | +#define GFP_KERNEL (1 << 2) |
| 15 | +#define GFP_ATOMIC (1 << 3) |
| 16 | +#define GFP_NOWAIT (1 << 4) |
14 | 17 |
|
15 | | -// 常用组合 |
16 | 18 | #define GFP_KERNEL_NORMAL (GFP_KERNEL) |
17 | | -#define GFP_KERNEL_DMA (GFP_KERNEL | GFP_DMA) |
18 | | -#define GFP_KERNEL_DMA32 (GFP_KERNEL | GFP_DMA32) |
19 | | - |
20 | | -#define PG_reserved 0 |
21 | | -#define PG_slab 1 |
22 | | -#define PG_buddy 2 |
23 | | -#define PG_compound 3 |
24 | | -#define PG_head 4 |
25 | | -#define PG_dirty 5 |
26 | | -#define PG_lru 6 |
27 | | - |
28 | | -#define PCPU_CACHE_LOW 4 |
29 | | -#define PCPU_CACHE_HIGH 32 |
30 | | -#define PCPU_BATCH 8 |
31 | | - |
32 | | -// 页面标志操作 |
33 | | -#define PageBuddy(page) test_bit(PG_buddy, &(page)->flags) |
34 | | -#define SetPageBuddy(page) set_bit(PG_buddy, &(page)->flags) |
35 | | -#define ClearPageBuddy(page) clear_bit(PG_buddy, &(page)->flags) |
36 | | - |
37 | | -#define PageCompound(page) test_bit(PG_compound, &(page)->flags) |
38 | | -#define SetPageCompound(page) set_bit(PG_compound, &(page)->flags) |
39 | | -#define ClearPageCompound(page) clear_bit(PG_compound, &(page)->flags) |
40 | | - |
41 | | -#define PageHead(page) test_bit(PG_head, &(page)->flags) |
42 | | -#define SetPageHead(page) set_bit(PG_head, &(page)->flags) |
43 | | -#define ClearPageHead(page) clear_bit(PG_head, &(page)->flags) |
44 | | - |
45 | | -#define PageReserved(page) test_bit(PG_reserved, &(page)->flags) |
46 | | -#define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags) |
47 | | -#define ClearPageReserved(page) clear_bit(PG_reserved, &(page)->flags) |
48 | | - |
49 | | -#define pfn_to_page(pfn) (&mem_map[(pfn) - min_pfn]) |
50 | | -#define page_to_pfn(page) ((uint64_t)((page) - mem_map) + min_pfn) |
51 | | -#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) |
52 | | -#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT) |
53 | | -#define virt_to_page(virt) phys_to_page(virt_to_phys(virt)) |
54 | | -#define page_to_virt(page) phys_to_virt(page_to_phys(page)) |
| 19 | +#define GFP_KERNEL_DMA (GFP_KERNEL | GFP_DMA) |
| 20 | +#define GFP_KERNEL_DMA32 (GFP_KERNEL | GFP_DMA32) |
55 | 21 |
|
56 | 22 | #include "lock.h" |
57 | 23 | #include "types.h" |
58 | 24 |
|
| 25 | +typedef struct buddy_allocator { |
| 26 | + uintptr_t free_area[ORDER_COUNT]; |
| 27 | + spin_t lock; |
| 28 | +} buddy_allocator_t; |
| 29 | + |
59 | 30 | enum zone_type { |
60 | 31 | #if defined(__x86_64__) |
61 | | - ZONE_DMA, // 0-16MB,用于传统 ISA DMA |
| 32 | + ZONE_DMA, // 0-16MB |
62 | 33 | #endif |
63 | | - ZONE_DMA32, // 0-4GB,用于 32 位 DMA |
64 | | - ZONE_NORMAL, // 正常内存 |
| 34 | + ZONE_DMA32, // 0-4GB |
| 35 | + ZONE_NORMAL, // 4GB+ |
65 | 36 | __MAX_NR_ZONES |
66 | 37 | }; |
67 | 38 |
|
68 | | -extern const char *zone_names[__MAX_NR_ZONES]; |
69 | | - |
70 | | -enum zone_type pfn_to_zone_type(uint64_t pfn); |
71 | | - |
72 | | -typedef struct { |
73 | | - volatile int counter; |
74 | | -} atomic_t; |
75 | | - |
76 | | -static inline void atomic_set(atomic_t *v, int i) { |
77 | | - v->counter = i; |
78 | | -} |
79 | | - |
80 | | -static inline int atomic_read(atomic_t *v) { |
81 | | - return v->counter; |
82 | | -} |
83 | | - |
84 | | -static inline void atomic_inc(atomic_t *v) { |
85 | | - __sync_add_and_fetch(&v->counter, 1); |
86 | | -} |
87 | | - |
88 | | -static inline int atomic_dec_and_test(atomic_t *v) { |
89 | | - return __sync_sub_and_fetch(&v->counter, 1) == 0; |
90 | | -} |
91 | | - |
92 | | -static inline void atomic_add(int i, atomic_t *v) { |
93 | | - __sync_add_and_fetch(&v->counter, i); |
94 | | -} |
95 | | - |
96 | | -static inline void atomic_sub(int i, atomic_t *v) { |
97 | | - __sync_sub_and_fetch(&v->counter, i); |
98 | | -} |
99 | | - |
100 | | -typedef struct page { |
101 | | - atomic_t _refcount; |
102 | | - uint64_t flags; |
103 | | - |
104 | | - union { |
105 | | - struct { |
106 | | - struct page *next; |
107 | | - struct page *prev; |
108 | | - } lru; |
109 | | - struct { |
110 | | - void *private; |
111 | | - }; |
112 | | - }; |
113 | | - |
114 | | - unsigned char order; |
115 | | - uint32_t compound_nr; |
116 | | - |
117 | | - // 新增:所属的 zone |
118 | | - unsigned char zone_id; |
119 | | - |
120 | | - uint32_t magic; |
121 | | -} page_t; |
122 | | - |
123 | | -#define PAGE_MAGIC 0xDEADBEEF |
124 | | - |
125 | | -enum zone_stat_item { |
126 | | - NR_FREE_PAGES, // 空闲页数 |
127 | | - NR_ALLOC_PAGES, // 已分配页数 |
128 | | - NR_ACTIVE, // 活跃页数 |
129 | | - NR_INACTIVE, // 非活跃页数 |
130 | | - NR_ZONE_STATS |
131 | | -}; |
132 | | - |
133 | | -typedef struct zone_stats { |
134 | | - atomic_t count[NR_ZONE_STATS]; |
135 | | -} zone_stats_t; |
136 | | - |
137 | | -typedef struct free_area { |
138 | | - struct page *free_list; |
139 | | - uint64_t nr_free; |
140 | | -} free_area_t; |
141 | | - |
142 | | -typedef struct per_cpu_pages { |
143 | | - struct page *pages[PCPU_CACHE_HIGH]; |
144 | | - int count; |
145 | | - int low; // 低水位 |
146 | | - int high; // 高水位 |
147 | | - int batch; // 批量操作数量 |
148 | | - |
149 | | - uint64_t alloc_hits; |
150 | | - uint64_t alloc_misses; |
151 | | - uint64_t free_hits; |
152 | | - uint64_t free_misses; |
153 | | -} per_cpu_pages_t; |
154 | | - |
| 39 | +// Zone 结构 |
155 | 40 | typedef struct zone { |
156 | | - // Buddy 分配器 |
157 | | - free_area_t free_area[MAX_ORDER]; |
158 | | - |
159 | | - // Zone 范围 |
| 41 | + buddy_allocator_t allocator; |
160 | 42 | uint64_t zone_start_pfn; |
161 | 43 | uint64_t zone_end_pfn; |
162 | | - uint64_t spanned_pages; // 跨越的页数(包括空洞) |
163 | | - uint64_t present_pages; // 物理存在的页数 |
164 | | - uint64_t managed_pages; // 可管理的页数 |
165 | | - |
166 | | - // Zone 类型 |
| 44 | + uint64_t managed_pages; |
| 45 | + uint64_t free_pages; |
167 | 46 | enum zone_type type; |
168 | 47 | const char *name; |
169 | | - |
170 | | - // 统计信息 |
171 | | - zone_stats_t vm_stat; |
172 | | - |
173 | | - // Per-CPU 页面缓存(每个CPU一个) |
174 | | - per_cpu_pages_t *per_cpu_pageset; |
175 | | - |
176 | | - // 锁 |
177 | | - spin_t lock; |
178 | | - |
179 | | - // 链表节点(用于遍历所有zone) |
180 | | - struct zone *next; |
181 | 48 | } zone_t; |
182 | 49 |
|
183 | | -typedef struct zonelist { |
184 | | - zone_t *zones[__MAX_NR_ZONES]; // 按优先级排序的 zone 列表 |
185 | | - int nr_zones; // zone 数量 |
186 | | -} zonelist_t; |
187 | | - |
188 | | -extern page_t *mem_map; |
189 | | -extern uint64_t max_pfn; |
190 | | -extern uint64_t min_pfn; |
191 | 50 | extern zone_t *zones[__MAX_NR_ZONES]; |
192 | 51 | extern int nr_zones; |
193 | | - |
194 | | -// 获取页面所属的 zone |
195 | | -#define page_zone(page) (zones[(page)->zone_id]) |
196 | | - |
197 | | -static inline void set_bit(int nr, volatile uint64_t *addr) { |
198 | | - *addr |= (1UL << nr); |
199 | | -} |
200 | | - |
201 | | -static inline void clear_bit(int nr, volatile uint64_t *addr) { |
202 | | - *addr &= ~(1UL << nr); |
203 | | -} |
204 | | - |
205 | | -static inline int test_bit(int nr, const volatile uint64_t *addr) { |
206 | | - return (*addr >> nr) & 1; |
207 | | -} |
208 | | - |
209 | | -// 引用计数操作 |
210 | | -static inline int page_ref_count(page_t *page) { |
211 | | - return atomic_read(&page->_refcount); |
212 | | -} |
213 | | - |
214 | | -static inline void set_page_refcounted(page_t *page) { |
215 | | - atomic_set(&page->_refcount, 1); |
216 | | -} |
217 | | - |
218 | | -static inline void get_page(page_t *page) { |
219 | | - atomic_inc(&page->_refcount); |
220 | | -} |
221 | | - |
222 | | -static inline bool put_page_testzero(page_t *page) { |
223 | | - return atomic_dec_and_test(&page->_refcount); |
224 | | -} |
225 | | - |
226 | | -// 复合页操作 |
227 | | -static inline void set_compound_order(page_t *page, uint32_t order) { |
228 | | - page->order = order; |
229 | | - page->compound_nr = 1U << order; |
230 | | -} |
231 | | - |
232 | | -static inline uint32_t compound_order(page_t *page) { |
233 | | - if (!PageHead(page)) |
234 | | - return 0; |
235 | | - return page->order; |
236 | | -} |
237 | | - |
238 | | -// Zone 统计操作 |
239 | | -static inline void zone_page_state_add(long delta, zone_t *zone, enum zone_stat_item item) { |
240 | | - atomic_add(delta, &zone->vm_stat.count[item]); |
241 | | -} |
242 | | - |
243 | | -static inline uint64_t zone_page_state(zone_t *zone, enum zone_stat_item item) { |
244 | | - return atomic_read(&zone->vm_stat.count[item]); |
245 | | -} |
| 52 | +extern const char *zone_names[__MAX_NR_ZONES]; |
246 | 53 |
|
247 | 54 | // 初始化 |
248 | | -void zones_init(uint64_t memory_size); |
| 55 | +void buddy_init(void); |
249 | 56 | void add_memory_region(uintptr_t start, uintptr_t end, enum zone_type type); |
250 | | -void percpu_pagecache_init(); |
251 | | - |
252 | | -// 分配(多 zone 版本) |
253 | | -page_t *alloc_pages(uint32_t gfp_flags, uint32_t order); |
254 | | -#define alloc_page(gfp) alloc_pages(gfp, 0) |
255 | 57 |
|
256 | | -// 兼容接口(默认从 NORMAL zone) |
257 | | -#define __alloc_pages(order) alloc_pages(GFP_KERNEL, order) |
258 | | -#define __alloc_page() alloc_pages(GFP_KERNEL, 0) |
| 58 | +// 分配/释放(底层接口) |
| 59 | +uintptr_t buddy_alloc_zone(zone_t *zone, size_t count); |
| 60 | +void buddy_free_zone(zone_t *zone, uintptr_t addr, size_t order); |
259 | 61 |
|
260 | | -// 释放 |
261 | | -void __free_pages(page_t *page, uint32_t order); |
262 | | -#define free_page(page) __free_pages(page, 0) |
263 | | - |
264 | | -// Zone 查询 |
| 62 | +// 辅助函数 |
265 | 63 | zone_t *get_zone(enum zone_type type); |
266 | 64 | bool zone_has_memory(zone_t *zone); |
| 65 | +enum zone_type phys_to_zone_type(uintptr_t phys); |
267 | 66 |
|
268 | | -// Zonelist 构建 |
269 | | -void build_zonelist(zonelist_t *zl, uint32_t gfp_flags); |
270 | | - |
271 | | -void init_frame_buddy(uint64_t memory_size); |
272 | | - |
273 | | -uintptr_t buddy_alloc_frames(size_t count); |
274 | | -void buddy_free_frames(uintptr_t addr, size_t count); |
| 67 | +void free_frames_released(uintptr_t addr, size_t count); |
0 commit comments