Changeset 24424
- Timestamp:
- 03/17/08 15:50:46 (8 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
haiku/trunk/src/system/kernel/arch/x86/arch_vm.cpp
r24244 r24424 32 32 #endif 33 33 34 #define TRACE_MTRR_ARCH_VM 35 #ifdef TRACE_MTRR_ARCH_VM 36 # define TRACE_MTRR(x...) dprintf(x) 37 #else 38 # define TRACE_MTRR(x...) 39 #endif 40 34 41 35 42 #define kMaxMemoryTypeRegisters 32 … … 84 91 85 92 93 static void 94 nearest_powers(uint64 value, uint64 *lower, uint64 *upper) 95 { 96 uint64 power = 1UL << 12; 97 *lower = power; 98 // 12 bits is the smallest supported alignment/length 99 100 while (value >= power) { 101 *lower = power; 102 power <<= 1; 103 } 104 105 *upper = power; 106 } 107 108 86 109 static status_t 87 110 set_memory_type(int32 id, uint64 base, uint64 length, uint32 type) … … 92 115 return B_OK; 93 116 94 uint32 newType;95 96 117 switch (type) { 97 118 case B_MTR_UC: 98 newType = IA32_MTR_UNCACHED;119 type = IA32_MTR_UNCACHED; 99 120 break; 100 121 case B_MTR_WC: 101 newType = IA32_MTR_WRITE_COMBINING;122 type = IA32_MTR_WRITE_COMBINING; 102 123 break; 103 124 case B_MTR_WT: 104 newType = IA32_MTR_WRITE_THROUGH;125 type = IA32_MTR_WRITE_THROUGH; 105 126 break; 106 127 case B_MTR_WP: 107 newType = IA32_MTR_WRITE_PROTECTED;128 type = IA32_MTR_WRITE_PROTECTED; 108 129 break; 109 130 case B_MTR_WB: 110 newType = IA32_MTR_WRITE_BACK;131 type = IA32_MTR_WRITE_BACK; 111 132 break; 112 133 … … 119 140 120 141 // length must be a power of 2; just round it up to the next value 121 uint64 newLength = nearest_power(length); 122 123 // avoids more than 2GB slots 124 if (newLength > 0x80000000) 125 newLength = 0x80000000; 126 127 if (newLength + base <= base) { 142 length = nearest_power(length); 143 144 if (length + base <= base) { 128 145 // 4GB overflow 129 146 return B_BAD_VALUE; … … 131 148 132 149 // base must be aligned to the length 133 if (base & ( newLength - 1))150 if (base & (length - 1)) 134 151 return B_BAD_VALUE; 135 152 … … 138 155 return B_ERROR; 139 156 140 TRACE(("allocate MTRR slot %ld, base = %Lx, length = %Lx\n", index, 141 base, newLength)); 157 TRACE_MTRR("allocate MTRR slot %ld, base = %Lx, length = %Lx\n", index, base, length); 142 158 143 159 sMemoryTypeIDs[index] = id; 144 x86_set_mtrr(index, base, newLength, newType); 145 146 // now handle remaining memory 147 if (length > newLength) { 148 // TODO iterate over smaller lengths to avoid the PCI hole after the physical memory. 149 set_memory_type(id, base + newLength, length - newLength, type); 150 } 160 x86_set_mtrr(index, base, length, type); 151 161 152 162 return B_OK; 163 } 164 165 166 static int64 sols[5]; 167 static int solCount; 168 static int64 props[5]; 169 170 171 static void 172 find_nearest(uint64 value, int iteration) 173 { 174 TRACE_MTRR("find_nearest %Lx %d\n", value, iteration); 175 if (iteration > 4 || (iteration + 1) >= solCount) 176 return; 177 uint64 down, up; 178 int i; 179 nearest_powers(value, &down, &up); 180 props[iteration] = down; 181 if (value - down < 0x100000) { 182 for (i=0; i<=iteration; i++) 183 sols[i] = props[i]; 184 solCount = iteration + 1; 185 return; 186 } 187 find_nearest(value - down, iteration + 1); 188 props[iteration] = -up; 189 if (up - value < 0x100000) { 190 for (i=0; i<=iteration; i++) 191 sols[i] = props[i]; 192 solCount = iteration + 1; 193 return; 194 } 195 find_nearest(up - value, iteration + 1); 196 } 197 198 199 static status_t 200 set_memory_write_back(int32 id, uint64 base, uint64 length) 201 { 202 int i; 203 TRACE_MTRR("set_memory_write_back base %Lx length %Lx\n", base, length); 204 solCount = 5; 205 find_nearest(length, 0); 206 207 #ifdef TRACE_MTRR 208 dprintf("sols: "); 209 for (i=0; i<solCount; i++) { 210 dprintf("0x%Lx ", sols[i]); 211 } 212 dprintf("\n"); 213 #endif 214 215 bool nextDown = false; 216 for (int i = 0; i < solCount; i++) { 217 if (sols[i] < 0) { 218 if (nextDown) 219 base += sols[i]; 220 set_memory_type(id, base, -sols[i], nextDown ? B_MTR_UC : B_MTR_WB); 221 if (!nextDown) 222 base -= sols[i]; 223 nextDown = !nextDown; 224 } else { 225 if (nextDown) 226 base -= sols[i]; 227 set_memory_type(id, base, sols[i], nextDown ? B_MTR_UC : B_MTR_WB); 228 if (!nextDown) 229 base += sols[i]; 230 } 231 } 153 232 } 154 233 … … 227 306 228 307 for (uint32 i = 0; i < args->num_physical_memory_ranges; i++) { 229 set_memory_ type(-1, args->physical_memory_range[i].start,230 args->physical_memory_range[i].size , B_MTR_WB);308 set_memory_write_back(-1, args->physical_memory_range[i].start, 309 args->physical_memory_range[i].size); 231 310 } 232 311
