258 lines
9.8 KiB
C
258 lines
9.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
/*
|
|
*
|
|
* (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
|
|
*
|
|
* This program is free software and is provided to you under the terms of the
|
|
* GNU General Public License version 2 as published by the Free Software
|
|
* Foundation, and any use by you of this program is subject to the terms
|
|
* of such GNU license.
|
|
*
|
|
* 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, you can access it online at
|
|
* http://www.gnu.org/licenses/gpl-2.0.html.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* mali_kbase_kinstr_jm.h
|
|
* Kernel driver public interface to job manager atom tracing. This API provides
|
|
* a method to get the atom state changes into user space.
|
|
*
|
|
* The flow of operation is:
|
|
*
|
|
* | kernel | user |
|
|
* | ----------------------------------- | ----------------------------------- |
|
|
* | Initialize API with | |
|
|
* | kbase_kinstr_jm_init() | |
|
|
* | | |
|
|
* | Kernel code injects states with | |
|
|
* | kbase_kinstr_jm_atom_state_*() APIs | |
|
|
* | | Call ioctl() to get file descriptor |
|
|
* | | via KBASE_IOCTL_KINSTR_JM_FD |
|
|
* | Allocates a reader attached to FD | |
|
|
* | Allocates circular buffer and | |
|
|
* | patches, via ASM goto, the | |
|
|
* | kbase_kinstr_jm_atom_state_*() | |
|
|
* | | loop: |
|
|
* | | Call poll() on FD for POLLIN |
|
|
* | When threshold of changes is hit, | |
|
|
* | the poll is interrupted with | |
|
|
* | POLLIN. If circular buffer is | |
|
|
* | full then store the missed count | |
|
|
* | and interrupt poll | Call read() to get data from |
|
|
* | | circular buffer via the fd |
|
|
* | Kernel advances tail of circular | |
|
|
* | buffer | |
|
|
* | | Close file descriptor |
|
|
* | Deallocates circular buffer | |
|
|
* | | |
|
|
* | Terminate API with | |
|
|
* | kbase_kinstr_jm_term() | |
|
|
*
|
|
* All tracepoints are guarded on a static key. The static key is activated when
|
|
* a user space reader gets created. This means that there is negligible cost
|
|
* inserting the tracepoints into code when there are no readers.
|
|
*/
|
|
|
|
#ifndef _KBASE_KINSTR_JM_H_
|
|
#define _KBASE_KINSTR_JM_H_
|
|
|
|
#include <uapi/gpu/arm/bifrost/mali_kbase_kinstr_jm_reader.h>
|
|
|
|
#ifdef __KERNEL__
|
|
#include <linux/version.h>
|
|
#include <linux/static_key.h>
|
|
#else
|
|
/* empty wrapper macros for userspace */
|
|
#define static_branch_unlikely(key) (1)
|
|
#endif /* __KERNEL__ */
|
|
|
|
/* Forward declarations */
|
|
struct kbase_context;
|
|
struct kbase_kinstr_jm;
|
|
struct kbase_jd_atom;
|
|
union kbase_kinstr_jm_fd;
|
|
|
|
/**
|
|
* kbase_kinstr_jm_init() - Initialise an instrumentation job manager context.
|
|
* @ctx: Non-NULL pointer to where the pointer to the created context will
|
|
* be stored on success.
|
|
*
|
|
* Return: 0 on success, else error code.
|
|
*/
|
|
int kbase_kinstr_jm_init(struct kbase_kinstr_jm **ctx);
|
|
|
|
/**
|
|
* kbase_kinstr_jm_term() - Terminate an instrumentation job manager context.
|
|
* @ctx: Pointer to context to be terminated.
|
|
*/
|
|
void kbase_kinstr_jm_term(struct kbase_kinstr_jm *ctx);
|
|
|
|
/**
|
|
* kbase_kinstr_jm_get_fd() - Retrieves a file descriptor that can be used to
|
|
* read the atom state changes from userspace
|
|
*
|
|
* @ctx: Pointer to the initialized context
|
|
* @jm_fd_arg: Pointer to the union containing the in/out params
|
|
* Return: -1 on failure, valid file descriptor on success
|
|
*/
|
|
int kbase_kinstr_jm_get_fd(struct kbase_kinstr_jm *const ctx, union kbase_kinstr_jm_fd *jm_fd_arg);
|
|
|
|
/**
|
|
* kbasep_kinstr_jm_atom_state() - Signifies that an atom has changed state
|
|
* @atom: The atom that has changed state
|
|
* @state: The new state of the atom
|
|
*
|
|
* This performs the actual storage of the state ready for user space to
|
|
* read the data. It is only called when the static key is enabled from
|
|
* kbase_kinstr_jm_atom_state(). There is almost never a need to invoke this
|
|
* function directly.
|
|
*/
|
|
void kbasep_kinstr_jm_atom_state(struct kbase_jd_atom *const atom,
|
|
const enum kbase_kinstr_jm_reader_atom_state state);
|
|
|
|
/* Allows ASM goto patching to reduce tracing overhead. This is
|
|
* incremented/decremented when readers are created and terminated. This really
|
|
* shouldn't be changed externally, but if you do, make sure you use
|
|
* a static_key_inc()/static_key_dec() pair.
|
|
*/
|
|
extern struct static_key_false basep_kinstr_jm_reader_static_key;
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_state() - Signifies that an atom has changed state
|
|
* @atom: The atom that has changed state
|
|
* @state: The new state of the atom
|
|
*
|
|
* This uses a static key to reduce overhead when tracing is disabled
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_state(struct kbase_jd_atom *const atom,
|
|
const enum kbase_kinstr_jm_reader_atom_state state)
|
|
{
|
|
if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key))
|
|
kbasep_kinstr_jm_atom_state(atom, state);
|
|
}
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_state_queue() - Signifies that an atom has entered a
|
|
* hardware or software queue.
|
|
* @atom: The atom that has changed state
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_state_queue(struct kbase_jd_atom *const atom)
|
|
{
|
|
kbase_kinstr_jm_atom_state(atom, KBASE_KINSTR_JM_READER_ATOM_STATE_QUEUE);
|
|
}
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_state_start() - Signifies that work has started on an
|
|
* atom
|
|
* @atom: The atom that has changed state
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_state_start(struct kbase_jd_atom *const atom)
|
|
{
|
|
kbase_kinstr_jm_atom_state(atom, KBASE_KINSTR_JM_READER_ATOM_STATE_START);
|
|
}
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_state_stop() - Signifies that work has stopped on an
|
|
* atom
|
|
* @atom: The atom that has changed state
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_state_stop(struct kbase_jd_atom *const atom)
|
|
{
|
|
kbase_kinstr_jm_atom_state(atom, KBASE_KINSTR_JM_READER_ATOM_STATE_STOP);
|
|
}
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_state_complete() - Signifies that all work has completed
|
|
* on an atom
|
|
* @atom: The atom that has changed state
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_state_complete(struct kbase_jd_atom *const atom)
|
|
{
|
|
kbase_kinstr_jm_atom_state(atom, KBASE_KINSTR_JM_READER_ATOM_STATE_COMPLETE);
|
|
}
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_queue() - A software *or* hardware atom is queued for
|
|
* execution
|
|
* @atom: The atom that has changed state
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_queue(struct kbase_jd_atom *const atom)
|
|
{
|
|
kbase_kinstr_jm_atom_state_queue(atom);
|
|
}
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_complete() - A software *or* hardware atom is fully
|
|
* completed
|
|
* @atom: The atom that has changed state
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_complete(struct kbase_jd_atom *const atom)
|
|
{
|
|
kbase_kinstr_jm_atom_state_complete(atom);
|
|
}
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_sw_start() - A software atom has started work
|
|
* @atom: The atom that has changed state
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_sw_start(struct kbase_jd_atom *const atom)
|
|
{
|
|
kbase_kinstr_jm_atom_state_start(atom);
|
|
}
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_sw_stop() - A software atom has stopped work
|
|
* @atom: The atom that has changed state
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_sw_stop(struct kbase_jd_atom *const atom)
|
|
{
|
|
kbase_kinstr_jm_atom_state_stop(atom);
|
|
}
|
|
|
|
/**
|
|
* kbasep_kinstr_jm_atom_hw_submit() - A hardware atom has been submitted
|
|
* @atom: The atom that has been submitted
|
|
*
|
|
* This private implementation should not be called directly, it is protected
|
|
* by a static key in kbase_kinstr_jm_atom_hw_submit(). Use that instead.
|
|
*/
|
|
void kbasep_kinstr_jm_atom_hw_submit(struct kbase_jd_atom *const atom);
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_hw_submit() - A hardware atom has been submitted
|
|
* @atom: The atom that has been submitted
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_hw_submit(struct kbase_jd_atom *const atom)
|
|
{
|
|
if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key))
|
|
kbasep_kinstr_jm_atom_hw_submit(atom);
|
|
}
|
|
|
|
/**
|
|
* kbasep_kinstr_jm_atom_hw_release() - A hardware atom has been released
|
|
* @atom: The atom that has been released
|
|
*
|
|
* This private implementation should not be called directly, it is protected
|
|
* by a static key in kbase_kinstr_jm_atom_hw_release(). Use that instead.
|
|
*/
|
|
void kbasep_kinstr_jm_atom_hw_release(struct kbase_jd_atom *const atom);
|
|
|
|
/**
|
|
* kbase_kinstr_jm_atom_hw_release() - A hardware atom has been released
|
|
* @atom: The atom that has been released
|
|
*/
|
|
static inline void kbase_kinstr_jm_atom_hw_release(struct kbase_jd_atom *const atom)
|
|
{
|
|
if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key))
|
|
kbasep_kinstr_jm_atom_hw_release(atom);
|
|
}
|
|
|
|
#endif /* _KBASE_KINSTR_JM_H_ */
|