summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4v/sys/ldc.h
blob: 47f50499a9afa0c433c0e7f4363277d9ca0818fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef _LDC_H
#define	_LDC_H

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/types.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/ioctl.h>
#include <sys/processor.h>
#include <sys/ontrap.h>

/* Types */
typedef uint64_t ldc_handle_t;		/* Channel handle */
typedef uint64_t ldc_mem_handle_t;	/* Channel memory handle */
typedef uint64_t ldc_dring_handle_t;	/* Descriptor ring handle */

/* LDC transport mode */
typedef enum {
	LDC_MODE_RAW,			/* Raw mode */
	LDC_MODE_UNRELIABLE,		/* Unreliable packet mode */
	_LDC_MODE_RESERVED_,		/* reserved */
	LDC_MODE_RELIABLE		/* Reliable packet mode */
} ldc_mode_t;

/* LDC message payload sizes */
#define	LDC_ELEM_SIZE			8		/* size in bytes */
#define	LDC_PACKET_SIZE			(LDC_ELEM_SIZE * 8)
#define	LDC_PAYLOAD_SIZE_RAW		(LDC_PACKET_SIZE)
#define	LDC_PAYLOAD_SIZE_UNRELIABLE	(LDC_PACKET_SIZE - LDC_ELEM_SIZE)
#define	LDC_PAYLOAD_SIZE_RELIABLE	(LDC_PACKET_SIZE - (LDC_ELEM_SIZE * 2))

/* LDC Channel Status */
typedef enum {
	LDC_INIT = 1,			/* Channel initialized */
	LDC_OPEN,			/* Channel open */
	LDC_READY,			/* Channel peer opened (hw-link-up) */
	LDC_UP				/* Channel UP - ready for data xfer */
} ldc_status_t;

/* Callback return values */
#define	LDC_SUCCESS	0
#define	LDC_FAILURE	1

/* LDC callback mode */
typedef enum {
	LDC_CB_ENABLE,			/* Enable callbacks */
	LDC_CB_DISABLE			/* Disable callbacks */
} ldc_cb_mode_t;

/* Callback events */
#define	LDC_EVT_DOWN		0x1	/* Channel DOWN, status = OPEN */
#define	LDC_EVT_RESET		0x2	/* Channel RESET, status = READY */
#define	LDC_EVT_UP		0x4	/* Channel UP, status = UP */
#define	LDC_EVT_READ		0x8	/* Channel has data for read */
#define	LDC_EVT_WRITE		0x10	/* Channel has space for write */

/* LDC device classes */
typedef enum {
	LDC_DEV_GENERIC = 1,		/* generic device */
	LDC_DEV_BLK,			/* block device, eg. vdc */
	LDC_DEV_BLK_SVC,		/* block device service, eg. vds */
	LDC_DEV_NT,			/* network device, eg. vnet */
	LDC_DEV_NT_SVC,			/* network service eg. vsw */
	LDC_DEV_SERIAL			/* serial device eg. vldc, vcc */
} ldc_dev_t;

/* Channel nexus registration */
typedef struct ldc_cnex {
	dev_info_t	*dip;		/* dip of channel nexus */
	int		(*reg_chan)();	/* interface for channel register */
	int		(*unreg_chan)(); /* interface for channel unregister */
	int		(*add_intr)();	/* interface for adding interrupts */
	int		(*rem_intr)();	/* interface for removing interrupts */
	int		(*clr_intr)();	/* interface for clearing interrupts */
} ldc_cnex_t;

/* LDC attribute structure */
typedef struct ldc_attr {
	ldc_dev_t	devclass;	/* device class */
	uint64_t	instance;	/* device class instance */
	ldc_mode_t	mode;		/* channel mode */
	uint64_t	mtu;		/* channel mtu */
} ldc_attr_t;

/* LDC memory cookie */
typedef struct ldc_mem_cookie {
	uint64_t	addr;		/* cookie address */
	uint64_t	size;		/* size @ offset */
} ldc_mem_cookie_t;

