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",
18 i, map[i].Type, map[i].NUMADomain,
19 map[i].Start, map[i].Length
24 int PMemMap_SplitBlock(tPMemMapEnt *map, int NEnts, int MaxEnts, int Block, Uint64 Offset)
26 LOG("Splitting %i (%llx+%llx) at %llx", Block, map[Block].Start, map[Block].Length, Offset);
28 Uint64 _len = map[Block].Length;
29 map[Block].Length = Offset;
30 if( NEnts == MaxEnts ) {
35 LOG("Moving %i entries from %i to %i", (NEnts - Block-1), Block+1, Block);
36 memmove(&map[Block+2], &map[Block+1], (NEnts - Block)*sizeof(map[0]));
42 map[Block].Start = map[Block-1].Start + Offset;
43 map[Block].Length = _len - Offset;
44 map[Block].Type = map[Block-1].Type;
45 map[Block].NUMADomain = map[Block-1].NUMADomain;
46 LOG("- New %i %02x %llx+%llx", map[Block].Type, map[Block].NUMADomain, map[Block].Start, map[Block].Length);
51 int PMemMap_CompactMap(tPMemMapEnt *map, int NEnts, int MaxEnts)
53 for( int i = 1; i < NEnts; i ++ )
55 // Check if the ranges are contiguous
56 if( map[i-1].Start + map[i-1].Length < map[i].Start )
58 // Check if the type is the same
59 if( map[i-1].Type != map[i].Type )
61 // Check if the NUMA Domains are the same
62 if( map[i-1].NUMADomain != map[i].NUMADomain )
65 // Ok, they should be together
66 map[i-1].Length += map[i].Length;
67 memmove(&map[i], &map[i+1], (NEnts - (i+1))*sizeof(map[0]));
68 LOG("Joined %i and %i into %llx+%llx", i-1, i, map[i-1].Start, map[i-1].Length);
70 // Counteract the i++ in the loop iterator
77 int PMemMap_ValidateMap(tPMemMapEnt *map, int NEnts, int MaxEnts)
81 for( int i = 1; i < NEnts; i ++ )
83 if( map[i-1].Start > map[i].Start ) {
90 // Use a selection/swap sort
91 for( int i = 0; i < NEnts; i ++ )
94 for( int j = i+1; j < NEnts; j ++ )
96 if( map[j].Start < map[sel].Start )
100 LOG("Swapping %i and %i", i, sel);
101 LOG(" - %llx+%llx", map[i].Start, map[i].Length);
102 LOG(" - %llx+%llx", map[sel].Start, map[sel].Length);
103 tPMemMapEnt tmp = map[i];
110 // Ensure that the map has no overlaps
111 for( int i = 1; i < NEnts; i ++ )
113 if( map[i-1].Start + map[i-1].Length <= map[i].Start )
116 Log_Notice("Arch", "Map ranges %llx+%llx and %llx+%llx overlap",
117 map[i-1].Start, map[i-1].Length,
118 map[i].Start, map[i].Length
122 NEnts = PMemMap_CompactMap(map, NEnts, MaxEnts);
127 int PMemMap_MarkRangeUsed(tPMemMapEnt *map, int NEnts, int MaxEnts, Uint64 Base, Uint64 Size)
131 Size = (Size + 0xFFF) & ~0xFFF;
132 Base = Base & ~0xFFF;
135 for( int i = 0; i < NEnts; i ++ )
137 if( map[i].Start + map[i].Length > Base ) {
144 LOG("%llx+%llx not in map (past end)", Base, Size);
148 if( map[first].Start > Base ) {
150 LOG("%llx+%llx not in map (in hole)", Base, Size);
155 if( map[first].Start <= Base && Base + Size <= map[first].Start + map[first].Length )
158 if( map[first].Start < Base )
160 if( NEnts == MaxEnts ) {
161 // out of space... oops
164 NEnts = PMemMap_SplitBlock(map, NEnts, MaxEnts, first, Base - map[first].Start);
168 // map[first].Start == Base
170 if( map[first].Length > Size )
172 if( NEnts == MaxEnts ) {
176 NEnts = PMemMap_SplitBlock(map, NEnts, MaxEnts, first, Size);
179 // map[first] is now exactly the block
180 map[first].Type = PMEMTYPE_USED;
182 return PMemMap_CompactMap(map, NEnts, MaxEnts);
186 // Wait... this should never happen, right?
187 Log_Notice("Arch", "Module %llx+%llx overlaps two or more ranges",
189 PMemMap_DumpBlocks(map, NEnts);