xref: /freebsd/sys/arm64/spe/arm_spe_dev.h (revision 68f185ccc9f8f9498d536f4737d888b37cf11882)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2024 Arm Ltd
5  * Copyright (c) 2022 The FreeBSD Foundation
6  *
7  * Portions of this software were developed by Andrew Turner under sponsorship
8  * from the FreeBSD Foundation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #ifndef _ARM64_ARM_SPE_DEV_H_
33 #define _ARM64_ARM_SPE_DEV_H_
34 
35 #include <sys/mutex.h>
36 #include <sys/taskqueue.h>
37 
38 #include <vm/vm.h>
39 
40 #include <arm64/spe/arm_spe.h>
41 
42 #include <dev/hwt/hwt_context.h>
43 
44 #define        ARM_SPE_DEBUG
45 #undef ARM_SPE_DEBUG
46 
47 #ifdef ARM_SPE_DEBUG
48 #define		dprintf(fmt, ...)	printf(fmt, ##__VA_ARGS__)
49 #else
50 #define		dprintf(fmt, ...)
51 #endif
52 
53 DECLARE_CLASS(arm_spe_driver);
54 
55 struct cdev;
56 struct resource;
57 
58 extern bool arm64_pid_in_contextidr;
59 
60 int spe_register(device_t dev);
61 void arm_spe_disable(void *arg __unused);
62 int spe_backend_disable_smp(struct hwt_context *ctx);
63 void arm_spe_send_buffer(void *arg, int pending __unused);
64 
65 /*
66   PSB CSYNC is a Profiling Synchronization Barrier encoded in the hint space
67  * so it is a NOP on earlier architecture.
68  */
69 #define		psb_csync()	__asm __volatile("hint #17" ::: "memory");
70 
71 struct arm_spe_softc {
72 	device_t                dev;
73 
74 	struct resource         *sc_irq_res;
75 	void                    *sc_irq_cookie;
76 	struct cdev             *sc_cdev;
77 	struct mtx              sc_lock;
78 	struct task             task;
79 
80 	int64_t                sc_pmsidr;
81 	int                     kqueue_fd;
82 	struct thread           *hwt_td;
83 	struct arm_spe_info     *spe_info;
84 	struct hwt_context      *ctx;
85 	STAILQ_HEAD(, arm_spe_queue) pending;
86 	uint64_t                npending;
87 
88 	uint64_t                pmbidr;
89 	uint64_t                pmsidr;
90 
91 	uint16_t                kva_align;
92 };
93 
94 struct arm_spe_buf_info {
95 	struct arm_spe_info     *info;
96 	uint64_t                pmbptr;
97 	uint8_t                 buf_idx : 1;
98 	bool                    buf_svc : 1;
99 	bool                    buf_wait : 1;
100 	bool                    partial_rec : 1;
101 };
102 
103 struct arm_spe_info {
104 	int                     ident; /* tid or cpu_id */
105 	struct mtx              lock;
106 	struct arm_spe_softc    *sc;
107 	struct task             task[2];
108 	bool                    enabled : 1;
109 
110 	/* buffer is split in half as a ping-pong buffer */
111 	vm_object_t             bufobj;
112 	vm_offset_t             kvaddr;
113 	size_t                  buf_size;
114 	uint8_t                 buf_idx : 1; /* 0 = first half of buf, 1 = 2nd half */
115 	struct arm_spe_buf_info buf_info[2];
116 
117 	/* config */
118 	enum arm_spe_profiling_level level;
119 	enum arm_spe_ctx_field  ctx_field;
120 	/* filters */
121 	uint64_t                pmsfcr;
122 	uint64_t                pmsevfr;
123 	uint64_t                pmslatfr;
124 	/* interval */
125 	uint64_t                pmsirr;
126 	uint64_t                pmsicr;
127 	/* control */
128 	uint64_t                pmscr;
129 };
130 
131 struct arm_spe_queue {
132 	int             ident;
133 	u_int           buf_idx  : 1;
134 	bool            partial_rec : 1;
135 	bool            final_buf : 1;
136 	vm_offset_t     offset;
137 	STAILQ_ENTRY(arm_spe_queue) next;
138 };
139 
buf_start_addr(u_int buf_idx,struct arm_spe_info * info)140 static inline vm_offset_t buf_start_addr(u_int buf_idx, struct arm_spe_info *info)
141 {
142 	vm_offset_t addr;
143 	if (buf_idx == 0)
144 		addr = info->kvaddr;
145 	if (buf_idx == 1)
146 	addr = info->kvaddr + (info->buf_size/2);
147 
148 	return (addr);
149 }
150 
buf_end_addr(u_int buf_idx,struct arm_spe_info * info)151 static inline vm_offset_t buf_end_addr(u_int buf_idx, struct arm_spe_info *info)
152 {
153 	vm_offset_t addr;
154 	if (buf_idx == 0)
155 		addr = info->kvaddr + (info->buf_size/2);
156 	if (buf_idx == 1)
157 		addr = info->kvaddr + info->buf_size;
158 
159 	return (addr);
160 }
161 
162 #endif /* _ARM64_ARM_SPE_DEV_H_ */
163