cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

affinity.c (1947B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Manage affinity to optimize IPIs inside the kernel perf API. */
      3#define _GNU_SOURCE 1
      4#include <sched.h>
      5#include <stdlib.h>
      6#include <linux/bitmap.h>
      7#include <linux/zalloc.h>
      8#include "perf.h"
      9#include "cpumap.h"
     10#include "affinity.h"
     11
     12static int get_cpu_set_size(void)
     13{
     14	int sz = cpu__max_cpu().cpu + 8 - 1;
     15	/*
     16	 * sched_getaffinity doesn't like masks smaller than the kernel.
     17	 * Hopefully that's big enough.
     18	 */
     19	if (sz < 4096)
     20		sz = 4096;
     21	return sz / 8;
     22}
     23
     24int affinity__setup(struct affinity *a)
     25{
     26	int cpu_set_size = get_cpu_set_size();
     27
     28	a->orig_cpus = bitmap_zalloc(cpu_set_size * 8);
     29	if (!a->orig_cpus)
     30		return -1;
     31	sched_getaffinity(0, cpu_set_size, (cpu_set_t *)a->orig_cpus);
     32	a->sched_cpus = bitmap_zalloc(cpu_set_size * 8);
     33	if (!a->sched_cpus) {
     34		zfree(&a->orig_cpus);
     35		return -1;
     36	}
     37	bitmap_zero((unsigned long *)a->sched_cpus, cpu_set_size);
     38	a->changed = false;
     39	return 0;
     40}
     41
     42/*
     43 * perf_event_open does an IPI internally to the target CPU.
     44 * It is more efficient to change perf's affinity to the target
     45 * CPU and then set up all events on that CPU, so we amortize
     46 * CPU communication.
     47 */
     48void affinity__set(struct affinity *a, int cpu)
     49{
     50	int cpu_set_size = get_cpu_set_size();
     51
     52	if (cpu == -1)
     53		return;
     54	a->changed = true;
     55	set_bit(cpu, a->sched_cpus);
     56	/*
     57	 * We ignore errors because affinity is just an optimization.
     58	 * This could happen for example with isolated CPUs or cpusets.
     59	 * In this case the IPIs inside the kernel's perf API still work.
     60	 */
     61	sched_setaffinity(0, cpu_set_size, (cpu_set_t *)a->sched_cpus);
     62	clear_bit(cpu, a->sched_cpus);
     63}
     64
     65static void __affinity__cleanup(struct affinity *a)
     66{
     67	int cpu_set_size = get_cpu_set_size();
     68
     69	if (a->changed)
     70		sched_setaffinity(0, cpu_set_size, (cpu_set_t *)a->orig_cpus);
     71	zfree(&a->sched_cpus);
     72	zfree(&a->orig_cpus);
     73}
     74
     75void affinity__cleanup(struct affinity *a)
     76{
     77	if (a != NULL)
     78		__affinity__cleanup(a);
     79}