1643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/*
2643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Copyright (C) 2008 The Android Open Source Project
3643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
4643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Licensed under the Apache License, Version 2.0 (the "License");
5643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * you may not use this file except in compliance with the License.
6643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * You may obtain a copy of the License at
7643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
8643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *      http://www.apache.org/licenses/LICENSE-2.0
9643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
10643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Unless required by applicable law or agreed to in writing, software
11643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * distributed under the License is distributed on an "AS IS" BASIS,
12643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * See the License for the specific language governing permissions and
14643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * limitations under the License.
15643ca7872b450ea4efacab6188849e5aac2ba161Steve Block */
16643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
17643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#ifndef _PAGEMAP_PAGEMAP_H
18643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define _PAGEMAP_PAGEMAP_H
19643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
20643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <stdint.h>
21643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <stdio.h>
22643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <sys/types.h>
23643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
24643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocktypedef struct pm_memusage pm_memusage_t;
25643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
26643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Holds the various metrics for memory usage of a process or a mapping. */
27643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstruct pm_memusage {
28643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    size_t vss;
29643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    size_t rss;
30643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    size_t pss;
31643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    size_t uss;
32643ca7872b450ea4efacab6188849e5aac2ba161Steve Block};
33643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
34643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Clears a memusage. */
35643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid pm_memusage_zero(pm_memusage_t *mu);
36643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Adds one memusage (a) to another (b). */
37643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b);
38643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
39643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocktypedef struct pm_kernel   pm_kernel_t;
40643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocktypedef struct pm_process  pm_process_t;
41643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocktypedef struct pm_map      pm_map_t;
42643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
43643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* pm_kernel_t holds the state necessary to interface to the kernel's pagemap
44643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * system on a global level. */
45643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstruct pm_kernel {
46643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int kpagecount_fd;
47643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int kpageflags_fd;
48643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
49643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int pagesize;
50643ca7872b450ea4efacab6188849e5aac2ba161Steve Block};
51643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
52643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* pm_process_t holds the state necessary to interface to a particular process'
53643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * pagemap. */
54643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstruct pm_process {
55643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    pm_kernel_t *ker;
56643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
57643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    pid_t pid;
58643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
59643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    pm_map_t **maps;
60643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int num_maps;
61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int pagemap_fd;
63643ca7872b450ea4efacab6188849e5aac2ba161Steve Block};
64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* pm_map_t holds the state necessary to access information about a particular
66643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * mapping in a particular process. */
67643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstruct pm_map {
68643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    pm_process_t *proc;
69643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
70643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    unsigned long start;
71643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    unsigned long end;
72643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    unsigned long offset;
73643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int flags;
74643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
75643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    char *name;
76643ca7872b450ea4efacab6188849e5aac2ba161Steve Block};
77643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Create a pm_kernel_t. */
79643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint pm_kernel_create(pm_kernel_t **ker_out);
80643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
81643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define pm_kernel_pagesize(ker) ((ker)->pagesize)
82643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
83643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Get a list of probably-existing PIDs (returned through *pids_out).
84643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Length of the array (in sizeof(pid_t) units) is returned through *len.
85643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * The array should be freed by the caller. */
86643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint pm_kernel_pids(pm_kernel_t *ker, pid_t **pids_out, size_t *len);
87643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
88643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Get the map count (from /proc/kpagecount) of a physical frame.
89643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * The count is returned through *count_out. */
90643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint pm_kernel_count(pm_kernel_t *ker, unsigned long pfn, uint64_t *count_out);
91643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
92643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Get the page flags (from /proc/kpageflags) of a physical frame.
93643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * The count is returned through *flags_out. */
94643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint pm_kernel_flags(pm_kernel_t *ker, unsigned long pfn, uint64_t *flags_out);
95643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
96643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_LOCKED     (1 <<  0)
97643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_ERROR      (1 <<  1)
98643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_REFERENCED (1 <<  2)
99643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_UPTODATE   (1 <<  3)
100643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_DIRTY      (1 <<  4)
101643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_LRU        (1 <<  5)
102643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_ACTIVE     (1 <<  6)
103643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_SLAB       (1 <<  7)
104643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_WRITEBACK  (1 <<  8)
105643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_RECLAIM    (1 <<  9)
106643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define PM_PAGE_BUDDY      (1 << 10)
107643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
108643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Destroy a pm_kernel_t. */
109643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint pm_kernel_destroy(pm_kernel_t *ker);
110643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
111643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Get the PID of a pm_process_t. */
112643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define pm_process_pid(proc) ((proc)->pid)
113643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
114643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Create a pm_process_t and returns it through *proc_out.
115643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Takes a pm_kernel_t, and the PID of the process. */
116643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint pm_process_create(pm_kernel_t *ker, pid_t pid, pm_process_t **proc_out);
117643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
118643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Get the total memory usage of a process and store in *usage_out. */
119643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint pm_process_usage(pm_process_t *proc, pm_memusage_t *usage_out);
120643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Get the working set of a process (if ws_out != NULL), and reset it
122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * (if reset != 0). */
123643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint pm_process_workingset(pm_process_t *proc, pm_memusage_t *ws_out, int reset);
124643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
125643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/* Get the PFNs corresponding to a range of virtual addresses.
126643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * The array of PFNs is returned through *range_out, and the caller has the
127643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * responsibility to free it. */
128643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint pm_process_pagemap_range(pm_process_t *proc,
129643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                             unsigned long low, unsigned long hi,
130                             uint64_t **range_out, size_t *len);
131
132#define _BITS(x, offset, bits) (((x) >> offset) & ((1LL << (bits)) - 1))
133
134#define PM_PAGEMAP_PRESENT(x)     (_BITS(x, 63, 1))
135#define PM_PAGEMAP_SWAPPED(x)     (_BITS(x, 62, 1))
136#define PM_PAGEMAP_SHIFT(x)       (_BITS(x, 55, 6))
137#define PM_PAGEMAP_PFN(x)         (_BITS(x, 0, 55))
138#define PM_PAGEMAP_SWAP_OFFSET(x) (_BITS(x, 5, 50))
139#define PM_PAGEMAP_SWAP_TYPE(x)   (_BITS(x, 0,  5))
140
141/* Get the maps in the virtual address space of this process.
142 * Returns an array of pointers to pm_map_t through *maps.
143 * The array should be freed by the caller, but the maps should not be
144 * modified or destroyed. */
145int pm_process_maps(pm_process_t *proc, pm_map_t ***maps_out, size_t *len);
146
147/* Destroy a pm_process_t. */
148int pm_process_destroy(pm_process_t *proc);
149
150/* Get the name, flags, start/end address, or offset of a map. */
151#define pm_map_name(map)   ((map)->name)
152#define pm_map_flags(map)  ((map)->flags)
153#define PM_MAP_READ  1
154#define PM_MAP_WRITE 2
155#define PM_MAP_EXEC  4
156#define pm_map_start(map)  ((map)->start)
157#define pm_map_end(map)    ((map)->end)
158#define pm_map_offset(map) ((map)->offset)
159
160/* Get the PFNs of the pages in the virtual address space of this map.
161 * Array of PFNs is returned through *pagemap_out, and should be freed by the
162 * caller. */
163int pm_map_pagemap(pm_map_t *map, uint64_t **pagemap_out, size_t *len);
164
165/* Get the memory usage of this map alone. */
166int pm_map_usage(pm_map_t *map, pm_memusage_t *usage_out);
167
168/* Get the working set of this map alone. */
169int pm_map_workingset(pm_map_t *map, pm_memusage_t *ws_out);
170
171#endif
172