Kernel/x86 - Cleaned up PMM init (and removed mboot from pmm code)
[tpg/acess2.git] / KernelLand / Kernel / pmemmap.c
1 /*
2  * Acess2 Kernel
3  * - By John Hodge (thePowersGang)
4  *
5  * pmemmap.c
6  * - Physical memory map manipulation
7  */
8 #include <acess.h>
9 #include <pmemmap.h>
10
11 // === CODE ===
12 void PMemMap_DumpBlocks(tPMemMapEnt *map, int NEnts)
13 {
14         for( int i = 0; i < NEnts; i ++ )
15         {
16                 Log_Debug("Arch", "%i: %i 0x%02x %08llx+%llx",
17                         i, map[i].Type, map[i].NUMADomain,
18                         map[i].Start, map[i].Length
19                         );
20         }
21 }
22
23 int PMemMap_SplitBlock(tPMemMapEnt *map, int NEnts, int MaxEnts, int Block, Uint64 Offset)
24 {
25         LOG("Splitting %i (%llx+%llx) at %llx", Block, map[Block].Start, map[Block].Length, Offset);
26         
27         Uint64 _len = map[Block].Length;
28         map[Block].Length = Offset;
29         if( NEnts == MaxEnts ) {
30                 // out of space
31                 return NEnts;
32         }
33         Block ++;
34         if( Block < NEnts ) {
35                 // Can't be anything after
36                 memmove(&map[Block+1], &map[Block], (NEnts - Block)*sizeof(map[0]));
37         }
38         NEnts ++;
39         
40         // New (free) block
41         map[Block].Start  = map[Block-1].Start + Offset;
42         map[Block].Length = _len - Offset;
43         map[Block].Type = map[Block-1].Type;
44         map[Block].NUMADomain = map[Block-1].NUMADomain;
45         LOG("- New %i %02x %llx+%llx", map[Block].Type, map[Block].NUMADomain, map[Block].Start, map[Block].Length);
46
47         return NEnts;
48 }
49
50 int PMemMap_CompactMap(tPMemMapEnt *map, int NEnts, int MaxEnts)
51 {
52         for( int i = 1; i < NEnts; i ++ )
53         {
54                 // Check if the ranges are contiguous
55                 if( map[i-1].Start + map[i-1].Length < map[i].Start )
56                         continue ;
57                 // Check if the type is the same
58                 if( map[i-1].Type != map[i].Type )
59                         continue ;
60                 // Check if the NUMA Domains are the same
61                 if( map[i-1].NUMADomain != map[i].NUMADomain )
62                         continue ;
63                 
64                 // Ok, they should be together
65                 map[i-1].Length += map[i].Length;
66                 memmove(&map[i], &map[i+1], (NEnts - (i+1))*sizeof(map[0]));
67                 
68                 // Counteract the i++ in the loop iterator
69                 i --;
70                 NEnts --;
71         }
72         return NEnts;
73 }
74
75 int PMemMap_ValidateMap(tPMemMapEnt *map, int NEnts, int MaxEnts)
76 {
77         // Sort the pmem map
78          int     bNeedsSort = 0;
79         for( int i = 1; i < NEnts; i ++ )
80         {
81                 if( map[i-1].Start > map[i].Start ) {
82                         bNeedsSort = 1;
83                         break;
84                 }
85         }
86         if( bNeedsSort )
87         {
88                 Log_Warning("Arch", "TODO: Impliment memory map sorting");
89                 // TODO: Sort memory map
90         }
91         
92         // Ensure that the map has no overlaps
93         for( int i = 1; i < NEnts; i ++ )
94         {
95                 if( map[i-1].Start + map[i-1].Length <= map[i].Start )
96                         continue ;
97                 // Oops, overlap!
98                 Log_Notice("Arch", "Map ranges %llx+%llx and %llx+%llx overlap",
99                         map[i-1].Start, map[i-1].Length,
100                         map[i].Start,   map[i].Length
101                         );
102         }
103         
104         return PMemMap_CompactMap(map, NEnts, MaxEnts);
105 }
106
107
108 int PMemMap_MarkRangeUsed(tPMemMapEnt *map, int NEnts, int MaxEnts, Uint64 Base, Uint64 Size)
109 {
110          int    first;
111         
112         Size = (Size + 0xFFF) & ~0xFFF;
113         Base = Base & ~0xFFF;
114         
115         first = -1;
116         for( int i = 0; i < NEnts; i ++ )
117         {
118                 if( map[i].Start + map[i].Length > Base ) {
119                         first = i;
120                         break;
121                 }
122         }
123         if( first == -1 ) {
124                 // Not in map
125                 LOG("%llx+%llx not in map (past end)", Base, Size);
126                 return NEnts;
127         }
128         
129         if( map[first].Start > Base ) {
130                 // Not in map
131                 LOG("%llx+%llx not in map (in hole)", Base, Size);
132                 return NEnts;
133         }
134         
135         // Detect single
136         if( map[first].Start <= Base && Base + Size <= map[first].Start + map[first].Length )
137         {
138                 // Split before
139                 if( map[first].Start < Base )
140                 {
141                         if( NEnts == MaxEnts ) {
142                                 // out of space... oops
143                                 return NEnts;
144                         }
145                         NEnts = PMemMap_SplitBlock(map, NEnts, MaxEnts, first, Base - map[first].Start);
146                         first ++;
147                 }
148                 
149                 // map[first].Start == Base
150                 // Split after
151                 if( map[first].Length > Size )
152                 {
153                         if( NEnts == MaxEnts ) {
154                                 // out of space
155                                 return NEnts;
156                         }
157                         NEnts = PMemMap_SplitBlock(map, NEnts, MaxEnts, first, Size);
158                 }
159                 
160                 // map[first] is now exactly the block
161                 map[first].Type = PMEMTYPE_USED;
162         
163                 return PMemMap_CompactMap(map, NEnts, MaxEnts);
164         }
165         else
166         {
167                 // Wait... this should never happen, right?
168                 Log_Notice("Arch", "Module %llx+%llx overlaps two or more ranges",
169                         Base, Size);
170                 PMemMap_DumpBlocks(map, NEnts);
171                 // TODO: Error?
172                 return NEnts;
173         }
174 }
175
176
177

UCC git Repository :: git.ucc.asn.au