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