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