summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4v/sys/n2cp.h
blob: 5c67b46e6f61b706d6cf801abe186b960c5d637d (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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
/*
 * 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 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_N2CP_H
#define	_SYS_N2CP_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <sys/types.h>
#include <sys/kmem.h>
#include <sys/mdesc.h>
#include <sys/crypto/common.h>
#include <sys/crypto/spi.h>
#include <sys/ncs.h>

#ifdef	__cplusplus
extern "C" {
#endif

#define	DRIVER			"n2cp"
#define	N2CP_MANUFACTURER_ID	"SUNWn2cp"

#if defined(_KERNEL)

#define	FALSE		0
#define	TRUE		1

#define	BITS2BYTES(b)	((b) >> 3)
#define	BYTES2BITS(b)	((b) << 3)

#define	N_MBLKL(mp)	((uint64_t)(mp)->b_wptr - (uint64_t)(mp)->b_rptr)

/*
 * N2CP Structures.
 */
typedef struct n2cp n2cp_t;
typedef struct n2cp_minor n2cp_minor_t;
typedef struct n2cp_listnode n2cp_listnode_t;
typedef struct n2cp_request n2cp_request_t;
typedef struct n2cp_stat n2cp_stat_t;
typedef	struct n2cp_block_ctx n2cp_block_ctx_t;
typedef	struct n2cp_hash_ctx n2cp_hash_ctx_t;
typedef	struct n2cp_hmac_ctx n2cp_hmac_ctx_t;

/*
 * Linked-list linkage.
 */
struct n2cp_listnode {
	n2cp_listnode_t *nl_next;
	n2cp_listnode_t *nl_prev;
};

#define	N2CP_MODE_STRING	"n2cp-mode"

typedef enum {
	N_ASYNC,
	N_SYNC
} n2cp_mode_t;


#define	N2CP_MAX_NCWQS		32
#define	N2CP_MAX_CPUS_PER_CWQ	8
#define	N2CP_MAX_HELPERTHREADS	(N2CP_MAX_NCWQS * N2CP_MAX_CPUS_PER_CWQ)
#define	N2CP_MAX_BUF_CNT	1024

/* numbers of completion theads */
#define	NUM_COMPLETE_THREADS	1

/*
 * Device flags (n2cp_t.n_flags)
 */
#define	N2CP_FAILED		0x0000001
#define	N2CP_ATTACHED		0x0000002
#define	N2CP_REGISTERED		0x0000004
#define	N2CP_CPU_REGISTERED	0x0000008

/*
 * HW limitaions for Data and Key. For an input greater than 64KB, Driver will
 * break up the input into 64KB blocks, and send the jobs to the hardware.
 */
#define	CW_MAX_DATA_LEN		(1 << 16)	/* 64K */
#define	CW_MAX_KEY_LEN		(1 << 8)	/* 256 */

#define	CW_TYPE_INITIAL		1
#define	CW_TYPE_EXTENSION	2
#define	CW_TYPE_FINAL		3
#define	CW_TYPE_COMPLETE	4

/*
 * Defines for fields in Initial Control Word.
 */
#define	CW_OP_SSL		16
#define	CW_OP_COPY		32
#define	CW_OP_ENCRYPT		64
#define	CW_OP_MAC_AUTH		65
#define	CW_OP_INLINE_BIT	(1 << 7)

#define	CW_AUTH_MD5		1
#define	CW_AUTH_SHA1		2
#define	CW_AUTH_SHA256		3
#define	CW_AUTH_CRC32		4
#define	CW_AUTH_HMAC_MD5	5
#define	CW_AUTH_HMAC_SHA1	6
#define	CW_AUTH_HMAC_SHA256	7
#define	CW_AUTH_TCPCKSUM	8
#define	CW_AUTH_SSL_HMAC_MD5	9
#define	CW_AUTH_SSL_HMAC_SHA1	10
#define	CW_AUTH_SSL_HMAC_SHA256 11

#define	CW_ENC_ALGO_RC4WSTRM	0
#define	CW_ENC_ALGO_RC4WOSTRM	1
#define	CW_ENC_ALGO_DES		2
#define	CW_ENC_ALGO_3DES	3
#define	CW_ENC_ALGO_AES128	4
#define	CW_ENC_ALGO_AES192	5
#define	CW_ENC_ALGO_AES256	6

#define	CW_ENC_CHAIN_ECB	0
#define	CW_ENC_CHAIN_CBC	1
#define	CW_ENC_CHAIN_CFB	2
#define	CW_ENC_CHAIN_AESCTR	3

#define	CW_ENC_TYPE(a, c)	((((a) & 7) << 2) | ((c) & 3))

#define	CWQ_NENTRIES		(1 << 5)	/* 32 */
#define	CWQ_WRAPMASK		(CWQ_NENTRIES - 1)

/* CWS_ALIGNMENT is used as an alignment parameter to contig_mem_alloc */
#define	CWQ_ALIGNMENT		64
#define	CWQ_SLOTS_USED(q)	(((q)->cq_tail - (q)->cq_head) & CWQ_WRAPMASK)
#define	CWQ_SLOTS_AVAIL(q)	(CWQ_NENTRIES - CWQ_SLOTS_USED(q) - 1)
#define	CWQ_QINDEX_TO_QOFFSET(i)	((i) * sizeof (cwq_cw_t))
#define	CWQ_QOFFSET_TO_QINDEX(o)	((o) / sizeof (cwq_cw_t))
#define	CWQ_QINDEX_INCR(i)		(((i) + 1) & CWQ_WRAPMASK)
#define	CWQ_QINDEX_IS_VALID(i)		(((i) >= 0) && ((i) < CWQ_NENTRIES))

#define	N2CP_QTIMEOUT_SECONDS		60

/* needs up to 9 pages for 64KB buffers */
#define	N2CP_MAX_CHAIN			9

#define	N2CP_JOB_DONE	0xDEADBEEF

typedef struct {
	uint64_t		cq_handle;
	uint64_t		cq_devino;
	int			cq_inum;
	kmutex_t		cq_lock;
	int			cq_id;
	int			cq_init;
	int			cq_busy_wait;
	kcondvar_t		cq_busy_cv;

	n2cp_t			*cq_n2cp;
	n2cp_listnode_t		cq_joblist;	/* runq */

	ddi_taskq_t		*cq_cworker;
	kmutex_t		cq_complete_lock;
	kcondvar_t		cq_complete_cv;
	kcondvar_t		cq_wait_complete_cv;

	/* head of completed job linked list */
	n2cp_request_t		 *cq_rdylist;

	n2cp_request_t		**cq_jobs;
	size_t			cq_jobs_size;
	void			*cq_mem;
	int			cq_memsize;
	cwq_cw_t		*cq_first;
	cwq_cw_t		*cq_last;
	cwq_cw_t		*cq_head;
	cwq_cw_t		*cq_tail;

	struct {
		uint64_t	qks_njobs;
		uint64_t	qks_ncws;
		uint64_t	qks_qfull;
		uint64_t	qks_qbusy;
		uint64_t	qks_qfail;
		uint64_t	qks_nintr;
		uint64_t	qks_nintr_err;
		uint64_t	qks_nintr_jobs;
		uint64_t	qks_nsync_jobs;
		uint64_t	qks_nsync_err;
	} cq_ks;
	kmutex_t		cq_sync_lock;
	n2cp_request_t		*cq_sync_req;
	kcondvar_t		cq_sync_cv;
} cwq_t;

#define	CWQ_STATE_ERROR		(-1)
#define	CWQ_STATE_OFFLINE	0
#define	CWQ_STATE_ONLINE	1
#define	CWQ_STATE_DETACHING	2

typedef struct {
	int		mm_cwqid;
	int		mm_cpulistsz;
	int		*mm_cpulist;
	int		mm_ncpus;
	int		mm_nextcpuidx;
	/*
	 * Only protects mm_nextcpuidx
	 */
	kmutex_t	mm_lock;
	int		mm_state;	/* CWQ_STATE_... */
	cwq_t		mm_queue;
} cwq_entry_t;

typedef struct {
	int		mc_cpuid;
	int		mc_cwqid;
	int		mc_state;	/* CWQ_STATE_... */
} cpu_entry_t;

typedef struct {
	/*
	 * CWQ stuff
	 */
	int		m_cwqlistsz;
	cwq_entry_t	*m_cwqlist;
	int		m_ncwqs;
	int		m_ncwqs_online;
	int		m_nextcwqidx;
	/*
	 * Only protects m_nextcwqidx and m_ncwqs_online
	 */
	kmutex_t	m_lock;

	/*
	 * CPU stuff
	 */
	int		m_cpulistsz;
	cpu_entry_t	*m_cpulist;
	int		m_ncpus;
} n2cp_cwq2cpu_map_t;

#define	SECOND				1000000 /* micro seconds */
#define	N2CP_JOB_STALL_LIMIT		2

typedef uint64_t	n2cp_counter_t;

/* Information for performing periodic timeout (stall) checks */
typedef struct n2cp_timeout {
	clock_t		ticks;	/* Number of clock ticks before next check */
	timeout_id_t	id;	/* ID of timeout thread (used in detach) */
	n2cp_counter_t	count;	/* Number of timeout checks made (statistic) */
} n2cp_timeout_t;

/*
 * Job timeout information:
 *
 * A timeout condition will be detected if all "submitted" jobs have not been
 * "reclaimed" (completed) and we have not made any "progress" within the
 * cumulative timeout "limit".  The cumulative timeout "limit" is incremented
 * with a job specific timeout value (usually one second) each time a new job
 * is submitted.
 */
typedef struct n2cp_job_info {
	kmutex_t	lock;		/* Lock for all other elements */
	n2cp_counter_t	submitted;	/* Number of jobs submitted */
	n2cp_counter_t	reclaimed;	/* Number of jobs completed */
	n2cp_counter_t	progress;	/* Progress recorded during TO check */
	n2cp_timeout_t	timeout;	/* Timeout processing information */
	struct {
		clock_t count;		/* Ticks since last completion */
		clock_t addend;		/* Added to count during TO check */
		clock_t limit;		/* Cumulative timeout value */
	} stalled;
} n2cp_job_info_t;

#define	MAX_FIXED_IV_WORDS	8
typedef struct fixed_iv {
	int		ivsize;
	uint32_t	iv[MAX_FIXED_IV_WORDS];
} fixed_iv_t;

#define	MD5_DIGESTSZ	(4 * sizeof (uint32_t))
#define	SHA1_DIGESTSZ	(5 * sizeof (uint32_t))
#define	SHA256_DIGESTSZ	(8 * sizeof (uint32_t))
#define	MAX_DIGESTSZ	(MAX_FIXED_IV_WORDS * sizeof (uint32_t))

#define	MAX_DATA_LEN		0x10000

#define	DES_KEY_LEN	8
#define	DES3_KEY_LEN	24
#define	DESBLOCK	8
#define	AES_MIN_KEY_LEN	16
#define	AES_MAX_KEY_LEN	32
#define	AESBLOCK	16
#define	MAXBLOCK	AESBLOCK
#define	MAXVALUE	AES_MAX_KEY_LEN

#define	RC4_MIN_KEY_LEN		1
#define	RC4_MAX_KEY_LEN		256

/*
 * We only support up to 64 counter bit
 */
#define	MAX_CTR_BITS	64


#define	HMAC_MIN_KEY_LEN	1
#define	HMAC_MAX_KEY_LEN	CW_MAX_KEY_LEN


/*
 * Some pkcs#11 defines as there are no pkcs#11 header files included.
 */
#define	CKA_VALUE		0x00000011
#define	CKA_KEY_TYPE		0x00000100

/*
 * Request flags (n2cp_request_t.nr_flags).
 */
#define	N2CP_SCATTER		0x01
#define	N2CP_GATHER		0x02
#define	N2CP_SYNC		0x04
#define	N2CP_FREEREQ		0x08

/* define	the mechanisms strings not defined in <sys/crypto/common.h> */
#define	SUN_CKM_SSL3_MD5_MAC		"CKM_SSL3_MD5_MAC"
#define	SUN_CKM_SSL3_SHA1_MAC		"CKM_SSL3_SHA1_MAC"

#ifdef	SSL3_SHA256_MAC_SUPPORT
#define	SUN_CKM_SSL3_SHA256_MAC		"CKM_SSL3_SHA256_MAC"
#endif

/*
 * XXX: Vendor defined version of CKM_AES_CTR. This lets us test AES_CTR
 * from PKCS#11. Note: this is temporally added until CKM_AES_CTR is officially
 * added to PKCS#11 spec.
 */
#define	N2CP_CKM_AES_CTR		"0x80001086"

/*
 * Scatter/gather checks.
 */
#define	N2CP_SG_CONTIG		0x01	/* contiguous buffer */
#define	N2CP_SG_WALIGN		0x02	/* word aligned */
#define	N2CP_SG_PALIGN		0x04	/* page aligned */
#define	N2CP_SG_PCONTIG		0x08	/* physically contiguous buffer */
#define	N2CP_SG_ALIGN16		0x10	/* page aligned */


/*
 * Kstats.
 */
#define	DS_DES			0
#define	DS_DES3			1
#define	DS_AES			2
#define	DS_MD5			3
#define	DS_SHA1			4
#define	DS_SHA256		5
#define	DS_MD5_HMAC		6
#define	DS_SHA1_HMAC		7
#define	DS_SHA256_HMAC		8
#define	DS_SSL_MD5_MAC		9
#define	DS_SSL_SHA1_MAC		10
#define	DS_SSL_SHA256_MAC	11
#define	DS_RC4			12
#define	DS_MAX			13

struct n2cp_stat {
	kstat_named_t		ns_status;
	kstat_named_t		ns_algs[DS_MAX];
	struct {
		kstat_named_t	ns_cwqid;
		kstat_named_t	ns_cwqhandle;
		kstat_named_t	ns_cwqstate;
		kstat_named_t	ns_submit;
		kstat_named_t	ns_cwcount;
		kstat_named_t	ns_qfull;
		kstat_named_t	ns_qbusy;
		kstat_named_t	ns_qupdate_failure;
		kstat_named_t	ns_nintr;
		kstat_named_t	ns_nintr_err;
		kstat_named_t	ns_nintr_jobs;
		kstat_named_t	ns_nsync_jobs;
		kstat_named_t	ns_nsync_err;
	} ns_cwq[N2CP_MAX_NCWQS];
};


typedef enum n2cp_mech_type {
	DES_CBC_MECH_INFO_TYPE,			/* CKM_DES_CBC */
	DES_ECB_MECH_INFO_TYPE,			/* CKM_DES_ECB */
	DES_CFB_MECH_INFO_TYPE,			/* CKM_DES_CFB */
	DES3_CBC_MECH_INFO_TYPE,		/* CKM_DES3_CBC */
	DES3_ECB_MECH_INFO_TYPE,		/* CKM_DES3_ECB */
	DES3_CFB_MECH_INFO_TYPE,		/* CKM_DES3_CFB */
	AES_CBC_MECH_INFO_TYPE,			/* CKM_AES_CBC */
	AES_ECB_MECH_INFO_TYPE,			/* CKM_AES_ECB */
	AES_CTR_MECH_INFO_TYPE,			/* CKM_AES_CTR */
	RC4_WSTRM_MECH_INFO_TYPE,		/* CKM_RC4 */
	RC4_WOSTRM_MECH_INFO_TYPE,		/* CKM_RC4 w/o stream */
	MD5_MECH_INFO_TYPE,			/* CKM_MD5 */
	SHA1_MECH_INFO_TYPE,			/* CKM_SHA_1 */
	SHA256_MECH_INFO_TYPE,			/* CKM_SHA256 */
	MD5_HMAC_MECH_INFO_TYPE,		/* CKM_MD5_HMAC */
	SHA1_HMAC_MECH_INFO_TYPE,		/* CKM_SHA_1_HMAC */
	SHA256_HMAC_MECH_INFO_TYPE,		/* CKM_SHA256_HMAC */
	MD5_HMAC_GENERAL_MECH_INFO_TYPE,	/* CKM_MD5_HMAC_GENERAL */
	SHA1_HMAC_GENERAL_MECH_INFO_TYPE,	/* CKM_SHA_1_HMAC_GENERAL */
	SHA256_HMAC_GENERAL_MECH_INFO_TYPE,	/* CKM_SHA256_HMAC_GENERAL */
	SSL3_MD5_MAC_MECH_INFO_TYPE,		/* CKM_SSL3_MD5_MAC */
	SSL3_SHA1_MAC_MECH_INFO_TYPE,		/* CKM_SSL3_SHA1_MAC */
	SSL3_SHA256_MAC_MECH_INFO_TYPE,		/* CKM_SSL3_SHA256_MAC */
	/* Vendor Defined Mechanism */
	N2CP_AES_CTR_MECH_INFO_TYPE		/* CKM_AES_CTR */
} n2cp_mech_type_t;

/*
 * Operation Flags: These flags are used internally within driver to specify
 * the kind of operation for a job.
 */
#define	N2CP_CMD_MASK		0x0000ffff
#define	N2CP_OP_ENCRYPT		0x00010000
#define	N2CP_OP_DECRYPT		0x00020000
#define	N2CP_OP_SIGN		0x00040000
#define	N2CP_OP_VERIFY		0x00080000
#define	N2CP_OP_DIGEST		0x00100000
#define	N2CP_OP_SINGLE		0x00200000
#define	N2CP_OP_MULTI		0x00400000

/*
 * Mechanism Specific Contexts
 */

typedef struct {
	uchar_t		key[RC4_MAX_KEY_LEN];
	uchar_t		i, j;
} rc4_key_t;

/*
 * Offset within the ctx.
 */
#define	BLOCK_KEY_OFFSET	offsetof(n2cp_block_ctx_t, keystruct)
#define	BLOCK_IV_OFFSET		offsetof(n2cp_block_ctx_t, iv)
#define	HASH_IV_OFFSET		offsetof(n2cp_hash_ctx_t, iv)
#define	HMAC_KEY_OFFSET		offsetof(n2cp_hmac_ctx_t, keyval)
#define	HMAC_IV_OFFSET		offsetof(n2cp_hmac_ctx_t, iv)

struct n2cp_block_ctx {
	int		keylen;
	union {
		uchar_t		val[MAXVALUE];
		rc4_key_t	rc4val;
		arcfour_state_t	kcf_rc4val;
	} keystruct;
	uint64_t	key_paddr;	/* paddr of value */
	int		ivlen;
	uchar_t		iv[MAXBLOCK];
	uint64_t	iv_paddr;	/* paddr of iv */
	int		nextivlen;
	uchar_t		nextiv[MAXBLOCK];
	int		ctrbits;	/* used for AES_CTR */
	int		residlen;
	char		resid[MAXBLOCK];
	int		lastblocklen;
	char		lastblock[MAXBLOCK];
};

#define	keyvalue	keystruct.val
#define	rc4keyvalue	keystruct.rc4val


struct n2cp_hash_ctx {
	uint32_t	hashsz;
	uint32_t	iv[MAX_FIXED_IV_WORDS];
};

struct n2cp_hmac_ctx {
	uint32_t	hashsz;
	uint32_t	signlen;
	uint32_t	iv[MAX_FIXED_IV_WORDS];
	int		keylen;
	uchar_t		keyval[CW_MAX_KEY_LEN];
};


/*
 * Work structure.
 * Contains everything we need to submit the job, and everything we
 * need to notify caller and release resources.
 */
typedef union {
		n2cp_block_ctx_t	blockctx;
		n2cp_hash_ctx_t		hashctx;
		n2cp_hmac_ctx_t		hmacctx;
} nr_ctx_t;

#define	N2CP_OP_PATTERN		"BROKE HW"
#define	N2CP_OP_PATTERN_SZ	8

/* n2cp_request.nr_job_state */
#define	N2CP_JOBSTATE_FREED		0	/* in freed list */
#define	N2CP_JOBSTATE_WAITQ		1	/* in waitq */
#define	N2CP_JOBSTATE_PENDING		2	/* in runq */
#define	N2CP_JOBSTATE_SOLO		3	/* not linked */

typedef struct n2cp_buf_struct {
	n2cp_listnode_t		link;
	uchar_t			*buf;
	uint64_t		buf_paddr;
} n2cp_buf_struct_t;


struct n2cp_request {
	n2cp_listnode_t		nr_linkage;	/* must be at the top */
	n2cp_listnode_t		nr_activectx;	/* must be at the top */
	uint32_t		nr_cmd;	/* N2CP_OP | MECH_INFO_TYPE */
	uint16_t		nr_pkt_length;
	crypto_req_handle_t	nr_kcfreq;
	n2cp_t			*nr_n2cp;
	clock_t			nr_timeout;
	int			nr_errno;
	/*
	 * Consumer's I/O buffers.
	 */
	crypto_data_t		*nr_in;
	crypto_data_t		*nr_out;
	crypto_data_t		nr_tmpin;

	/*
	 * CWB
	 */
	int			nr_cwq_id;	/* Associated CWQ ID */
	int			nr_id;		/* job id */
	int			nr_job_state;
	cwq_cw_t		nr_cws[N2CP_MAX_CHAIN];
	cwq_cw_t		*nr_cwb;
	int			nr_cwcnt;

	nr_ctx_t		*nr_context;
	int			nr_context_sz;
	int			nr_blocksz;
	uint64_t		nr_context_paddr;

	n2cp_request_t		*nr_rdylink;

	/*
	 * Callback.
	 */
	void			(*nr_callback)(n2cp_request_t *);
	/*
	 * Other stuff.
	 */
	/* pre-allocated buffers */
	uchar_t			*nr_in_buf;
	uint64_t		nr_in_buf_paddr;
	n2cp_buf_struct_t	*nr_in_buf_struct;
	uchar_t			*nr_out_buf;
	uint64_t		nr_out_buf_paddr;
	n2cp_buf_struct_t	*nr_out_buf_struct;

	uint32_t		nr_flags;
	int			nr_resultlen;
	/*
	 * Statistics.
	 */
	int			nr_job_stat;
};

struct n2cp {
	int				n_hvapi_major_version;
	int				n_hvapi_minor_version;
	dev_info_t			*n_dip;

	unsigned			n_flags;	/* dev state flags */

	kstat_t				*n_ksp;
	uint64_t			n_stats[DS_MAX];

	ddi_intr_handle_t		*n_htable;
	int				n_intr_cid[N2CP_MAX_NCWQS];
	int				n_intr_cnt;
	size_t				n_intr_size;
	uint_t				n_intr_pri;

	size_t				n_reqctx_sz;
	crypto_kcf_provider_handle_t	n_prov;

	kmutex_t			n_freereqslock;
	n2cp_listnode_t			n_freereqs; /* available requests */
	n2cp_listnode_t			n_ctx_list; /* list of all requests */

	/* pool of 64KB contig buffer used for scatter-gather */
	n2cp_listnode_t			n_buf_pool;
	uint32_t			n_buf_cnt;
	kmutex_t			n_buf_pool_lock;

	md_t				*n_mdp;
	n2cp_cwq2cpu_map_t		n_cwqmap;

	kmutex_t			n_timeout_lock;
	n2cp_timeout_t			n_timeout;
	n2cp_job_info_t			n_job[N2CP_MAX_NCWQS];
	n2cp_mode_t			n_mode;
	int				n_spins_per_usec;
};

/* CK_AES_CTR_PARAMS provides the parameters to the CKM_AES_CTR mechanism */
typedef struct CK_AES_CTR_PARAMS {
	ulong_t		ulCounterBits;
	uint8_t		iv[AESBLOCK];
} CK_AES_CTR_PARAMS;

typedef struct CK_AES_CTR_PARAMS32 {
	uint32_t	ulCounterBits;
	uint8_t		iv[AESBLOCK];
} CK_AES_CTR_PARAMS32;


/*
 * Priority of task threads used for handling interrupts.
 */
#define	N2CP_INTRTASK_PRI	80

#endif	/* _KERNEL */

/*
 * Miscellaneous defines.
 */
#define	ROUNDUP(a, n)		(((a) + ((n) - 1)) & ~((n) - 1))
#define	ROUNDDOWN(a, n)		((a) & ~((n) - 1))
#define	PAD32(x)		ROUNDUP(x, sizeof (uint32_t))
#define	PADAES(x)		ROUNDUP(x, AESBLOCK)
#define	BYTES_TO_UINT64(n)	\
	(((n) + (sizeof (uint64_t) - 1)) / sizeof (uint64_t))
#define	BYTES_TO_UINT32(n)	\
	(((n) + (sizeof (uint32_t) - 1)) / sizeof (uint32_t))

#if defined(_KERNEL)

#define	N2CP_REQ_SETUP(reqp, in, out) \
	reqp->nr_tmpin = *in; \
	reqp->nr_in = &reqp->nr_tmpin; \
	if (in == out) { \
		reqp->nr_out = in; \
	} else { \
		reqp->nr_out = out; \
	} \
	reqp->nr_out->cd_length = 0;

#if defined(DEBUG)

#define	DWARN		0x00000001
#define	DMA_ARGS	0x00000002
#define	DMA_LDST	0x00000004
#define	DNCS_QTAIL	0x00000008
#define	DATTACH		0x00000010
#define	DMD		0x00000020
#define	DHV		0x00000040
#define	DINTR		0x00000080
#define	DMOD		0x00000100  /* _init/_fini/_info/attach/detach */
#define	DCHATTY		0x00000400
#define	DALL		0xFFFFFFFF

void	n2cp_dprintf(n2cp_t *, int, const char *, ...);
void	n2cp_dumphex(void *, int);
int	n2cp_dflagset(int);

#define	DBG0	n2cp_dprintf
#define	DBG1	n2cp_dprintf
#define	DBG2	n2cp_dprintf
#define	DBG3	n2cp_dprintf
#define	DBG4	n2cp_dprintf

#else	/* !defined(DEBUG) */

#define	DBG0(vca, lvl, fmt)
#define	DBG1(vca, lvl, fmt, arg1)
#define	DBG2(vca, lvl, fmt, arg1, arg2)
#define	DBG3(vca, lvl, fmt, arg1, arg2, arg3)
#define	DBG4(vca, lvl, fmt, arg1, arg2, arg3, arg4)


#endif	/* !defined(DEBUG) */

/*
 * n2cp.c
 */
int	n2cp_start(n2cp_t *, n2cp_request_t *);
void	*n2_contig_alloc(int);
void	n2_contig_free(void *, int);


/*
 * n2cp_debug.c
 */
void	n2cp_error(n2cp_t *, const char *, ...);
void	n2cp_diperror(dev_info_t *, const char *, ...);
void	n2cp_dipverror(dev_info_t *, const char *, va_list);
void	n2cp_dump_cwb(cwq_cw_t *cw);
void	n2cp_dumphex(void *, int);
void	n2cp_offline_cwq(n2cp_t *n2cp, int cwq_id);

/*
 * n2cp_kstat.c
 */
void	n2cp_ksinit(n2cp_t *);
void	n2cp_ksdeinit(n2cp_t *);

/*
 * n2cp_kcf.c
 */
int	n2cp_init(n2cp_t *);
int	n2cp_uninit(n2cp_t *);
int	n2cp_get_inbuf(n2cp_t *, n2cp_request_t *);
int	n2cp_get_outbuf(n2cp_t *, n2cp_request_t *);
void	n2cp_free_buf(n2cp_t *, n2cp_request_t *);
n2cp_request_t *n2cp_getreq(n2cp_t *, int);
void	n2cp_freereq(n2cp_request_t *);
void	n2cp_destroyreq(n2cp_request_t *);
caddr_t	n2cp_bufdaddr(crypto_data_t *);
int	n2cp_gather(crypto_data_t *, char *, int);
int	n2cp_gather_zero_pad(crypto_data_t *, caddr_t, size_t, int);
int	n2cp_scatter(const char *, crypto_data_t *, int);
int	n2cp_sgcheck(crypto_data_t *, int);
int	n2cp_construct_chain(cwq_cw_t *, crypto_data_t *, int, int *chaincnt);
int	n2cp_attr_lookup_uint8_array(crypto_object_attribute_t *, uint_t,
			uint64_t, void **, unsigned int *);
crypto_object_attribute_t *
	n2cp_find_attribute(crypto_object_attribute_t *, uint_t, uint64_t);
char	*n2cp_get_dataaddr(crypto_data_t *, off_t);
void	n2cp_setresid(crypto_data_t *, int);
void	n2cp_getbufbytes(crypto_data_t *, int, int, char *);
uint16_t n2cp_padhalf(int);
uint16_t n2cp_padfull(int);

void n2cp_initq(n2cp_listnode_t *);
void n2cp_enqueue(n2cp_listnode_t *, n2cp_listnode_t *);
n2cp_listnode_t *n2cp_dequeue(n2cp_listnode_t *);
void    n2cp_rmqueue(n2cp_listnode_t *);
int	n2cp_is_emptyqueue(n2cp_listnode_t *);
void    n2cp_mvqueue(n2cp_listnode_t *, n2cp_listnode_t *);
void n2cp_enqueue_ctx(n2cp_t *, n2cp_listnode_t *);
void n2cp_dequeue_ctx(n2cp_t *, n2cp_listnode_t *);


/*
 * n2cp_hash.c
 */
int	n2cp_hashatomic(n2cp_t *, crypto_mechanism_t *,
    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
int	n2cp_hashinit(crypto_ctx_t *, crypto_mechanism_t *);
int	n2cp_hash(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t);

/*
 * n2cp_block.c
 */
int	n2cp_blockinit(crypto_ctx_t *, crypto_mechanism_t *,
    crypto_key_t *, int);
int	n2cp_block(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t);
int	n2cp_blockupdate(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t *);
int	n2cp_blockfinal(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t *);
int	n2cp_blockatomic(n2cp_t *, crypto_mechanism_t *, crypto_key_t *,
    crypto_data_t *, crypto_data_t *, crypto_req_handle_t, int);
void	n2cp_clean_blockctx(n2cp_request_t *);
int	n2cp_aes_ctr_allocmech(crypto_mechanism_t *, crypto_mechanism_t *,
    int *, int);
int	n2cp_aes_ctr_freemech(crypto_mechanism_t *);


/*
 * n2cp_hmac.c
 */
int	n2cp_hmacinit(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *);
int	n2cp_hmac_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t);
int	n2cp_hmac_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t);
int	n2cp_hmac_signatomic(n2cp_t *, crypto_mechanism_t *, crypto_key_t *,
    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
int	n2cp_hmac_verifyatomic(n2cp_t *, crypto_mechanism_t *, crypto_key_t *,
    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
void	n2cp_clean_hmacctx(n2cp_request_t *);
int	n2cp_ssl3_sha1_mac_signatomic(n2cp_t *, crypto_mechanism_t *,
    crypto_key_t *, crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
int	n2cp_ssl3_sha1_mac_verifyatomic(n2cp_t *, crypto_mechanism_t *,
    crypto_key_t *, crypto_data_t *, crypto_data_t *, crypto_req_handle_t);

/*
 * n2cp_md.c
 */
int	n2cp_init_cwq2cpu_map(n2cp_t *);
void	n2cp_deinit_cwq2cpu_map(n2cp_t *);
int	n2cp_map_cwq_to_cpu(n2cp_t *, int, int);
int	n2cp_map_cpu_to_cwq(n2cp_t *, int);
int	n2cp_map_nextcwq(n2cp_t *);
cwq_entry_t	*n2cp_map_findcwq(n2cp_t *, int);
void	n2cp_online_cwq(n2cp_t *, int cwq_id);
void	n2cp_offline_cwq(n2cp_t *, int cwq_id);
void	n2cp_online_cpu(n2cp_t *, int cpu_id);
void	n2cp_offline_cpu(n2cp_t *, int cpu_id);

/*
 * n2cp_asm.s
 */
void n2cp_delay(void);

#ifdef N2_ERRATUM_175

typedef struct noncache_info {
	int		n_workaround_enabled;
	/*
	 * Stats to track how many (4M) slabs get allocated.
	 * Intended for debugging problems or performance analysis.
	 */
	uint64_t	n_alloc;	/* # contig slabs alloc'd */
	uint64_t	n_free;		/* # contig slabs free'd */
	uint64_t	n_alloc_fail;	/* contig_mem_alloc failures */
	uint64_t	n_hat_fail;	/* hat_getattr failures */
	uint64_t	n_sync_fail;	/* mem_sync failures */
	/*
	 * The following are function pointers to switch between
	 * standard contig_mem_alloc/free and bcopy, and our special
	 * noncache_contig_mem_alloc/free and noncache_bcopy.
	 * Set up at driver attach time.
	 */
	void		*(*n_contig_alloc)(size_t);
	void		(*n_contig_free)(void *, size_t);
	void		(*n_bcopy)(const void *, void *, size_t);
} noncache_info_t;

extern noncache_info_t	n2cp_nc;

#define	BCOPY	n2cp_nc.n_bcopy

#else /* N2_ERRATUM_175 */

#define	BCOPY	bcopy

#endif /* N2_ERRATUM_175 */

#define	n2cp_setfailed(n2cp)		((n2cp)->n_flags |= N2CP_FAILED)
#define	n2cp_isfailed(n2cp)		((n2cp)->n_flags & N2CP_FAILED)
#define	n2cp_setregistered(n2cp)	((n2cp)->n_flags |= N2CP_REGISTERED)
#define	n2cp_clrregistered(n2cp)	((n2cp)->n_flags &= ~N2CP_REGISTERED)
#define	n2cp_isregistered(n2cp)		((n2cp)->n_flags & N2CP_REGISTERED)
#define	n2cp_setcpuregistered(n2cp)	((n2cp)->n_flags |= N2CP_CPU_REGISTERED)
#define	n2cp_clrcpuregistered(n2cp) ((n2cp)->n_flags &= ~N2CP_CPU_REGISTERED)
#define	n2cp_iscpuregistered(n2cp)	((n2cp)->n_flags & N2CP_CPU_REGISTERED)

#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_N2CP_H */