MachVMMemory.cpp revision 3a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5
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{
238fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    mach_vm_address_t address = 0;
239fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    mach_vm_size_t size;
240fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    kern_return_t err = 0;
241fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    unsigned nestingDepth = 0;
242fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    mach_vm_size_t pages_resident = 0;
243fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    mach_vm_size_t pages_dirtied = 0;
244fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
245fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    while (1)
246fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    {
2472a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong        mach_msg_type_number_t count;
248fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        struct vm_region_submap_info_64 info;
249fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
250fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        count = VM_REGION_SUBMAP_INFO_COUNT_64;
251fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        err = mach_vm_region_recurse(task, &address, &size, &nestingDepth, (vm_region_info_t)&info, &count);
252fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        if (err == KERN_INVALID_ADDRESS)
253fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        {
254fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            // It seems like this is a good break too.
255fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            break;
256fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        }
257fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        else if (err)
258fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        {
259fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            mach_error("vm_region",err);
260fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            break; // reached last region
261fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        }
262fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
263fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        bool should_count = true;
264fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        if (info.is_submap)
265fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        { // is it a submap?
266fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            nestingDepth++;
267fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            should_count = false;
268fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        }
269fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        else
270fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        {
271fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            // Don't count malloc stack logging data in the TOTAL VM usage lines.
272fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            if (info.user_tag == VM_MEMORY_ANALYSIS_TOOL)
273fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong                should_count = false;
274190276872994426fb0398e1cf521748249b75875Han Ming Ong
275fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            address = address+size;
276fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        }
277fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
278fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        if (should_count)
279fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        {
280fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            pages_resident += info.pages_resident;
281fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            pages_dirtied += info.pages_dirtied;
282fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        }
283fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    }
284fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
28577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    vm_size_t pagesize = PageSize (task);
2862a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong    rsize = pages_resident * pagesize;
2872a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong    dirty_size = pages_dirtied * pagesize;
288fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong}
289fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
290fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong// Test whether the virtual address is within the architecture's shared region.
291fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongstatic bool InSharedRegion(mach_vm_address_t addr, cpu_type_t type)
292fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{
293559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda    mach_vm_address_t base = 0, size = 0;
294fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
295559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda    switch(type) {
296559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        case CPU_TYPE_ARM:
297559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            base = SHARED_REGION_BASE_ARM;
298559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            size = SHARED_REGION_SIZE_ARM;
299fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            break;
300fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
301559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        case CPU_TYPE_X86_64:
302559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            base = SHARED_REGION_BASE_X86_64;
303559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            size = SHARED_REGION_SIZE_X86_64;
304fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            break;
305fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
306559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        case CPU_TYPE_I386:
307559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            base = SHARED_REGION_BASE_I386;
308559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            size = SHARED_REGION_SIZE_I386;
309fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            break;
310fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
311559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        default: {
312fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            // Log error abut unknown CPU type
313fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            break;
314559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        }
315559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda    }
316fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
317fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
318559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda    return(addr >= base && addr < (base + size));
319fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong}
320fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
321fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molendavoid
322fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::GetMemorySizes(task_t task, cpu_type_t cputype, nub_process_t pid, mach_vm_size_t &rprvt, mach_vm_size_t &vprvt)
323fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{
324fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    // Collecting some other info cheaply but not reporting for now.
325fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    mach_vm_size_t empty = 0;
326559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda    mach_vm_size_t fw_private = 0;
327fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
328559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda    mach_vm_size_t aliased = 0;
329fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    bool global_shared_text_data_mapped = false;
33077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    vm_size_t pagesize = PageSize (task);
3312a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong
332559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda    for (mach_vm_address_t addr=0, size=0; ; addr += size)
333fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    {
334559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        vm_region_top_info_data_t info;
335559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        mach_msg_type_number_t count = VM_REGION_TOP_INFO_COUNT;
336559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        mach_port_t object_name;
337fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
338559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        kern_return_t kr = mach_vm_region(task, &addr, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count, &object_name);
339559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        if (kr != KERN_SUCCESS) break;
340559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda
341559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        if (InSharedRegion(addr, cputype))
342fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        {
343559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            // Private Shared
344559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            fw_private += info.private_pages_resident * pagesize;
345fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
346559cf6e8b52b940f5f4362b32d628838d6301e2eJason 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.
347559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            if (global_shared_text_data_mapped == FALSE && info.share_mode == SM_EMPTY) {
3482a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong                vm_region_basic_info_data_64_t b_info;
349559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                mach_vm_address_t b_addr = addr;
350559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                mach_vm_size_t b_size = size;
351559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                count = VM_REGION_BASIC_INFO_COUNT_64;
352559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda
353559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                kr = mach_vm_region(task, &b_addr, &b_size, VM_REGION_BASIC_INFO, (vm_region_info_t)&b_info, &count, &object_name);
354559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                if (kr != KERN_SUCCESS) break;
355fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
356559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                if (b_info.reserved) {
357559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                    global_shared_text_data_mapped = TRUE;
358559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                }
359559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            }
360559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda
361559cf6e8b52b940f5f4362b32d628838d6301e2eJason 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.
362559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            if (info.share_mode != SM_PRIVATE)
363fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            {
364559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                continue;
365559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            }
366559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        }
367559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda
368559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        // Update counters according to the region type.
369559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        if (info.share_mode == SM_COW && info.ref_count == 1)
370fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        {
371559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            // Treat single reference SM_COW as SM_PRIVATE
372559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            info.share_mode = SM_PRIVATE;
373559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        }
374fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
375559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        switch (info.share_mode)
376fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong        {
377559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            case SM_LARGE_PAGE:
378559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                // Treat SM_LARGE_PAGE the same as SM_PRIVATE
379559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                // since they are not shareable and are wired.
380559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            case SM_PRIVATE:
381559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                rprvt += info.private_pages_resident * pagesize;
382559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                rprvt += info.shared_pages_resident * pagesize;
383559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                vprvt += size;
384559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                break;
385559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda
386559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            case SM_EMPTY:
387fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong                empty += size;
388559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                break;
389559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda
390559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            case SM_COW:
391559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            case SM_SHARED:
392fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            {
393559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                if (pid == 0)
394fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong                {
395559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                    // Treat kernel_task specially
396559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                    if (info.share_mode == SM_COW)
397fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong                    {
398559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                        rprvt += info.private_pages_resident * pagesize;
399559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                        vprvt += size;
400559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                    }
401559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                    break;
402559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                }
403fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
404559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                if (info.share_mode == SM_COW)
405fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong                {
406559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                    rprvt += info.private_pages_resident * pagesize;
407559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                    vprvt += info.private_pages_resident * pagesize;
408559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                }
409559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                break;
410fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            }
411559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda            default:
412fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong                // log that something is really bad.
413559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda                break;
414559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda        }
415559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda    }
416fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
417559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda    rprvt += aliased;
418fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong}
419fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
42077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22
42177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
42277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong// cribbed from sysmond
42377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ongstatic uint64_t
42477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming OngSumVMPurgeableInfo(const vm_purgeable_info_t info)
42577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong{
42677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    uint64_t sum = 0;
42777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    int i;
42877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
42977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    for (i = 0; i < 8; i++)
43077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    {
43177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        sum += info->fifo_data[i].size;
43277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    }
43377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    sum += info->obsolete_data.size;
43477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    for (i = 0; i < 8; i++)
43577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    {
43677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        sum += info->lifo_data[i].size;
43777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    }
43877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
43977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    return sum;
44077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong}
44177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
44277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#endif
44377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
44477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ongstatic void
44577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming OngGetPurgeableAndAnonymous(task_t task, uint64_t &purgeable, uint64_t &anonymous)
44677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong{
44777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22
44877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
44977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    kern_return_t kr;
45077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    task_purgable_info_t purgeable_info;
45177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    uint64_t purgeable_sum = 0;
45277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    mach_msg_type_number_t info_count;
45377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    task_vm_info_data_t vm_info;
45477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
4553a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong    typedef kern_return_t (*task_purgable_info_type) (task_t, task_purgable_info_t *);
4563a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong    task_purgable_info_type task_purgable_info_ptr = NULL;
4573a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong    task_purgable_info_ptr = (task_purgable_info_type)dlsym(RTLD_NEXT, "task_purgable_info");
4583a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong    if (task_purgable_info_ptr != NULL)
45977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    {
4603a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong        kr = (*task_purgable_info_ptr)(task, &purgeable_info);
46177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        if (kr == KERN_SUCCESS) {
46277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong            purgeable_sum = SumVMPurgeableInfo(&purgeable_info);
46377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong            purgeable = purgeable_sum;
46477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        }
46577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    }
46677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
46777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    info_count = TASK_VM_INFO_COUNT;
46877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    kr = task_info(task, TASK_VM_INFO, (task_info_t)&vm_info, &info_count);
46977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    if (kr == KERN_SUCCESS)
47077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    {
47177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        if (purgeable_sum < vm_info.internal)
47277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        {
47377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong            anonymous = vm_info.internal - purgeable_sum;
47477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        }
47577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        else
47677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        {
47777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong            anonymous = 0;
47877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        }
47977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong    }
4803a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong
48177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#endif
48277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong}
48377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
484fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongnub_bool_t
48577d340f114b99ec8e2f7a48cbb674c93e237022bHan 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)
486fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{
487cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong    if (scanType & eProfileHostMemory)
488cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong        physical_memory = GetPhysicalMemory();
489cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong
490cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong    if (scanType & eProfileMemory)
491cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong    {
492cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong        static mach_port_t localHost = mach_host_self();
493cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong        mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
494cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong        host_statistics(localHost, HOST_VM_INFO, (host_info_t)&vm_stats, &count);
495fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda        vm_stats.wire_count += GetStolenPages(task);
496fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
497cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong        GetMemorySizes(task, cputype, pid, rprvt, vprvt);
498fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
499cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong        rsize = ti.resident_size;
500cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong        vsize = ti.virtual_size;
501a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong
502a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong        if (scanType & eProfileMemoryDirtyPage)
503a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong        {
504a53a76965eb603afe5705c694ee8e3344f91cc61Han 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.
505a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong            GetRegionSizes(task, rsize, dirty_size);
506a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong        }
50777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong
50877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        if (scanType & eProfileMemoryAnonymous)
50977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        {
51077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong            GetPurgeableAndAnonymous(task, purgeable, anonymous);
51177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong        }
512cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong    }
513fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
514fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong    return true;
515fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong}
516dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda
51724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t
51824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::Read(task_t task, nub_addr_t address, void *data, nub_size_t data_count)
51924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (data == NULL || data_count == 0)
52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return 0;
52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_size_t total_bytes_read = 0;
52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_addr_t curr_addr = address;
52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint8_t *curr_data = (uint8_t*)data;
52624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    while (total_bytes_read < data_count)
52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
528fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda        mach_vm_size_t curr_size = MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_read);
52924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        mach_msg_type_number_t curr_bytes_read = 0;
53024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        vm_offset_t vm_memory = NULL;
53124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_err = ::mach_vm_read (task, curr_addr, curr_size, &vm_memory, &curr_bytes_read);
532d906b1b24a6c838d78039b399ee43dc57598ab52Jim Ingham
53355f768792c75eb5f9474edb09ca416c8737eeac0Jim Ingham        if (DNBLogCheckLogBit(LOG_MEMORY))
53424943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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);
53524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
53624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (m_err.Success())
53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
53824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (curr_bytes_read != curr_size)
53924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (DNBLogCheckLogBit(LOG_MEMORY))
54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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);
54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            ::memcpy (curr_data, (void *)vm_memory, curr_bytes_read);
54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            ::vm_deallocate (mach_task_self (), vm_memory, curr_bytes_read);
54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            total_bytes_read += curr_bytes_read;
54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            curr_addr += curr_bytes_read;
54724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            curr_data += curr_bytes_read;
54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return total_bytes_read;
55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t
55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count)
56024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    MachVMRegion vmRegion(task);
56224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_size_t total_bytes_written = 0;
56424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_addr_t curr_addr = address;
56524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint8_t *curr_data = (const uint8_t*)data;
56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    while (total_bytes_written < data_count)
56924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
57024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (vmRegion.GetRegionForAddress(curr_addr))
57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            mach_vm_size_t curr_data_count = data_count - total_bytes_written;
57324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            mach_vm_size_t region_bytes_left = vmRegion.BytesRemaining(curr_addr);
57424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (region_bytes_left == 0)
57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
57624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
57724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
57824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (curr_data_count > region_bytes_left)
57924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                curr_data_count = region_bytes_left;
58024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
58124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (vmRegion.SetProtections(curr_addr, curr_data_count, VM_PROT_READ | VM_PROT_WRITE))
58224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
58324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                nub_size_t bytes_written = WriteRegion(task, curr_addr, curr_data, curr_data_count);
58424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (bytes_written <= 0)
58524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
58624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // Error should have already be posted by WriteRegion...
58724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    break;
58824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
58924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
59024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
59124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    total_bytes_written += bytes_written;
59224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    curr_addr += bytes_written;
59324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    curr_data += bytes_written;
59424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
59524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
59624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            else
59724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
59824943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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));
59924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
60024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
60124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
60224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
60324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
60424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, "Failed to get region for address: 0x%8.8llx", (uint64_t)address);
60524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
60624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
60724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
60824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
60924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return total_bytes_written;
61024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
61124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
61224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
61324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t
61424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::WriteRegion(task_t task, const nub_addr_t address, const void *data, const nub_size_t data_count)
61524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
61624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (data == NULL || data_count == 0)
61724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return 0;
61824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
61924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_size_t total_bytes_written = 0;
62024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_addr_t curr_addr = address;
62124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint8_t *curr_data = (const uint8_t*)data;
62224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    while (total_bytes_written < data_count)
62324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
624fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda        mach_msg_type_number_t curr_data_count = MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_written);
62524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_err = ::mach_vm_write (task, curr_addr, (pointer_t) curr_data, curr_data_count);
62624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail())
62724943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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);
62824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
62924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#if !defined (__i386__) && !defined (__x86_64__)
63024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH;
63124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
63224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_err = ::vm_machine_attribute (task, curr_addr, curr_data_count, MATTR_CACHE, &mattr_value);
63324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail())
63424943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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);
63524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif
63624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
63724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (m_err.Success())
63824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
63924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            total_bytes_written += curr_data_count;
64024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            curr_addr += curr_data_count;
64124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            curr_data += curr_data_count;
64224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
64324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
64424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
64524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
64624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
64724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
64824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return total_bytes_written;
64924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
650