3 * - By John Hodge (thePowersGang)
6 * - Physical memory map manipulation
12 void PMemMap_DumpBlocks(tPMemMapEnt *map, int NEnts)
14 for( int i = 0; i < NEnts; i ++ )
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
23 int PMemMap_SplitBlock(tPMemMapEnt *map, int NEnts, int MaxEnts, int Block, Uint64 Offset)
25 LOG("Splitting %i (%llx+%llx) at %llx", Block, map[Block].Start, map[Block].Length, Offset);
27 Uint64 _len = map[Block].Length;
28 map[Block].Length = Offset;
29 if( NEnts == MaxEnts ) {
35 // Can't be anything after
36 memmove(&map[Block+1], &map[Block], (NEnts - Block)*sizeof(map[0]));
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);
50 int PMemMap_CompactMap(tPMemMapEnt *map, int NEnts, int MaxEnts)
52 for( int i = 1; i < NEnts; i ++ )
54 // Check if the ranges are contiguous
55 if( map[i-1].Start + map[i-1].Length < map[i].Start )
57 // Check if the type is the same
58 if( map[i-1].Type != map[i].Type )
60 // Check if the NUMA Domains are the same
61 if( map[i-1].NUMADomain != map[i].NUMADomain )
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]));
68 // Counteract the i++ in the loop iterator
75 int PMemMap_ValidateMap(tPMemMapEnt *map, int NEnts, int MaxEnts)
79 for( int i = 1; i < NEnts; i ++ )
81 if( map[i-1].Start > map[i].Start ) {
88 Log_Warning("Arch", "TODO: Impliment memory map sorting");
89 // TODO: Sort memory map
92 // Ensure that the map has no overlaps
93 for( int i = 1; i < NEnts; i ++ )
95 if( map[i-1].Start + map[i-1].Length <= map[i].Start )
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
104 return PMemMap_CompactMap(map, NEnts, MaxEnts);
108 int PMemMap_MarkRangeUsed(tPMemMapEnt *map, int NEnts, int MaxEnts, Uint64 Base, Uint64 Size)
112 Size = (Size + 0xFFF) & ~0xFFF;
113 Base = Base & ~0xFFF;
116 for( int i = 0; i < NEnts; i ++ )
118 if( map[i].Start + map[i].Length > Base ) {
125 LOG("%llx+%llx not in map (past end)", Base, Size);
129 if( map[first].Start > Base ) {
131 LOG("%llx+%llx not in map (in hole)", Base, Size);
136 if( map[first].Start <= Base && Base + Size <= map[first].Start + map[first].Length )
139 if( map[first].Start < Base )
141 if( NEnts == MaxEnts ) {
142 // out of space... oops
145 NEnts = PMemMap_SplitBlock(map, NEnts, MaxEnts, first, Base - map[first].Start);
149 // map[first].Start == Base
151 if( map[first].Length > Size )
153 if( NEnts == MaxEnts ) {
157 NEnts = PMemMap_SplitBlock(map, NEnts, MaxEnts, first, Size);
160 // map[first] is now exactly the block
161 map[first].Type = PMEMTYPE_USED;
163 return PMemMap_CompactMap(map, NEnts, MaxEnts);
167 // Wait... this should never happen, right?
168 Log_Notice("Arch", "Module %llx+%llx overlaps two or more ranges",
170 PMemMap_DumpBlocks(map, NEnts);