1/* $OpenBSD: kstat.h,v 1.5 2024/03/26 00:53:51 dlg Exp $ */
2
3/*
4 * Copyright (c) 2020 David Gwynne <dlg@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#ifndef _SYS_KSTAT_H_
20#define _SYS_KSTAT_H_
21
22#include <sys/ioccom.h>
23
24#define KSTAT_STRLEN		32
25
26#define KSTAT_T_RAW		0
27#define KSTAT_T_KV		1
28#define KSTAT_T_COUNTERS	2
29
30struct kstat_req {
31	unsigned int		 ks_rflags;
32#define KSTATIOC_F_IGNVER		(1 << 0)
33	/* the current version of the kstat subsystem */
34	unsigned int		 ks_version;
35
36	uint64_t		 ks_id;
37
38	char			 ks_provider[KSTAT_STRLEN];
39	unsigned int		 ks_instance;
40	char			 ks_name[KSTAT_STRLEN];
41	unsigned int		 ks_unit;
42
43	struct timespec		 ks_created;
44	struct timespec		 ks_updated;
45	struct timespec		 ks_interval;
46	unsigned int		 ks_type;
47	unsigned int		 ks_state;
48
49	void			*ks_data;
50	size_t			 ks_datalen;
51	unsigned int		 ks_dataver;
52};
53
54/* ioctls */
55
56#define KSTATIOC_VERSION	_IOR('k', 1, unsigned int)
57#define KSTATIOC_FIND_ID	_IOWR('k', 2, struct kstat_req)
58#define KSTATIOC_NFIND_ID	_IOWR('k', 3, struct kstat_req)
59#define KSTATIOC_FIND_PROVIDER	_IOWR('k', 4, struct kstat_req)
60#define KSTATIOC_NFIND_PROVIDER	_IOWR('k', 5, struct kstat_req)
61#define KSTATIOC_FIND_NAME	_IOWR('k', 6, struct kstat_req)
62#define KSTATIOC_NFIND_NAME	_IOWR('k', 7, struct kstat_req)
63
64/* named data */
65
66#define KSTAT_KV_NAMELEN	16
67#define KSTAT_KV_ALIGN		sizeof(uint64_t)
68
69enum kstat_kv_type {
70	KSTAT_KV_T_NULL,
71	KSTAT_KV_T_BOOL,
72	KSTAT_KV_T_COUNTER64,
73	KSTAT_KV_T_COUNTER32,
74	KSTAT_KV_T_UINT64,
75	KSTAT_KV_T_INT64,
76	KSTAT_KV_T_UINT32,
77	KSTAT_KV_T_INT32,
78	KSTAT_KV_T_ISTR,	/* inline string */
79	KSTAT_KV_T_STR,		/* trailing string */
80	KSTAT_KV_T_BYTES,	/* trailing bytes */
81	KSTAT_KV_T_TEMP,	/* temperature (uK) */
82	KSTAT_KV_T_COUNTER16,
83	KSTAT_KV_T_UINT16,
84	KSTAT_KV_T_INT16,
85	KSTAT_KV_T_FREQ,	/* frequency (Hz) */
86	KSTAT_KV_T_VOLTS_DC,	/* voltage (uV DC) */
87	KSTAT_KV_T_VOLTS_AC,	/* voltage (uV AC) */
88	KSTAT_KV_T_AMPS,	/* current (uA) */
89	KSTAT_KV_T_WATTS,	/* power (uW) */
90};
91
92/* units only apply to integer types */
93enum kstat_kv_unit {
94	KSTAT_KV_U_NONE = 0,
95	KSTAT_KV_U_PACKETS,	/* packets */
96	KSTAT_KV_U_BYTES,	/* bytes */
97	KSTAT_KV_U_CYCLES,	/* cycles */
98};
99
100struct kstat_kv {
101	char			 kv_key[KSTAT_KV_NAMELEN];
102	union {
103		char			v_istr[16];
104		unsigned int		v_bool;
105		uint64_t		v_u64;
106		int64_t			v_s64;
107		uint32_t		v_u32;
108		int32_t			v_s32;
109		uint16_t		v_u16;
110		int16_t			v_s16;
111		size_t			v_len;
112	}			 kv_v;
113	enum kstat_kv_type	 kv_type;
114	enum kstat_kv_unit	 kv_unit;
115} __aligned(KSTAT_KV_ALIGN);
116
117#define kstat_kv_istr(_kv)	(_kv)->kv_v.v_istr
118#define kstat_kv_bool(_kv)	(_kv)->kv_v.v_bool
119#define kstat_kv_u64(_kv)	(_kv)->kv_v.v_u64
120#define kstat_kv_s64(_kv)	(_kv)->kv_v.v_s64
121#define kstat_kv_u32(_kv)	(_kv)->kv_v.v_u32
122#define kstat_kv_s32(_kv)	(_kv)->kv_v.v_s32
123#define kstat_kv_u16(_kv)	(_kv)->kv_v.v_u16
124#define kstat_kv_s16(_kv)	(_kv)->kv_v.v_s16
125#define kstat_kv_len(_kv)	(_kv)->kv_v.v_len
126#define kstat_kv_temp(_kv)	(_kv)->kv_v.v_u64
127#define kstat_kv_freq(_kv)	(_kv)->kv_v.v_u64
128#define kstat_kv_volts(_kv)	(_kv)->kv_v.v_u64
129#define kstat_kv_amps(_kv)	(_kv)->kv_v.v_u64
130#define kstat_kv_watts(_kv)	(_kv)->kv_v.v_u64
131
132#ifdef _KERNEL
133
134#include <sys/tree.h>
135
136struct kstat_lock_ops;
137
138struct kstat {
139	uint64_t		  ks_id;
140
141	const char		 *ks_provider;
142	unsigned int		  ks_instance;
143	const char		 *ks_name;
144	unsigned int		  ks_unit;
145
146	unsigned int		  ks_type;
147	unsigned int		  ks_flags;
148#define KSTAT_F_REALLOC			(1 << 0)
149	unsigned int		  ks_state;
150#define KSTAT_S_CREATED			0
151#define KSTAT_S_INSTALLED		1
152
153	struct timespec		  ks_created;
154	RBT_ENTRY(kstat)	  ks_id_entry;
155	RBT_ENTRY(kstat)	  ks_pv_entry;
156	RBT_ENTRY(kstat)	  ks_nm_entry;
157
158	/* the driver can update these between kstat creation and install */
159	unsigned int		  ks_dataver;
160	void			 *ks_softc;
161	void			 *ks_ptr;
162	int			(*ks_read)(struct kstat *);
163	int			(*ks_copy)(struct kstat *, void *);
164
165	const struct kstat_lock_ops *
166				  ks_lock_ops;
167	void			 *ks_lock;
168
169	/* the data that is updated by ks_read */
170	void			 *ks_data;
171	size_t			  ks_datalen;
172	struct timespec		  ks_updated;
173	struct timespec		  ks_interval;
174};
175
176struct kstat	*kstat_create(const char *, unsigned int,
177		     const char *, unsigned int,
178		     unsigned int, unsigned int);
179
180void		 kstat_set_rlock(struct kstat *, struct rwlock *);
181void		 kstat_set_wlock(struct kstat *, struct rwlock *);
182void		 kstat_set_mutex(struct kstat *, struct mutex *);
183void		 kstat_set_cpu(struct kstat *, struct cpu_info *);
184
185int		 kstat_read_nop(struct kstat *);
186
187void		 kstat_install(struct kstat *);
188void		 kstat_remove(struct kstat *);
189void		 kstat_destroy(struct kstat *);
190
191/*
192 * kstat_kv api
193 */
194
195#define KSTAT_KV_UNIT_INITIALIZER(_key, _type, _unit) {	\
196	.kv_key = (_key),				\
197	.kv_type = (_type),				\
198	.kv_unit = (_unit),				\
199}
200
201#define KSTAT_KV_INITIALIZER(_key, _type)		\
202    KSTAT_KV_UNIT_INITIALIZER((_key), (_type), KSTAT_KV_U_NONE)
203
204void	kstat_kv_init(struct kstat_kv *, const char *, enum kstat_kv_type);
205void	kstat_kv_unit_init(struct kstat_kv *, const char *,
206	    enum kstat_kv_type, enum kstat_kv_unit);
207
208#endif /* _KERNEL */
209
210#endif /* _SYS_KSTAT_H_ */
211