1fcb45ec0SMichael Ellerman /* 2fcb45ec0SMichael Ellerman * Copyright 2013-2015, Michael Ellerman, IBM Corp. 3fcb45ec0SMichael Ellerman * Licensed under GPLv2. 4fcb45ec0SMichael Ellerman */ 5fcb45ec0SMichael Ellerman 6*d1301afdSMichael Ellerman #define _GNU_SOURCE /* For CPU_ZERO etc. */ 7*d1301afdSMichael Ellerman 8fcb45ec0SMichael Ellerman #include <elf.h> 9fcb45ec0SMichael Ellerman #include <errno.h> 10fcb45ec0SMichael Ellerman #include <fcntl.h> 11fcb45ec0SMichael Ellerman #include <link.h> 12*d1301afdSMichael Ellerman #include <sched.h> 13fcb45ec0SMichael Ellerman #include <stdio.h> 14fcb45ec0SMichael Ellerman #include <sys/stat.h> 15fcb45ec0SMichael Ellerman #include <sys/types.h> 16fcb45ec0SMichael Ellerman #include <unistd.h> 17fcb45ec0SMichael Ellerman 18fcb45ec0SMichael Ellerman #include "utils.h" 19fcb45ec0SMichael Ellerman 20fcb45ec0SMichael Ellerman static char auxv[4096]; 21fcb45ec0SMichael Ellerman 22fcb45ec0SMichael Ellerman void *get_auxv_entry(int type) 23fcb45ec0SMichael Ellerman { 24fcb45ec0SMichael Ellerman ElfW(auxv_t) *p; 25fcb45ec0SMichael Ellerman void *result; 26fcb45ec0SMichael Ellerman ssize_t num; 27fcb45ec0SMichael Ellerman int fd; 28fcb45ec0SMichael Ellerman 29fcb45ec0SMichael Ellerman fd = open("/proc/self/auxv", O_RDONLY); 30fcb45ec0SMichael Ellerman if (fd == -1) { 31fcb45ec0SMichael Ellerman perror("open"); 32fcb45ec0SMichael Ellerman return NULL; 33fcb45ec0SMichael Ellerman } 34fcb45ec0SMichael Ellerman 35fcb45ec0SMichael Ellerman result = NULL; 36fcb45ec0SMichael Ellerman 37fcb45ec0SMichael Ellerman num = read(fd, auxv, sizeof(auxv)); 38fcb45ec0SMichael Ellerman if (num < 0) { 39fcb45ec0SMichael Ellerman perror("read"); 40fcb45ec0SMichael Ellerman goto out; 41fcb45ec0SMichael Ellerman } 42fcb45ec0SMichael Ellerman 43fcb45ec0SMichael Ellerman if (num > sizeof(auxv)) { 44fcb45ec0SMichael Ellerman printf("Overflowed auxv buffer\n"); 45fcb45ec0SMichael Ellerman goto out; 46fcb45ec0SMichael Ellerman } 47fcb45ec0SMichael Ellerman 48fcb45ec0SMichael Ellerman p = (ElfW(auxv_t) *)auxv; 49fcb45ec0SMichael Ellerman 50fcb45ec0SMichael Ellerman while (p->a_type != AT_NULL) { 51fcb45ec0SMichael Ellerman if (p->a_type == type) { 52fcb45ec0SMichael Ellerman result = (void *)p->a_un.a_val; 53fcb45ec0SMichael Ellerman break; 54fcb45ec0SMichael Ellerman } 55fcb45ec0SMichael Ellerman 56fcb45ec0SMichael Ellerman p++; 57fcb45ec0SMichael Ellerman } 58fcb45ec0SMichael Ellerman out: 59fcb45ec0SMichael Ellerman close(fd); 60fcb45ec0SMichael Ellerman return result; 61fcb45ec0SMichael Ellerman } 62*d1301afdSMichael Ellerman 63*d1301afdSMichael Ellerman int pick_online_cpu(void) 64*d1301afdSMichael Ellerman { 65*d1301afdSMichael Ellerman cpu_set_t mask; 66*d1301afdSMichael Ellerman int cpu; 67*d1301afdSMichael Ellerman 68*d1301afdSMichael Ellerman CPU_ZERO(&mask); 69*d1301afdSMichael Ellerman 70*d1301afdSMichael Ellerman if (sched_getaffinity(0, sizeof(mask), &mask)) { 71*d1301afdSMichael Ellerman perror("sched_getaffinity"); 72*d1301afdSMichael Ellerman return -1; 73*d1301afdSMichael Ellerman } 74*d1301afdSMichael Ellerman 75*d1301afdSMichael Ellerman /* We prefer a primary thread, but skip 0 */ 76*d1301afdSMichael Ellerman for (cpu = 8; cpu < CPU_SETSIZE; cpu += 8) 77*d1301afdSMichael Ellerman if (CPU_ISSET(cpu, &mask)) 78*d1301afdSMichael Ellerman return cpu; 79*d1301afdSMichael Ellerman 80*d1301afdSMichael Ellerman /* Search for anything, but in reverse */ 81*d1301afdSMichael Ellerman for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--) 82*d1301afdSMichael Ellerman if (CPU_ISSET(cpu, &mask)) 83*d1301afdSMichael Ellerman return cpu; 84*d1301afdSMichael Ellerman 85*d1301afdSMichael Ellerman printf("No cpus in affinity mask?!\n"); 86*d1301afdSMichael Ellerman return -1; 87*d1301afdSMichael Ellerman } 88