MachVMMemory.cpp revision cec43ab7f30085ac7f65a26a58b956a69e363a3b
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> 2024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::MachVMMemory() : 2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_page_size (kInvalidPageSize), 2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err (0) 2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::~MachVMMemory() 2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::PageSize() 3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_page_size == kInvalidPageSize) 3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::host_page_size( ::mach_host_self(), &m_page_size); 3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_err.Fail()) 3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_page_size = 0; 3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return m_page_size; 4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::MaxBytesLeftInPage(nub_addr_t addr, nub_size_t count) 4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const nub_size_t page_size = PageSize(); 4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (page_size > 0) 4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t page_offset = (addr % page_size); 5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t bytes_left_in_page = page_size - page_offset; 5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (count > bytes_left_in_page) 5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner count = bytes_left_in_page; 5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return count; 5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 571308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Claytonnub_bool_t 58a9385537809ef342c843c5ab972e513742652047Greg ClaytonMachVMMemory::GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info) 59dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda{ 60dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda MachVMRegion vmRegion(task); 61dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda 62a9385537809ef342c843c5ab972e513742652047Greg Clayton if (vmRegion.GetRegionForAddress(address)) 63a9385537809ef342c843c5ab972e513742652047Greg Clayton { 64a9385537809ef342c843c5ab972e513742652047Greg Clayton region_info->addr = vmRegion.StartAddress(); 65a9385537809ef342c843c5ab972e513742652047Greg Clayton region_info->size = vmRegion.GetByteSize(); 66a9385537809ef342c843c5ab972e513742652047Greg Clayton region_info->permissions = vmRegion.GetDNBPermissions(); 67a9385537809ef342c843c5ab972e513742652047Greg Clayton } 681308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton else 691308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton { 701308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->addr = address; 711308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->size = 0; 721308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton if (vmRegion.GetError().Success()) 731308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton { 741308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // vmRegion.GetRegionForAddress() return false, indicating that "address" 751308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // wasn't in a valid region, but the "vmRegion" info was successfully 761308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // read from the task which means the info describes the next valid 771308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // region from which we can infer the size of this invalid region 781308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton mach_vm_address_t start_addr = vmRegion.StartAddress(); 791308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton if (address < start_addr) 801308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->size = start_addr - address; 811308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton } 821308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // If we can't get any infor about the size from the next region, just fill 831308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // 1 in as the byte size 841308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton if (region_info->size == 0) 851308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->size = 1; 861308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton 871308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // Not readable, writeable or executable 881308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->permissions = 0; 891308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton } 901308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton return true; 91dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda} 92fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 93e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong// For integrated graphics chip, this makes the accounting info for 'wired' memory more like top. 94e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ongstatic uint64_t GetStolenPages() 95e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong{ 96e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static uint64_t stolenPages = 0; 97e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static bool calculated = false; 98e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if (calculated) return stolenPages; 99e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 100e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static int mib_reserved[CTL_MAXNAME]; 101e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static int mib_unusable[CTL_MAXNAME]; 102e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static int mib_other[CTL_MAXNAME]; 103e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static size_t mib_reserved_len = 0; 104e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static size_t mib_unusable_len = 0; 105e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static size_t mib_other_len = 0; 106e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong int r; 107e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 108e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong /* This can be used for testing: */ 109e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong //tsamp->pages_stolen = (256 * 1024 * 1024ULL) / tsamp->pagesize; 110e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 111e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(0 == mib_reserved_len) 112e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 113e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = CTL_MAXNAME; 114e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 115e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong r = sysctlnametomib("machdep.memmap.Reserved", mib_reserved, 116e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &mib_reserved_len); 117e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 118e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == r) 119e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 120e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = 0; 121e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 122e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 123e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 124e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_unusable_len = CTL_MAXNAME; 125e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 126e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong r = sysctlnametomib("machdep.memmap.Unusable", mib_unusable, 127e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &mib_unusable_len); 128e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 129e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == r) 130e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 131e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = 0; 132e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 133e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 134e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 135e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 136e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_other_len = CTL_MAXNAME; 137e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 138e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong r = sysctlnametomib("machdep.memmap.Other", mib_other, 139e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &mib_other_len); 140e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 141e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == r) 142e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 143e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = 0; 144e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 145e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 146e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 147e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 148e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(mib_reserved_len > 0 && mib_unusable_len > 0 && mib_other_len > 0) 149e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 150e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong uint64_t reserved = 0, unusable = 0, other = 0; 151e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t reserved_len; 152e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t unusable_len; 153e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t other_len; 154e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 155e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong reserved_len = sizeof(reserved); 156e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong unusable_len = sizeof(unusable); 157e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong other_len = sizeof(other); 158e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 159e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong /* These are all declared as QUAD/uint64_t sysctls in the kernel. */ 160e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 161e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == sysctl(mib_reserved, mib_reserved_len, &reserved, 162e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &reserved_len, NULL, 0)) 163e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 164e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 165e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 166e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 167e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == sysctl(mib_unusable, mib_unusable_len, &unusable, 168e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &unusable_len, NULL, 0)) 169e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 170e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 171e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 172e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 173e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == sysctl(mib_other, mib_other_len, &other, 174e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &other_len, NULL, 0)) 175e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 176e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 177e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 178e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 179e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(reserved_len == sizeof(reserved) 180e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong && unusable_len == sizeof(unusable) 181e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong && other_len == sizeof(other)) 182e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 183e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong uint64_t stolen = reserved + unusable + other; 184e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong uint64_t mb128 = 128 * 1024 * 1024ULL; 185e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 186e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(stolen >= mb128) 187e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 188e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong stolen = (stolen & ~((128 * 1024 * 1024ULL) - 1)); // rounding down 189e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong stolenPages = stolen/vm_page_size; 190e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 191e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 192e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 193e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 194e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong calculated = true; 195e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return stolenPages; 196e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong} 197e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 198e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ongstatic uint64_t GetPhysicalMemory() 199e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong{ 200e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong // This doesn't change often at all. No need to poll each time. 201e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static uint64_t physical_memory = 0; 202e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static bool calculated = false; 203e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if (calculated) return physical_memory; 204e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 205e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong int mib[2]; 206e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib[0] = CTL_HW; 207e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib[1] = HW_MEMSIZE; 208e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t len = sizeof(physical_memory); 209e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong sysctl(mib, 2, &physical_memory, &len, NULL, 0); 210e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return physical_memory; 211e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong} 212e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 213fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han 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. 214fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongstatic void GetRegionSizes(task_t task, mach_vm_size_t &rsize, mach_vm_size_t &dirty_size) 215fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 216fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_address_t address = 0; 217fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t size; 218fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong kern_return_t err = 0; 219fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong unsigned nestingDepth = 0; 220fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t pages_resident = 0; 221fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t pages_dirtied = 0; 222fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 223fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong while (1) 224fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 225559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_msg_type_number_t count; 226fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong struct vm_region_submap_info_64 info; 227fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 228fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong count = VM_REGION_SUBMAP_INFO_COUNT_64; 229fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong err = mach_vm_region_recurse(task, &address, &size, &nestingDepth, (vm_region_info_t)&info, &count); 230fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (err == KERN_INVALID_ADDRESS) 231fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 232fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // It seems like this is a good break too. 233fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 234fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 235fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong else if (err) 236fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 237fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_error("vm_region",err); 238fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; // reached last region 239fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 240fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 241fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong bool should_count = true; 242fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (info.is_submap) 243fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { // is it a submap? 244fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong nestingDepth++; 245fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong should_count = false; 246fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 247fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong else 248fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 249fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Don't count malloc stack logging data in the TOTAL VM usage lines. 250fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (info.user_tag == VM_MEMORY_ANALYSIS_TOOL) 251fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong should_count = false; 252fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Don't count system shared library region not used by this process. 253fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (address >= SHARED_REGION_BASE && address < (SHARED_REGION_BASE + SHARED_REGION_SIZE)) 254fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong should_count = false; 255fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 256fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong address = address+size; 257fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 258fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 259fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (should_count) 260fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 261fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong pages_resident += info.pages_resident; 262fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong pages_dirtied += info.pages_dirtied; 263fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 264fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 265fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 266fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong rsize = pages_resident * vm_page_size; 267fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong dirty_size = pages_dirtied * vm_page_size; 268fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 269fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 270fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong// Test whether the virtual address is within the architecture's shared region. 271fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongstatic bool InSharedRegion(mach_vm_address_t addr, cpu_type_t type) 272fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 273559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_address_t base = 0, size = 0; 274fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 275559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda switch(type) { 276559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case CPU_TYPE_ARM: 277559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda base = SHARED_REGION_BASE_ARM; 278559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda size = SHARED_REGION_SIZE_ARM; 279fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 280fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 281559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case CPU_TYPE_X86_64: 282559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda base = SHARED_REGION_BASE_X86_64; 283559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda size = SHARED_REGION_SIZE_X86_64; 284fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 285fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 286559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case CPU_TYPE_I386: 287559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda base = SHARED_REGION_BASE_I386; 288559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda size = SHARED_REGION_SIZE_I386; 289fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 290fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 291559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda default: { 292fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Log error abut unknown CPU type 293fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 294559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 295559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 296fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 297fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 298559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda return(addr >= base && addr < (base + size)); 299fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 300fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 301fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongstatic void GetMemorySizes(task_t task, cpu_type_t cputype, nub_process_t pid, mach_vm_size_t &rprvt, mach_vm_size_t &vprvt) 302fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 303fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Collecting some other info cheaply but not reporting for now. 304fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t empty = 0; 305559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t fw_private = 0; 306fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 307559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t aliased = 0; 308559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t pagesize = vm_page_size; 309fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong bool global_shared_text_data_mapped = false; 310fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 311559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda for (mach_vm_address_t addr=0, size=0; ; addr += size) 312fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 313559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vm_region_top_info_data_t info; 314559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_msg_type_number_t count = VM_REGION_TOP_INFO_COUNT; 315559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_port_t object_name; 316fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 317559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda kern_return_t kr = mach_vm_region(task, &addr, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count, &object_name); 318559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (kr != KERN_SUCCESS) break; 319559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 320559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (InSharedRegion(addr, cputype)) 321fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 322559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Private Shared 323559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda fw_private += info.private_pages_resident * pagesize; 324fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 325559cf6e8b52b940f5f4362b32d628838d6301e2eJason 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. 326559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (global_shared_text_data_mapped == FALSE && info.share_mode == SM_EMPTY) { 327559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vm_region_basic_info_data_64_t b_info; 328559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_address_t b_addr = addr; 329559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t b_size = size; 330559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda count = VM_REGION_BASIC_INFO_COUNT_64; 331559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 332559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda kr = mach_vm_region(task, &b_addr, &b_size, VM_REGION_BASIC_INFO, (vm_region_info_t)&b_info, &count, &object_name); 333559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (kr != KERN_SUCCESS) break; 334fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 335559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (b_info.reserved) { 336559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda global_shared_text_data_mapped = TRUE; 337559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 338559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 339559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 340559cf6e8b52b940f5f4362b32d628838d6301e2eJason 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. 341559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode != SM_PRIVATE) 342fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 343559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda continue; 344559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 345559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 346559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 347559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Update counters according to the region type. 348559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode == SM_COW && info.ref_count == 1) 349fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 350559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Treat single reference SM_COW as SM_PRIVATE 351559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda info.share_mode = SM_PRIVATE; 352559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 353fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 354559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda switch (info.share_mode) 355fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 356559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_LARGE_PAGE: 357559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Treat SM_LARGE_PAGE the same as SM_PRIVATE 358559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // since they are not shareable and are wired. 359559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_PRIVATE: 360559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.private_pages_resident * pagesize; 361559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.shared_pages_resident * pagesize; 362559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vprvt += size; 363559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 364559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 365559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_EMPTY: 366fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong empty += size; 367559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 368559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 369559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_COW: 370559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_SHARED: 371fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 372559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (pid == 0) 373fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 374559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Treat kernel_task specially 375559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode == SM_COW) 376fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 377559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.private_pages_resident * pagesize; 378559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vprvt += size; 379559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 380559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 381559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 382fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 383559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode == SM_COW) 384fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 385559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.private_pages_resident * pagesize; 386559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vprvt += info.private_pages_resident * pagesize; 387559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 388559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 389fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 390559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda default: 391fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // log that something is really bad. 392559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 393559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 394559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 395fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 396559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += aliased; 397fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 398fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 399fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongnub_bool_t 400cec43ab7f30085ac7f65a26a58b956a69e363a3bHan 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) 401fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 402cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong if (scanType & eProfileHostMemory) 403cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong physical_memory = GetPhysicalMemory(); 404cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong 405cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong if (scanType & eProfileMemory) 406cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong { 407cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong static mach_port_t localHost = mach_host_self(); 408cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong mach_msg_type_number_t count = HOST_VM_INFO_COUNT; 409cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong host_statistics(localHost, HOST_VM_INFO, (host_info_t)&vm_stats, &count); 410cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong vm_stats.wire_count += GetStolenPages(); 411fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 412cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong GetMemorySizes(task, cputype, pid, rprvt, vprvt); 413fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 414cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong rsize = ti.resident_size; 415cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong vsize = ti.virtual_size; 416cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong } 417cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong 418cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong if (scanType & eProfileMemoryDirtyPage) 419cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong { 420cec43ab7f30085ac7f65a26a58b956a69e363a3bHan 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. 421cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong GetRegionSizes(task, rsize, dirty_size); 422cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong } 423fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 424fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong return true; 425fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 426dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda 42724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 42824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::Read(task_t task, nub_addr_t address, void *data, nub_size_t data_count) 42924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 43024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (data == NULL || data_count == 0) 43124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return 0; 43224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 43324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t total_bytes_read = 0; 43424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t curr_addr = address; 43524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner uint8_t *curr_data = (uint8_t*)data; 43624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (total_bytes_read < data_count) 43724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 43824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_vm_size_t curr_size = MaxBytesLeftInPage(curr_addr, data_count - total_bytes_read); 43924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_msg_type_number_t curr_bytes_read = 0; 44024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner vm_offset_t vm_memory = NULL; 44124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::mach_vm_read (task, curr_addr, curr_size, &vm_memory, &curr_bytes_read); 442d906b1b24a6c838d78039b399ee43dc57598ab52Jim Ingham 44355f768792c75eb5f9474edb09ca416c8737eeac0Jim Ingham if (DNBLogCheckLogBit(LOG_MEMORY)) 44424943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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); 44524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 44624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_err.Success()) 44724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 44824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (curr_bytes_read != curr_size) 44924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 45024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (DNBLogCheckLogBit(LOG_MEMORY)) 45124943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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); 45224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 45324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::memcpy (curr_data, (void *)vm_memory, curr_bytes_read); 45424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::vm_deallocate (mach_task_self (), vm_memory, curr_bytes_read); 45524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner total_bytes_read += curr_bytes_read; 45624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_addr += curr_bytes_read; 45724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data += curr_bytes_read; 45824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 45924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 46024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 46124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 46224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 46324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 46424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return total_bytes_read; 46524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 46624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 46724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 46824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 46924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count) 47024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 47124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MachVMRegion vmRegion(task); 47224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 47324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t total_bytes_written = 0; 47424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t curr_addr = address; 47524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const uint8_t *curr_data = (const uint8_t*)data; 47624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 47724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 47824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (total_bytes_written < data_count) 47924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (vmRegion.GetRegionForAddress(curr_addr)) 48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 48224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_vm_size_t curr_data_count = data_count - total_bytes_written; 48324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_vm_size_t region_bytes_left = vmRegion.BytesRemaining(curr_addr); 48424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (region_bytes_left == 0) 48524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 48624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 48724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 48824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (curr_data_count > region_bytes_left) 48924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data_count = region_bytes_left; 49024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 49124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (vmRegion.SetProtections(curr_addr, curr_data_count, VM_PROT_READ | VM_PROT_WRITE)) 49224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 49324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t bytes_written = WriteRegion(task, curr_addr, curr_data, curr_data_count); 49424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (bytes_written <= 0) 49524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 49624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Error should have already be posted by WriteRegion... 49724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 49824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 49924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 50024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 50124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner total_bytes_written += bytes_written; 50224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_addr += bytes_written; 50324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data += bytes_written; 50424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 50524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 50624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 50724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 50824943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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)); 50924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 51024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 51124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 51224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 51324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 51424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, "Failed to get region for address: 0x%8.8llx", (uint64_t)address); 51524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 51624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 51724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 51824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 51924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return total_bytes_written; 52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::WriteRegion(task_t task, const nub_addr_t address, const void *data, const nub_size_t data_count) 52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 52624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (data == NULL || data_count == 0) 52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return 0; 52824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 52924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t total_bytes_written = 0; 53024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t curr_addr = address; 53124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const uint8_t *curr_data = (const uint8_t*)data; 53224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (total_bytes_written < data_count) 53324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 53424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_msg_type_number_t curr_data_count = MaxBytesLeftInPage(curr_addr, data_count - total_bytes_written); 53524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::mach_vm_write (task, curr_addr, (pointer_t) curr_data, curr_data_count); 53624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) 53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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); 53824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 53924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#if !defined (__i386__) && !defined (__x86_64__) 54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH; 54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::vm_machine_attribute (task, curr_addr, curr_data_count, MATTR_CACHE, &mattr_value); 54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) 54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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); 54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif 54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 54724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_err.Success()) 54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner total_bytes_written += curr_data_count; 55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_addr += curr_data_count; 55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data += curr_data_count; 55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return total_bytes_written; 55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 560