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 1174785e79SIngo Weinhold #include <stdlib.h> 1274785e79SIngo Weinhold #include <string.h> 1374785e79SIngo Weinhold 14393fceb5SAxel Dörfler #include <KernelExport.h> 1574785e79SIngo Weinhold 16393fceb5SAxel Dörfler #include <smp.h> 17393fceb5SAxel Dörfler #include <util/AutoLock.h> 18393fceb5SAxel Dörfler #include <vm.h> 1974785e79SIngo Weinhold #include <vm_address_space.h> 20393fceb5SAxel Dörfler #include <vm_page.h> 21393fceb5SAxel Dörfler #include <vm_priv.h> 22393fceb5SAxel Dörfler 23393fceb5SAxel Dörfler #include <arch/vm.h> 24393fceb5SAxel Dörfler #include <arch/int.h> 25393fceb5SAxel Dörfler #include <arch/cpu.h> 26393fceb5SAxel Dörfler 27393fceb5SAxel Dörfler #include <arch/x86/bios.h> 28393fceb5SAxel Dörfler 2947c40a10SIngo Weinhold #include "x86_paging.h" 3047c40a10SIngo Weinhold 31393fceb5SAxel Dörfler 32393fceb5SAxel Dörfler //#define TRACE_ARCH_VM 33393fceb5SAxel Dörfler #ifdef TRACE_ARCH_VM 34393fceb5SAxel Dörfler # define TRACE(x) dprintf x 35393fceb5SAxel Dörfler #else 36393fceb5SAxel Dörfler # define TRACE(x) ; 37393fceb5SAxel Dörfler #endif 38393fceb5SAxel Dörfler 394f893e39SJérôme Duval #define TRACE_MTRR_ARCH_VM 404f893e39SJérôme Duval #ifdef TRACE_MTRR_ARCH_VM 414f893e39SJérôme Duval # define TRACE_MTRR(x...) dprintf(x) 424f893e39SJérôme Duval #else 434f893e39SJérôme Duval # define TRACE_MTRR(x...) 444f893e39SJérôme Duval #endif 454f893e39SJérôme Duval 46393fceb5SAxel Dörfler 47393fceb5SAxel Dörfler #define kMaxMemoryTypeRegisters 32 48393fceb5SAxel Dörfler 49393fceb5SAxel Dörfler void *gDmaAddress; 50393fceb5SAxel Dörfler 51393fceb5SAxel Dörfler static uint32 sMemoryTypeBitmap; 52393fceb5SAxel Dörfler static int32 sMemoryTypeIDs[kMaxMemoryTypeRegisters]; 53393fceb5SAxel Dörfler static uint32 sMemoryTypeRegisterCount; 54393fceb5SAxel Dörfler static spinlock sMemoryTypeLock; 55393fceb5SAxel Dörfler 56393fceb5SAxel Dörfler 57393fceb5SAxel Dörfler static int32 58393fceb5SAxel Dörfler allocate_mtrr(void) 59393fceb5SAxel Dörfler { 60393fceb5SAxel Dörfler InterruptsSpinLocker _(&sMemoryTypeLock); 61393fceb5SAxel Dörfler 62393fceb5SAxel Dörfler // find free bit 63393fceb5SAxel Dörfler 64393fceb5SAxel Dörfler for (uint32 index = 0; index < sMemoryTypeRegisterCount; index++) { 65393fceb5SAxel Dörfler if (sMemoryTypeBitmap & (1UL << index)) 66393fceb5SAxel Dörfler continue; 67393fceb5SAxel Dörfler 68393fceb5SAxel Dörfler sMemoryTypeBitmap |= 1UL << index; 69393fceb5SAxel Dörfler return index; 70393fceb5SAxel Dörfler } 71393fceb5SAxel Dörfler 72393fceb5SAxel Dörfler return -1; 73393fceb5SAxel Dörfler } 74393fceb5SAxel Dörfler 75393fceb5SAxel Dörfler 76393fceb5SAxel Dörfler static void 77393fceb5SAxel Dörfler free_mtrr(int32 index) 78393fceb5SAxel Dörfler { 79393fceb5SAxel Dörfler InterruptsSpinLocker _(&sMemoryTypeLock); 80393fceb5SAxel Dörfler 81393fceb5SAxel Dörfler sMemoryTypeBitmap &= ~(1UL << index); 82393fceb5SAxel Dörfler } 83393fceb5SAxel Dörfler 84393fceb5SAxel Dörfler 85b50e6202SIngo Weinhold #if 0 86cd9ce121SJérôme Duval /*! 87cd9ce121SJérôme Duval Checks if the provided range overlaps an existing mtrr range 88cd9ce121SJérôme Duval If it actually extends an existing range, extendedIndex is filled 89cd9ce121SJérôme Duval */ 90e958cea5SJérôme Duval static bool 91cd9ce121SJérôme Duval is_memory_overlapping(uint64 base, uint64 length, int32 *extendedIndex) 92e958cea5SJérôme Duval { 93cd9ce121SJérôme Duval *extendedIndex = -1; 94e958cea5SJérôme Duval for (uint32 index = 0; index < sMemoryTypeRegisterCount; index++) { 95e958cea5SJérôme Duval if (sMemoryTypeBitmap & (1UL << index)) { 96e958cea5SJérôme Duval uint64 b,l; 97e958cea5SJérôme Duval uint8 t; 98e958cea5SJérôme Duval x86_get_mtrr(index, &b, &l, &t); 99cd9ce121SJérôme Duval 100cd9ce121SJérôme Duval // check first for write combining extensions 1019fcee65eSJérôme Duval if (base <= b 1029fcee65eSJérôme Duval && (base + length) >= (b + l) 103cd9ce121SJérôme Duval && t == IA32_MTR_WRITE_COMBINING) { 104cd9ce121SJérôme Duval *extendedIndex = index; 105cd9ce121SJérôme Duval return true; 106cd9ce121SJérôme Duval } 1079fcee65eSJérôme Duval if ((base >= b && base < (b + l)) 108e958cea5SJérôme Duval || ((base + length) > b 1099fcee65eSJérôme Duval && (base + length) <= (b + l))) 110e958cea5SJérôme Duval return true; 111e958cea5SJérôme Duval } 112e958cea5SJérôme Duval } 113e958cea5SJérôme Duval return false; 114e958cea5SJérôme Duval } 115b50e6202SIngo Weinhold #endif // 0 116e958cea5SJérôme Duval 117e958cea5SJérôme Duval 118393fceb5SAxel Dörfler static uint64 1194e8c60ceSJérôme Duval nearest_power(uint64 value) 120393fceb5SAxel Dörfler { 121393fceb5SAxel Dörfler uint64 power = 1UL << 12; 122393fceb5SAxel Dörfler // 12 bits is the smallest supported alignment/length 123393fceb5SAxel Dörfler 124393fceb5SAxel Dörfler while (value > power) 125393fceb5SAxel Dörfler power <<= 1; 126393fceb5SAxel Dörfler 127393fceb5SAxel Dörfler return power; 128393fceb5SAxel Dörfler } 129393fceb5SAxel Dörfler 130393fceb5SAxel Dörfler 1314f893e39SJérôme Duval static void 1324f893e39SJérôme Duval nearest_powers(uint64 value, uint64 *lower, uint64 *upper) 1334f893e39SJérôme Duval { 1344f893e39SJérôme Duval uint64 power = 1UL << 12; 1354f893e39SJérôme Duval *lower = power; 1364f893e39SJérôme Duval // 12 bits is the smallest supported alignment/length 1374f893e39SJérôme Duval 1384f893e39SJérôme Duval while (value >= power) { 1394f893e39SJérôme Duval *lower = power; 1404f893e39SJérôme Duval power <<= 1; 1414f893e39SJérôme Duval } 1424f893e39SJérôme Duval 1434f893e39SJérôme Duval *upper = power; 1444f893e39SJérôme Duval } 1454f893e39SJérôme Duval 1464f893e39SJérôme Duval 147393fceb5SAxel Dörfler static status_t 148393fceb5SAxel Dörfler set_memory_type(int32 id, uint64 base, uint64 length, uint32 type) 149393fceb5SAxel Dörfler { 150cd9ce121SJérôme Duval int32 index = -1; 151393fceb5SAxel Dörfler 152393fceb5SAxel Dörfler if (type == 0) 153393fceb5SAxel Dörfler return B_OK; 154393fceb5SAxel Dörfler 155393fceb5SAxel Dörfler switch (type) { 156393fceb5SAxel Dörfler case B_MTR_UC: 1574f893e39SJérôme Duval type = IA32_MTR_UNCACHED; 158393fceb5SAxel Dörfler break; 159393fceb5SAxel Dörfler case B_MTR_WC: 1604f893e39SJérôme Duval type = IA32_MTR_WRITE_COMBINING; 161393fceb5SAxel Dörfler break; 162393fceb5SAxel Dörfler case B_MTR_WT: 1634f893e39SJérôme Duval type = IA32_MTR_WRITE_THROUGH; 164393fceb5SAxel Dörfler break; 165393fceb5SAxel Dörfler case B_MTR_WP: 1664f893e39SJérôme Duval type = IA32_MTR_WRITE_PROTECTED; 167393fceb5SAxel Dörfler break; 168393fceb5SAxel Dörfler case B_MTR_WB: 1694f893e39SJérôme Duval type = IA32_MTR_WRITE_BACK; 170393fceb5SAxel Dörfler break; 171393fceb5SAxel Dörfler default: 172393fceb5SAxel Dörfler return B_BAD_VALUE; 173393fceb5SAxel Dörfler } 174393fceb5SAxel Dörfler 175393fceb5SAxel Dörfler if (sMemoryTypeRegisterCount == 0) 176393fceb5SAxel Dörfler return B_NOT_SUPPORTED; 177393fceb5SAxel Dörfler 178c103aef2SJérôme Duval #if 0 179e958cea5SJérôme Duval // check if it overlaps 180e958cea5SJérôme Duval if (type == IA32_MTR_WRITE_COMBINING 181cd9ce121SJérôme Duval && is_memory_overlapping(base, length, &index)) { 182cd9ce121SJérôme Duval if (index < 0) { 183e958cea5SJérôme Duval dprintf("allocate MTRR failed, it overlaps an existing MTRR slot\n"); 184e958cea5SJérôme Duval return B_BAD_VALUE; 185e958cea5SJérôme Duval } 186cd9ce121SJérôme Duval // we replace an existing write-combining mtrr with a bigger one at the index position 187cd9ce121SJérôme Duval } 188c103aef2SJérôme Duval #endif 189e958cea5SJérôme Duval 190393fceb5SAxel Dörfler // length must be a power of 2; just round it up to the next value 1914f893e39SJérôme Duval length = nearest_power(length); 1922d2212bdSJérôme Duval 1934f893e39SJérôme Duval if (length + base <= base) { 194393fceb5SAxel Dörfler // 4GB overflow 195393fceb5SAxel Dörfler return B_BAD_VALUE; 196393fceb5SAxel Dörfler } 197393fceb5SAxel Dörfler 198393fceb5SAxel Dörfler // base must be aligned to the length 1994f893e39SJérôme Duval if (base & (length - 1)) 200393fceb5SAxel Dörfler return B_BAD_VALUE; 201393fceb5SAxel Dörfler 202cd9ce121SJérôme Duval if (index < 0) 203393fceb5SAxel Dörfler index = allocate_mtrr(); 204393fceb5SAxel Dörfler if (index < 0) 205393fceb5SAxel Dörfler return B_ERROR; 206393fceb5SAxel Dörfler 2074e8c60ceSJérôme Duval TRACE_MTRR("allocate MTRR slot %ld, base = %Lx, length = %Lx, type=0x%lx\n", 2084e8c60ceSJérôme Duval index, base, length, type); 209393fceb5SAxel Dörfler 210393fceb5SAxel Dörfler sMemoryTypeIDs[index] = id; 2114f893e39SJérôme Duval x86_set_mtrr(index, base, length, type); 212393fceb5SAxel Dörfler 213393fceb5SAxel Dörfler return B_OK; 214393fceb5SAxel Dörfler } 215393fceb5SAxel Dörfler 216393fceb5SAxel Dörfler 217b20d05b4SJérôme Duval #define MTRR_MAX_SOLUTIONS 5 // usually MTRR count is eight, keep a few for other needs 2187522f308SJérôme Duval #define MTRR_MIN_SIZE 0x80000 // 512 KB 2194e8c60ceSJérôme Duval static int64 sSolutions[MTRR_MAX_SOLUTIONS]; 2204e8c60ceSJérôme Duval static int32 sSolutionCount; 2214e8c60ceSJérôme Duval static int64 sPropositions[MTRR_MAX_SOLUTIONS]; 2224f893e39SJérôme Duval 2234f893e39SJérôme Duval 224b20d05b4SJérôme Duval /*! Find the nearest powers of two for a value, save current iteration, 225b20d05b4SJérôme Duval then make recursives calls for the remaining values. 226b20d05b4SJérôme Duval It uses at most MTRR_MAX_SOLUTIONS levels of recursion because 227b20d05b4SJérôme Duval only that count of MTRR registers are available to map the memory. 228b20d05b4SJérôme Duval */ 2294f893e39SJérôme Duval static void 2304f893e39SJérôme Duval find_nearest(uint64 value, int iteration) 2314f893e39SJérôme Duval { 2324f893e39SJérôme Duval int i; 233f7c655c7SJérôme Duval uint64 down, up; 234f7c655c7SJérôme Duval TRACE_MTRR("find_nearest %Lx %d\n", value, iteration); 235f7c655c7SJérôme Duval if (iteration > (MTRR_MAX_SOLUTIONS - 1) || (iteration + 1) >= sSolutionCount) { 236f7c655c7SJérôme Duval if (sSolutionCount > MTRR_MAX_SOLUTIONS) { 237f7c655c7SJérôme Duval // no solutions yet, save something 238f7c655c7SJérôme Duval for (i=0; i<iteration; i++) 239f7c655c7SJérôme Duval sSolutions[i] = sPropositions[i]; 240f7c655c7SJérôme Duval sSolutionCount = iteration; 241f7c655c7SJérôme Duval } 242f7c655c7SJérôme Duval return; 243f7c655c7SJérôme Duval } 2444f893e39SJérôme Duval nearest_powers(value, &down, &up); 2454e8c60ceSJérôme Duval sPropositions[iteration] = down; 246b20d05b4SJérôme Duval if (value - down < MTRR_MIN_SIZE) { 2474f893e39SJérôme Duval for (i=0; i<=iteration; i++) 2484e8c60ceSJérôme Duval sSolutions[i] = sPropositions[i]; 2494e8c60ceSJérôme Duval sSolutionCount = iteration + 1; 2504f893e39SJérôme Duval return; 2514f893e39SJérôme Duval } 2524f893e39SJérôme Duval find_nearest(value - down, iteration + 1); 2534e8c60ceSJérôme Duval sPropositions[iteration] = -up; 254b20d05b4SJérôme Duval if (up - value < MTRR_MIN_SIZE) { 2554f893e39SJérôme Duval for (i=0; i<=iteration; i++) 2564e8c60ceSJérôme Duval sSolutions[i] = sPropositions[i]; 2574e8c60ceSJérôme Duval sSolutionCount = iteration + 1; 2584f893e39SJérôme Duval return; 2594f893e39SJérôme Duval } 2604f893e39SJérôme Duval find_nearest(up - value, iteration + 1); 2614f893e39SJérôme Duval } 2624f893e39SJérôme Duval 2634f893e39SJérôme Duval 264b20d05b4SJérôme Duval /*! Set up MTRR to map the memory to write-back using uncached if necessary */ 26548e299e2SIngo Weinhold static void 2664f893e39SJérôme Duval set_memory_write_back(int32 id, uint64 base, uint64 length) 2674f893e39SJérôme Duval { 2684e8c60ceSJérôme Duval status_t err; 2694f893e39SJérôme Duval TRACE_MTRR("set_memory_write_back base %Lx length %Lx\n", base, length); 270f7c655c7SJérôme Duval sSolutionCount = MTRR_MAX_SOLUTIONS + 1; 2714f893e39SJérôme Duval find_nearest(length, 0); 2724f893e39SJérôme Duval 2734f893e39SJérôme Duval #ifdef TRACE_MTRR 2744e8c60ceSJérôme Duval dprintf("solutions: "); 2754e8c60ceSJérôme Duval for (int i=0; i<sSolutionCount; i++) { 2764e8c60ceSJérôme Duval dprintf("0x%Lx ", sSolutions[i]); 2774f893e39SJérôme Duval } 2784f893e39SJérôme Duval dprintf("\n"); 2794f893e39SJérôme Duval #endif 2804f893e39SJérôme Duval 2814f893e39SJérôme Duval bool nextDown = false; 2824e8c60ceSJérôme Duval for (int i = 0; i < sSolutionCount; i++) { 2834e8c60ceSJérôme Duval if (sSolutions[i] < 0) { 2844f893e39SJérôme Duval if (nextDown) 2854e8c60ceSJérôme Duval base += sSolutions[i]; 2864e8c60ceSJérôme Duval err = set_memory_type(id, base, -sSolutions[i], nextDown ? B_MTR_UC : B_MTR_WB); 2874e8c60ceSJérôme Duval if (err != B_OK) { 2884e8c60ceSJérôme Duval dprintf("set_memory_type returned %s (0x%lx)\n", strerror(err), err); 2894e8c60ceSJérôme Duval } 2904f893e39SJérôme Duval if (!nextDown) 2914e8c60ceSJérôme Duval base -= sSolutions[i]; 2924f893e39SJérôme Duval nextDown = !nextDown; 2934f893e39SJérôme Duval } else { 2944f893e39SJérôme Duval if (nextDown) 2954e8c60ceSJérôme Duval base -= sSolutions[i]; 2964e8c60ceSJérôme Duval err = set_memory_type(id, base, sSolutions[i], nextDown ? B_MTR_UC : B_MTR_WB); 2974e8c60ceSJérôme Duval if (err != B_OK) { 2984e8c60ceSJérôme Duval dprintf("set_memory_type returned %s (0x%lx)\n", strerror(err), err); 2994e8c60ceSJérôme Duval } 3004f893e39SJérôme Duval if (!nextDown) 3014e8c60ceSJérôme Duval base += sSolutions[i]; 3024f893e39SJérôme Duval } 3034f893e39SJérôme Duval } 3044f893e39SJérôme Duval } 3054f893e39SJérôme Duval 3064f893e39SJérôme Duval 307393fceb5SAxel Dörfler // #pragma mark - 308393fceb5SAxel Dörfler 309393fceb5SAxel Dörfler 310393fceb5SAxel Dörfler status_t 311393fceb5SAxel Dörfler arch_vm_init(kernel_args *args) 312393fceb5SAxel Dörfler { 313393fceb5SAxel Dörfler TRACE(("arch_vm_init: entry\n")); 314393fceb5SAxel Dörfler return 0; 315393fceb5SAxel Dörfler } 316393fceb5SAxel Dörfler 317393fceb5SAxel Dörfler 318393fceb5SAxel Dörfler /*! Marks DMA region as in-use, and maps it into the kernel space */ 319393fceb5SAxel Dörfler status_t 320393fceb5SAxel Dörfler arch_vm_init_post_area(kernel_args *args) 321393fceb5SAxel Dörfler { 322393fceb5SAxel Dörfler area_id id; 323393fceb5SAxel Dörfler 324393fceb5SAxel Dörfler TRACE(("arch_vm_init_post_area: entry\n")); 325393fceb5SAxel Dörfler 326393fceb5SAxel Dörfler // account for DMA area and mark the pages unusable 327393fceb5SAxel Dörfler vm_mark_page_range_inuse(0x0, 0xa0000 / B_PAGE_SIZE); 328393fceb5SAxel Dörfler 329393fceb5SAxel Dörfler // map 0 - 0xa0000 directly 330393fceb5SAxel Dörfler id = map_physical_memory("dma_region", (void *)0x0, 0xa0000, 331393fceb5SAxel Dörfler B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 332393fceb5SAxel Dörfler &gDmaAddress); 333393fceb5SAxel Dörfler if (id < 0) { 334393fceb5SAxel Dörfler panic("arch_vm_init_post_area: unable to map dma region\n"); 335393fceb5SAxel Dörfler return B_NO_MEMORY; 336393fceb5SAxel Dörfler } 337393fceb5SAxel Dörfler 338393fceb5SAxel Dörfler return bios_init(); 339393fceb5SAxel Dörfler } 340393fceb5SAxel Dörfler 341393fceb5SAxel Dörfler 342393fceb5SAxel Dörfler /*! Gets rid of all yet unmapped (and therefore now unused) page tables */ 343393fceb5SAxel Dörfler status_t 344393fceb5SAxel Dörfler arch_vm_init_end(kernel_args *args) 345393fceb5SAxel Dörfler { 346393fceb5SAxel Dörfler TRACE(("arch_vm_init_endvm: entry\n")); 347393fceb5SAxel Dörfler 348393fceb5SAxel Dörfler // throw away anything in the kernel_args.pgtable[] that's not yet mapped 349393fceb5SAxel Dörfler vm_free_unused_boot_loader_range(KERNEL_BASE, 350393fceb5SAxel Dörfler 0x400000 * args->arch_args.num_pgtables); 351393fceb5SAxel Dörfler 352393fceb5SAxel Dörfler return B_OK; 353393fceb5SAxel Dörfler } 354393fceb5SAxel Dörfler 355393fceb5SAxel Dörfler 356393fceb5SAxel Dörfler status_t 357393fceb5SAxel Dörfler arch_vm_init_post_modules(kernel_args *args) 358393fceb5SAxel Dörfler { 359393fceb5SAxel Dörfler // void *cookie; 360393fceb5SAxel Dörfler 361393fceb5SAxel Dörfler // the x86 CPU modules are now accessible 362393fceb5SAxel Dörfler 363393fceb5SAxel Dörfler sMemoryTypeRegisterCount = x86_count_mtrrs(); 364393fceb5SAxel Dörfler if (sMemoryTypeRegisterCount == 0) 365393fceb5SAxel Dörfler return B_OK; 366393fceb5SAxel Dörfler 367393fceb5SAxel Dörfler // not very likely, but play safe here 368393fceb5SAxel Dörfler if (sMemoryTypeRegisterCount > kMaxMemoryTypeRegisters) 369393fceb5SAxel Dörfler sMemoryTypeRegisterCount = kMaxMemoryTypeRegisters; 370393fceb5SAxel Dörfler 371393fceb5SAxel Dörfler // init memory type ID table 372393fceb5SAxel Dörfler 373393fceb5SAxel Dörfler for (uint32 i = 0; i < sMemoryTypeRegisterCount; i++) { 374393fceb5SAxel Dörfler sMemoryTypeIDs[i] = -1; 375393fceb5SAxel Dörfler } 376393fceb5SAxel Dörfler 377393fceb5SAxel Dörfler // set the physical memory ranges to write-back mode 378393fceb5SAxel Dörfler 379393fceb5SAxel Dörfler for (uint32 i = 0; i < args->num_physical_memory_ranges; i++) { 3804f893e39SJérôme Duval set_memory_write_back(-1, args->physical_memory_range[i].start, 3814f893e39SJérôme Duval args->physical_memory_range[i].size); 382393fceb5SAxel Dörfler } 383393fceb5SAxel Dörfler 384393fceb5SAxel Dörfler return B_OK; 385393fceb5SAxel Dörfler } 386393fceb5SAxel Dörfler 387393fceb5SAxel Dörfler 388393fceb5SAxel Dörfler void 38974785e79SIngo Weinhold arch_vm_aspace_swap(struct vm_address_space *from, struct vm_address_space *to) 390393fceb5SAxel Dörfler { 391*9a42ad7aSIngo Weinhold // This functions is only invoked when a userland thread is in the process 392*9a42ad7aSIngo Weinhold // of dying. It switches to the kernel team and does whatever cleanup is 393*9a42ad7aSIngo Weinhold // necessary (in case it is the team's main thread, it will delete the 394*9a42ad7aSIngo Weinhold // team). 395*9a42ad7aSIngo Weinhold // It is however not necessary to change the page directory. Userland team's 396*9a42ad7aSIngo Weinhold // page directories include all kernel mappings as well. Furthermore our 397*9a42ad7aSIngo Weinhold // arch specific translation map data objects are ref-counted, so they won't 398*9a42ad7aSIngo Weinhold // go away as long as they are still used on any CPU. 399393fceb5SAxel Dörfler } 400393fceb5SAxel Dörfler 401393fceb5SAxel Dörfler 402393fceb5SAxel Dörfler bool 403393fceb5SAxel Dörfler arch_vm_supports_protection(uint32 protection) 404393fceb5SAxel Dörfler { 405393fceb5SAxel Dörfler // x86 always has the same read/write properties for userland and the 406393fceb5SAxel Dörfler // kernel. 407393fceb5SAxel Dörfler // That's why we do not support user-read/kernel-write access. While the 408393fceb5SAxel Dörfler // other way around is not supported either, we don't care in this case 409393fceb5SAxel Dörfler // and give the kernel full access. 410393fceb5SAxel Dörfler if ((protection & (B_READ_AREA | B_WRITE_AREA)) == B_READ_AREA 411393fceb5SAxel Dörfler && protection & B_KERNEL_WRITE_AREA) 412393fceb5SAxel Dörfler return false; 413393fceb5SAxel Dörfler 414393fceb5SAxel Dörfler return true; 415393fceb5SAxel Dörfler } 416393fceb5SAxel Dörfler 417393fceb5SAxel Dörfler 418393fceb5SAxel Dörfler void 419393fceb5SAxel Dörfler arch_vm_unset_memory_type(struct vm_area *area) 420393fceb5SAxel Dörfler { 421393fceb5SAxel Dörfler uint32 index; 422393fceb5SAxel Dörfler 423393fceb5SAxel Dörfler if (area->memory_type == 0) 424393fceb5SAxel Dörfler return; 425393fceb5SAxel Dörfler 426393fceb5SAxel Dörfler // find index for area ID 427393fceb5SAxel Dörfler 428393fceb5SAxel Dörfler for (index = 0; index < sMemoryTypeRegisterCount; index++) { 429393fceb5SAxel Dörfler if (sMemoryTypeIDs[index] == area->id) { 430393fceb5SAxel Dörfler x86_set_mtrr(index, 0, 0, 0); 431393fceb5SAxel Dörfler 432393fceb5SAxel Dörfler sMemoryTypeIDs[index] = -1; 433393fceb5SAxel Dörfler free_mtrr(index); 434393fceb5SAxel Dörfler break; 435393fceb5SAxel Dörfler } 436393fceb5SAxel Dörfler } 437393fceb5SAxel Dörfler } 438393fceb5SAxel Dörfler 439393fceb5SAxel Dörfler 440393fceb5SAxel Dörfler status_t 441393fceb5SAxel Dörfler arch_vm_set_memory_type(struct vm_area *area, addr_t physicalBase, 442393fceb5SAxel Dörfler uint32 type) 443393fceb5SAxel Dörfler { 444393fceb5SAxel Dörfler area->memory_type = type >> MEMORY_TYPE_SHIFT; 445393fceb5SAxel Dörfler return set_memory_type(area->id, physicalBase, area->size, type); 446393fceb5SAxel Dörfler } 447