3 * - By John Hodge (thePowersGang)
6 * - Physical memory map manipulation
13 void PMemMap_DumpBlocks(tPMemMapEnt *map, int NEnts)
15 for( int i = 0; i < NEnts; i ++ )
17 Log_Debug("PMemMap", "%i: %i 0x%02x %08llx+%llx (end %llx)",
18 i, map[i].Type, map[i].NUMADomain,
19 map[i].Start, map[i].Length,
20 map[i].Start + map[i].Length
25 int PMemMap_SplitBlock(tPMemMapEnt *map, int NEnts, int MaxEnts, int Block, Uint64 Offset)
27 LOG("Splitting %i (%llx+%llx) at %llx", Block, map[Block].Start, map[Block].Length, Offset);
29 Uint64 _len = map[Block].Length;
30 map[Block].Length = Offset;
31 if( NEnts == MaxEnts ) {
36 LOG("Moving %i entries from %i to %i", (NEnts - Block-1), Block+1, Block);
37 memmove(&map[Block+2], &map[Block+1], (NEnts - Block)*sizeof(map[0]));
43 map[Block].Start = map[Block-1].Start + Offset;
44 map[Block].Length = _len - Offset;
45 map[Block].Type = map[Block-1].Type;
46 map[Block].NUMADomain = map[Block-1].NUMADomain;
47 LOG("- New %i %02x %llx+%llx", map[Block].Type, map[Block].NUMADomain, map[Block].Start, map[Block].Length);
52 int PMemMap_CompactMap(tPMemMapEnt *map, int NEnts, int MaxEnts)
54 for( int i = 1; i < NEnts; i ++ )
56 // Check if the ranges are contiguous
57 if( map[i-1].Start + map[i-1].Length < map[i].Start )
59 // Check if the type is the same
60 if( map[i-1].Type != map[i].Type )
62 // Check if the NUMA Domains are the same
63 if( map[i-1].NUMADomain != map[i].NUMADomain )
66 // Ok, they should be together
67 map[i-1].Length += map[i].Length;
68 memmove(&map[i], &map[i+1], (NEnts - (i+1))*sizeof(map[0]));
69 LOG("Joined %i and %i into %llx+%llx", i-1, i, map[i-1].Start, map[i-1].Length);
71 // Counteract the i++ in the loop iterator
78 int PMemMap_ValidateMap(tPMemMapEnt *map, int NEnts, int MaxEnts)
82 for( int i = 1; i < NEnts; i ++ )
84 if( map[i-1].Start > map[i].Start ) {
91 // Use a selection/swap sort
92 for( int i = 0; i < NEnts; i ++ )
95 for( int j = i+1; j < NEnts; j ++ )
97 if( map[j].Start < map[sel].Start )
101 LOG("Swapping %i and %i", i, sel);
102 LOG(" - %llx+%llx", map[i].Start, map[i].Length);
103 LOG(" - %llx+%llx", map[sel].Start, map[sel].Length);
104 tPMemMapEnt tmp = map[i];
111 // Ensure that the map has no overlaps
112 for( int i = 1; i < NEnts; i ++ )
114 if( map[i-1].Start + map[i-1].Length <= map[i].Start )
117 Log_Notice("Arch", "Map ranges %llx+%llx and %llx+%llx overlap",
118 map[i-1].Start, map[i-1].Length,
119 map[i].Start, map[i].Length
123 NEnts = PMemMap_CompactMap(map, NEnts, MaxEnts);
128 int PMemMap_MarkRangeUsed(tPMemMapEnt *map, int NEnts, int MaxEnts, Uint64 Base, Uint64 Size)
132 Size = (Size + 0xFFF) & ~0xFFF;
133 Base = Base & ~0xFFF;
136 for( int i = 0; i < NEnts; i ++ )
138 if( map[i].Start + map[i].Length > Base ) {
145 LOG("%llx+%llx not in map (past end)", Base, Size);
149 if( map[first].Start > Base ) {
151 LOG("%llx+%llx not in map (in hole)", Base, Size);
156 if( map[first].Start <= Base && Base + Size <= map[first].Start + map[first].Length )
159 if( map[first].Start < Base )
161 if( NEnts == MaxEnts ) {
162 // out of space... oops
165 NEnts = PMemMap_SplitBlock(map, NEnts, MaxEnts, first, Base - map[first].Start);
169 // map[first].Start == Base
171 if( map[first].Length > Size )
173 if( NEnts == MaxEnts ) {
177 NEnts = PMemMap_SplitBlock(map, NEnts, MaxEnts, first, Size);
180 // map[first] is now exactly the block
181 map[first].Type = PMEMTYPE_USED;
183 return PMemMap_CompactMap(map, NEnts, MaxEnts);
187 // Wait... this should never happen, right?
188 Log_Notice("Arch", "Module %llx+%llx overlaps two or more ranges",
190 PMemMap_DumpBlocks(map, NEnts);