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