1393fceb5SAxel Dörfler /* 2393fceb5SAxel Dörfler * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. 3b20d05b4SJérôme Duval * Copyright 2008, Jérôme Duval. 4393fceb5SAxel Dörfler * Distributed under the terms of the MIT License. 5393fceb5SAxel Dörfler * 6393fceb5SAxel Dörfler * Copyright 2001, Travis Geiselbrecht. All rights reserved. 7393fceb5SAxel Dörfler * Distributed under the terms of the NewOS License. 8393fceb5SAxel Dörfler */ 9393fceb5SAxel Dörfler 10393fceb5SAxel Dörfler 11393fceb5SAxel Dörfler #include <KernelExport.h> 12393fceb5SAxel Dörfler #include <smp.h> 13393fceb5SAxel Dörfler #include <util/AutoLock.h> 14393fceb5SAxel Dörfler #include <vm.h> 15393fceb5SAxel Dörfler #include <vm_page.h> 16393fceb5SAxel Dörfler #include <vm_priv.h> 17393fceb5SAxel Dörfler 18393fceb5SAxel Dörfler #include <arch/vm.h> 19393fceb5SAxel Dörfler #include <arch/int.h> 20393fceb5SAxel Dörfler #include <arch/cpu.h> 21393fceb5SAxel Dörfler 22393fceb5SAxel Dörfler #include <arch/x86/bios.h> 23393fceb5SAxel Dörfler 24393fceb5SAxel Dörfler #include <stdlib.h> 25393fceb5SAxel Dörfler #include <string.h> 26393fceb5SAxel Dörfler 27393fceb5SAxel Dörfler 28393fceb5SAxel Dörfler //#define TRACE_ARCH_VM 29393fceb5SAxel Dörfler #ifdef TRACE_ARCH_VM 30393fceb5SAxel Dörfler # define TRACE(x) dprintf x 31393fceb5SAxel Dörfler #else 32393fceb5SAxel Dörfler # define TRACE(x) ; 33393fceb5SAxel Dörfler #endif 34393fceb5SAxel Dörfler 354f893e39SJérôme Duval #define TRACE_MTRR_ARCH_VM 364f893e39SJérôme Duval #ifdef TRACE_MTRR_ARCH_VM 374f893e39SJérôme Duval # define TRACE_MTRR(x...) dprintf(x) 384f893e39SJérôme Duval #else 394f893e39SJérôme Duval # define TRACE_MTRR(x...) 404f893e39SJérôme Duval #endif 414f893e39SJérôme Duval 42393fceb5SAxel Dörfler 43393fceb5SAxel Dörfler #define kMaxMemoryTypeRegisters 32 44393fceb5SAxel Dörfler 45393fceb5SAxel Dörfler void *gDmaAddress; 46393fceb5SAxel Dörfler 47393fceb5SAxel Dörfler static uint32 sMemoryTypeBitmap; 48393fceb5SAxel Dörfler static int32 sMemoryTypeIDs[kMaxMemoryTypeRegisters]; 49393fceb5SAxel Dörfler static uint32 sMemoryTypeRegisterCount; 50393fceb5SAxel Dörfler static spinlock sMemoryTypeLock; 51393fceb5SAxel Dörfler 52393fceb5SAxel Dörfler 53393fceb5SAxel Dörfler static int32 54393fceb5SAxel Dörfler allocate_mtrr(void) 55393fceb5SAxel Dörfler { 56393fceb5SAxel Dörfler InterruptsSpinLocker _(&sMemoryTypeLock); 57393fceb5SAxel Dörfler 58393fceb5SAxel Dörfler // find free bit 59393fceb5SAxel Dörfler 60393fceb5SAxel Dörfler for (uint32 index = 0; index < sMemoryTypeRegisterCount; index++) { 61393fceb5SAxel Dörfler if (sMemoryTypeBitmap & (1UL << index)) 62393fceb5SAxel Dörfler continue; 63393fceb5SAxel Dörfler 64393fceb5SAxel Dörfler sMemoryTypeBitmap |= 1UL << index; 65393fceb5SAxel Dörfler return index; 66393fceb5SAxel Dörfler } 67393fceb5SAxel Dörfler 68393fceb5SAxel Dörfler return -1; 69393fceb5SAxel Dörfler } 70393fceb5SAxel Dörfler 71393fceb5SAxel Dörfler 72393fceb5SAxel Dörfler static void 73393fceb5SAxel Dörfler free_mtrr(int32 index) 74393fceb5SAxel Dörfler { 75393fceb5SAxel Dörfler InterruptsSpinLocker _(&sMemoryTypeLock); 76393fceb5SAxel Dörfler 77393fceb5SAxel Dörfler sMemoryTypeBitmap &= ~(1UL << index); 78393fceb5SAxel Dörfler } 79393fceb5SAxel Dörfler 80393fceb5SAxel Dörfler 81cd9ce121SJérôme Duval /*! 82cd9ce121SJérôme Duval Checks if the provided range overlaps an existing mtrr range 83cd9ce121SJérôme Duval If it actually extends an existing range, extendedIndex is filled 84cd9ce121SJérôme Duval */ 85e958cea5SJérôme Duval static bool 86cd9ce121SJérôme Duval is_memory_overlapping(uint64 base, uint64 length, int32 *extendedIndex) 87e958cea5SJérôme Duval { 88cd9ce121SJérôme Duval *extendedIndex = -1; 89e958cea5SJérôme Duval for (uint32 index = 0; index < sMemoryTypeRegisterCount; index++) { 90e958cea5SJérôme Duval if (sMemoryTypeBitmap & (1UL << index)) { 91e958cea5SJérôme Duval uint64 b,l; 92e958cea5SJérôme Duval uint8 t; 93e958cea5SJérôme Duval x86_get_mtrr(index, &b, &l, &t); 94cd9ce121SJérôme Duval 95cd9ce121SJérôme Duval // check first for write combining extensions 969fcee65eSJérôme Duval if (base <= b 979fcee65eSJérôme Duval && (base + length) >= (b + l) 98cd9ce121SJérôme Duval && t == IA32_MTR_WRITE_COMBINING) { 99cd9ce121SJérôme Duval *extendedIndex = index; 100cd9ce121SJérôme Duval return true; 101cd9ce121SJérôme Duval } 1029fcee65eSJérôme Duval if ((base >= b && base < (b + l)) 103e958cea5SJérôme Duval || ((base + length) > b 1049fcee65eSJérôme Duval && (base + length) <= (b + l))) 105e958cea5SJérôme Duval return true; 106e958cea5SJérôme Duval } 107e958cea5SJérôme Duval } 108e958cea5SJérôme Duval return false; 109e958cea5SJérôme Duval } 110e958cea5SJérôme Duval 111e958cea5SJérôme Duval 112393fceb5SAxel Dörfler static uint64 1134e8c60ceSJérôme Duval nearest_power(uint64 value) 114393fceb5SAxel Dörfler { 115393fceb5SAxel Dörfler uint64 power = 1UL << 12; 116393fceb5SAxel Dörfler // 12 bits is the smallest supported alignment/length 117393fceb5SAxel Dörfler 118393fceb5SAxel Dörfler while (value > power) 119393fceb5SAxel Dörfler power <<= 1; 120393fceb5SAxel Dörfler 121393fceb5SAxel Dörfler return power; 122393fceb5SAxel Dörfler } 123393fceb5SAxel Dörfler 124393fceb5SAxel Dörfler 1254f893e39SJérôme Duval static void 1264f893e39SJérôme Duval nearest_powers(uint64 value, uint64 *lower, uint64 *upper) 1274f893e39SJérôme Duval { 1284f893e39SJérôme Duval uint64 power = 1UL << 12; 1294f893e39SJérôme Duval *lower = power; 1304f893e39SJérôme Duval // 12 bits is the smallest supported alignment/length 1314f893e39SJérôme Duval 1324f893e39SJérôme Duval while (value >= power) { 1334f893e39SJérôme Duval *lower = power; 1344f893e39SJérôme Duval power <<= 1; 1354f893e39SJérôme Duval } 1364f893e39SJérôme Duval 1374f893e39SJérôme Duval *upper = power; 1384f893e39SJérôme Duval } 1394f893e39SJérôme Duval 1404f893e39SJérôme Duval 141393fceb5SAxel Dörfler static status_t 142393fceb5SAxel Dörfler set_memory_type(int32 id, uint64 base, uint64 length, uint32 type) 143393fceb5SAxel Dörfler { 144cd9ce121SJérôme Duval int32 index = -1; 145393fceb5SAxel Dörfler 146393fceb5SAxel Dörfler if (type == 0) 147393fceb5SAxel Dörfler return B_OK; 148393fceb5SAxel Dörfler 149393fceb5SAxel Dörfler switch (type) { 150393fceb5SAxel Dörfler case B_MTR_UC: 1514f893e39SJérôme Duval type = IA32_MTR_UNCACHED; 152393fceb5SAxel Dörfler break; 153393fceb5SAxel Dörfler case B_MTR_WC: 1544f893e39SJérôme Duval type = IA32_MTR_WRITE_COMBINING; 155393fceb5SAxel Dörfler break; 156393fceb5SAxel Dörfler case B_MTR_WT: 1574f893e39SJérôme Duval type = IA32_MTR_WRITE_THROUGH; 158393fceb5SAxel Dörfler break; 159393fceb5SAxel Dörfler case B_MTR_WP: 1604f893e39SJérôme Duval type = IA32_MTR_WRITE_PROTECTED; 161393fceb5SAxel Dörfler break; 162393fceb5SAxel Dörfler case B_MTR_WB: 1634f893e39SJérôme Duval type = IA32_MTR_WRITE_BACK; 164393fceb5SAxel Dörfler break; 165393fceb5SAxel Dörfler default: 166393fceb5SAxel Dörfler return B_BAD_VALUE; 167393fceb5SAxel Dörfler } 168393fceb5SAxel Dörfler 169393fceb5SAxel Dörfler if (sMemoryTypeRegisterCount == 0) 170393fceb5SAxel Dörfler return B_NOT_SUPPORTED; 171393fceb5SAxel Dörfler 172e958cea5SJérôme Duval // check if it overlaps 173e958cea5SJérôme Duval if (type == IA32_MTR_WRITE_COMBINING 174cd9ce121SJérôme Duval && is_memory_overlapping(base, length, &index)) { 175cd9ce121SJérôme Duval if (index < 0) { 176e958cea5SJérôme Duval dprintf("allocate MTRR failed, it overlaps an existing MTRR slot\n"); 177e958cea5SJérôme Duval return B_BAD_VALUE; 178e958cea5SJérôme Duval } 179cd9ce121SJérôme Duval // we replace an existing write-combining mtrr with a bigger one at the index position 180cd9ce121SJérôme Duval } 181e958cea5SJérôme Duval 182393fceb5SAxel Dörfler // length must be a power of 2; just round it up to the next value 1834f893e39SJérôme Duval length = nearest_power(length); 1842d2212bdSJérôme Duval 1854f893e39SJérôme Duval if (length + base <= base) { 186393fceb5SAxel Dörfler // 4GB overflow 187393fceb5SAxel Dörfler return B_BAD_VALUE; 188393fceb5SAxel Dörfler } 189393fceb5SAxel Dörfler 190393fceb5SAxel Dörfler // base must be aligned to the length 1914f893e39SJérôme Duval if (base & (length - 1)) 192393fceb5SAxel Dörfler return B_BAD_VALUE; 193393fceb5SAxel Dörfler 194cd9ce121SJérôme Duval if (index < 0) 195393fceb5SAxel Dörfler index = allocate_mtrr(); 196393fceb5SAxel Dörfler if (index < 0) 197393fceb5SAxel Dörfler return B_ERROR; 198393fceb5SAxel Dörfler 1994e8c60ceSJérôme Duval TRACE_MTRR("allocate MTRR slot %ld, base = %Lx, length = %Lx, type=0x%lx\n", 2004e8c60ceSJérôme Duval index, base, length, type); 201393fceb5SAxel Dörfler 202393fceb5SAxel Dörfler sMemoryTypeIDs[index] = id; 2034f893e39SJérôme Duval x86_set_mtrr(index, base, length, type); 204393fceb5SAxel Dörfler 205393fceb5SAxel Dörfler return B_OK; 206393fceb5SAxel Dörfler } 207393fceb5SAxel Dörfler 208393fceb5SAxel Dörfler 209b20d05b4SJérôme Duval #define MTRR_MAX_SOLUTIONS 5 // usually MTRR count is eight, keep a few for other needs 210*7522f308SJérôme Duval #define MTRR_MIN_SIZE 0x80000 // 512 KB 2114e8c60ceSJérôme Duval static int64 sSolutions[MTRR_MAX_SOLUTIONS]; 2124e8c60ceSJérôme Duval static int32 sSolutionCount; 2134e8c60ceSJérôme Duval static int64 sPropositions[MTRR_MAX_SOLUTIONS]; 2144f893e39SJérôme Duval 2154f893e39SJérôme Duval 216b20d05b4SJérôme Duval /*! Find the nearest powers of two for a value, save current iteration, 217b20d05b4SJérôme Duval then make recursives calls for the remaining values. 218b20d05b4SJérôme Duval It uses at most MTRR_MAX_SOLUTIONS levels of recursion because 219b20d05b4SJérôme Duval only that count of MTRR registers are available to map the memory. 220b20d05b4SJérôme Duval */ 2214f893e39SJérôme Duval static void 2224f893e39SJérôme Duval find_nearest(uint64 value, int iteration) 2234f893e39SJérôme Duval { 2244f893e39SJérôme Duval TRACE_MTRR("find_nearest %Lx %d\n", value, iteration); 2254e8c60ceSJérôme Duval if (iteration > (MTRR_MAX_SOLUTIONS - 1) || (iteration + 1) >= sSolutionCount) 2264f893e39SJérôme Duval return; 2274f893e39SJérôme Duval uint64 down, up; 2284f893e39SJérôme Duval int i; 2294f893e39SJérôme Duval nearest_powers(value, &down, &up); 2304e8c60ceSJérôme Duval sPropositions[iteration] = down; 231b20d05b4SJérôme Duval if (value - down < MTRR_MIN_SIZE) { 2324f893e39SJérôme Duval for (i=0; i<=iteration; i++) 2334e8c60ceSJérôme Duval sSolutions[i] = sPropositions[i]; 2344e8c60ceSJérôme Duval sSolutionCount = iteration + 1; 2354f893e39SJérôme Duval return; 2364f893e39SJérôme Duval } 2374f893e39SJérôme Duval find_nearest(value - down, iteration + 1); 2384e8c60ceSJérôme Duval sPropositions[iteration] = -up; 239b20d05b4SJérôme Duval if (up - value < MTRR_MIN_SIZE) { 2404f893e39SJérôme Duval for (i=0; i<=iteration; i++) 2414e8c60ceSJérôme Duval sSolutions[i] = sPropositions[i]; 2424e8c60ceSJérôme Duval sSolutionCount = iteration + 1; 2434f893e39SJérôme Duval return; 2444f893e39SJérôme Duval } 2454f893e39SJérôme Duval find_nearest(up - value, iteration + 1); 2464f893e39SJérôme Duval } 2474f893e39SJérôme Duval 2484f893e39SJérôme Duval 249b20d05b4SJérôme Duval /*! Set up MTRR to map the memory to write-back using uncached if necessary */ 25048e299e2SIngo Weinhold static void 2514f893e39SJérôme Duval set_memory_write_back(int32 id, uint64 base, uint64 length) 2524f893e39SJérôme Duval { 2534e8c60ceSJérôme Duval status_t err; 2544f893e39SJérôme Duval TRACE_MTRR("set_memory_write_back base %Lx length %Lx\n", base, length); 2554e8c60ceSJérôme Duval sSolutionCount = MTRR_MAX_SOLUTIONS; 2564f893e39SJérôme Duval find_nearest(length, 0); 2574f893e39SJérôme Duval 2584f893e39SJérôme Duval #ifdef TRACE_MTRR 2594e8c60ceSJérôme Duval dprintf("solutions: "); 2604e8c60ceSJérôme Duval for (int i=0; i<sSolutionCount; i++) { 2614e8c60ceSJérôme Duval dprintf("0x%Lx ", sSolutions[i]); 2624f893e39SJérôme Duval } 2634f893e39SJérôme Duval dprintf("\n"); 2644f893e39SJérôme Duval #endif 2654f893e39SJérôme Duval 2664f893e39SJérôme Duval bool nextDown = false; 2674e8c60ceSJérôme Duval for (int i = 0; i < sSolutionCount; i++) { 2684e8c60ceSJérôme Duval if (sSolutions[i] < 0) { 2694f893e39SJérôme Duval if (nextDown) 2704e8c60ceSJérôme Duval base += sSolutions[i]; 2714e8c60ceSJérôme Duval err = set_memory_type(id, base, -sSolutions[i], nextDown ? B_MTR_UC : B_MTR_WB); 2724e8c60ceSJérôme Duval if (err != B_OK) { 2734e8c60ceSJérôme Duval dprintf("set_memory_type returned %s (0x%lx)\n", strerror(err), err); 2744e8c60ceSJérôme Duval } 2754f893e39SJérôme Duval if (!nextDown) 2764e8c60ceSJérôme Duval base -= sSolutions[i]; 2774f893e39SJérôme Duval nextDown = !nextDown; 2784f893e39SJérôme Duval } else { 2794f893e39SJérôme Duval if (nextDown) 2804e8c60ceSJérôme Duval base -= sSolutions[i]; 2814e8c60ceSJérôme Duval err = set_memory_type(id, base, sSolutions[i], nextDown ? B_MTR_UC : B_MTR_WB); 2824e8c60ceSJérôme Duval if (err != B_OK) { 2834e8c60ceSJérôme Duval dprintf("set_memory_type returned %s (0x%lx)\n", strerror(err), err); 2844e8c60ceSJérôme Duval } 2854f893e39SJérôme Duval if (!nextDown) 2864e8c60ceSJérôme Duval base += sSolutions[i]; 2874f893e39SJérôme Duval } 2884f893e39SJérôme Duval } 2894f893e39SJérôme Duval } 2904f893e39SJérôme Duval 2914f893e39SJérôme Duval 292393fceb5SAxel Dörfler // #pragma mark - 293393fceb5SAxel Dörfler 294393fceb5SAxel Dörfler 295393fceb5SAxel Dörfler status_t 296393fceb5SAxel Dörfler arch_vm_init(kernel_args *args) 297393fceb5SAxel Dörfler { 298393fceb5SAxel Dörfler TRACE(("arch_vm_init: entry\n")); 299393fceb5SAxel Dörfler return 0; 300393fceb5SAxel Dörfler } 301393fceb5SAxel Dörfler 302393fceb5SAxel Dörfler 303393fceb5SAxel Dörfler /*! Marks DMA region as in-use, and maps it into the kernel space */ 304393fceb5SAxel Dörfler status_t 305393fceb5SAxel Dörfler arch_vm_init_post_area(kernel_args *args) 306393fceb5SAxel Dörfler { 307393fceb5SAxel Dörfler area_id id; 308393fceb5SAxel Dörfler 309393fceb5SAxel Dörfler TRACE(("arch_vm_init_post_area: entry\n")); 310393fceb5SAxel Dörfler 311393fceb5SAxel Dörfler // account for DMA area and mark the pages unusable 312393fceb5SAxel Dörfler vm_mark_page_range_inuse(0x0, 0xa0000 / B_PAGE_SIZE); 313393fceb5SAxel Dörfler 314393fceb5SAxel Dörfler // map 0 - 0xa0000 directly 315393fceb5SAxel Dörfler id = map_physical_memory("dma_region", (void *)0x0, 0xa0000, 316393fceb5SAxel Dörfler B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 317393fceb5SAxel Dörfler &gDmaAddress); 318393fceb5SAxel Dörfler if (id < 0) { 319393fceb5SAxel Dörfler panic("arch_vm_init_post_area: unable to map dma region\n"); 320393fceb5SAxel Dörfler return B_NO_MEMORY; 321393fceb5SAxel Dörfler } 322393fceb5SAxel Dörfler 323393fceb5SAxel Dörfler return bios_init(); 324393fceb5SAxel Dörfler } 325393fceb5SAxel Dörfler 326393fceb5SAxel Dörfler 327393fceb5SAxel Dörfler /*! Gets rid of all yet unmapped (and therefore now unused) page tables */ 328393fceb5SAxel Dörfler status_t 329393fceb5SAxel Dörfler arch_vm_init_end(kernel_args *args) 330393fceb5SAxel Dörfler { 331393fceb5SAxel Dörfler TRACE(("arch_vm_init_endvm: entry\n")); 332393fceb5SAxel Dörfler 333393fceb5SAxel Dörfler // throw away anything in the kernel_args.pgtable[] that's not yet mapped 334393fceb5SAxel Dörfler vm_free_unused_boot_loader_range(KERNEL_BASE, 335393fceb5SAxel Dörfler 0x400000 * args->arch_args.num_pgtables); 336393fceb5SAxel Dörfler 337393fceb5SAxel Dörfler return B_OK; 338393fceb5SAxel Dörfler } 339393fceb5SAxel Dörfler 340393fceb5SAxel Dörfler 341393fceb5SAxel Dörfler status_t 342393fceb5SAxel Dörfler arch_vm_init_post_modules(kernel_args *args) 343393fceb5SAxel Dörfler { 344393fceb5SAxel Dörfler // void *cookie; 345393fceb5SAxel Dörfler 346393fceb5SAxel Dörfler // the x86 CPU modules are now accessible 347393fceb5SAxel Dörfler 348393fceb5SAxel Dörfler sMemoryTypeRegisterCount = x86_count_mtrrs(); 349393fceb5SAxel Dörfler if (sMemoryTypeRegisterCount == 0) 350393fceb5SAxel Dörfler return B_OK; 351393fceb5SAxel Dörfler 352393fceb5SAxel Dörfler // not very likely, but play safe here 353393fceb5SAxel Dörfler if (sMemoryTypeRegisterCount > kMaxMemoryTypeRegisters) 354393fceb5SAxel Dörfler sMemoryTypeRegisterCount = kMaxMemoryTypeRegisters; 355393fceb5SAxel Dörfler 356393fceb5SAxel Dörfler // init memory type ID table 357393fceb5SAxel Dörfler 358393fceb5SAxel Dörfler for (uint32 i = 0; i < sMemoryTypeRegisterCount; i++) { 359393fceb5SAxel Dörfler sMemoryTypeIDs[i] = -1; 360393fceb5SAxel Dörfler } 361393fceb5SAxel Dörfler 362393fceb5SAxel Dörfler // set the physical memory ranges to write-back mode 363393fceb5SAxel Dörfler 364393fceb5SAxel Dörfler for (uint32 i = 0; i < args->num_physical_memory_ranges; i++) { 3654f893e39SJérôme Duval set_memory_write_back(-1, args->physical_memory_range[i].start, 3664f893e39SJérôme Duval args->physical_memory_range[i].size); 367393fceb5SAxel Dörfler } 368393fceb5SAxel Dörfler 369393fceb5SAxel Dörfler return B_OK; 370393fceb5SAxel Dörfler } 371393fceb5SAxel Dörfler 372393fceb5SAxel Dörfler 373393fceb5SAxel Dörfler void 374393fceb5SAxel Dörfler arch_vm_aspace_swap(vm_address_space *aspace) 375393fceb5SAxel Dörfler { 376393fceb5SAxel Dörfler i386_swap_pgdir((addr_t)i386_translation_map_get_pgdir( 377393fceb5SAxel Dörfler &aspace->translation_map)); 378393fceb5SAxel Dörfler } 379393fceb5SAxel Dörfler 380393fceb5SAxel Dörfler 381393fceb5SAxel Dörfler bool 382393fceb5SAxel Dörfler arch_vm_supports_protection(uint32 protection) 383393fceb5SAxel Dörfler { 384393fceb5SAxel Dörfler // x86 always has the same read/write properties for userland and the 385393fceb5SAxel Dörfler // kernel. 386393fceb5SAxel Dörfler // That's why we do not support user-read/kernel-write access. While the 387393fceb5SAxel Dörfler // other way around is not supported either, we don't care in this case 388393fceb5SAxel Dörfler // and give the kernel full access. 389393fceb5SAxel Dörfler if ((protection & (B_READ_AREA | B_WRITE_AREA)) == B_READ_AREA 390393fceb5SAxel Dörfler && protection & B_KERNEL_WRITE_AREA) 391393fceb5SAxel Dörfler return false; 392393fceb5SAxel Dörfler 393393fceb5SAxel Dörfler return true; 394393fceb5SAxel Dörfler } 395393fceb5SAxel Dörfler 396393fceb5SAxel Dörfler 397393fceb5SAxel Dörfler void 398393fceb5SAxel Dörfler arch_vm_unset_memory_type(struct vm_area *area) 399393fceb5SAxel Dörfler { 400393fceb5SAxel Dörfler uint32 index; 401393fceb5SAxel Dörfler 402393fceb5SAxel Dörfler if (area->memory_type == 0) 403393fceb5SAxel Dörfler return; 404393fceb5SAxel Dörfler 405393fceb5SAxel Dörfler // find index for area ID 406393fceb5SAxel Dörfler 407393fceb5SAxel Dörfler for (index = 0; index < sMemoryTypeRegisterCount; index++) { 408393fceb5SAxel Dörfler if (sMemoryTypeIDs[index] == area->id) { 409393fceb5SAxel Dörfler x86_set_mtrr(index, 0, 0, 0); 410393fceb5SAxel Dörfler 411393fceb5SAxel Dörfler sMemoryTypeIDs[index] = -1; 412393fceb5SAxel Dörfler free_mtrr(index); 413393fceb5SAxel Dörfler break; 414393fceb5SAxel Dörfler } 415393fceb5SAxel Dörfler } 416393fceb5SAxel Dörfler } 417393fceb5SAxel Dörfler 418393fceb5SAxel Dörfler 419393fceb5SAxel Dörfler status_t 420393fceb5SAxel Dörfler arch_vm_set_memory_type(struct vm_area *area, addr_t physicalBase, 421393fceb5SAxel Dörfler uint32 type) 422393fceb5SAxel Dörfler { 423393fceb5SAxel Dörfler area->memory_type = type >> MEMORY_TYPE_SHIFT; 424393fceb5SAxel Dörfler return set_memory_type(area->id, physicalBase, area->size, type); 425393fceb5SAxel Dörfler } 426