/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2024 Arm Ltd4* Copyright (c) 2022 The FreeBSD Foundation5*6* Portions of this software were developed by Andrew Turner under sponsorship7* from the FreeBSD Foundation.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND19* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE22* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL23* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS24* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT26* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY27* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF28* SUCH DAMAGE.29*/3031#ifndef _ARM64_ARM_SPE_DEV_H_32#define _ARM64_ARM_SPE_DEV_H_3334#include <sys/mutex.h>35#include <sys/taskqueue.h>3637#include <vm/vm.h>3839#include <arm64/spe/arm_spe.h>4041#include <dev/hwt/hwt_context.h>4243#define ARM_SPE_DEBUG44#undef ARM_SPE_DEBUG4546#ifdef ARM_SPE_DEBUG47#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)48#else49#define dprintf(fmt, ...)50#endif5152DECLARE_CLASS(arm_spe_driver);5354struct cdev;55struct resource;5657extern bool arm64_pid_in_contextidr;5859int spe_register(device_t dev);60void arm_spe_disable(void *arg __unused);61int spe_backend_disable_smp(struct hwt_context *ctx);62void arm_spe_send_buffer(void *arg, int pending __unused);6364/*65PSB CSYNC is a Profiling Synchronization Barrier encoded in the hint space66* so it is a NOP on earlier architecture.67*/68#define psb_csync() __asm __volatile("hint #17" ::: "memory");6970struct arm_spe_softc {71device_t dev;7273struct resource *sc_irq_res;74void *sc_irq_cookie;75struct cdev *sc_cdev;76struct mtx sc_lock;77struct task task;7879int64_t sc_pmsidr;80int kqueue_fd;81struct thread *hwt_td;82struct arm_spe_info **spe_info;83struct hwt_context *ctx;84STAILQ_HEAD(, arm_spe_queue) pending;85uint64_t npending;8687uint64_t pmbidr;88uint64_t pmsidr;8990uint16_t kva_align;91};9293struct arm_spe_buf_info {94struct arm_spe_info *info;95uint64_t pmbptr;96uint8_t buf_idx : 1;97bool buf_svc : 1;98bool buf_wait : 1;99bool partial_rec : 1;100};101102struct arm_spe_info {103int ident; /* tid or cpu_id */104struct mtx lock;105struct arm_spe_softc *sc;106struct task task[2];107struct task flush_task;108bool enabled : 1;109bool stopped : 1;110111/* buffer is split in half as a ping-pong buffer */112vm_object_t bufobj;113vm_offset_t kvaddr;114size_t buf_size;115uint8_t buf_idx : 1; /* 0 = first half of buf, 1 = 2nd half */116struct arm_spe_buf_info buf_info[2];117118/* config */119enum arm_spe_profiling_level level;120enum arm_spe_ctx_field ctx_field;121/* filters */122uint64_t pmsfcr;123uint64_t pmsevfr;124uint64_t pmslatfr;125/* interval */126uint64_t pmsirr;127uint64_t pmsicr;128/* control */129uint64_t pmscr;130};131132struct arm_spe_queue {133int ident;134u_int buf_idx : 1;135bool partial_rec : 1;136bool final_buf : 1;137vm_offset_t offset;138STAILQ_ENTRY(arm_spe_queue) next;139};140141static inline vm_offset_t buf_start_addr(u_int buf_idx, struct arm_spe_info *info)142{143vm_offset_t addr;144if (buf_idx == 0)145addr = info->kvaddr;146if (buf_idx == 1)147addr = info->kvaddr + (info->buf_size/2);148149return (addr);150}151152static inline vm_offset_t buf_end_addr(u_int buf_idx, struct arm_spe_info *info)153{154vm_offset_t addr;155if (buf_idx == 0)156addr = info->kvaddr + (info->buf_size/2);157if (buf_idx == 1)158addr = info->kvaddr + info->buf_size;159160return (addr);161}162163#endif /* _ARM64_ARM_SPE_DEV_H_ */164165166