1
1
use os_bootinfo:: { MemoryMap , MemoryRegion , MemoryRegionType } ;
2
2
use x86_64:: structures:: paging:: { PhysFrame , PAGE_SIZE } ;
3
- use x86_64:: align_up;
3
+ use x86_64:: { align_up, PhysAddr } ;
4
4
5
5
pub ( crate ) struct FrameAllocator < ' a > {
6
6
pub memory_map : & ' a mut MemoryMap ,
@@ -10,26 +10,48 @@ impl<'a> FrameAllocator<'a> {
10
10
pub ( crate ) fn allocate_frame ( & mut self , region_type : MemoryRegionType ) -> Option < PhysFrame > {
11
11
let page_size = u64:: from ( PAGE_SIZE ) ;
12
12
let mut frame = None ;
13
- for region in self . memory_map . iter_mut ( ) {
14
- if region. region_type != MemoryRegionType :: Usable {
15
- continue ;
16
- }
17
- if region. len < page_size {
18
- continue ;
13
+
14
+ if frame. is_none ( ) {
15
+ // look for an adjacent regions of same types
16
+ let mut last_region_end = PhysAddr :: new ( 0 ) ;
17
+ for region in self . memory_map . iter_mut ( ) {
18
+ if region. region_type == region_type {
19
+ last_region_end = region. end_addr ( ) ;
20
+ } else if region. region_type == MemoryRegionType :: Usable {
21
+ if region. start_addr ( ) == last_region_end {
22
+ frame = Some ( PhysFrame :: containing_address ( region. start_addr ) ) ;
23
+ region. start_addr += page_size;
24
+ region. len -= page_size;
25
+ break
26
+ }
27
+ }
19
28
}
29
+ }
20
30
21
- assert_eq ! (
22
- 0 ,
23
- region. start_addr. as_u64( ) & 0xfff ,
24
- "Region start address is not page aligned: {:?}" ,
25
- region
26
- ) ;
31
+ if frame. is_none ( ) {
32
+ // search all regions
33
+ for region in self . memory_map . iter_mut ( ) {
34
+ if region. region_type != MemoryRegionType :: Usable {
35
+ continue ;
36
+ }
37
+ if region. len < page_size {
38
+ continue ;
39
+ }
40
+
41
+ assert_eq ! (
42
+ 0 ,
43
+ region. start_addr. as_u64( ) & 0xfff ,
44
+ "Region start address is not page aligned: {:?}" ,
45
+ region
46
+ ) ;
27
47
28
- frame = Some ( PhysFrame :: containing_address ( region. start_addr ) ) ;
29
- region. start_addr += page_size;
30
- region. len -= page_size;
31
- break ;
48
+ frame = Some ( PhysFrame :: containing_address ( region. start_addr ) ) ;
49
+ region. start_addr += page_size;
50
+ region. len -= page_size;
51
+ break ;
52
+ }
32
53
}
54
+
33
55
if let Some ( frame) = frame {
34
56
self . add_region ( MemoryRegion {
35
57
start_addr : frame. start_address ( ) ,
0 commit comments