root/tools/perf/arch/powerpc/util/auxtrace.c
// SPDX-License-Identifier: GPL-2.0
/*
 * VPA support
 */
#include <errno.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>

#include "../../util/evlist.h"
#include "../../util/debug.h"
#include "../../util/auxtrace.h"
#include "../../util/powerpc-vpadtl.h"
#include "../../util/record.h"
#include <internal/lib.h> // page_size

#define KiB(x) ((x) * 1024)

static int
powerpc_vpadtl_recording_options(struct auxtrace_record *ar __maybe_unused,
                        struct evlist *evlist __maybe_unused,
                        struct record_opts *opts)
{
        opts->full_auxtrace = true;

        /*
         * Set auxtrace_mmap_pages to minimum
         * two pages
         */
        if (!opts->auxtrace_mmap_pages) {
                opts->auxtrace_mmap_pages = KiB(128) / page_size;
                if (opts->mmap_pages == UINT_MAX)
                        opts->mmap_pages = KiB(256) / page_size;
        }

        return 0;
}

static size_t powerpc_vpadtl_info_priv_size(struct auxtrace_record *itr __maybe_unused,
                                        struct evlist *evlist __maybe_unused)
{
        return VPADTL_AUXTRACE_PRIV_SIZE;
}

static int
powerpc_vpadtl_info_fill(struct auxtrace_record *itr __maybe_unused,
                struct perf_session *session __maybe_unused,
                struct perf_record_auxtrace_info *auxtrace_info,
                size_t priv_size __maybe_unused)
{
        auxtrace_info->type = PERF_AUXTRACE_VPA_DTL;

        return 0;
}

static void powerpc_vpadtl_free(struct auxtrace_record *itr)
{
        free(itr);
}

static u64 powerpc_vpadtl_reference(struct auxtrace_record *itr __maybe_unused)
{
        return 0;
}

struct auxtrace_record *auxtrace_record__init(struct evlist *evlist,
                                                int *err)
{
        struct auxtrace_record *aux;
        struct evsel *pos;
        int found = 0;

        evlist__for_each_entry(evlist, pos) {
                if (strstarts(pos->name, "vpa_dtl")) {
                        found = 1;
                        pos->needs_auxtrace_mmap = true;
                        break;
                }
        }

        if (!found)
                return NULL;

        /*
         * To obtain the auxtrace buffer file descriptor, the auxtrace event
         * must come first.
         */
        evlist__to_front(pos->evlist, pos);

        aux = zalloc(sizeof(*aux));
        if (aux == NULL) {
                pr_debug("aux record is NULL\n");
                *err = -ENOMEM;
                return NULL;
        }

        aux->recording_options = powerpc_vpadtl_recording_options;
        aux->info_priv_size = powerpc_vpadtl_info_priv_size;
        aux->info_fill = powerpc_vpadtl_info_fill;
        aux->free = powerpc_vpadtl_free;
        aux->reference = powerpc_vpadtl_reference;
        return aux;
}