xref: /haiku/src/system/kernel/arch/x86/arch_vm.cpp (revision 7522f3082d8a249e7ab59381dd35212d52ab398a)
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