/*
 * LDC Memory Map Type
 * Specifies how shared memory being created is shared with its
 * peer and/or how the peer has mapped in the exported memory.
 */
#define	LDC_SHADOW_MAP		0x1	/* share mem via shadow copy only */
#define	LDC_DIRECT_MAP		0x2	/* share mem direct access */
#define	LDC_IO_MAP		0x4	/* share mem for IOMMU/DMA access */

/*
 * Default mapin size supported with legacy f/w.
 */
#define	LDC_DIRECT_MAP_SIZE_DEFAULT	(64 * 1024 * 1024)

/* LDC Memory Access Permissions  */
#define	LDC_MEM_R		0x1	/* Memory region is read only */
#define	LDC_MEM_W		0x2	/* Memory region is write only */
#define	LDC_MEM_X		0x4	/* Memory region is execute only */
#define	LDC_MEM_RW		(LDC_MEM_R|LDC_MEM_W)
#define	LDC_MEM_RWX		(LDC_MEM_R|LDC_MEM_W|LDC_MEM_X)

/* LDC Memory Copy Direction */
#define	LDC_COPY_IN		0x0	/* Copy data to VA from cookie mem */
#define	LDC_COPY_OUT		0x1	/* Copy data from VA to cookie mem */

/* LDC memory/dring (handle) status */
typedef enum {
	LDC_UNBOUND,			/* Memory handle is unbound */
	LDC_BOUND,			/* Memory handle is bound */
	LDC_MAPPED			/* Memory handle is mapped */
} ldc_mstatus_t;

/* LDC [dring] memory info */
typedef struct ldc_mem_info {
	uint8_t		mtype;		/* map type */
	uint8_t		perm;		/* RWX permissions */
	caddr_t		vaddr;		/* base VA */
	uintptr_t	raddr;		/* base RA */
	ldc_mstatus_t	status;		/* dring/mem handle status */
} ldc_mem_info_t;

/* LDC channel info */
typedef struct ldc_info {
	uint64_t direct_map_size_max;	/* Max direct mapin space size */
} ldc_info_t;

/* API functions */
int ldc_register(ldc_cnex_t *cinfo);
int ldc_unregister(ldc_cnex_t *cinfo);

int ldc_init(uint64_t id, ldc_attr_t *attr, ldc_handle_t *handle);
int ldc_fini(ldc_handle_t handle);
int ldc_open(ldc_handle_t handle);
int ldc_close(ldc_handle_t handle);
int ldc_up(ldc_handle_t handle);
int ldc_down(ldc_handle_t handle);
int ldc_reg_callback(ldc_handle_t handle,
    uint_t(*callback)(uint64_t event, caddr_t arg), caddr_t arg);
int ldc_unreg_callback(ldc_handle_t handle);
int ldc_set_cb_mode(ldc_handle_t handle, ldc_cb_mode_t imode);
int ldc_chkq(ldc_handle_t handle, boolean_t *hasdata);
int ldc_read(ldc_handle_t handle, caddr_t buf, size_t *size);
int ldc_write(ldc_handle_t handle, caddr_t buf, size_t *size);
int ldc_status(ldc_handle_t handle, ldc_status_t *status);

int ldc_mem_alloc_handle(ldc_handle_t handle, ldc_mem_handle_t *mhandle);
int ldc_mem_free_handle(ldc_mem_handle_t mhandle);
int ldc_mem_bind_handle(ldc_mem_handle_t mhandle, caddr_t vaddr, size_t len,
    uint8_t mtype, uint8_t perm, ldc_mem_cookie_t *cookie, uint32_t *ccount);
