xref: /haiku/src/system/kernel/arch/generic/generic_vm_physical_page_ops.cpp (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
1 /*
2  * Copyright 2008, Ingo Weinhold <ingo_weinhold@gmx.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 #include "generic_vm_physical_page_ops.h"
7 
8 #include <vm/vm.h>
9 #include <util/AutoLock.h>
10 
11 
12 status_t
13 generic_vm_memset_physical(addr_t address, int value, size_t length)
14 {
15 	ThreadCPUPinner _(thread_get_current_thread());
16 
17 	while (length > 0) {
18 		addr_t pageOffset = address % B_PAGE_SIZE;
19 		addr_t virtualAddress;
20 		void* handle;
21 		status_t error = vm_get_physical_page_current_cpu(address - pageOffset,
22 			&virtualAddress, &handle);
23 		if (error != B_OK)
24 			return error;
25 
26 		size_t toSet = min_c(length, B_PAGE_SIZE - pageOffset);
27 		memset((void*)(virtualAddress + pageOffset), value, toSet);
28 
29 		vm_put_physical_page_current_cpu(virtualAddress, handle);
30 
31 		length -= toSet;
32 		address += toSet;
33 	}
34 
35 	return B_OK;
36 }
37 
38 
39 status_t
40 generic_vm_memcpy_from_physical(void* _to, addr_t from, size_t length,
41 	bool user)
42 {
43 	uint8* to = (uint8*)_to;
44 	addr_t pageOffset = from % B_PAGE_SIZE;
45 
46 	ThreadCPUPinner _(thread_get_current_thread());
47 
48 	while (length > 0) {
49 		size_t toCopy = min_c(length, B_PAGE_SIZE - pageOffset);
50 
51 		addr_t virtualAddress;
52 		void* handle;
53 		status_t error = vm_get_physical_page_current_cpu(from - pageOffset,
54 			&virtualAddress, &handle);
55 		if (error != B_OK)
56 			return error;
57 
58 		if (user) {
59 			error = user_memcpy(to, (void*)(virtualAddress + pageOffset),
60 				toCopy);
61 		} else
62 			memcpy(to, (void*)(virtualAddress + pageOffset), toCopy);
63 
64 		vm_put_physical_page_current_cpu(virtualAddress, handle);
65 
66 		if (error != B_OK)
67 			return error;
68 
69 		to += toCopy;
70 		from += toCopy;
71 		length -= toCopy;
72 		pageOffset = 0;
73 	}
74 
75 	return B_OK;
76 }
77 
78 
79 status_t
80 generic_vm_memcpy_to_physical(addr_t to, const void* _from, size_t length,
81 	bool user)
82 {
83 	const uint8* from = (const uint8*)_from;
84 	addr_t pageOffset = to % B_PAGE_SIZE;
85 
86 	ThreadCPUPinner _(thread_get_current_thread());
87 
88 	while (length > 0) {
89 		size_t toCopy = min_c(length, B_PAGE_SIZE - pageOffset);
90 
91 		addr_t virtualAddress;
92 		void* handle;
93 		status_t error = vm_get_physical_page_current_cpu(to - pageOffset,
94 			&virtualAddress, &handle);
95 		if (error != B_OK)
96 			return error;
97 
98 		if (user) {
99 			error = user_memcpy((void*)(virtualAddress + pageOffset), from,
100 				toCopy);
101 		} else
102 			memcpy((void*)(virtualAddress + pageOffset), from, toCopy);
103 
104 		vm_put_physical_page_current_cpu(virtualAddress, handle);
105 
106 		if (error != B_OK)
107 			return error;
108 
109 		to += toCopy;
110 		from += toCopy;
111 		length -= toCopy;
112 		pageOffset = 0;
113 	}
114 
115 	return B_OK;
116 }
117 
118 
119 /*!	NOTE: If this function is used, vm_get_physical_page_current_cpu() must not
120 	be blocking, since we need to call it twice and could thus deadlock.
121 */
122 void
123 generic_vm_memcpy_physical_page(addr_t to, addr_t from)
124 {
125 	ThreadCPUPinner _(thread_get_current_thread());
126 
127 	// map source page
128 	addr_t fromVirtual;
129 	void* fromHandle;
130 	status_t error = vm_get_physical_page_current_cpu(from, &fromVirtual,
131 		&fromHandle);
132 	if (error != B_OK) {
133 		panic("generic_vm_memcpy_physical_page(): Failed to map source page!");
134 		return;
135 	}
136 
137 	// map destination page
138 	addr_t toVirtual;
139 	void* toHandle;
140 	error = vm_get_physical_page_current_cpu(to, &toVirtual, &toHandle);
141 	if (error == B_OK) {
142 		// both pages are mapped -- copy
143 		memcpy((void*)toVirtual, (const void*)fromVirtual, B_PAGE_SIZE);
144 		vm_put_physical_page_current_cpu(toVirtual, toHandle);
145 	} else {
146 		panic("generic_vm_memcpy_physical_page(): Failed to map destination "
147 			"page!");
148 	}
149 
150 	vm_put_physical_page_current_cpu(fromVirtual, fromHandle);
151 }
152