sched_impl.h revision 6a1073f89079df9576bccd94a24df8c011db8169
/*
* 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
* 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_CRYPTO_SCHED_IMPL_H
#define _SYS_CRYPTO_SCHED_IMPL_H
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Scheduler internal structures.
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef void (kcf_func_t)(void *, int);
typedef enum kcf_req_status {
REQ_ALLOCATED = 1,
REQ_WAITING, /* At the framework level */
REQ_INPROGRESS, /* At the provider level */
typedef enum kcf_call_type {
CRYPTO_SYNCH = 1,
#define CHECK_RESTRICT_FALSE B_FALSE
/*
* The framework keeps an internal handle to use in the adaptive
* asynchronous case. This is the case when a client has the
* CRYPTO_ALWAYS_QUEUE bit clear and a software provider is used for
* the request. The request is completed in the context of the calling
* thread and kernel memory must be allocated with KM_NOSLEEP.
*
* The framework passes a pointer to the handle in crypto_req_handle_t
* argument when it calls the SPI of the software provider. The macros
* KCF_RHNDL() and KCF_SWFP_RHNDL() are used to do this.
*
* When a provider asks the framework for kmflag value via
* crypto_kmflag(9S) we use REQHNDL2_KMFLAG() macro.
*/
extern ulong_t kcf_swprov_hndl;
#define REQHNDL2_KMFLAG(rhndl) \
/* Internal call_req flags. They start after the public ones in api.h */
/* submitting the request */
#define KCF_ISDUALREQ(crq) \
typedef struct kcf_prov_tried {
struct kcf_prov_tried *pt_next;
#define IS_RECOVERABLE(error) \
(error == CRYPTO_BUFFER_TOO_BIG || \
error == CRYPTO_BUSY || \
error == CRYPTO_DEVICE_ERROR || \
error == CRYPTO_DEVICE_MEMORY || \
error == CRYPTO_KEY_SIZE_RANGE || \
/*
* Node structure for synchronous requests.
*/
typedef struct kcf_sreq_node {
/* Should always be the first field in this structure */
/*
* sn_cv and sr_lock are used to wait for the
* operation to complete. sn_lock also protects
* the sn_state field.
*/
/*
* Return value from the operation. This will be
* one of the CRYPTO_* errors defined in common.h.
*/
int sn_rv;
/*
* parameters to call the SPI with. This can be
*/
struct kcf_req_params *sn_params;
/* Internal context for this request */
struct kcf_context *sn_context;
/* Provider handling this request */
/*
* Node structure for asynchronous requests. A node can be on
* on a chain of requests hanging of the internal context
* structure and can be in the global software provider queue.
*/
typedef struct kcf_areq_node {
/* Should always be the first field in this structure */
/* an_lock protects the field an_state */
/*
* parameters to call the SPI with. We need to
* save the params since the caller stack can go away.
*/
struct kcf_req_params an_params;
/*
* The next two fields should be NULL for operations that
* don't need a context.
*/
/* Internal context for this request */
struct kcf_context *an_context;
/* next in chain of requests for context */
struct kcf_areq_node *an_ctxchain_next;
/*
* Next and previous nodes in the global software
* queue. These fields are NULL for a hardware
* provider since we use a taskq there.
*/
struct kcf_areq_node *an_next;
struct kcf_areq_node *an_prev;
/* Provider handling this request */
#define KCF_AREQ_REFHOLD(areq) { \
}
#define KCF_AREQ_REFRELE(areq) { \
membar_exit(); \
kcf_free_req(areq); \
}
/* For internally generated call requests for dual operations */
typedef struct kcf_call_req {
/*
* The following are some what similar to macros in callo.h, which implement
* callout tables.
*
* The lower four bits of the ID are used to encode the table ID to
* index in to. The REQID_COUNTER_HIGH bit is used to avoid any check for
* wrap around when generating ID. We assume that there won't be a request
* which takes more time than 2^^(sizeof (long) - 5) other requests submitted
* after it. This ensures there won't be any ID collision.
*/
#define REQID_COUNTER_SHIFT 4
#define REQID_TABLES 16
#define REQID_BUCKETS 512
/*
* Hash table for async requests.
*/
typedef struct kcf_reqid_table {
/*
* Global software provider queue structure. Requests to be
* handled by a SW provider and have the ALWAYS_QUEUE flag set
* get queued here.
*/
typedef struct kcf_global_swq {
/*
* gs_cv and gs_lock are used to wait for new requests.
* gs_lock protects the changes to the queue.
*/
/*
* Internal representation of a canonical context. We contain crypto_ctx_t
* structure in order to have just one memory allocation. The SPI
* ((crypto_ctx_t *)ctx)->cc_framework_private maps to this structure.
*/
typedef struct kcf_context {
/*
* kc_req_chain_first and kc_req_chain_last are used to chain
* multiple async requests using the same context. They should be
* NULL for sync requests.
*/
/*
* Bump up the reference count on the framework private context. A
* global context or a request that references this structure should
* do a hold.
*/
#define KCF_CONTEXT_REFHOLD(ictx) { \
}
/*
* Decrement the reference count on the framework private context.
* When the last reference is released, the framework private
* context structure is freed along with the global context.
*/
#define KCF_CONTEXT_REFRELE(ictx) { \
membar_exit(); \
kcf_free_context(ictx); \
}
/*
* Check if we can release the context now. In case of CRYPTO_QUEUED
* we do not release it as we can do it only after the provider notified
* us. In case of CRYPTO_BUSY, the client can retry the request using
* the context, so we do not release the context.
*
* This macro should be called only from the final routine in
* of update operations. We require the consumer to free it
* explicitly, in case it wants to abandon the operation. This is done
* as there may be mechanisms in ECB mode that can continue even if
* an operation on a block fails.
*/
if (KCF_CONTEXT_DONE(rv)) \
}
/*
* This macro determines whether we're done with a context.
*/
#define KCF_CONTEXT_DONE(rv) \
(rv) != CRYPTO_BUFFER_TOO_SMALL)
/*
* A crypto_ctx_template_t is internally a pointer to this struct
*/
typedef struct kcf_ctx_template {
/* from the SW prov */
/*
* Structure for pool of threads working on global software queue.
*/
typedef struct kcf_pool {
/*
* cv & lock to monitor the condition when no threads
* are around. In this case the failover thread kicks in.
*/
/* Userspace thread creator variables. */
int kp_nthrs; /* # of threads to create */
/*
* cv & lock for the condition where more threads need to be
* created. kp_user_lock also protects the three fileds above.
*/
} kcf_pool_t;
/*
* State of a crypto bufcall element.
*/
typedef enum cbuf_state {
CBUF_FREE = 1,
} cbuf_state_t;
/*
* Structure of a crypto bufcall element.
*/
typedef struct kcf_cbuf_elem {
/*
* lock and cv to wait for CBUF_RUNNING to be done
* kc_lock also protects kc_state.
*/
struct kcf_cbuf_elem *kc_next;
struct kcf_cbuf_elem *kc_prev;
void *kc_arg;
/*
* State of a notify element.
*/
typedef enum ntfy_elem_state {
NTFY_WAITING = 1,
/*
* Structure of a notify list element.
*/
typedef struct kcf_ntfy_elem {
/*
* lock and cv to wait for NTFY_RUNNING to be done.
* kn_lock also protects kn_state.
*/
struct kcf_ntfy_elem *kn_next;
struct kcf_ntfy_elem *kn_prev;
/*
* The following values are based on the assumption that it would
* take around eight cpus to load a hardware provider (This is true for
* at least one product) and a kernel client may come from different
* low-priority interrupt levels. We will have CYRPTO_TASKQ_MIN number
* of cached taskq entries. These are just reasonable estimates and
* might need to change in future.
*/
#define CYRPTO_TASKQ_MIN 64
#define CRYPTO_TASKQ_MAX 1024
extern int crypto_taskq_minalloc;
extern int crypto_taskq_maxalloc;
extern kcf_global_swq_t *gswq;
extern int kcf_maxthreads;
extern int kcf_minthreads;
/* Door handle for talking to kcfd */
extern door_handle_t kcf_dh;
extern kmutex_t kcf_dh_lock;
/*
* All pending crypto bufcalls are put on a list. cbuf_list_lock
* protects changes to this list.
*/
extern kmutex_t cbuf_list_lock;
extern kcondvar_t cbuf_list_cv;
/*
* All event subscribers are put on a list. kcf_notify_list_lock
* protects changes to this list.
*/
extern kmutex_t ntfy_list_lock;
extern kcondvar_t ntfy_list_cv;
extern void kcf_free_triedlist(kcf_prov_tried_t *);
kcf_provider_desc_t *, int);
crypto_mech_type_t *, int *, kcf_prov_tried_t *,
extern void kcf_sched_init(void);
extern void kcf_sched_start(void);
extern void kcf_sop_done(kcf_sreq_node_t *, int);
extern void kcf_aop_done(kcf_areq_node_t *, int);
extern int common_submit_request(kcf_provider_desc_t *,
extern void kcf_free_context(kcf_context_t *);
extern int kcf_svc_wait(int *);
extern int kcf_svc_do_run(void);
extern int kcf_verify_signature(kcf_provider_desc_t *);
extern void verify_unverified_providers();
extern void crypto_bufcall_service(void);
extern void kcf_walk_ntfylist(uint32_t, void *);
extern void kcf_next_req(void *, int);
extern void kcf_last_req(void *, int);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_CRYPTO_SCHED_IMPL_H */