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 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 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 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 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