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