headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / kernel / arch / generic / generic_vm_physical_page_ops.cpp
blob8053fbf330462a26a693aafc2d2515c171b4b74c
1 /*
2 * Copyright 2008-2010, Ingo Weinhold <ingo_weinhold@gmx.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
7 #include "generic_vm_physical_page_ops.h"
9 #include <vm/vm.h>
10 #include <util/AutoLock.h>
13 status_t
14 generic_vm_memset_physical(phys_addr_t address, int value, phys_size_t length)
16 ThreadCPUPinner _(thread_get_current_thread());
18 while (length > 0) {
19 phys_addr_t pageOffset = address % B_PAGE_SIZE;
20 addr_t virtualAddress;
21 void* handle;
22 status_t error = vm_get_physical_page_current_cpu(address - pageOffset,
23 &virtualAddress, &handle);
24 if (error != B_OK)
25 return error;
27 size_t toSet = min_c(length, B_PAGE_SIZE - pageOffset);
28 memset((void*)(virtualAddress + pageOffset), value, toSet);
30 vm_put_physical_page_current_cpu(virtualAddress, handle);
32 length -= toSet;
33 address += toSet;
36 return B_OK;
40 status_t
41 generic_vm_memcpy_from_physical(void* _to, phys_addr_t from, size_t length,
42 bool user)
44 uint8* to = (uint8*)_to;
45 phys_addr_t pageOffset = from % B_PAGE_SIZE;
47 ThreadCPUPinner _(thread_get_current_thread());
49 while (length > 0) {
50 size_t toCopy = min_c(length, B_PAGE_SIZE - pageOffset);
52 addr_t virtualAddress;
53 void* handle;
54 status_t error = vm_get_physical_page_current_cpu(from - pageOffset,
55 &virtualAddress, &handle);
56 if (error != B_OK)
57 return error;
59 if (user) {
60 error = user_memcpy(to, (void*)(virtualAddress + pageOffset),
61 toCopy);
62 } else
63 memcpy(to, (void*)(virtualAddress + pageOffset), toCopy);
65 vm_put_physical_page_current_cpu(virtualAddress, handle);
67 if (error != B_OK)
68 return error;
70 to += toCopy;
71 from += toCopy;
72 length -= toCopy;
73 pageOffset = 0;
76 return B_OK;
80 status_t
81 generic_vm_memcpy_to_physical(phys_addr_t to, const void* _from, size_t length,
82 bool user)
84 const uint8* from = (const uint8*)_from;
85 phys_addr_t pageOffset = to % B_PAGE_SIZE;
87 ThreadCPUPinner _(thread_get_current_thread());
89 while (length > 0) {
90 size_t toCopy = min_c(length, B_PAGE_SIZE - pageOffset);
92 addr_t virtualAddress;
93 void* handle;
94 status_t error = vm_get_physical_page_current_cpu(to - pageOffset,
95 &virtualAddress, &handle);
96 if (error != B_OK)
97 return error;
99 if (user) {
100 error = user_memcpy((void*)(virtualAddress + pageOffset), from,
101 toCopy);
102 } else
103 memcpy((void*)(virtualAddress + pageOffset), from, toCopy);
105 vm_put_physical_page_current_cpu(virtualAddress, handle);
107 if (error != B_OK)
108 return error;
110 to += toCopy;
111 from += toCopy;
112 length -= toCopy;
113 pageOffset = 0;
116 return B_OK;
120 /*! NOTE: If this function is used, vm_get_physical_page_current_cpu() must not
121 be blocking, since we need to call it twice and could thus deadlock.
123 void
124 generic_vm_memcpy_physical_page(phys_addr_t to, phys_addr_t from)
126 ThreadCPUPinner _(thread_get_current_thread());
128 // map source page
129 addr_t fromVirtual;
130 void* fromHandle;
131 status_t error = vm_get_physical_page_current_cpu(from, &fromVirtual,
132 &fromHandle);
133 if (error != B_OK) {
134 panic("generic_vm_memcpy_physical_page(): Failed to map source page!");
135 return;
138 // map destination page
139 addr_t toVirtual;
140 void* toHandle;
141 error = vm_get_physical_page_current_cpu(to, &toVirtual, &toHandle);
142 if (error == B_OK) {
143 // both pages are mapped -- copy
144 memcpy((void*)toVirtual, (const void*)fromVirtual, B_PAGE_SIZE);
145 vm_put_physical_page_current_cpu(toVirtual, toHandle);
146 } else {
147 panic("generic_vm_memcpy_physical_page(): Failed to map destination "
148 "page!");
151 vm_put_physical_page_current_cpu(fromVirtual, fromHandle);