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 172c103aef2SJérôme Duval #if 0 173e958cea5SJérôme Duval // check if it overlaps 174e958cea5SJérôme Duval if (type == IA32_MTR_WRITE_COMBINING 175cd9ce121SJérôme Duval && is_memory_overlapping(base, length, &index)) { 176cd9ce121SJérôme Duval if (index < 0) { 177e958cea5SJérôme Duval dprintf("allocate MTRR failed, it overlaps an existing MTRR slot\n"); 178e958cea5SJérôme Duval return B_BAD_VALUE; 179e958cea5SJérôme Duval } 180cd9ce121SJérôme Duval // we replace an existing write-combining mtrr with a bigger one at the index position 181cd9ce121SJérôme Duval } 182c103aef2SJérôme Duval #endif 183e958cea5SJérôme Duval 184393fceb5SAxel Dörfler // length must be a power of 2; just round it up to the next value 1854f893e39SJérôme Duval length = nearest_power(length); 1862d2212bdSJérôme Duval 1874f893e39SJérôme Duval if (length + base <= base) { 188393fceb5SAxel Dörfler // 4GB overflow 189393fceb5SAxel Dörfler return B_BAD_VALUE; 190393fceb5SAxel Dörfler } 191393fceb5SAxel Dörfler 192393fceb5SAxel Dörfler // base must be aligned to the length 1934f893e39SJérôme Duval if (base & (length - 1)) 194393fceb5SAxel Dörfler return B_BAD_VALUE; 195393fceb5SAxel Dörfler 196cd9ce121SJérôme Duval if (index < 0) 197393fceb5SAxel Dörfler index = allocate_mtrr(); 198393fceb5SAxel Dörfler if (index < 0) 199393fceb5SAxel Dörfler return B_ERROR; 200393fceb5SAxel Dörfler 2014e8c60ceSJérôme Duval TRACE_MTRR("allocate MTRR slot %ld, base = %Lx, length = %Lx, type=0x%lx\n", 2024e8c60ceSJérôme Duval index, base, length, type); 203393fceb5SAxel Dörfler 204393fceb5SAxel Dörfler sMemoryTypeIDs[index] = id; 2054f893e39SJérôme Duval x86_set_mtrr(index, base, length, type); 206393fceb5SAxel Dörfler 207393fceb5SAxel Dörfler return B_OK; 208393fceb5SAxel Dörfler } 209393fceb5SAxel Dörfler 210393fceb5SAxel Dörfler 211b20d05b4SJérôme Duval #define MTRR_MAX_SOLUTIONS 5 // usually MTRR count is eight, keep a few for other needs 2127522f308SJérôme Duval #define MTRR_MIN_SIZE 0x80000 // 512 KB 2134e8c60ceSJérôme Duval static int64 sSolutions[MTRR_MAX_SOLUTIONS]; 2144e8c60ceSJérôme Duval static int32 sSolutionCount; 2154e8c60ceSJérôme Duval static int64 sPropositions[MTRR_MAX_SOLUTIONS]; 2164f893e39SJérôme Duval 2174f893e39SJérôme Duval 218b20d05b4SJérôme Duval /*! Find the nearest powers of two for a value, save current iteration, 219b20d05b4SJérôme Duval then make recursives calls for the remaining values. 220b20d05b4SJérôme Duval It uses at most MTRR_MAX_SOLUTIONS levels of recursion because 221b20d05b4SJérôme Duval only that count of MTRR registers are available to map the memory. 222b20d05b4SJérôme Duval */ 2234f893e39SJérôme Duval static void 2244f893e39SJérôme Duval find_nearest(uint64 value, int iteration) 2254f893e39SJérôme Duval { 2264f893e39SJérôme Duval int i; 227*f7c655c7SJérôme Duval uint64 down, up; 228*f7c655c7SJérôme Duval TRACE_MTRR("find_nearest %Lx %d\n", value, iteration); 229*f7c655c7SJérôme Duval if (iteration > (MTRR_MAX_SOLUTIONS - 1) || (iteration + 1) >= sSolutionCount) { 230*f7c655c7SJérôme Duval if (sSolutionCount > MTRR_MAX_SOLUTIONS) { 231*f7c655c7SJérôme Duval // no solutions yet, save something 232*f7c655c7SJérôme Duval for (i=0; i<iteration; i++) 233*f7c655c7SJérôme Duval sSolutions[i] = sPropositions[i]; 234*f7c655c7SJérôme Duval sSolutionCount = iteration; 235*f7c655c7SJérôme Duval } 236*f7c655c7SJérôme Duval return; 237*f7c655c7SJérôme Duval } 2384f893e39SJérôme Duval nearest_powers(value, &down, &up); 2394e8c60ceSJérôme Duval sPropositions[iteration] = down; 240b20d05b4SJérôme Duval if (value - down < MTRR_MIN_SIZE) { 2414f893e39SJérôme Duval for (i=0; i<=iteration; i++) 2424e8c60ceSJérôme Duval sSolutions[i] = sPropositions[i]; 2434e8c60ceSJérôme Duval sSolutionCount = iteration + 1; 2444f893e39SJérôme Duval return; 2454f893e39SJérôme Duval } 2464f893e39SJérôme Duval find_nearest(value - down, iteration + 1); 2474e8c60ceSJérôme Duval sPropositions[iteration] = -up; 248b20d05b4SJérôme Duval if (up - value < MTRR_MIN_SIZE) { 2494f893e39SJérôme Duval for (i=0; i<=iteration; i++) 2504e8c60ceSJérôme Duval sSolutions[i] = sPropositions[i]; 2514e8c60ceSJérôme Duval sSolutionCount = iteration + 1; 2524f893e39SJérôme Duval return; 2534f893e39SJérôme Duval } 2544f893e39SJérôme Duval find_nearest(up - value, iteration + 1); 2554f893e39SJérôme Duval } 2564f893e39SJérôme Duval 2574f893e39SJérôme Duval 258b20d05b4SJérôme Duval /*! Set up MTRR to map the memory to write-back using uncached if necessary */ 25948e299e2SIngo Weinhold static void 2604f893e39SJérôme Duval set_memory_write_back(int32 id, uint64 base, uint64 length) 2614f893e39SJérôme Duval { 2624e8c60ceSJérôme Duval status_t err; 2634f893e39SJérôme Duval TRACE_MTRR("set_memory_write_back base %Lx length %Lx\n", base, length); 264*f7c655c7SJérôme Duval sSolutionCount = MTRR_MAX_SOLUTIONS + 1; 2654f893e39SJérôme Duval find_nearest(length, 0); 2664f893e39SJérôme Duval 2674f893e39SJérôme Duval #ifdef TRACE_MTRR 2684e8c60ceSJérôme Duval dprintf("solutions: "); 2694e8c60ceSJérôme Duval for (int i=0; i<sSolutionCount; i++) { 2704e8c60ceSJérôme Duval dprintf("0x%Lx ", sSolutions[i]); 2714f893e39SJérôme Duval } 2724f893e39SJérôme Duval dprintf("\n"); 2734f893e39SJérôme Duval #endif 2744f893e39SJérôme Duval 2754f893e39SJérôme Duval bool nextDown = false; 2764e8c60ceSJérôme Duval for (int i = 0; i < sSolutionCount; i++) { 2774e8c60ceSJérôme Duval if (sSolutions[i] < 0) { 2784f893e39SJérôme Duval if (nextDown) 2794e8c60ceSJérôme Duval base += sSolutions[i]; 2804e8c60ceSJérôme Duval err = set_memory_type(id, base, -sSolutions[i], nextDown ? B_MTR_UC : B_MTR_WB); 2814e8c60ceSJérôme Duval if (err != B_OK) { 2824e8c60ceSJérôme Duval dprintf("set_memory_type returned %s (0x%lx)\n", strerror(err), err); 2834e8c60ceSJérôme Duval } 2844f893e39SJérôme Duval if (!nextDown) 2854e8c60ceSJérôme Duval base -= sSolutions[i]; 2864f893e39SJérôme Duval nextDown = !nextDown; 2874f893e39SJérôme Duval } else { 2884f893e39SJérôme Duval if (nextDown) 2894e8c60ceSJérôme Duval base -= sSolutions[i]; 2904e8c60ceSJérôme Duval err = set_memory_type(id, base, sSolutions[i], nextDown ? B_MTR_UC : B_MTR_WB); 2914e8c60ceSJérôme Duval if (err != B_OK) { 2924e8c60ceSJérôme Duval dprintf("set_memory_type returned %s (0x%lx)\n", strerror(err), err); 2934e8c60ceSJérôme Duval } 2944f893e39SJérôme Duval if (!nextDown) 2954e8c60ceSJérôme Duval base += sSolutions[i]; 2964f893e39SJérôme Duval } 2974f893e39SJérôme Duval } 2984f893e39SJérôme Duval } 2994f893e39SJérôme Duval 3004f893e39SJérôme Duval 301393fceb5SAxel Dörfler // #pragma mark - 302393fceb5SAxel Dörfler 303393fceb5SAxel Dörfler 304393fceb5SAxel Dörfler status_t 305393fceb5SAxel Dörfler arch_vm_init(kernel_args *args) 306393fceb5SAxel Dörfler { 307393fceb5SAxel Dörfler TRACE(("arch_vm_init: entry\n")); 308393fceb5SAxel Dörfler return 0; 309393fceb5SAxel Dörfler } 310393fceb5SAxel Dörfler 311393fceb5SAxel Dörfler 312393fceb5SAxel Dörfler /*! Marks DMA region as in-use, and maps it into the kernel space */ 313393fceb5SAxel Dörfler status_t 314393fceb5SAxel Dörfler arch_vm_init_post_area(kernel_args *args) 315393fceb5SAxel Dörfler { 316393fceb5SAxel Dörfler area_id id; 317393fceb5SAxel Dörfler 318393fceb5SAxel Dörfler TRACE(("arch_vm_init_post_area: entry\n")); 319393fceb5SAxel Dörfler 320393fceb5SAxel Dörfler // account for DMA area and mark the pages unusable 321393fceb5SAxel Dörfler vm_mark_page_range_inuse(0x0, 0xa0000 / B_PAGE_SIZE); 322393fceb5SAxel Dörfler 323393fceb5SAxel Dörfler // map 0 - 0xa0000 directly 324393fceb5SAxel Dörfler id = map_physical_memory("dma_region", (void *)0x0, 0xa0000, 325393fceb5SAxel Dörfler B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 326393fceb5SAxel Dörfler &gDmaAddress); 327393fceb5SAxel Dörfler if (id < 0) { 328393fceb5SAxel Dörfler panic("arch_vm_init_post_area: unable to map dma region\n"); 329393fceb5SAxel Dörfler return B_NO_MEMORY; 330393fceb5SAxel Dörfler } 331393fceb5SAxel Dörfler 332393fceb5SAxel Dörfler return bios_init(); 333393fceb5SAxel Dörfler } 334393fceb5SAxel Dörfler 335393fceb5SAxel Dörfler 336393fceb5SAxel Dörfler /*! Gets rid of all yet unmapped (and therefore now unused) page tables */ 337393fceb5SAxel Dörfler status_t 338393fceb5SAxel Dörfler arch_vm_init_end(kernel_args *args) 339393fceb5SAxel Dörfler { 340393fceb5SAxel Dörfler TRACE(("arch_vm_init_endvm: entry\n")); 341393fceb5SAxel Dörfler 342393fceb5SAxel Dörfler // throw away anything in the kernel_args.pgtable[] that's not yet mapped 343393fceb5SAxel Dörfler vm_free_unused_boot_loader_range(KERNEL_BASE, 344393fceb5SAxel Dörfler 0x400000 * args->arch_args.num_pgtables); 345393fceb5SAxel Dörfler 346393fceb5SAxel Dörfler return B_OK; 347393fceb5SAxel Dörfler } 348393fceb5SAxel Dörfler 349393fceb5SAxel Dörfler 350393fceb5SAxel Dörfler status_t 351393fceb5SAxel Dörfler arch_vm_init_post_modules(kernel_args *args) 352393fceb5SAxel Dörfler { 353393fceb5SAxel Dörfler // void *cookie; 354393fceb5SAxel Dörfler 355393fceb5SAxel Dörfler // the x86 CPU modules are now accessible 356393fceb5SAxel Dörfler 357393fceb5SAxel Dörfler sMemoryTypeRegisterCount = x86_count_mtrrs(); 358393fceb5SAxel Dörfler if (sMemoryTypeRegisterCount == 0) 359393fceb5SAxel Dörfler return B_OK; 360393fceb5SAxel Dörfler 361393fceb5SAxel Dörfler // not very likely, but play safe here 362393fceb5SAxel Dörfler if (sMemoryTypeRegisterCount > kMaxMemoryTypeRegisters) 363393fceb5SAxel Dörfler sMemoryTypeRegisterCount = kMaxMemoryTypeRegisters; 364393fceb5SAxel Dörfler 365393fceb5SAxel Dörfler // init memory type ID table 366393fceb5SAxel Dörfler 367393fceb5SAxel Dörfler for (uint32 i = 0; i < sMemoryTypeRegisterCount; i++) { 368393fceb5SAxel Dörfler sMemoryTypeIDs[i] = -1; 369393fceb5SAxel Dörfler } 370393fceb5SAxel Dörfler 371393fceb5SAxel Dörfler // set the physical memory ranges to write-back mode 372393fceb5SAxel Dörfler 373393fceb5SAxel Dörfler for (uint32 i = 0; i < args->num_physical_memory_ranges; i++) { 3744f893e39SJérôme Duval set_memory_write_back(-1, args->physical_memory_range[i].start, 3754f893e39SJérôme Duval args->physical_memory_range[i].size); 376393fceb5SAxel Dörfler } 377393fceb5SAxel Dörfler 378393fceb5SAxel Dörfler return B_OK; 379393fceb5SAxel Dörfler } 380393fceb5SAxel Dörfler 381393fceb5SAxel Dörfler 382393fceb5SAxel Dörfler void 383393fceb5SAxel Dörfler arch_vm_aspace_swap(vm_address_space *aspace) 384393fceb5SAxel Dörfler { 385393fceb5SAxel Dörfler i386_swap_pgdir((addr_t)i386_translation_map_get_pgdir( 386393fceb5SAxel Dörfler &aspace->translation_map)); 387393fceb5SAxel Dörfler } 388393fceb5SAxel Dörfler 389393fceb5SAxel Dörfler 390393fceb5SAxel Dörfler bool 391393fceb5SAxel Dörfler arch_vm_supports_protection(uint32 protection) 392393fceb5SAxel Dörfler { 393393fceb5SAxel Dörfler // x86 always has the same read/write properties for userland and the 394393fceb5SAxel Dörfler // kernel. 395393fceb5SAxel Dörfler // That's why we do not support user-read/kernel-write access. While the 396393fceb5SAxel Dörfler // other way around is not supported either, we don't care in this case 397393fceb5SAxel Dörfler // and give the kernel full access. 398393fceb5SAxel Dörfler if ((protection & (B_READ_AREA | B_WRITE_AREA)) == B_READ_AREA 399393fceb5SAxel Dörfler && protection & B_KERNEL_WRITE_AREA) 400393fceb5SAxel Dörfler return false; 401393fceb5SAxel Dörfler 402393fceb5SAxel Dörfler return true; 403393fceb5SAxel Dörfler } 404393fceb5SAxel Dörfler 405393fceb5SAxel Dörfler 406393fceb5SAxel Dörfler void 407393fceb5SAxel Dörfler arch_vm_unset_memory_type(struct vm_area *area) 408393fceb5SAxel Dörfler { 409393fceb5SAxel Dörfler uint32 index; 410393fceb5SAxel Dörfler 411393fceb5SAxel Dörfler if (area->memory_type == 0) 412393fceb5SAxel Dörfler return; 413393fceb5SAxel Dörfler 414393fceb5SAxel Dörfler // find index for area ID 415393fceb5SAxel Dörfler 416393fceb5SAxel Dörfler for (index = 0; index < sMemoryTypeRegisterCount; index++) { 417393fceb5SAxel Dörfler if (sMemoryTypeIDs[index] == area->id) { 418393fceb5SAxel Dörfler x86_set_mtrr(index, 0, 0, 0); 419393fceb5SAxel Dörfler 420393fceb5SAxel Dörfler sMemoryTypeIDs[index] = -1; 421393fceb5SAxel Dörfler free_mtrr(index); 422393fceb5SAxel Dörfler break; 423393fceb5SAxel Dörfler } 424393fceb5SAxel Dörfler } 425393fceb5SAxel Dörfler } 426393fceb5SAxel Dörfler 427393fceb5SAxel Dörfler 428393fceb5SAxel Dörfler status_t 429393fceb5SAxel Dörfler arch_vm_set_memory_type(struct vm_area *area, addr_t physicalBase, 430393fceb5SAxel Dörfler uint32 type) 431393fceb5SAxel Dörfler { 432393fceb5SAxel Dörfler area->memory_type = type >> MEMORY_TYPE_SHIFT; 433393fceb5SAxel Dörfler return set_memory_type(area->id, physicalBase, area->size, type); 434393fceb5SAxel Dörfler } 435