xref: /illumos-gate/usr/src/uts/sun4v/sys/ds_impl.h (revision 1a220b56b93ff1dc80855691548503117af4cc10)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _DS_IMPL_H
28 #define	_DS_IMPL_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 /*
37  * The Domain Services Protocol
38  *
39  * The DS protocol is divided into two parts. The first is fixed and
40  * must remain exactly the same for *all* versions of the DS protocol.
41  * The only messages supported by the fixed portion of the protocol are
42  * to negotiate a version to use for the rest of the protocol.
43  */
44 
45 /*
46  * Domain Services Header
47  */
48 typedef struct ds_hdr {
49 	uint32_t	msg_type;	/* message type */
50 	uint32_t	payload_len;	/* payload length */
51 } ds_hdr_t;
52 
53 #define	DS_HDR_SZ	(sizeof (ds_hdr_t))
54 
55 /*
56  * DS Fixed Message Types
57  */
58 #define	DS_INIT_REQ		0x0	/* initiate DS connection */
59 #define	DS_INIT_ACK		0x1	/* initiation acknowledgement */
60 #define	DS_INIT_NACK		0x2	/* initiation negative acknowledgment */
61 
62 /*
63  * DS Fixed Initialization Messages
64  */
65 typedef struct ds_init_req {
66 	uint16_t	major_vers;	/* requested major version */
67 	uint16_t	minor_vers;	/* requested minor version */
68 } ds_init_req_t;
69 
70 typedef struct ds_init_ack {
71 	uint16_t	minor_vers;	/* highest supported minor version */
72 } ds_init_ack_t;
73 
74 typedef struct ds_init_nack {
75 	uint16_t	major_vers;	/* alternate supported major version */
76 } ds_init_nack_t;
77 
78 /*
79  * DS Message Types for Version 1.0
80  */
81 #define	DS_REG_REQ		0x3	/* register a service */
82 #define	DS_REG_ACK		0x4	/* register acknowledgement */
83 #define	DS_REG_NACK		0x5	/* register failed */
84 #define	DS_UNREG		0x6	/* unregister a service */
85 #define	DS_UNREG_ACK		0x7	/* unregister acknowledgement */
86 #define	DS_UNREG_NACK		0x8	/* unregister failed */
87 #define	DS_DATA			0x9	/* data message */
88 #define	DS_NACK			0xa	/* data error */
89 
90 /* result codes */
91 #define	DS_OK			0x0	/* success */
92 #define	DS_REG_VER_NACK		0x1	/* unsupported major version */
93 #define	DS_REG_DUP		0x2	/* duplicate registration attempted */
94 #define	DS_INV_HDL		0x3	/* service handle not valid */
95 #define	DS_TYPE_UNKNOWN		0x4	/* unknown message type received */
96 
97 /*
98  * Service Register Messages
99  */
100 typedef struct ds_reg_req {
101 	uint64_t	svc_handle;	/* service handle to register */
102 	uint16_t	major_vers;	/* requested major version */
103 	uint16_t	minor_vers;	/* requested minor version */
104 	char		svc_id[1];	/* service identifier string */
105 } ds_reg_req_t;
106 
107 typedef struct ds_reg_ack {
108 	uint64_t	svc_handle;	/* service handle sent in register */
109 	uint16_t	minor_vers;	/* highest supported minor version */
110 } ds_reg_ack_t;
111 
112 typedef struct ds_reg_nack {
113 	uint64_t	svc_handle;	/* service handle sent in register */
114 	uint64_t	result;		/* reason for the failure */
115 	uint16_t	major_vers;	/* alternate supported major version */
116 } ds_reg_nack_t;
117 
118 /*
119  * Service Unregister Messages
120  */
121 typedef struct ds_unreg_req {
122 	uint64_t	svc_handle;	/* service handle to unregister */
123 } ds_unreg_req_t;
124 
125 typedef struct ds_unreg_ack {
126 	uint64_t	svc_handle;	/* service handle sent in unregister */
127 } ds_unreg_ack_t;
128 
129 typedef struct ds_unreg_nack {
130 	uint64_t	svc_handle;	/* service handle sent in unregister */
131 } ds_unreg_nack_t;
132 
133 /*
134  * Data Transfer Messages
135  */
136 typedef struct ds_data_handle {
137 	uint64_t	svc_handle;	/* service handle for data */
138 } ds_data_handle_t;
139 
140 typedef struct ds_data_nack {
141 	uint64_t	svc_handle;	/* service handle sent in data msg */
142 	uint64_t	result;		/* reason for failure */
143 } ds_data_nack_t;
144 
145 /*
146  * Message Processing Utilities
147  */
148 #define	DS_MSG_TYPE_VALID(type)		((type) <= DS_NACK)
149 #define	DS_MSG_LEN(ds_type)		(sizeof (ds_hdr_t) + sizeof (ds_type))
150 
151 
152 /*
153  * Domain Service Port
154  *
155  * A DS port is a logical representation of an LDC dedicated to
156  * communication between DS endpoints. The ds_port_t maintains state
157  * associated with a connection to a remote endpoint. This includes
158  * the state of the port, the LDC state, the current version of the
159  * DS protocol in use on the port, and other port properties.
160  *
161  * Locking: The port is protected by a single mutex. It must be held
162  *   while the port structure is being accessed and also when data is
163  *   being read or written using the port
164  */
165 typedef enum {
166 	DS_PORT_FREE,			/* port structure not in use */
167 	DS_PORT_INIT,			/* port structure created */
168 	DS_PORT_LDC_INIT,		/* ldc successfully initialized */
169 	DS_PORT_INIT_REQ,		/* initialization handshake sent */
170 	DS_PORT_READY			/* init handshake completed */
171 } ds_port_state_t;
172 
173 typedef struct ds_ldc {
174 	uint64_t	id;		/* LDC id */
175 	ldc_handle_t	hdl;		/* LDC handle */
176 	ldc_status_t	state;		/* current LDC state */
177 } ds_ldc_t;
178 
179 typedef struct ds_port {
180 	kmutex_t	lock;		/* port lock */
181 	uint64_t	id;		/* port id from MD */
182 	ds_port_state_t	state;		/* state of the port */
183 	ds_ver_t	ver;		/* DS protocol version in use */
184 	uint32_t	ver_idx;	/* index of version during handshake */
185 	ds_ldc_t	ldc;		/* LDC for this port */
186 } ds_port_t;
187 
188 /*
189  * A DS portset is a bitmap that represents a collection of DS
190  * ports. Each bit represent a particular port id. The current
191  * implementation constrains the maximum number of ports to 64.
192  */
193 typedef uint64_t ds_portset_t;
194 
195 #define	DS_MAX_PORTS			((sizeof (ds_portset_t)) * 8)
196 #define	DS_MAX_PORT_ID			(DS_MAX_PORTS - 1)
197 
198 #define	DS_PORT_SET(port)		(1UL << (port))
199 #define	DS_PORT_IN_SET(set, port)	((set) & DS_PORT_SET(port))
200 #define	DS_PORTSET_ADD(set, port)	((void)((set) |= DS_PORT_SET(port)))
201 #define	DS_PORTSET_DEL(set, port)	((void)((set) &= ~DS_PORT_SET(port)))
202 #define	DS_PORTSET_ISNULL(set)		((set) == 0)
203 #define	DS_PORTSET_DUP(set1, set2)	((void)((set1) = (set2)))
204 
205 /*
206  * LDC Information
207  */
208 #define	DS_QUEUE_LEN	128		/* LDC queue size */
209 
210 /*
211  * Machine Description Constants
212  */
213 #define	DS_MD_PORT_NAME		"domain-services-port"
214 #define	DS_MD_CHAN_NAME		"channel-endpoint"
215 
216 /*
217  * DS Services
218  *
219  * A DS Service is a mapping between a DS capability and a client
220  * of the DS framework that provides that capability. It includes
221  * information on the state of the service, the currently negotiated
222  * version of the capability specific protocol, the port that is
223  * currently in use by the capability, etc.
224  */
225 
226 typedef enum {
227 	DS_SVC_INVAL,			/* svc structure uninitialized */
228 	DS_SVC_FREE,			/* svc structure not in use */
229 	DS_SVC_INACTIVE,		/* svc not registered */
230 	DS_SVC_REG_PENDING,		/* register message sent */
231 	DS_SVC_ACTIVE			/* register message acknowledged */
232 } ds_svc_state_t;
233 
234 typedef struct ds_svc {
235 	ds_capability_t	cap;		/* capability information */
236 	ds_clnt_ops_t	ops;		/* client ops vector */
237 	ds_svc_hdl_t	hdl;		/* handle assigned by DS */
238 	ds_svc_state_t	state;		/* current service state */
239 	ds_ver_t	ver;		/* svc protocol version in use */
240 	uint_t		ver_idx;	/* index into client version array */
241 	ds_port_t	*port;		/* port for this service */
242 	ds_portset_t	avail;		/* ports available to this service */
243 } ds_svc_t;
244 
245 #define	DS_SVC_ISFREE(svc)	((svc == NULL) || (svc->state == DS_SVC_FREE))
246 
247 /*
248  * A service handle is a 64 bit value with two pieces of information
249  * encoded in it. The upper 32 bits is the index into the table of
250  * a particular service structure. The lower 32 bits is a counter
251  * that is incremented each time a service structure is reused.
252  */
253 #define	DS_IDX_SHIFT			32
254 #define	DS_COUNT_MASK			0xfffffffful
255 
256 #define	DS_ALLOC_HDL(_idx, _count)	(((uint64_t)_idx << DS_IDX_SHIFT) | \
257 					((uint64_t)(_count + 1) &	    \
258 					DS_COUNT_MASK))
259 #define	DS_HDL2IDX(hdl)			(hdl >> DS_IDX_SHIFT)
260 #define	DS_HDL2COUNT(hdl)		(hdl & DS_COUNT_MASK)
261 
262 /*
263  * DS Message Logging
264  *
265  * The DS framework logs all incoming and outgoing messages to a
266  * ring buffer. This provides the ability to reconstruct a trace
267  * of DS activity for use in debugging. In addition to the message
268  * data, each log entry contains a timestamp and the destination
269  * of the message. The destination is based on the port number the
270  * message passed through (port number + 1). The sign of the dest
271  * field distinguishes incoming messages from outgoing messages.
272  * Incoming messages have a negative destination field.
273  */
274 
275 typedef struct ds_log_entry {
276 	struct ds_log_entry	*next;		/* next in log or free list */
277 	struct ds_log_entry	*prev;		/* previous in log */
278 	time_t			timestamp;	/* time message added to log */
279 	size_t			datasz;		/* size of the data */
280 	void			*data;		/* the data itself */
281 	int32_t			dest;		/* message destination */
282 } ds_log_entry_t;
283 
284 #define	DS_LOG_IN(pid)		(-(pid + 1))
285 #define	DS_LOG_OUT(pid)		(pid + 1)
286 
287 /*
288  * DS Log Limits:
289  *
290  * The size of the log is controlled by two limits. The first is
291  * a soft limit that is configurable by the user (via the global
292  * variable ds_log_sz). When this limit is exceeded, each new
293  * message that is added to the log replaces the oldest message.
294  *
295  * The second is a hard limit that is calculated based on the soft
296  * limit (DS_LOG_LIMIT). It is defined to be ~3% above the soft limit.
297  * Once this limit is exceeded, a thread is scheduled to delete old
298  * messages until the size of the log is below the soft limit.
299  */
300 #define	DS_LOG_DEFAULT_SZ	(128 * 1024)	/* 128 KB */
301 
302 #define	DS_LOG_LIMIT		(ds_log_sz + (ds_log_sz >> 5))
303 
304 #define	DS_LOG_ENTRY_SZ(ep)	(sizeof (ds_log_entry_t) + (ep)->datasz)
305 
306 /*
307  * DS Log Memory Usage:
308  *
309  * The log free list is initialized from a pre-allocated pool of entry
310  * structures (the global ds_log_entry_pool). The number of entries
311  * in the pool (DS_LOG_NPOOL) is the number of entries that would
312  * take up half the default size of the log.
313  *
314  * As messages are added to the log, entry structures are pulled from
315  * the free list. If the free list is empty, memory is allocated for
316  * the entry. When entries are removed from the log, they are placed
317  * on the free list. Allocated memory is only deallocated when the
318  * entire log is destroyed.
319  */
320 #define	DS_LOG_NPOOL		((DS_LOG_DEFAULT_SZ >> 1) / \
321 				sizeof (ds_log_entry_t))
322 
323 #define	DS_LOG_POOL_END		(ds_log_entry_pool + DS_LOG_NPOOL)
324 
325 #define	DS_IS_POOL_ENTRY(ep)	(((ep) >= ds_log_entry_pool) && \
326 				((ep) <= &(ds_log_entry_pool[DS_LOG_NPOOL])))
327 
328 #ifdef __cplusplus
329 }
330 #endif
331 
332 #endif /* _DS_IMPL_H */
333