124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- MachVMMemory.cpp ----------------------------------------*- C++ -*-===// 224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The LLVM Compiler Infrastructure 424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source 624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details. 724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Created by Greg Clayton on 6/26/07. 1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "MachVMMemory.h" 1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "MachVMRegion.h" 1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "DNBLog.h" 1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <mach/mach_vm.h> 18fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong#include <mach/shared_region.h> 19e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong#include <sys/sysctl.h> 2077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#include <dlfcn.h> 2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::MachVMMemory() : 2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_page_size (kInvalidPageSize), 2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err (0) 2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::~MachVMMemory() 2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 33fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::PageSize(task_t task) 3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_page_size == kInvalidPageSize) 3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 37fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 38fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda if (task != TASK_NULL) 39fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda { 40fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda kern_return_t kr; 41fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda mach_msg_type_number_t info_count = TASK_VM_INFO_COUNT; 42fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda task_vm_info_data_t vm_info; 43fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda kr = task_info (task, TASK_VM_INFO, (task_info_t) &vm_info, &info_count); 44fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda if (kr == KERN_SUCCESS) 45fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda { 46dfb7c7f12cbefccf5f097ec90f6d157e2a32f35dJason Molenda DNBLogThreadedIf(LOG_TASK, "MachVMMemory::PageSize task_info returned page size of 0x%x", (int) vm_info.page_size); 47e255a7d13780e35b97e0f2954cba47cc9eaae7e0Jason Molenda m_page_size = vm_info.page_size; 48e255a7d13780e35b97e0f2954cba47cc9eaae7e0Jason Molenda return m_page_size; 49fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda } 5092748483a4c36e9bf2535abb863dbca1271053a1Jason Molenda else 5192748483a4c36e9bf2535abb863dbca1271053a1Jason Molenda { 5292748483a4c36e9bf2535abb863dbca1271053a1Jason Molenda DNBLogThreadedIf(LOG_TASK, "MachVMMemory::PageSize task_info call failed to get page size, TASK_VM_INFO %d, TASK_VM_INFO_COUNT %d, kern return %d", TASK_VM_INFO, TASK_VM_INFO_COUNT, kr); 5392748483a4c36e9bf2535abb863dbca1271053a1Jason Molenda } 54fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda } 55fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda#endif 5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::host_page_size( ::mach_host_self(), &m_page_size); 5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_err.Fail()) 5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_page_size = 0; 5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return m_page_size; 6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 64fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::MaxBytesLeftInPage(task_t task, nub_addr_t addr, nub_size_t count) 6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 66fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda const nub_size_t page_size = PageSize(task); 6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (page_size > 0) 6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t page_offset = (addr % page_size); 7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t bytes_left_in_page = page_size - page_offset; 7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (count > bytes_left_in_page) 7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner count = bytes_left_in_page; 7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return count; 7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 771308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Claytonnub_bool_t 78a9385537809ef342c843c5ab972e513742652047Greg ClaytonMachVMMemory::GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info) 79dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda{ 80dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda MachVMRegion vmRegion(task); 81dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda 82a9385537809ef342c843c5ab972e513742652047Greg Clayton if (vmRegion.GetRegionForAddress(address)) 83a9385537809ef342c843c5ab972e513742652047Greg Clayton { 84a9385537809ef342c843c5ab972e513742652047Greg Clayton region_info->addr = vmRegion.StartAddress(); 85a9385537809ef342c843c5ab972e513742652047Greg Clayton region_info->size = vmRegion.GetByteSize(); 86a9385537809ef342c843c5ab972e513742652047Greg Clayton region_info->permissions = vmRegion.GetDNBPermissions(); 87a9385537809ef342c843c5ab972e513742652047Greg Clayton } 881308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton else 891308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton { 901308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->addr = address; 911308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->size = 0; 921308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton if (vmRegion.GetError().Success()) 931308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton { 941308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // vmRegion.GetRegionForAddress() return false, indicating that "address" 951308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // wasn't in a valid region, but the "vmRegion" info was successfully 961308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // read from the task which means the info describes the next valid 971308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // region from which we can infer the size of this invalid region 981308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton mach_vm_address_t start_addr = vmRegion.StartAddress(); 991308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton if (address < start_addr) 1001308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->size = start_addr - address; 1011308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton } 1021308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // If we can't get any infor about the size from the next region, just fill 1031308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // 1 in as the byte size 1041308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton if (region_info->size == 0) 1051308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->size = 1; 1061308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton 1071308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // Not readable, writeable or executable 1081308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->permissions = 0; 1091308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton } 1101308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton return true; 111dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda} 112fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 113e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong// For integrated graphics chip, this makes the accounting info for 'wired' memory more like top. 114fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molendauint64_t 115fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::GetStolenPages(task_t task) 116e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong{ 117e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static uint64_t stolenPages = 0; 118e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static bool calculated = false; 119e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if (calculated) return stolenPages; 120e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 121e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static int mib_reserved[CTL_MAXNAME]; 122e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static int mib_unusable[CTL_MAXNAME]; 123e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static int mib_other[CTL_MAXNAME]; 124e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static size_t mib_reserved_len = 0; 125e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static size_t mib_unusable_len = 0; 126e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static size_t mib_other_len = 0; 127e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong int r; 128e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 129e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong /* This can be used for testing: */ 130e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong //tsamp->pages_stolen = (256 * 1024 * 1024ULL) / tsamp->pagesize; 131e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 132e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(0 == mib_reserved_len) 133e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 134e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = CTL_MAXNAME; 135e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 136e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong r = sysctlnametomib("machdep.memmap.Reserved", mib_reserved, 137e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &mib_reserved_len); 138e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 139e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == r) 140e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 141e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = 0; 142e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 143e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 144e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 145e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_unusable_len = CTL_MAXNAME; 146e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 147e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong r = sysctlnametomib("machdep.memmap.Unusable", mib_unusable, 148e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &mib_unusable_len); 149e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 150e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == r) 151e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 152e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = 0; 153e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 154e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 155e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 156e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 157e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_other_len = CTL_MAXNAME; 158e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 159e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong r = sysctlnametomib("machdep.memmap.Other", mib_other, 160e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &mib_other_len); 161e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 162e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == r) 163e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 164e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = 0; 165e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 166e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 167e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 168e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 169e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(mib_reserved_len > 0 && mib_unusable_len > 0 && mib_other_len > 0) 170e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 171e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong uint64_t reserved = 0, unusable = 0, other = 0; 172e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t reserved_len; 173e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t unusable_len; 174e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t other_len; 175e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 176e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong reserved_len = sizeof(reserved); 177e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong unusable_len = sizeof(unusable); 178e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong other_len = sizeof(other); 179e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 180e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong /* These are all declared as QUAD/uint64_t sysctls in the kernel. */ 181e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 182e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == sysctl(mib_reserved, mib_reserved_len, &reserved, 183e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &reserved_len, NULL, 0)) 184e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 185e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 186e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 187e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 188e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == sysctl(mib_unusable, mib_unusable_len, &unusable, 189e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &unusable_len, NULL, 0)) 190e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 191e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 192e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 193e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 194e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == sysctl(mib_other, mib_other_len, &other, 195e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &other_len, NULL, 0)) 196e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 197e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 198e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 199e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 200e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(reserved_len == sizeof(reserved) 201e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong && unusable_len == sizeof(unusable) 202e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong && other_len == sizeof(other)) 203e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 204e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong uint64_t stolen = reserved + unusable + other; 205e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong uint64_t mb128 = 128 * 1024 * 1024ULL; 206e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 207e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(stolen >= mb128) 208e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 209e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong stolen = (stolen & ~((128 * 1024 * 1024ULL) - 1)); // rounding down 21008f60c88b61c42c35abf3233f0cbe19d29fbe814Jason Molenda stolenPages = stolen / PageSize (task); 211e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 212e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 213e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 214e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 215e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong calculated = true; 216e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return stolenPages; 217e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong} 218e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 219e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ongstatic uint64_t GetPhysicalMemory() 220e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong{ 221e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong // This doesn't change often at all. No need to poll each time. 222e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static uint64_t physical_memory = 0; 223e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static bool calculated = false; 224e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if (calculated) return physical_memory; 225e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 226e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong int mib[2]; 227e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib[0] = CTL_HW; 228e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib[1] = HW_MEMSIZE; 229e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t len = sizeof(physical_memory); 230e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong sysctl(mib, 2, &physical_memory, &len, NULL, 0); 231e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return physical_memory; 232e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong} 233e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 234fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong// rsize and dirty_size is not adjusted for dyld shared cache and multiple __LINKEDIT segment, as in vmmap. In practice, dirty_size doesn't differ much but rsize may. There is performance penalty for the adjustment. Right now, only use the dirty_size. 235fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molendavoid 236fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::GetRegionSizes(task_t task, mach_vm_size_t &rsize, mach_vm_size_t &dirty_size) 237fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 238fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 239fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong 240fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong task_vm_info_data_t vm_info; 241fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong mach_msg_type_number_t info_count; 242fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong kern_return_t kr; 243fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong 244fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong info_count = TASK_VM_INFO_COUNT; 245fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong#ifdef TASK_VM_INFO_PURGEABLE 246fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong kr = task_info(task, TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &info_count); 247fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong#else 248fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong kr = task_info(task, TASK_VM_INFO, (task_info_t)&vm_info, &info_count); 249fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong#endif 250fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong if (kr == KERN_SUCCESS) 251fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong dirty_size = vm_info.internal; 252fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong 253fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong#else 254fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_address_t address = 0; 255fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t size; 256fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong kern_return_t err = 0; 257fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong unsigned nestingDepth = 0; 258fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t pages_resident = 0; 259fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t pages_dirtied = 0; 260fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 261fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong while (1) 262fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 2632a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong mach_msg_type_number_t count; 264fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong struct vm_region_submap_info_64 info; 265fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 266fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong count = VM_REGION_SUBMAP_INFO_COUNT_64; 267fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong err = mach_vm_region_recurse(task, &address, &size, &nestingDepth, (vm_region_info_t)&info, &count); 268fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (err == KERN_INVALID_ADDRESS) 269fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 270fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // It seems like this is a good break too. 271fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 272fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 273fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong else if (err) 274fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 275fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_error("vm_region",err); 276fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; // reached last region 277fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 278fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 279fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong bool should_count = true; 280fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (info.is_submap) 281fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { // is it a submap? 282fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong nestingDepth++; 283fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong should_count = false; 284fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 285fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong else 286fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 287fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Don't count malloc stack logging data in the TOTAL VM usage lines. 288fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (info.user_tag == VM_MEMORY_ANALYSIS_TOOL) 289fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong should_count = false; 290190276872994426fb0398e1cf521748249b75875Han Ming Ong 291fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong address = address+size; 292fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 293fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 294fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (should_count) 295fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 296fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong pages_resident += info.pages_resident; 297fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong pages_dirtied += info.pages_dirtied; 298fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 299fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 300fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 30177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong vm_size_t pagesize = PageSize (task); 3022a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong rsize = pages_resident * pagesize; 3032a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong dirty_size = pages_dirtied * pagesize; 304fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong 305fa72100a0ac0267163cacde1af4ef43822dc390aHan Ming Ong#endif 306fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 307fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 308fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong// Test whether the virtual address is within the architecture's shared region. 309fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongstatic bool InSharedRegion(mach_vm_address_t addr, cpu_type_t type) 310fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 311559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_address_t base = 0, size = 0; 312fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 313559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda switch(type) { 314559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case CPU_TYPE_ARM: 315559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda base = SHARED_REGION_BASE_ARM; 316559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda size = SHARED_REGION_SIZE_ARM; 317fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 318fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 319559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case CPU_TYPE_X86_64: 320559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda base = SHARED_REGION_BASE_X86_64; 321559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda size = SHARED_REGION_SIZE_X86_64; 322fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 323fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 324559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case CPU_TYPE_I386: 325559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda base = SHARED_REGION_BASE_I386; 326559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda size = SHARED_REGION_SIZE_I386; 327fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 328fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 329559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda default: { 330fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Log error abut unknown CPU type 331fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 332559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 333559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 334fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 335fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 336559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda return(addr >= base && addr < (base + size)); 337fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 338fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 339fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molendavoid 340fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::GetMemorySizes(task_t task, cpu_type_t cputype, nub_process_t pid, mach_vm_size_t &rprvt, mach_vm_size_t &vprvt) 341fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 342fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Collecting some other info cheaply but not reporting for now. 343fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t empty = 0; 344559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t fw_private = 0; 345fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 346559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t aliased = 0; 347fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong bool global_shared_text_data_mapped = false; 34877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong vm_size_t pagesize = PageSize (task); 3492a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong 350559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda for (mach_vm_address_t addr=0, size=0; ; addr += size) 351fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 352559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vm_region_top_info_data_t info; 353559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_msg_type_number_t count = VM_REGION_TOP_INFO_COUNT; 354559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_port_t object_name; 355fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 356559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda kern_return_t kr = mach_vm_region(task, &addr, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count, &object_name); 357559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (kr != KERN_SUCCESS) break; 358559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 359559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (InSharedRegion(addr, cputype)) 360fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 361559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Private Shared 362559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda fw_private += info.private_pages_resident * pagesize; 363fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 364559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Check if this process has the globally shared text and data regions mapped in. If so, set global_shared_text_data_mapped to TRUE and avoid checking again. 365559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (global_shared_text_data_mapped == FALSE && info.share_mode == SM_EMPTY) { 3662a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong vm_region_basic_info_data_64_t b_info; 367559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_address_t b_addr = addr; 368559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t b_size = size; 369559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda count = VM_REGION_BASIC_INFO_COUNT_64; 370559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 371559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda kr = mach_vm_region(task, &b_addr, &b_size, VM_REGION_BASIC_INFO, (vm_region_info_t)&b_info, &count, &object_name); 372559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (kr != KERN_SUCCESS) break; 373fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 374559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (b_info.reserved) { 375559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda global_shared_text_data_mapped = TRUE; 376559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 377559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 378559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 379559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Short circuit the loop if this isn't a shared private region, since that's the only region type we care about within the current address range. 380559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode != SM_PRIVATE) 381fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 382559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda continue; 383559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 384559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 385559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 386559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Update counters according to the region type. 387559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode == SM_COW && info.ref_count == 1) 388fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 389559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Treat single reference SM_COW as SM_PRIVATE 390559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda info.share_mode = SM_PRIVATE; 391559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 392fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 393559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda switch (info.share_mode) 394fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 395559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_LARGE_PAGE: 396559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Treat SM_LARGE_PAGE the same as SM_PRIVATE 397559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // since they are not shareable and are wired. 398559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_PRIVATE: 399559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.private_pages_resident * pagesize; 400559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.shared_pages_resident * pagesize; 401559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vprvt += size; 402559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 403559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 404559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_EMPTY: 405fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong empty += size; 406559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 407559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 408559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_COW: 409559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_SHARED: 410fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 411559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (pid == 0) 412fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 413559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Treat kernel_task specially 414559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode == SM_COW) 415fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 416559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.private_pages_resident * pagesize; 417559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vprvt += size; 418559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 419559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 420559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 421fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 422559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode == SM_COW) 423fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 424559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.private_pages_resident * pagesize; 425559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vprvt += info.private_pages_resident * pagesize; 426559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 427559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 428fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 429559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda default: 430fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // log that something is really bad. 431559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 432559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 433559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 434fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 435559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += aliased; 436fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 437fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 43877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 439813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#ifndef TASK_VM_INFO_PURGEABLE 44077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong// cribbed from sysmond 44177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ongstatic uint64_t 44277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming OngSumVMPurgeableInfo(const vm_purgeable_info_t info) 44377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong{ 44477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong uint64_t sum = 0; 44577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong int i; 44677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 44777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong for (i = 0; i < 8; i++) 44877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 44977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong sum += info->fifo_data[i].size; 45077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 45177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong sum += info->obsolete_data.size; 45277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong for (i = 0; i < 8; i++) 45377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 45477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong sum += info->lifo_data[i].size; 45577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 45677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 45777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong return sum; 45877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong} 459813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#endif /* !TASK_VM_INFO_PURGEABLE */ 46077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#endif 46177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 46277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ongstatic void 46377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming OngGetPurgeableAndAnonymous(task_t task, uint64_t &purgeable, uint64_t &anonymous) 46477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong{ 46577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 46677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 46777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong kern_return_t kr; 468813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#ifndef TASK_VM_INFO_PURGEABLE 46977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong task_purgable_info_t purgeable_info; 47077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong uint64_t purgeable_sum = 0; 471813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#endif /* !TASK_VM_INFO_PURGEABLE */ 47277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong mach_msg_type_number_t info_count; 47377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong task_vm_info_data_t vm_info; 47477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 475813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#ifndef TASK_VM_INFO_PURGEABLE 4763a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong typedef kern_return_t (*task_purgable_info_type) (task_t, task_purgable_info_t *); 4773a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong task_purgable_info_type task_purgable_info_ptr = NULL; 4783a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong task_purgable_info_ptr = (task_purgable_info_type)dlsym(RTLD_NEXT, "task_purgable_info"); 4793a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong if (task_purgable_info_ptr != NULL) 48077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 4813a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong kr = (*task_purgable_info_ptr)(task, &purgeable_info); 48277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong if (kr == KERN_SUCCESS) { 48377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong purgeable_sum = SumVMPurgeableInfo(&purgeable_info); 48477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong purgeable = purgeable_sum; 48577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 48677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 487813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#endif /* !TASK_VM_INFO_PURGEABLE */ 48877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 48977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong info_count = TASK_VM_INFO_COUNT; 490813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#ifdef TASK_VM_INFO_PURGEABLE 491813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong kr = task_info(task, TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &info_count); 492813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#else 49377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong kr = task_info(task, TASK_VM_INFO, (task_info_t)&vm_info, &info_count); 494813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#endif 49577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong if (kr == KERN_SUCCESS) 49677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 497813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#ifdef TASK_VM_INFO_PURGEABLE 498813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong purgeable = vm_info.purgeable_volatile_resident; 499813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong anonymous = vm_info.internal - vm_info.purgeable_volatile_pmap; 500813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#else 50177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong if (purgeable_sum < vm_info.internal) 50277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 50377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong anonymous = vm_info.internal - purgeable_sum; 50477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 50577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong else 50677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 50777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong anonymous = 0; 50877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 509813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong#endif 51077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 511813bec3072bc145dc9d80c5ef04daf8406b91ac0Han Ming Ong 51277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#endif 51377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong} 51477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 515fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongnub_bool_t 51677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming OngMachVMMemory::GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, mach_vm_size_t &purgeable, mach_vm_size_t &anonymous) 517fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 518cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong if (scanType & eProfileHostMemory) 519cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong physical_memory = GetPhysicalMemory(); 520cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong 521cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong if (scanType & eProfileMemory) 522cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong { 523cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong static mach_port_t localHost = mach_host_self(); 524cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong mach_msg_type_number_t count = HOST_VM_INFO_COUNT; 525cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong host_statistics(localHost, HOST_VM_INFO, (host_info_t)&vm_stats, &count); 526fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda vm_stats.wire_count += GetStolenPages(task); 527fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 528cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong GetMemorySizes(task, cputype, pid, rprvt, vprvt); 529fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 530cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong rsize = ti.resident_size; 531cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong vsize = ti.virtual_size; 532a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong 533a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong if (scanType & eProfileMemoryDirtyPage) 534a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong { 535a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong // This uses vmmap strategy. We don't use the returned rsize for now. We prefer to match top's version since that's what we do for the rest of the metrics. 536a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong GetRegionSizes(task, rsize, dirty_size); 537a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong } 53877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 53977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong if (scanType & eProfileMemoryAnonymous) 54077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 54177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong GetPurgeableAndAnonymous(task, purgeable, anonymous); 54277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 543cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong } 544fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 545fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong return true; 546fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 547dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda 54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::Read(task_t task, nub_addr_t address, void *data, nub_size_t data_count) 55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (data == NULL || data_count == 0) 55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return 0; 55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t total_bytes_read = 0; 55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t curr_addr = address; 55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner uint8_t *curr_data = (uint8_t*)data; 55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (total_bytes_read < data_count) 55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 559fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda mach_vm_size_t curr_size = MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_read); 56024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_msg_type_number_t curr_bytes_read = 0; 56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner vm_offset_t vm_memory = NULL; 56224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::mach_vm_read (task, curr_addr, curr_size, &vm_memory, &curr_bytes_read); 563d906b1b24a6c838d78039b399ee43dc57598ab52Jim Ingham 56455f768792c75eb5f9474edb09ca416c8737eeac0Jim Ingham if (DNBLogCheckLogBit(LOG_MEMORY)) 56524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err.LogThreaded("::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, data => %8.8p, dataCnt => %i )", task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, curr_bytes_read); 56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 56724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_err.Success()) 56824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 56924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (curr_bytes_read != curr_size) 57024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (DNBLogCheckLogBit(LOG_MEMORY)) 57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err.LogThreaded("::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, data => %8.8p, dataCnt=>%i ) only read %u of %llu bytes", task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, curr_bytes_read, curr_bytes_read, (uint64_t)curr_size); 57324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 57424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::memcpy (curr_data, (void *)vm_memory, curr_bytes_read); 57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::vm_deallocate (mach_task_self (), vm_memory, curr_bytes_read); 57624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner total_bytes_read += curr_bytes_read; 57724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_addr += curr_bytes_read; 57824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data += curr_bytes_read; 57924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 58024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 58124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 58224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 58324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 58424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 58524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return total_bytes_read; 58624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 58724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 58824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 58924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 59024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count) 59124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 59224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MachVMRegion vmRegion(task); 59324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 59424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t total_bytes_written = 0; 59524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t curr_addr = address; 59624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const uint8_t *curr_data = (const uint8_t*)data; 59724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 59824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 59924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (total_bytes_written < data_count) 60024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 60124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (vmRegion.GetRegionForAddress(curr_addr)) 60224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 60324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_vm_size_t curr_data_count = data_count - total_bytes_written; 60424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_vm_size_t region_bytes_left = vmRegion.BytesRemaining(curr_addr); 60524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (region_bytes_left == 0) 60624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 60724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 60824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 60924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (curr_data_count > region_bytes_left) 61024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data_count = region_bytes_left; 61124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 61224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (vmRegion.SetProtections(curr_addr, curr_data_count, VM_PROT_READ | VM_PROT_WRITE)) 61324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 61424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t bytes_written = WriteRegion(task, curr_addr, curr_data, curr_data_count); 61524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (bytes_written <= 0) 61624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 61724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Error should have already be posted by WriteRegion... 61824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 61924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 62024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 62124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 62224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner total_bytes_written += bytes_written; 62324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_addr += bytes_written; 62424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data += bytes_written; 62524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 62624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 62724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 62824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 62924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, "Failed to set read/write protections on region for address: [0x%8.8llx-0x%8.8llx)", (uint64_t)curr_addr, (uint64_t)(curr_addr + curr_data_count)); 63024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 63124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 63224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 63324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 63424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 63524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, "Failed to get region for address: 0x%8.8llx", (uint64_t)address); 63624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 63724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 63824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 63924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 64024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return total_bytes_written; 64124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 64224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 64324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 64424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 64524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::WriteRegion(task_t task, const nub_addr_t address, const void *data, const nub_size_t data_count) 64624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 64724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (data == NULL || data_count == 0) 64824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return 0; 64924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 65024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t total_bytes_written = 0; 65124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t curr_addr = address; 65224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const uint8_t *curr_data = (const uint8_t*)data; 65324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (total_bytes_written < data_count) 65424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 655fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda mach_msg_type_number_t curr_data_count = MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_written); 65624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::mach_vm_write (task, curr_addr, (pointer_t) curr_data, curr_data_count); 65724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) 65824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err.LogThreaded("::mach_vm_write ( task = 0x%4.4x, addr = 0x%8.8llx, data = %8.8p, dataCnt = %u )", task, (uint64_t)curr_addr, curr_data, curr_data_count); 65924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 66024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#if !defined (__i386__) && !defined (__x86_64__) 66124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH; 66224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 66324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::vm_machine_attribute (task, curr_addr, curr_data_count, MATTR_CACHE, &mattr_value); 66424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) 66524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err.LogThreaded("::vm_machine_attribute ( task = 0x%4.4x, addr = 0x%8.8llx, size = %u, attr = MATTR_CACHE, mattr_value => MATTR_VAL_CACHE_FLUSH )", task, (uint64_t)curr_addr, curr_data_count); 66624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif 66724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 66824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_err.Success()) 66924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 67024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner total_bytes_written += curr_data_count; 67124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_addr += curr_data_count; 67224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data += curr_data_count; 67324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 67424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 67524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 67624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 67724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 67824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 67924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return total_bytes_written; 68024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 681