1844d9543SConrad Meyer /*- 2844d9543SConrad Meyer * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3844d9543SConrad Meyer * 4844d9543SConrad Meyer * Copyright (c) 2017 Chelsio Communications, Inc. 5844d9543SConrad Meyer * Copyright (c) 2017 Conrad Meyer <cem@FreeBSD.org> 6844d9543SConrad Meyer * All rights reserved. 7844d9543SConrad Meyer * Largely borrowed from ccr(4), Written by: John Baldwin <jhb@FreeBSD.org> 8844d9543SConrad Meyer * 9844d9543SConrad Meyer * Redistribution and use in source and binary forms, with or without 10844d9543SConrad Meyer * modification, are permitted provided that the following conditions 11844d9543SConrad Meyer * are met: 12844d9543SConrad Meyer * 1. Redistributions of source code must retain the above copyright 13844d9543SConrad Meyer * notice, this list of conditions and the following disclaimer. 14844d9543SConrad Meyer * 2. Redistributions in binary form must reproduce the above copyright 15844d9543SConrad Meyer * notice, this list of conditions and the following disclaimer in the 16844d9543SConrad Meyer * documentation and/or other materials provided with the distribution. 17844d9543SConrad Meyer * 18844d9543SConrad Meyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19844d9543SConrad Meyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20844d9543SConrad Meyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21844d9543SConrad Meyer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22844d9543SConrad Meyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23844d9543SConrad Meyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24844d9543SConrad Meyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25844d9543SConrad Meyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26844d9543SConrad Meyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27844d9543SConrad Meyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28844d9543SConrad Meyer * SUCH DAMAGE. 29844d9543SConrad Meyer */ 30844d9543SConrad Meyer 31844d9543SConrad Meyer #include <sys/cdefs.h> 32844d9543SConrad Meyer __FBSDID("$FreeBSD$"); 33844d9543SConrad Meyer 34844d9543SConrad Meyer #include "opt_ddb.h" 35844d9543SConrad Meyer 36844d9543SConrad Meyer #include <sys/types.h> 37844d9543SConrad Meyer #include <sys/bus.h> 38844d9543SConrad Meyer #include <sys/lock.h> 39844d9543SConrad Meyer #include <sys/kernel.h> 40844d9543SConrad Meyer #include <sys/malloc.h> 41844d9543SConrad Meyer #include <sys/mutex.h> 42844d9543SConrad Meyer #include <sys/module.h> 43844d9543SConrad Meyer #include <sys/random.h> 44844d9543SConrad Meyer #include <sys/sglist.h> 45844d9543SConrad Meyer #include <sys/sysctl.h> 46844d9543SConrad Meyer 47844d9543SConrad Meyer #ifdef DDB 48844d9543SConrad Meyer #include <ddb/ddb.h> 49844d9543SConrad Meyer #endif 50844d9543SConrad Meyer 51844d9543SConrad Meyer #include <dev/pci/pcivar.h> 52844d9543SConrad Meyer 53844d9543SConrad Meyer #include <dev/random/randomdev.h> 54844d9543SConrad Meyer 55844d9543SConrad Meyer #include <opencrypto/cryptodev.h> 56844d9543SConrad Meyer #include <opencrypto/xform.h> 57844d9543SConrad Meyer 58844d9543SConrad Meyer #include "cryptodev_if.h" 59844d9543SConrad Meyer 60844d9543SConrad Meyer #include "ccp.h" 61844d9543SConrad Meyer #include "ccp_hardware.h" 62844d9543SConrad Meyer 63844d9543SConrad Meyer MALLOC_DEFINE(M_CCP, "ccp", "AMD CCP crypto"); 64844d9543SConrad Meyer 65844d9543SConrad Meyer /* 66844d9543SConrad Meyer * Need a global softc available for garbage random_source API, which lacks any 67844d9543SConrad Meyer * context pointer. It's also handy for debugging. 68844d9543SConrad Meyer */ 69844d9543SConrad Meyer struct ccp_softc *g_ccp_softc; 70844d9543SConrad Meyer 71844d9543SConrad Meyer bool g_debug_print = false; 72844d9543SConrad Meyer SYSCTL_BOOL(_hw_ccp, OID_AUTO, debug, CTLFLAG_RWTUN, &g_debug_print, 0, 73844d9543SConrad Meyer "Set to enable debugging log messages"); 74844d9543SConrad Meyer 75844d9543SConrad Meyer static struct pciid { 76844d9543SConrad Meyer uint32_t devid; 77844d9543SConrad Meyer const char *desc; 78844d9543SConrad Meyer } ccp_ids[] = { 79844d9543SConrad Meyer { 0x14561022, "AMD CCP-5a" }, 80844d9543SConrad Meyer { 0x14681022, "AMD CCP-5b" }, 81844d9543SConrad Meyer }; 82844d9543SConrad Meyer 83844d9543SConrad Meyer static struct random_source random_ccp = { 84844d9543SConrad Meyer .rs_ident = "AMD CCP TRNG", 85844d9543SConrad Meyer .rs_source = RANDOM_PURE_CCP, 86844d9543SConrad Meyer .rs_read = random_ccp_read, 87844d9543SConrad Meyer }; 88844d9543SConrad Meyer 89844d9543SConrad Meyer /* 90844d9543SConrad Meyer * ccp_populate_sglist() generates a scatter/gather list that covers the entire 91844d9543SConrad Meyer * crypto operation buffer. 92844d9543SConrad Meyer */ 93844d9543SConrad Meyer static int 94844d9543SConrad Meyer ccp_populate_sglist(struct sglist *sg, struct cryptop *crp) 95844d9543SConrad Meyer { 96844d9543SConrad Meyer int error; 97844d9543SConrad Meyer 98844d9543SConrad Meyer sglist_reset(sg); 99844d9543SConrad Meyer if (crp->crp_flags & CRYPTO_F_IMBUF) 100844d9543SConrad Meyer error = sglist_append_mbuf(sg, crp->crp_mbuf); 101844d9543SConrad Meyer else if (crp->crp_flags & CRYPTO_F_IOV) 102844d9543SConrad Meyer error = sglist_append_uio(sg, crp->crp_uio); 103844d9543SConrad Meyer else 104844d9543SConrad Meyer error = sglist_append(sg, crp->crp_buf, crp->crp_ilen); 105844d9543SConrad Meyer return (error); 106844d9543SConrad Meyer } 107844d9543SConrad Meyer 108844d9543SConrad Meyer /* 109844d9543SConrad Meyer * Handle a GCM request with an empty payload by performing the 110844d9543SConrad Meyer * operation in software. Derived from swcr_authenc(). 111844d9543SConrad Meyer */ 112844d9543SConrad Meyer static void 113844d9543SConrad Meyer ccp_gcm_soft(struct ccp_session *s, struct cryptop *crp, 114844d9543SConrad Meyer struct cryptodesc *crda, struct cryptodesc *crde) 115844d9543SConrad Meyer { 116844d9543SConrad Meyer struct aes_gmac_ctx gmac_ctx; 117844d9543SConrad Meyer char block[GMAC_BLOCK_LEN]; 118844d9543SConrad Meyer char digest[GMAC_DIGEST_LEN]; 119844d9543SConrad Meyer char iv[AES_BLOCK_LEN]; 120844d9543SConrad Meyer int i, len; 121844d9543SConrad Meyer 122844d9543SConrad Meyer /* 123844d9543SConrad Meyer * This assumes a 12-byte IV from the crp. See longer comment 124844d9543SConrad Meyer * above in ccp_gcm() for more details. 125844d9543SConrad Meyer */ 126844d9543SConrad Meyer if (crde->crd_flags & CRD_F_ENCRYPT) { 127844d9543SConrad Meyer if (crde->crd_flags & CRD_F_IV_EXPLICIT) 128844d9543SConrad Meyer memcpy(iv, crde->crd_iv, 12); 129844d9543SConrad Meyer else 130844d9543SConrad Meyer arc4rand(iv, 12, 0); 1319ea9c34bSConrad Meyer if ((crde->crd_flags & CRD_F_IV_PRESENT) == 0) 1329ea9c34bSConrad Meyer crypto_copyback(crp->crp_flags, crp->crp_buf, 1339ea9c34bSConrad Meyer crde->crd_inject, 12, iv); 134844d9543SConrad Meyer } else { 135844d9543SConrad Meyer if (crde->crd_flags & CRD_F_IV_EXPLICIT) 136844d9543SConrad Meyer memcpy(iv, crde->crd_iv, 12); 137844d9543SConrad Meyer else 138844d9543SConrad Meyer crypto_copydata(crp->crp_flags, crp->crp_buf, 139844d9543SConrad Meyer crde->crd_inject, 12, iv); 140844d9543SConrad Meyer } 141844d9543SConrad Meyer *(uint32_t *)&iv[12] = htobe32(1); 142844d9543SConrad Meyer 143844d9543SConrad Meyer /* Initialize the MAC. */ 144844d9543SConrad Meyer AES_GMAC_Init(&gmac_ctx); 145844d9543SConrad Meyer AES_GMAC_Setkey(&gmac_ctx, s->blkcipher.enckey, s->blkcipher.key_len); 146844d9543SConrad Meyer AES_GMAC_Reinit(&gmac_ctx, iv, sizeof(iv)); 147844d9543SConrad Meyer 148844d9543SConrad Meyer /* MAC the AAD. */ 149844d9543SConrad Meyer for (i = 0; i < crda->crd_len; i += sizeof(block)) { 150844d9543SConrad Meyer len = imin(crda->crd_len - i, sizeof(block)); 151844d9543SConrad Meyer crypto_copydata(crp->crp_flags, crp->crp_buf, crda->crd_skip + 152844d9543SConrad Meyer i, len, block); 153844d9543SConrad Meyer bzero(block + len, sizeof(block) - len); 154844d9543SConrad Meyer AES_GMAC_Update(&gmac_ctx, block, sizeof(block)); 155844d9543SConrad Meyer } 156844d9543SConrad Meyer 157844d9543SConrad Meyer /* Length block. */ 158844d9543SConrad Meyer bzero(block, sizeof(block)); 159844d9543SConrad Meyer ((uint32_t *)block)[1] = htobe32(crda->crd_len * 8); 160844d9543SConrad Meyer AES_GMAC_Update(&gmac_ctx, block, sizeof(block)); 161844d9543SConrad Meyer AES_GMAC_Final(digest, &gmac_ctx); 162844d9543SConrad Meyer 163844d9543SConrad Meyer if (crde->crd_flags & CRD_F_ENCRYPT) { 164844d9543SConrad Meyer crypto_copyback(crp->crp_flags, crp->crp_buf, crda->crd_inject, 165844d9543SConrad Meyer sizeof(digest), digest); 166844d9543SConrad Meyer crp->crp_etype = 0; 167844d9543SConrad Meyer } else { 168844d9543SConrad Meyer char digest2[GMAC_DIGEST_LEN]; 169844d9543SConrad Meyer 170844d9543SConrad Meyer crypto_copydata(crp->crp_flags, crp->crp_buf, crda->crd_inject, 171844d9543SConrad Meyer sizeof(digest2), digest2); 172844d9543SConrad Meyer if (timingsafe_bcmp(digest, digest2, sizeof(digest)) == 0) 173844d9543SConrad Meyer crp->crp_etype = 0; 174844d9543SConrad Meyer else 175844d9543SConrad Meyer crp->crp_etype = EBADMSG; 176844d9543SConrad Meyer } 177844d9543SConrad Meyer crypto_done(crp); 178844d9543SConrad Meyer } 179844d9543SConrad Meyer 180844d9543SConrad Meyer static int 181844d9543SConrad Meyer ccp_probe(device_t dev) 182844d9543SConrad Meyer { 183844d9543SConrad Meyer struct pciid *ip; 184844d9543SConrad Meyer uint32_t id; 185844d9543SConrad Meyer 186844d9543SConrad Meyer id = pci_get_devid(dev); 187844d9543SConrad Meyer for (ip = ccp_ids; ip < &ccp_ids[nitems(ccp_ids)]; ip++) { 188844d9543SConrad Meyer if (id == ip->devid) { 189844d9543SConrad Meyer device_set_desc(dev, ip->desc); 190844d9543SConrad Meyer return (0); 191844d9543SConrad Meyer } 192844d9543SConrad Meyer } 193844d9543SConrad Meyer return (ENXIO); 194844d9543SConrad Meyer } 195844d9543SConrad Meyer 196844d9543SConrad Meyer static void 197844d9543SConrad Meyer ccp_initialize_queues(struct ccp_softc *sc) 198844d9543SConrad Meyer { 199844d9543SConrad Meyer struct ccp_queue *qp; 200844d9543SConrad Meyer size_t i; 201844d9543SConrad Meyer 202844d9543SConrad Meyer for (i = 0; i < nitems(sc->queues); i++) { 203844d9543SConrad Meyer qp = &sc->queues[i]; 204844d9543SConrad Meyer 205844d9543SConrad Meyer qp->cq_softc = sc; 206844d9543SConrad Meyer qp->cq_qindex = i; 207844d9543SConrad Meyer mtx_init(&qp->cq_lock, "ccp queue", NULL, MTX_DEF); 208844d9543SConrad Meyer /* XXX - arbitrarily chosen sizes */ 209844d9543SConrad Meyer qp->cq_sg_crp = sglist_alloc(32, M_WAITOK); 210844d9543SConrad Meyer /* Two more SGEs than sg_crp to accommodate ipad. */ 211844d9543SConrad Meyer qp->cq_sg_ulptx = sglist_alloc(34, M_WAITOK); 212844d9543SConrad Meyer qp->cq_sg_dst = sglist_alloc(2, M_WAITOK); 213844d9543SConrad Meyer } 214844d9543SConrad Meyer } 215844d9543SConrad Meyer 216844d9543SConrad Meyer static void 217844d9543SConrad Meyer ccp_free_queues(struct ccp_softc *sc) 218844d9543SConrad Meyer { 219844d9543SConrad Meyer struct ccp_queue *qp; 220844d9543SConrad Meyer size_t i; 221844d9543SConrad Meyer 222844d9543SConrad Meyer for (i = 0; i < nitems(sc->queues); i++) { 223844d9543SConrad Meyer qp = &sc->queues[i]; 224844d9543SConrad Meyer 225844d9543SConrad Meyer mtx_destroy(&qp->cq_lock); 226844d9543SConrad Meyer sglist_free(qp->cq_sg_crp); 227844d9543SConrad Meyer sglist_free(qp->cq_sg_ulptx); 228844d9543SConrad Meyer sglist_free(qp->cq_sg_dst); 229844d9543SConrad Meyer } 230844d9543SConrad Meyer } 231844d9543SConrad Meyer 232844d9543SConrad Meyer static int 233844d9543SConrad Meyer ccp_attach(device_t dev) 234844d9543SConrad Meyer { 235844d9543SConrad Meyer struct ccp_softc *sc; 236844d9543SConrad Meyer int error; 237844d9543SConrad Meyer 238844d9543SConrad Meyer sc = device_get_softc(dev); 239844d9543SConrad Meyer sc->dev = dev; 240844d9543SConrad Meyer 2411b0909d5SConrad Meyer sc->cid = crypto_get_driverid(dev, sizeof(struct ccp_session), 2421b0909d5SConrad Meyer CRYPTOCAP_F_HARDWARE); 243844d9543SConrad Meyer if (sc->cid < 0) { 244844d9543SConrad Meyer device_printf(dev, "could not get crypto driver id\n"); 245844d9543SConrad Meyer return (ENXIO); 246844d9543SConrad Meyer } 247844d9543SConrad Meyer 248844d9543SConrad Meyer error = ccp_hw_attach(dev); 249844d9543SConrad Meyer if (error != 0) 250844d9543SConrad Meyer return (error); 251844d9543SConrad Meyer 252844d9543SConrad Meyer mtx_init(&sc->lock, "ccp", NULL, MTX_DEF); 253844d9543SConrad Meyer 254844d9543SConrad Meyer ccp_initialize_queues(sc); 255844d9543SConrad Meyer 256844d9543SConrad Meyer if (g_ccp_softc == NULL) { 257844d9543SConrad Meyer g_ccp_softc = sc; 258844d9543SConrad Meyer if ((sc->hw_features & VERSION_CAP_TRNG) != 0) 259844d9543SConrad Meyer random_source_register(&random_ccp); 260844d9543SConrad Meyer } 261844d9543SConrad Meyer 262844d9543SConrad Meyer if ((sc->hw_features & VERSION_CAP_AES) != 0) { 263844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_AES_CBC, 0, 0); 264844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_AES_ICM, 0, 0); 265844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_AES_NIST_GCM_16, 0, 0); 266844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_AES_128_NIST_GMAC, 0, 0); 267844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_AES_192_NIST_GMAC, 0, 0); 268844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_AES_256_NIST_GMAC, 0, 0); 269844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_AES_XTS, 0, 0); 270844d9543SConrad Meyer } 271844d9543SConrad Meyer if ((sc->hw_features & VERSION_CAP_SHA) != 0) { 272844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_SHA1_HMAC, 0, 0); 273844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_SHA2_256_HMAC, 0, 0); 274844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_SHA2_384_HMAC, 0, 0); 275844d9543SConrad Meyer crypto_register(sc->cid, CRYPTO_SHA2_512_HMAC, 0, 0); 276844d9543SConrad Meyer } 277844d9543SConrad Meyer 278844d9543SConrad Meyer return (0); 279844d9543SConrad Meyer } 280844d9543SConrad Meyer 281844d9543SConrad Meyer static int 282844d9543SConrad Meyer ccp_detach(device_t dev) 283844d9543SConrad Meyer { 284844d9543SConrad Meyer struct ccp_softc *sc; 285844d9543SConrad Meyer 286844d9543SConrad Meyer sc = device_get_softc(dev); 287844d9543SConrad Meyer 288844d9543SConrad Meyer mtx_lock(&sc->lock); 289844d9543SConrad Meyer sc->detaching = true; 290844d9543SConrad Meyer mtx_unlock(&sc->lock); 291844d9543SConrad Meyer 292844d9543SConrad Meyer crypto_unregister_all(sc->cid); 293844d9543SConrad Meyer if (g_ccp_softc == sc && (sc->hw_features & VERSION_CAP_TRNG) != 0) 294844d9543SConrad Meyer random_source_deregister(&random_ccp); 295844d9543SConrad Meyer 296844d9543SConrad Meyer ccp_hw_detach(dev); 297844d9543SConrad Meyer ccp_free_queues(sc); 298844d9543SConrad Meyer 299844d9543SConrad Meyer if (g_ccp_softc == sc) 300844d9543SConrad Meyer g_ccp_softc = NULL; 301844d9543SConrad Meyer 302844d9543SConrad Meyer mtx_destroy(&sc->lock); 303844d9543SConrad Meyer return (0); 304844d9543SConrad Meyer } 305844d9543SConrad Meyer 306844d9543SConrad Meyer static void 307844d9543SConrad Meyer ccp_init_hmac_digest(struct ccp_session *s, int cri_alg, char *key, 308844d9543SConrad Meyer int klen) 309844d9543SConrad Meyer { 310844d9543SConrad Meyer union authctx auth_ctx; 311844d9543SConrad Meyer struct auth_hash *axf; 312844d9543SConrad Meyer u_int i; 313844d9543SConrad Meyer 314844d9543SConrad Meyer /* 315844d9543SConrad Meyer * If the key is larger than the block size, use the digest of 316844d9543SConrad Meyer * the key as the key instead. 317844d9543SConrad Meyer */ 318844d9543SConrad Meyer axf = s->hmac.auth_hash; 319844d9543SConrad Meyer klen /= 8; 320844d9543SConrad Meyer if (klen > axf->blocksize) { 321844d9543SConrad Meyer axf->Init(&auth_ctx); 322844d9543SConrad Meyer axf->Update(&auth_ctx, key, klen); 323844d9543SConrad Meyer axf->Final(s->hmac.ipad, &auth_ctx); 324844d9543SConrad Meyer explicit_bzero(&auth_ctx, sizeof(auth_ctx)); 325844d9543SConrad Meyer klen = axf->hashsize; 326844d9543SConrad Meyer } else 327844d9543SConrad Meyer memcpy(s->hmac.ipad, key, klen); 328844d9543SConrad Meyer 329844d9543SConrad Meyer memset(s->hmac.ipad + klen, 0, axf->blocksize - klen); 330844d9543SConrad Meyer memcpy(s->hmac.opad, s->hmac.ipad, axf->blocksize); 331844d9543SConrad Meyer 332844d9543SConrad Meyer for (i = 0; i < axf->blocksize; i++) { 333844d9543SConrad Meyer s->hmac.ipad[i] ^= HMAC_IPAD_VAL; 334844d9543SConrad Meyer s->hmac.opad[i] ^= HMAC_OPAD_VAL; 335844d9543SConrad Meyer } 336844d9543SConrad Meyer } 337844d9543SConrad Meyer 338844d9543SConrad Meyer static int 339844d9543SConrad Meyer ccp_aes_check_keylen(int alg, int klen) 340844d9543SConrad Meyer { 341844d9543SConrad Meyer 342844d9543SConrad Meyer switch (klen) { 343844d9543SConrad Meyer case 128: 344844d9543SConrad Meyer case 192: 345844d9543SConrad Meyer if (alg == CRYPTO_AES_XTS) 346844d9543SConrad Meyer return (EINVAL); 347844d9543SConrad Meyer break; 348844d9543SConrad Meyer case 256: 349844d9543SConrad Meyer break; 350844d9543SConrad Meyer case 512: 351844d9543SConrad Meyer if (alg != CRYPTO_AES_XTS) 352844d9543SConrad Meyer return (EINVAL); 353844d9543SConrad Meyer break; 354844d9543SConrad Meyer default: 355844d9543SConrad Meyer return (EINVAL); 356844d9543SConrad Meyer } 357844d9543SConrad Meyer return (0); 358844d9543SConrad Meyer } 359844d9543SConrad Meyer 360844d9543SConrad Meyer static void 361844d9543SConrad Meyer ccp_aes_setkey(struct ccp_session *s, int alg, const void *key, int klen) 362844d9543SConrad Meyer { 363844d9543SConrad Meyer unsigned kbits; 364844d9543SConrad Meyer 365844d9543SConrad Meyer if (alg == CRYPTO_AES_XTS) 366844d9543SConrad Meyer kbits = klen / 2; 367844d9543SConrad Meyer else 368844d9543SConrad Meyer kbits = klen; 369844d9543SConrad Meyer 370844d9543SConrad Meyer switch (kbits) { 371844d9543SConrad Meyer case 128: 372844d9543SConrad Meyer s->blkcipher.cipher_type = CCP_AES_TYPE_128; 373844d9543SConrad Meyer break; 374844d9543SConrad Meyer case 192: 375844d9543SConrad Meyer s->blkcipher.cipher_type = CCP_AES_TYPE_192; 376844d9543SConrad Meyer break; 377844d9543SConrad Meyer case 256: 378844d9543SConrad Meyer s->blkcipher.cipher_type = CCP_AES_TYPE_256; 379844d9543SConrad Meyer break; 380844d9543SConrad Meyer default: 381844d9543SConrad Meyer panic("should not get here"); 382844d9543SConrad Meyer } 383844d9543SConrad Meyer 384844d9543SConrad Meyer s->blkcipher.key_len = klen / 8; 385844d9543SConrad Meyer memcpy(s->blkcipher.enckey, key, s->blkcipher.key_len); 386844d9543SConrad Meyer } 387844d9543SConrad Meyer 388844d9543SConrad Meyer static int 3891b0909d5SConrad Meyer ccp_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) 390844d9543SConrad Meyer { 391844d9543SConrad Meyer struct ccp_softc *sc; 392844d9543SConrad Meyer struct ccp_session *s; 393844d9543SConrad Meyer struct auth_hash *auth_hash; 394844d9543SConrad Meyer struct cryptoini *c, *hash, *cipher; 395844d9543SConrad Meyer enum ccp_aes_mode cipher_mode; 396844d9543SConrad Meyer unsigned auth_mode, iv_len; 397844d9543SConrad Meyer unsigned partial_digest_len; 398844d9543SConrad Meyer unsigned q; 3991b0909d5SConrad Meyer int error; 400844d9543SConrad Meyer bool gcm_hash; 401844d9543SConrad Meyer 4021b0909d5SConrad Meyer if (cri == NULL) 403844d9543SConrad Meyer return (EINVAL); 404844d9543SConrad Meyer 4051b0909d5SConrad Meyer s = crypto_get_driver_session(cses); 4061b0909d5SConrad Meyer 407844d9543SConrad Meyer gcm_hash = false; 408844d9543SConrad Meyer cipher = NULL; 409844d9543SConrad Meyer hash = NULL; 410844d9543SConrad Meyer auth_hash = NULL; 411844d9543SConrad Meyer /* XXX reconcile auth_mode with use by ccp_sha */ 412844d9543SConrad Meyer auth_mode = 0; 413844d9543SConrad Meyer cipher_mode = CCP_AES_MODE_ECB; 414844d9543SConrad Meyer iv_len = 0; 415844d9543SConrad Meyer partial_digest_len = 0; 416844d9543SConrad Meyer for (c = cri; c != NULL; c = c->cri_next) { 417844d9543SConrad Meyer switch (c->cri_alg) { 418844d9543SConrad Meyer case CRYPTO_SHA1_HMAC: 419844d9543SConrad Meyer case CRYPTO_SHA2_256_HMAC: 420844d9543SConrad Meyer case CRYPTO_SHA2_384_HMAC: 421844d9543SConrad Meyer case CRYPTO_SHA2_512_HMAC: 422844d9543SConrad Meyer case CRYPTO_AES_128_NIST_GMAC: 423844d9543SConrad Meyer case CRYPTO_AES_192_NIST_GMAC: 424844d9543SConrad Meyer case CRYPTO_AES_256_NIST_GMAC: 425844d9543SConrad Meyer if (hash) 426844d9543SConrad Meyer return (EINVAL); 427844d9543SConrad Meyer hash = c; 428844d9543SConrad Meyer switch (c->cri_alg) { 429844d9543SConrad Meyer case CRYPTO_SHA1_HMAC: 430844d9543SConrad Meyer auth_hash = &auth_hash_hmac_sha1; 431844d9543SConrad Meyer auth_mode = SHA1; 432844d9543SConrad Meyer partial_digest_len = SHA1_HASH_LEN; 433844d9543SConrad Meyer break; 434844d9543SConrad Meyer case CRYPTO_SHA2_256_HMAC: 435844d9543SConrad Meyer auth_hash = &auth_hash_hmac_sha2_256; 436844d9543SConrad Meyer auth_mode = SHA2_256; 437844d9543SConrad Meyer partial_digest_len = SHA2_256_HASH_LEN; 438844d9543SConrad Meyer break; 439844d9543SConrad Meyer case CRYPTO_SHA2_384_HMAC: 440844d9543SConrad Meyer auth_hash = &auth_hash_hmac_sha2_384; 441844d9543SConrad Meyer auth_mode = SHA2_384; 442844d9543SConrad Meyer partial_digest_len = SHA2_512_HASH_LEN; 443844d9543SConrad Meyer break; 444844d9543SConrad Meyer case CRYPTO_SHA2_512_HMAC: 445844d9543SConrad Meyer auth_hash = &auth_hash_hmac_sha2_512; 446844d9543SConrad Meyer auth_mode = SHA2_512; 447844d9543SConrad Meyer partial_digest_len = SHA2_512_HASH_LEN; 448844d9543SConrad Meyer break; 449844d9543SConrad Meyer case CRYPTO_AES_128_NIST_GMAC: 450844d9543SConrad Meyer case CRYPTO_AES_192_NIST_GMAC: 451844d9543SConrad Meyer case CRYPTO_AES_256_NIST_GMAC: 452844d9543SConrad Meyer gcm_hash = true; 453844d9543SConrad Meyer #if 0 454844d9543SConrad Meyer auth_mode = CHCR_SCMD_AUTH_MODE_GHASH; 455844d9543SConrad Meyer #endif 456844d9543SConrad Meyer break; 457844d9543SConrad Meyer } 458844d9543SConrad Meyer break; 459844d9543SConrad Meyer case CRYPTO_AES_CBC: 460844d9543SConrad Meyer case CRYPTO_AES_ICM: 461844d9543SConrad Meyer case CRYPTO_AES_NIST_GCM_16: 462844d9543SConrad Meyer case CRYPTO_AES_XTS: 463844d9543SConrad Meyer if (cipher) 464844d9543SConrad Meyer return (EINVAL); 465844d9543SConrad Meyer cipher = c; 466844d9543SConrad Meyer switch (c->cri_alg) { 467844d9543SConrad Meyer case CRYPTO_AES_CBC: 468844d9543SConrad Meyer cipher_mode = CCP_AES_MODE_CBC; 469844d9543SConrad Meyer iv_len = AES_BLOCK_LEN; 470844d9543SConrad Meyer break; 471844d9543SConrad Meyer case CRYPTO_AES_ICM: 472844d9543SConrad Meyer cipher_mode = CCP_AES_MODE_CTR; 473844d9543SConrad Meyer iv_len = AES_BLOCK_LEN; 474844d9543SConrad Meyer break; 475844d9543SConrad Meyer case CRYPTO_AES_NIST_GCM_16: 476844d9543SConrad Meyer cipher_mode = CCP_AES_MODE_GCTR; 477844d9543SConrad Meyer iv_len = AES_GCM_IV_LEN; 478844d9543SConrad Meyer break; 479844d9543SConrad Meyer case CRYPTO_AES_XTS: 480844d9543SConrad Meyer cipher_mode = CCP_AES_MODE_XTS; 481844d9543SConrad Meyer iv_len = AES_BLOCK_LEN; 482844d9543SConrad Meyer break; 483844d9543SConrad Meyer } 484844d9543SConrad Meyer if (c->cri_key != NULL) { 485844d9543SConrad Meyer error = ccp_aes_check_keylen(c->cri_alg, 486844d9543SConrad Meyer c->cri_klen); 487844d9543SConrad Meyer if (error != 0) 488844d9543SConrad Meyer return (error); 489844d9543SConrad Meyer } 490844d9543SConrad Meyer break; 491844d9543SConrad Meyer default: 492844d9543SConrad Meyer return (EINVAL); 493844d9543SConrad Meyer } 494844d9543SConrad Meyer } 495844d9543SConrad Meyer if (gcm_hash != (cipher_mode == CCP_AES_MODE_GCTR)) 496844d9543SConrad Meyer return (EINVAL); 497844d9543SConrad Meyer if (hash == NULL && cipher == NULL) 498844d9543SConrad Meyer return (EINVAL); 499844d9543SConrad Meyer if (hash != NULL && hash->cri_key == NULL) 500844d9543SConrad Meyer return (EINVAL); 501844d9543SConrad Meyer 502844d9543SConrad Meyer sc = device_get_softc(dev); 503844d9543SConrad Meyer mtx_lock(&sc->lock); 504844d9543SConrad Meyer if (sc->detaching) { 505844d9543SConrad Meyer mtx_unlock(&sc->lock); 506844d9543SConrad Meyer return (ENXIO); 507844d9543SConrad Meyer } 508844d9543SConrad Meyer 509844d9543SConrad Meyer /* Just grab the first usable queue for now. */ 510844d9543SConrad Meyer for (q = 0; q < nitems(sc->queues); q++) 511844d9543SConrad Meyer if ((sc->valid_queues & (1 << q)) != 0) 512844d9543SConrad Meyer break; 513844d9543SConrad Meyer if (q == nitems(sc->queues)) { 514844d9543SConrad Meyer mtx_unlock(&sc->lock); 515844d9543SConrad Meyer return (ENXIO); 516844d9543SConrad Meyer } 517844d9543SConrad Meyer s->queue = q; 518844d9543SConrad Meyer 519844d9543SConrad Meyer if (gcm_hash) 520844d9543SConrad Meyer s->mode = GCM; 521844d9543SConrad Meyer else if (hash != NULL && cipher != NULL) 522844d9543SConrad Meyer s->mode = AUTHENC; 523844d9543SConrad Meyer else if (hash != NULL) 524844d9543SConrad Meyer s->mode = HMAC; 525844d9543SConrad Meyer else { 526844d9543SConrad Meyer MPASS(cipher != NULL); 527844d9543SConrad Meyer s->mode = BLKCIPHER; 528844d9543SConrad Meyer } 529844d9543SConrad Meyer if (gcm_hash) { 530844d9543SConrad Meyer if (hash->cri_mlen == 0) 531844d9543SConrad Meyer s->gmac.hash_len = AES_GMAC_HASH_LEN; 532844d9543SConrad Meyer else 533844d9543SConrad Meyer s->gmac.hash_len = hash->cri_mlen; 534844d9543SConrad Meyer } else if (hash != NULL) { 535844d9543SConrad Meyer s->hmac.auth_hash = auth_hash; 536844d9543SConrad Meyer s->hmac.auth_mode = auth_mode; 537844d9543SConrad Meyer s->hmac.partial_digest_len = partial_digest_len; 538844d9543SConrad Meyer if (hash->cri_mlen == 0) 539844d9543SConrad Meyer s->hmac.hash_len = auth_hash->hashsize; 540844d9543SConrad Meyer else 541844d9543SConrad Meyer s->hmac.hash_len = hash->cri_mlen; 542844d9543SConrad Meyer ccp_init_hmac_digest(s, hash->cri_alg, hash->cri_key, 543844d9543SConrad Meyer hash->cri_klen); 544844d9543SConrad Meyer } 545844d9543SConrad Meyer if (cipher != NULL) { 546844d9543SConrad Meyer s->blkcipher.cipher_mode = cipher_mode; 547844d9543SConrad Meyer s->blkcipher.iv_len = iv_len; 548844d9543SConrad Meyer if (cipher->cri_key != NULL) 549844d9543SConrad Meyer ccp_aes_setkey(s, cipher->cri_alg, cipher->cri_key, 550844d9543SConrad Meyer cipher->cri_klen); 551844d9543SConrad Meyer } 552844d9543SConrad Meyer 553844d9543SConrad Meyer s->active = true; 554844d9543SConrad Meyer mtx_unlock(&sc->lock); 555844d9543SConrad Meyer 556844d9543SConrad Meyer return (0); 557844d9543SConrad Meyer } 558844d9543SConrad Meyer 5591b0909d5SConrad Meyer static void 5601b0909d5SConrad Meyer ccp_freesession(device_t dev, crypto_session_t cses) 561844d9543SConrad Meyer { 5621b0909d5SConrad Meyer struct ccp_session *s; 563844d9543SConrad Meyer 5641b0909d5SConrad Meyer s = crypto_get_driver_session(cses); 5651b0909d5SConrad Meyer 5661b0909d5SConrad Meyer if (s->pending != 0) 567844d9543SConrad Meyer device_printf(dev, 5681b0909d5SConrad Meyer "session %p freed with %d pending requests\n", s, 5691b0909d5SConrad Meyer s->pending); 5701b0909d5SConrad Meyer s->active = false; 571844d9543SConrad Meyer } 572844d9543SConrad Meyer 573844d9543SConrad Meyer static int 574844d9543SConrad Meyer ccp_process(device_t dev, struct cryptop *crp, int hint) 575844d9543SConrad Meyer { 576844d9543SConrad Meyer struct ccp_softc *sc; 577844d9543SConrad Meyer struct ccp_queue *qp; 578844d9543SConrad Meyer struct ccp_session *s; 579844d9543SConrad Meyer struct cryptodesc *crd, *crda, *crde; 580844d9543SConrad Meyer int error; 581844d9543SConrad Meyer bool qpheld; 582844d9543SConrad Meyer 583844d9543SConrad Meyer qpheld = false; 584844d9543SConrad Meyer qp = NULL; 585844d9543SConrad Meyer if (crp == NULL) 586844d9543SConrad Meyer return (EINVAL); 587844d9543SConrad Meyer 588844d9543SConrad Meyer crd = crp->crp_desc; 5891b0909d5SConrad Meyer s = crypto_get_driver_session(crp->crp_session); 590844d9543SConrad Meyer sc = device_get_softc(dev); 591844d9543SConrad Meyer mtx_lock(&sc->lock); 592844d9543SConrad Meyer qp = &sc->queues[s->queue]; 593844d9543SConrad Meyer mtx_unlock(&sc->lock); 594844d9543SConrad Meyer error = ccp_queue_acquire_reserve(qp, 1 /* placeholder */, M_NOWAIT); 595844d9543SConrad Meyer if (error != 0) 596844d9543SConrad Meyer goto out; 597844d9543SConrad Meyer qpheld = true; 598844d9543SConrad Meyer 599844d9543SConrad Meyer error = ccp_populate_sglist(qp->cq_sg_crp, crp); 600844d9543SConrad Meyer if (error != 0) 601844d9543SConrad Meyer goto out; 602844d9543SConrad Meyer 603844d9543SConrad Meyer switch (s->mode) { 604844d9543SConrad Meyer case HMAC: 605844d9543SConrad Meyer if (crd->crd_flags & CRD_F_KEY_EXPLICIT) 606844d9543SConrad Meyer ccp_init_hmac_digest(s, crd->crd_alg, crd->crd_key, 607844d9543SConrad Meyer crd->crd_klen); 608844d9543SConrad Meyer error = ccp_hmac(qp, s, crp); 609844d9543SConrad Meyer break; 610844d9543SConrad Meyer case BLKCIPHER: 611844d9543SConrad Meyer if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { 612844d9543SConrad Meyer error = ccp_aes_check_keylen(crd->crd_alg, 613844d9543SConrad Meyer crd->crd_klen); 614844d9543SConrad Meyer if (error != 0) 615844d9543SConrad Meyer break; 616844d9543SConrad Meyer ccp_aes_setkey(s, crd->crd_alg, crd->crd_key, 617844d9543SConrad Meyer crd->crd_klen); 618844d9543SConrad Meyer } 619844d9543SConrad Meyer error = ccp_blkcipher(qp, s, crp); 620844d9543SConrad Meyer break; 621844d9543SConrad Meyer case AUTHENC: 622844d9543SConrad Meyer error = 0; 623844d9543SConrad Meyer switch (crd->crd_alg) { 624844d9543SConrad Meyer case CRYPTO_AES_CBC: 625844d9543SConrad Meyer case CRYPTO_AES_ICM: 626844d9543SConrad Meyer case CRYPTO_AES_XTS: 627844d9543SConrad Meyer /* Only encrypt-then-authenticate supported. */ 628844d9543SConrad Meyer crde = crd; 629844d9543SConrad Meyer crda = crd->crd_next; 630844d9543SConrad Meyer if (!(crde->crd_flags & CRD_F_ENCRYPT)) { 631844d9543SConrad Meyer error = EINVAL; 632844d9543SConrad Meyer break; 633844d9543SConrad Meyer } 634844d9543SConrad Meyer s->cipher_first = true; 635844d9543SConrad Meyer break; 636844d9543SConrad Meyer default: 637844d9543SConrad Meyer crda = crd; 638844d9543SConrad Meyer crde = crd->crd_next; 639844d9543SConrad Meyer if (crde->crd_flags & CRD_F_ENCRYPT) { 640844d9543SConrad Meyer error = EINVAL; 641844d9543SConrad Meyer break; 642844d9543SConrad Meyer } 643844d9543SConrad Meyer s->cipher_first = false; 644844d9543SConrad Meyer break; 645844d9543SConrad Meyer } 646844d9543SConrad Meyer if (error != 0) 647844d9543SConrad Meyer break; 648844d9543SConrad Meyer if (crda->crd_flags & CRD_F_KEY_EXPLICIT) 649844d9543SConrad Meyer ccp_init_hmac_digest(s, crda->crd_alg, crda->crd_key, 650844d9543SConrad Meyer crda->crd_klen); 651844d9543SConrad Meyer if (crde->crd_flags & CRD_F_KEY_EXPLICIT) { 652844d9543SConrad Meyer error = ccp_aes_check_keylen(crde->crd_alg, 653844d9543SConrad Meyer crde->crd_klen); 654844d9543SConrad Meyer if (error != 0) 655844d9543SConrad Meyer break; 656844d9543SConrad Meyer ccp_aes_setkey(s, crde->crd_alg, crde->crd_key, 657844d9543SConrad Meyer crde->crd_klen); 658844d9543SConrad Meyer } 659844d9543SConrad Meyer error = ccp_authenc(qp, s, crp, crda, crde); 660844d9543SConrad Meyer break; 661844d9543SConrad Meyer case GCM: 662844d9543SConrad Meyer error = 0; 663844d9543SConrad Meyer if (crd->crd_alg == CRYPTO_AES_NIST_GCM_16) { 664844d9543SConrad Meyer crde = crd; 665844d9543SConrad Meyer crda = crd->crd_next; 666844d9543SConrad Meyer s->cipher_first = true; 667844d9543SConrad Meyer } else { 668844d9543SConrad Meyer crda = crd; 669844d9543SConrad Meyer crde = crd->crd_next; 670844d9543SConrad Meyer s->cipher_first = false; 671844d9543SConrad Meyer } 672844d9543SConrad Meyer if (crde->crd_flags & CRD_F_KEY_EXPLICIT) { 673844d9543SConrad Meyer error = ccp_aes_check_keylen(crde->crd_alg, 674844d9543SConrad Meyer crde->crd_klen); 675844d9543SConrad Meyer if (error != 0) 676844d9543SConrad Meyer break; 677844d9543SConrad Meyer ccp_aes_setkey(s, crde->crd_alg, crde->crd_key, 678844d9543SConrad Meyer crde->crd_klen); 679844d9543SConrad Meyer } 680844d9543SConrad Meyer if (crde->crd_len == 0) { 681844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 682844d9543SConrad Meyer ccp_gcm_soft(s, crp, crda, crde); 683844d9543SConrad Meyer return (0); 684844d9543SConrad Meyer } 685844d9543SConrad Meyer error = ccp_gcm(qp, s, crp, crda, crde); 686844d9543SConrad Meyer break; 687844d9543SConrad Meyer } 688844d9543SConrad Meyer 689844d9543SConrad Meyer if (error == 0) 690844d9543SConrad Meyer s->pending++; 691844d9543SConrad Meyer 692844d9543SConrad Meyer out: 693844d9543SConrad Meyer if (qpheld) { 694844d9543SConrad Meyer if (error != 0) { 695844d9543SConrad Meyer /* 696844d9543SConrad Meyer * Squash EAGAIN so callers don't uselessly and 697844d9543SConrad Meyer * expensively retry if the ring was full. 698844d9543SConrad Meyer */ 699844d9543SConrad Meyer if (error == EAGAIN) 700844d9543SConrad Meyer error = ENOMEM; 701844d9543SConrad Meyer ccp_queue_abort(qp); 702844d9543SConrad Meyer } else 703844d9543SConrad Meyer ccp_queue_release(qp); 704844d9543SConrad Meyer } 705844d9543SConrad Meyer 706844d9543SConrad Meyer if (error != 0) { 707844d9543SConrad Meyer DPRINTF(dev, "%s: early error:%d\n", __func__, error); 708844d9543SConrad Meyer crp->crp_etype = error; 709844d9543SConrad Meyer crypto_done(crp); 710844d9543SConrad Meyer } 711844d9543SConrad Meyer return (0); 712844d9543SConrad Meyer } 713844d9543SConrad Meyer 714844d9543SConrad Meyer static device_method_t ccp_methods[] = { 715844d9543SConrad Meyer DEVMETHOD(device_probe, ccp_probe), 716844d9543SConrad Meyer DEVMETHOD(device_attach, ccp_attach), 717844d9543SConrad Meyer DEVMETHOD(device_detach, ccp_detach), 718844d9543SConrad Meyer 719844d9543SConrad Meyer DEVMETHOD(cryptodev_newsession, ccp_newsession), 720844d9543SConrad Meyer DEVMETHOD(cryptodev_freesession, ccp_freesession), 721844d9543SConrad Meyer DEVMETHOD(cryptodev_process, ccp_process), 722844d9543SConrad Meyer 723844d9543SConrad Meyer DEVMETHOD_END 724844d9543SConrad Meyer }; 725844d9543SConrad Meyer 726844d9543SConrad Meyer static driver_t ccp_driver = { 727844d9543SConrad Meyer "ccp", 728844d9543SConrad Meyer ccp_methods, 729844d9543SConrad Meyer sizeof(struct ccp_softc) 730844d9543SConrad Meyer }; 731844d9543SConrad Meyer 732844d9543SConrad Meyer static devclass_t ccp_devclass; 733844d9543SConrad Meyer DRIVER_MODULE(ccp, pci, ccp_driver, ccp_devclass, NULL, NULL); 734844d9543SConrad Meyer MODULE_VERSION(ccp, 1); 735844d9543SConrad Meyer MODULE_DEPEND(ccp, crypto, 1, 1, 1); 736844d9543SConrad Meyer MODULE_DEPEND(ccp, random_device, 1, 1, 1); 73791eeadc5SWarner Losh #if 0 /* There are enough known issues that we shouldn't load automatically */ 738*329e817fSWarner Losh MODULE_PNP_INFO("W32:vendor/device", pci, ccp, ccp_ids, 739b7220273SWarner Losh nitems(ccp_ids)); 74091eeadc5SWarner Losh #endif 741844d9543SConrad Meyer 742844d9543SConrad Meyer static int 743844d9543SConrad Meyer ccp_queue_reserve_space(struct ccp_queue *qp, unsigned n, int mflags) 744844d9543SConrad Meyer { 745844d9543SConrad Meyer struct ccp_softc *sc; 746844d9543SConrad Meyer 747844d9543SConrad Meyer mtx_assert(&qp->cq_lock, MA_OWNED); 748844d9543SConrad Meyer sc = qp->cq_softc; 749844d9543SConrad Meyer 750844d9543SConrad Meyer if (n < 1 || n >= (1 << sc->ring_size_order)) 751844d9543SConrad Meyer return (EINVAL); 752844d9543SConrad Meyer 753844d9543SConrad Meyer while (true) { 754844d9543SConrad Meyer if (ccp_queue_get_ring_space(qp) >= n) 755844d9543SConrad Meyer return (0); 756844d9543SConrad Meyer if ((mflags & M_WAITOK) == 0) 757844d9543SConrad Meyer return (EAGAIN); 758844d9543SConrad Meyer qp->cq_waiting = true; 759844d9543SConrad Meyer msleep(&qp->cq_tail, &qp->cq_lock, 0, "ccpqfull", 0); 760844d9543SConrad Meyer } 761844d9543SConrad Meyer } 762844d9543SConrad Meyer 763844d9543SConrad Meyer int 764844d9543SConrad Meyer ccp_queue_acquire_reserve(struct ccp_queue *qp, unsigned n, int mflags) 765844d9543SConrad Meyer { 766844d9543SConrad Meyer int error; 767844d9543SConrad Meyer 768844d9543SConrad Meyer mtx_lock(&qp->cq_lock); 769844d9543SConrad Meyer qp->cq_acq_tail = qp->cq_tail; 770844d9543SConrad Meyer error = ccp_queue_reserve_space(qp, n, mflags); 771844d9543SConrad Meyer if (error != 0) 772844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 773844d9543SConrad Meyer return (error); 774844d9543SConrad Meyer } 775844d9543SConrad Meyer 776844d9543SConrad Meyer void 777844d9543SConrad Meyer ccp_queue_release(struct ccp_queue *qp) 778844d9543SConrad Meyer { 779844d9543SConrad Meyer 780844d9543SConrad Meyer mtx_assert(&qp->cq_lock, MA_OWNED); 781844d9543SConrad Meyer if (qp->cq_tail != qp->cq_acq_tail) { 782844d9543SConrad Meyer wmb(); 783844d9543SConrad Meyer ccp_queue_write_tail(qp); 784844d9543SConrad Meyer } 785844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 786844d9543SConrad Meyer } 787844d9543SConrad Meyer 788844d9543SConrad Meyer void 789844d9543SConrad Meyer ccp_queue_abort(struct ccp_queue *qp) 790844d9543SConrad Meyer { 791844d9543SConrad Meyer unsigned i; 792844d9543SConrad Meyer 793844d9543SConrad Meyer mtx_assert(&qp->cq_lock, MA_OWNED); 794844d9543SConrad Meyer 795844d9543SConrad Meyer /* Wipe out any descriptors associated with this aborted txn. */ 796844d9543SConrad Meyer for (i = qp->cq_acq_tail; i != qp->cq_tail; 797844d9543SConrad Meyer i = (i + 1) % (1 << qp->cq_softc->ring_size_order)) { 798844d9543SConrad Meyer memset(&qp->desc_ring[i], 0, sizeof(qp->desc_ring[i])); 799844d9543SConrad Meyer } 800844d9543SConrad Meyer qp->cq_tail = qp->cq_acq_tail; 801844d9543SConrad Meyer 802844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 803844d9543SConrad Meyer } 804844d9543SConrad Meyer 805844d9543SConrad Meyer #ifdef DDB 806844d9543SConrad Meyer #define _db_show_lock(lo) LOCK_CLASS(lo)->lc_ddb_show(lo) 807844d9543SConrad Meyer #define db_show_lock(lk) _db_show_lock(&(lk)->lock_object) 808844d9543SConrad Meyer static void 809844d9543SConrad Meyer db_show_ccp_sc(struct ccp_softc *sc) 810844d9543SConrad Meyer { 811844d9543SConrad Meyer 812844d9543SConrad Meyer db_printf("ccp softc at %p\n", sc); 813844d9543SConrad Meyer db_printf(" cid: %d\n", (int)sc->cid); 814844d9543SConrad Meyer 815844d9543SConrad Meyer db_printf(" lock: "); 816844d9543SConrad Meyer db_show_lock(&sc->lock); 817844d9543SConrad Meyer 818844d9543SConrad Meyer db_printf(" detaching: %d\n", (int)sc->detaching); 819844d9543SConrad Meyer db_printf(" ring_size_order: %u\n", sc->ring_size_order); 820844d9543SConrad Meyer 821844d9543SConrad Meyer db_printf(" hw_version: %d\n", (int)sc->hw_version); 822844d9543SConrad Meyer db_printf(" hw_features: %b\n", (int)sc->hw_features, 823844d9543SConrad Meyer "\20\24ELFC\23TRNG\22Zip_Compress\16Zip_Decompress\13ECC\12RSA" 824844d9543SConrad Meyer "\11SHA\0103DES\07AES"); 825844d9543SConrad Meyer 826844d9543SConrad Meyer db_printf(" hw status:\n"); 827844d9543SConrad Meyer db_ccp_show_hw(sc); 828844d9543SConrad Meyer } 829844d9543SConrad Meyer 830844d9543SConrad Meyer static void 831844d9543SConrad Meyer db_show_ccp_qp(struct ccp_queue *qp) 832844d9543SConrad Meyer { 833844d9543SConrad Meyer 834844d9543SConrad Meyer db_printf(" lock: "); 835844d9543SConrad Meyer db_show_lock(&qp->cq_lock); 836844d9543SConrad Meyer 837844d9543SConrad Meyer db_printf(" cq_qindex: %u\n", qp->cq_qindex); 838844d9543SConrad Meyer db_printf(" cq_softc: %p\n", qp->cq_softc); 839844d9543SConrad Meyer 840844d9543SConrad Meyer db_printf(" head: %u\n", qp->cq_head); 841844d9543SConrad Meyer db_printf(" tail: %u\n", qp->cq_tail); 842844d9543SConrad Meyer db_printf(" acq_tail: %u\n", qp->cq_acq_tail); 843844d9543SConrad Meyer db_printf(" desc_ring: %p\n", qp->desc_ring); 844844d9543SConrad Meyer db_printf(" completions_ring: %p\n", qp->completions_ring); 845844d9543SConrad Meyer db_printf(" descriptors (phys): 0x%jx\n", 846844d9543SConrad Meyer (uintmax_t)qp->desc_ring_bus_addr); 847844d9543SConrad Meyer 848844d9543SConrad Meyer db_printf(" hw status:\n"); 849844d9543SConrad Meyer db_ccp_show_queue_hw(qp); 850844d9543SConrad Meyer } 851844d9543SConrad Meyer 852844d9543SConrad Meyer DB_SHOW_COMMAND(ccp, db_show_ccp) 853844d9543SConrad Meyer { 854844d9543SConrad Meyer struct ccp_softc *sc; 855844d9543SConrad Meyer unsigned unit, qindex; 856844d9543SConrad Meyer 857844d9543SConrad Meyer if (!have_addr) 858844d9543SConrad Meyer goto usage; 859844d9543SConrad Meyer 860844d9543SConrad Meyer unit = (unsigned)addr; 861844d9543SConrad Meyer 862844d9543SConrad Meyer sc = devclass_get_softc(ccp_devclass, unit); 863844d9543SConrad Meyer if (sc == NULL) { 864844d9543SConrad Meyer db_printf("No such device ccp%u\n", unit); 865844d9543SConrad Meyer goto usage; 866844d9543SConrad Meyer } 867844d9543SConrad Meyer 868844d9543SConrad Meyer if (count == -1) { 869844d9543SConrad Meyer db_show_ccp_sc(sc); 870844d9543SConrad Meyer return; 871844d9543SConrad Meyer } 872844d9543SConrad Meyer 873844d9543SConrad Meyer qindex = (unsigned)count; 874844d9543SConrad Meyer if (qindex >= nitems(sc->queues)) { 875844d9543SConrad Meyer db_printf("No such queue %u\n", qindex); 876844d9543SConrad Meyer goto usage; 877844d9543SConrad Meyer } 878844d9543SConrad Meyer db_show_ccp_qp(&sc->queues[qindex]); 879844d9543SConrad Meyer return; 880844d9543SConrad Meyer 881844d9543SConrad Meyer usage: 882844d9543SConrad Meyer db_printf("usage: show ccp <unit>[,<qindex>]\n"); 883844d9543SConrad Meyer return; 884844d9543SConrad Meyer } 885844d9543SConrad Meyer #endif /* DDB */ 886