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 12 13 status_t 14 generic_vm_memset_physical(phys_addr_t address, int value, phys_size_t length) 15 { 16 ThreadCPUPinner _(thread_get_current_thread()); 17 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; 26 27 size_t toSet = min_c(length, B_PAGE_SIZE - pageOffset); 28 memset((void*)(virtualAddress + pageOffset), value, toSet); 29 30 vm_put_physical_page_current_cpu(virtualAddress, handle); 31 32 length -= toSet; 33 address += toSet; 34 } 35 36 return B_OK; 37 } 38 39 40 status_t 41 generic_vm_memcpy_from_physical(void* _to, phys_addr_t from, size_t length, 42 bool user) 43 { 44 uint8* to = (uint8*)_to; 45 phys_addr_t pageOffset = from % B_PAGE_SIZE; 46 47 ThreadCPUPinner _(thread_get_current_thread()); 48 49 while (length > 0) { 50 size_t toCopy = min_c(length, B_PAGE_SIZE - pageOffset); 51 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; 58 59 if (user) { 60 error = user_memcpy(to, (void*)(virtualAddress + pageOffset), 61 toCopy); 62 } else 63 memcpy(to, (void*)(virtualAddress + pageOffset), toCopy); 64 65 vm_put_physical_page_current_cpu(virtualAddress, handle); 66 67 if (error != B_OK) 68 return error; 69 70 to += toCopy; 71 from += toCopy; 72 length -= toCopy; 73 pageOffset = 0; 74 } 75 76 return B_OK; 77 } 78 79 80 status_t 81 generic_vm_memcpy_to_physical(phys_addr_t to, const void* _from, size_t length, 82 bool user) 83 { 84 const uint8* from = (const uint8*)_from; 85 phys_addr_t pageOffset = to % B_PAGE_SIZE; 86 87 ThreadCPUPinner _(thread_get_current_thread()); 88 89 while (length > 0) { 90 size_t toCopy = min_c(length, B_PAGE_SIZE - pageOffset); 91 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; 98 99 if (user) { 100 error = user_memcpy((void*)(virtualAddress + pageOffset), from, 101 toCopy); 102 } else 103 memcpy((void*)(virtualAddress + pageOffset), from, toCopy); 104 105 vm_put_physical_page_current_cpu(virtualAddress, handle); 106 107 if (error != B_OK) 108 return error; 109 110 to += toCopy; 111 from += toCopy; 112 length -= toCopy; 113 pageOffset = 0; 114 } 115 116 return B_OK; 117 } 118 119 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. 122 */ 123 void 124 generic_vm_memcpy_physical_page(phys_addr_t to, phys_addr_t from) 125 { 126 ThreadCPUPinner _(thread_get_current_thread()); 127 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; 136 } 137 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!"); 149 } 150 151 vm_put_physical_page_current_cpu(fromVirtual, fromHandle); 152 } 153