1e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/* 2e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 4e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * you may not use this file except in compliance with the License. 6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * You may obtain a copy of the License at 7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * See the License for the specific language governing permissions and 14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * limitations under the License. 15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project */ 16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 17e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <dirent.h> 18e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <errno.h> 19e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <fcntl.h> 20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdint.h> 21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdlib.h> 22e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <sys/stat.h> 23e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <sys/types.h> 24e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <unistd.h> 25e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 26e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <pagemap/pagemap.h> 27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 28e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_kernel_create(pm_kernel_t **ker_out) { 29e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pm_kernel_t *ker; 30e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int error; 31e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 32e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!ker_out) 33e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 1; 34e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 35e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ker = calloc(1, sizeof(*ker)); 36e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!ker) 37e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return errno; 38e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 39e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ker->kpagecount_fd = open("/proc/kpagecount", O_RDONLY); 40e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (ker->kpagecount_fd < 0) { 41e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = errno; 42e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free(ker); 43e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return error; 44e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 45e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 46e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ker->kpageflags_fd = open("/proc/kpageflags", O_RDONLY); 47e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (ker->kpageflags_fd < 0) { 48e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = errno; 49e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project close(ker->kpagecount_fd); 50e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free(ker); 51e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return error; 52e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 53e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 54e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project ker->pagesize = getpagesize(); 55e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 56e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *ker_out = ker; 57e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 58e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 59e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 60e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 61e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define INIT_PIDS 20 62e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_kernel_pids(pm_kernel_t *ker, pid_t **pids_out, size_t *len) { 63e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project DIR *proc; 64e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct dirent *dir; 65e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pid_t pid, *pids, *new_pids; 66e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project size_t pids_count, pids_size; 67e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int error; 68e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 69e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project proc = opendir("/proc"); 70e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!proc) 71e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return errno; 72e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 73e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pids = malloc(INIT_PIDS * sizeof(pid_t)); 74e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!pids) { 75e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project closedir(proc); 76e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return errno; 77e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 78e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pids_count = 0; pids_size = INIT_PIDS; 79e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 80e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project while ((dir = readdir(proc))) { 81e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (sscanf(dir->d_name, "%d", &pid) < 1) 82e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project continue; 83e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 84e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (pids_count >= pids_size) { 85e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project new_pids = realloc(pids, 2 * pids_size * sizeof(pid_t)); 86e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!new_pids) { 87e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = errno; 88e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free(pids); 89e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project closedir(proc); 90e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return error; 91e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 92e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pids = new_pids; 93e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pids_size = 2 * pids_size; 94e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 95e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 96e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pids[pids_count] = pid; 97e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 98e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pids_count++; 99e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 100e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 101e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project closedir(proc); 102e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 103e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project new_pids = realloc(pids, pids_count * sizeof(pid_t)); 104e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!new_pids) { 105e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project error = errno; 106e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free(pids); 107e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return error; 108e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 109e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 110e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *pids_out = new_pids; 111e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *len = pids_count; 112e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 113e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 114e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 115e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 116e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_kernel_count(pm_kernel_t *ker, unsigned long pfn, uint64_t *count_out) { 117e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project off_t off; 118e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 119e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!ker || !count_out) 120e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return -1; 121e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 122e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project off = lseek(ker->kpagecount_fd, pfn * sizeof(uint64_t), SEEK_SET); 123e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (off == (off_t)-1) 124e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return errno; 125e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (read(ker->kpagecount_fd, count_out, sizeof(uint64_t)) < 126e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project (ssize_t)sizeof(uint64_t)) 127e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return errno; 128e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 129e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 130e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 131e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 132e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_kernel_flags(pm_kernel_t *ker, unsigned long pfn, uint64_t *flags_out) { 133e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project off_t off; 134e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 135e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!ker || !flags_out) 136e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return -1; 137e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 138e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project off = lseek(ker->kpageflags_fd, pfn * sizeof(uint64_t), SEEK_SET); 139e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (off == (off_t)-1) 140e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return errno; 141e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (read(ker->kpageflags_fd, flags_out, sizeof(uint64_t)) < 142e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project (ssize_t)sizeof(uint64_t)) 143e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return errno; 144e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 145e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 146e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 147e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 148e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pm_kernel_destroy(pm_kernel_t *ker) { 149e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!ker) 150e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return -1; 151e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 152e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project close(ker->kpagecount_fd); 153e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project close(ker->kpageflags_fd); 154e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 155e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free(ker); 156e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 157e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 158e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 159