int ldc_mem_unbind_handle(ldc_mem_handle_t mhandle);
int ldc_mem_info(ldc_mem_handle_t mhandle, ldc_mem_info_t *minfo);
int ldc_mem_nextcookie(ldc_mem_handle_t mhandle, ldc_mem_cookie_t *cookie);
int ldc_mem_copy(ldc_handle_t handle, caddr_t vaddr, uint64_t off, size_t *len,
    ldc_mem_cookie_t *cookies, uint32_t ccount, uint8_t direction);
int ldc_mem_rdwr_cookie(ldc_handle_t handle, caddr_t vaddr, size_t *size,
    caddr_t paddr, uint8_t  direction);
int ldc_mem_map(ldc_mem_handle_t mhandle, ldc_mem_cookie_t *cookie,
    uint32_t ccount, uint8_t mtype, uint8_t perm, caddr_t *vaddr,
    caddr_t *raddr);
int ldc_mem_unmap(ldc_mem_handle_t mhandle);
int ldc_mem_acquire(ldc_mem_handle_t mhandle, uint64_t offset, uint64_t size);
int ldc_mem_release(ldc_mem_handle_t mhandle, uint64_t offset, uint64_t size);

int ldc_mem_dring_create(uint32_t len, uint32_t dsize,
    ldc_dring_handle_t *dhandle);
int ldc_mem_dring_destroy(ldc_dring_handle_t dhandle);
int ldc_mem_dring_bind(ldc_handle_t handle, ldc_dring_handle_t dhandle,
    uint8_t mtype, uint8_t perm, ldc_mem_cookie_t *dcookie, uint32_t *ccount);
int ldc_mem_dring_nextcookie(ldc_dring_handle_t mhandle,
    ldc_mem_cookie_t *cookie);
int ldc_mem_dring_unbind(ldc_dring_handle_t dhandle);
int ldc_mem_dring_info(ldc_dring_handle_t dhandle, ldc_mem_info_t *minfo);
int ldc_mem_dring_map(ldc_handle_t handle, ldc_mem_cookie_t *cookie,
    uint32_t ccount, uint32_t len, uint32_t dsize, uint8_t mtype,
    ldc_dring_handle_t *dhandle);
int ldc_mem_dring_unmap(ldc_dring_handle_t dhandle);
int ldc_mem_dring_acquire(ldc_dring_handle_t dhandle, uint64_t start,
    uint64_t end);
int ldc_mem_dring_release(ldc_dring_handle_t dhandle, uint64_t start,
    uint64_t end);
int ldc_info(ldc_handle_t handle, ldc_info_t *info);

/*
 * Shared Memory (Direct Map) Acquire and Release API
 *
 * LDC_ON_TRAP and LDC_NO_TRAP provide on_trap protection for clients accessing
 * imported LDC_DIRECT_MAP'd shared memory segments. Use of these macros is
 * analogous to the ldc_mem_acquire/release and ldc_mem_dring_acquire/release
 * interfaces for LDC_SHADOW_MAP'd segments. After LDC_ON_TRAP is called,
 * unless an error is returned, LDC_NO_TRAP must be called.
 *
 * LDC_ON_TRAP returns zero on success and EACCES if a data access exception
 * occurs after enabling protection, but before it is disabled. If EACCES is
 * returned, the caller must not call LDC_NO_TRAP. In order to handle the
 * EACCES error return, callers should take the same precautions that apply
 * when calling on_trap() when calling LDC_ON_TRAP.
 *
 * LDC_ON_TRAP is implemented as a macro so that on_trap protection can be
 * enabled without first executing a save instruction and obtaining a new
 * register window. Aside from LDC clients calling on_trap() directly, one
 * alternative approach is to implement the LDC_ON_TRAP function in assembly
 * language without a save instruction and to then call on_trap() as a tail
 * call.
 */
#define	LDC_ON_TRAP(otd)					\
	(on_trap((otd), OT_DATA_ACCESS) != 0 ?			\
	(no_trap(), EACCES) : 0)

#define	LDC_NO_TRAP()						\
	(no_trap(), 0)

#ifdef __cplusplus
}
#endif

#endif /* _LDC_H */