/* bpf.c
 *
 * Copyright 2023 Ondřej Míchal
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

#include "vmlinux.h"

#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

#include "main.h"

const volatile bool has_rapl_cores = false;
const volatile bool has_rapl_pkg = false;
const volatile bool has_rapl_ram = false;
const volatile bool has_rapl_gpu = false;
const volatile bool has_rapl_psys = false;

struct {
  __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
  __uint(max_entries, 1);
  __type(key, int);
  __type(value, int);
} rapl_cores SEC(".maps");

struct {
  __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
  __uint(max_entries, 1);
  __type(key, int);
  __type(value, int);
} rapl_pkg SEC(".maps");

struct {
  __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
  __uint(max_entries, 1);
  __type(key, int);
  __type(value, int);
} rapl_ram SEC(".maps");

struct {
  __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
  __uint(max_entries, 1);
  __type(key, int);
  __type(value, int);
} rapl_gpu SEC(".maps");

struct {
  __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
  __uint(max_entries, 1);
  __type(key, int);
  __type(value, int);
} rapl_psys SEC(".maps");

struct {
  __uint(type, BPF_MAP_TYPE_RINGBUF);
  __uint(max_entries, 4096 * sizeof(data_t));
} ringbuffer SEC(".maps");

SEC("perf_event")
int collect_rapl_info(struct bpf_perf_event_data *ctx) {
  struct bpf_perf_event_value event_buf;
  data_t *data;

  return 0;

  data = bpf_ringbuf_reserve(&ringbuffer, sizeof(*data), 0);
  if (!data)
    return 1;

  data->time_ns = bpf_ktime_get_ns();
  data->rapl_cores = 0;
  data->rapl_pkg = 0;
  data->rapl_ram = 0;
  data->rapl_gpu = 0;
  data->rapl_psys = 0;

  if (has_rapl_cores) {
    bpf_perf_event_read_value(&rapl_cores, BPF_F_CURRENT_CPU, &event_buf,
                                  sizeof(struct bpf_perf_event_value));
    data->rapl_cores = event_buf.counter;
  }

  if (has_rapl_pkg) {
    bpf_perf_event_read_value(&rapl_pkg, BPF_F_CURRENT_CPU, &event_buf,
                                  sizeof(struct bpf_perf_event_value));
    data->rapl_pkg = event_buf.counter;
  }

  if (has_rapl_ram) {
    bpf_perf_event_read_value(&rapl_ram, BPF_F_CURRENT_CPU, &event_buf,
                                  sizeof(struct bpf_perf_event_value));
    data->rapl_ram = event_buf.counter;
  }

  if (has_rapl_gpu) {
    bpf_perf_event_read_value(&rapl_gpu, BPF_F_CURRENT_CPU, &event_buf,
                                  sizeof(struct bpf_perf_event_value));
    data->rapl_gpu = event_buf.counter;
  }

  if (has_rapl_psys) {
    bpf_perf_event_read_value(&rapl_psys, BPF_F_CURRENT_CPU, &event_buf,
                                  sizeof(struct bpf_perf_event_value));
    data->rapl_psys = event_buf.counter;
  }

  bpf_ringbuf_submit(data, 0);

  return 0;
}

char LICENSE[] SEC("license") = "GPL";
