Move session state from on-card memory to host memory so we no longer are

constrained to a small number of sessions by the small on-card memories found
in newer devices.  This is really a stopgap solution as having session state
in main memory incurs a (small but noticeable) performance penalty. The better
solution is to manage session state so that it's cached on chip.

Obtained from:	openbsd
This commit is contained in:
Sam Leffler 2004-10-15 00:36:07 +00:00
parent 71a77eda7d
commit fe9b390b9d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=136526
2 changed files with 46 additions and 43 deletions

View file

@ -465,10 +465,9 @@ hifn_attach(device_t dev)
rbase = 'M'; rbase = 'M';
rseg /= 1024; rseg /= 1024;
} }
device_printf(sc->sc_dev, "%s, rev %u, %d%cB %cram, %u sessions\n", device_printf(sc->sc_dev, "%s, rev %u, %d%cB %cram\n",
hifn_partname(sc), rev, hifn_partname(sc), rev,
rseg, rbase, sc->sc_drammodel ? 'd' : 's', rseg, rbase, sc->sc_drammodel ? 'd' : 's');
sc->sc_maxses);
sc->sc_cid = crypto_get_driverid(0); sc->sc_cid = crypto_get_driverid(0);
if (sc->sc_cid < 0) { if (sc->sc_cid < 0) {
@ -1465,7 +1464,7 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
base_cmd->total_dest_count = htole16(dlen & HIFN_BASE_CMD_LENMASK_LO); base_cmd->total_dest_count = htole16(dlen & HIFN_BASE_CMD_LENMASK_LO);
dlen >>= 16; dlen >>= 16;
slen >>= 16; slen >>= 16;
base_cmd->session_num = htole16(cmd->session_num | base_cmd->session_num = htole16(
((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) | ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M)); ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
buf_pos += sizeof(hifn_base_command_t); buf_pos += sizeof(hifn_base_command_t);
@ -2207,17 +2206,44 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
{ {
struct cryptoini *c; struct cryptoini *c;
struct hifn_softc *sc = arg; struct hifn_softc *sc = arg;
int i, mac = 0, cry = 0; int mac = 0, cry = 0, sesn;
struct hifn_session *ses = NULL
KASSERT(sc != NULL, ("hifn_newsession: null softc")); KASSERT(sc != NULL, ("hifn_newsession: null softc"));
if (sidp == NULL || cri == NULL || sc == NULL) if (sidp == NULL || cri == NULL || sc == NULL)
return (EINVAL); return (EINVAL);
for (i = 0; i < sc->sc_maxses; i++) if (sc->sc_sessions == NULL) {
if (sc->sc_sessions[i].hs_state == HS_STATE_FREE) ses = sc->sc_sessions = (struct hifn_session *)malloc(
break; sizeof(*ses), M_DEVBUF, M_NOWAIT);
if (i == sc->sc_maxses) if (ses == NULL)
return (ENOMEM); return (ENOMEM);
sesn = 0;
sc->sc_nsessions = 1;
} else {
for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
if (!sc->sc_sessions[sesn].hs_used) {
ses = &sc->sc_sessions[sesn];
break;
}
}
if (ses == NULL) {
sesn = sc->sc_nsessions;
ses = (struct hifn_session *)malloc((sesn + 1) *
sizeof(*ses), M_DEVBUF, M_NOWAIT);
if (ses == NULL)
return (ENOMEM);
bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
bzero(sc->sc_sessions, sesn * sizeof(*ses));
free(sc->sc_sessions, M_DEVBUF);
sc->sc_sessions = ses;
ses = &sc->sc_sessions[sesn];
sc->sc_nsessions++;
}
}
bzero(ses, sizeof(*ses));
ses->hs_used = 1;
for (c = cri; c != NULL; c = c->cri_next) { for (c = cri; c != NULL; c = c->cri_next) {
switch (c->cri_alg) { switch (c->cri_alg) {
@ -2233,7 +2259,7 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
case CRYPTO_3DES_CBC: case CRYPTO_3DES_CBC:
case CRYPTO_AES_CBC: case CRYPTO_AES_CBC:
/* XXX this may read fewer, does it matter? */ /* XXX this may read fewer, does it matter? */
read_random(sc->sc_sessions[i].hs_iv, read_random(ses->hs_iv,
c->cri_alg == CRYPTO_AES_CBC ? c->cri_alg == CRYPTO_AES_CBC ?
HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
/*FALLTHROUGH*/ /*FALLTHROUGH*/
@ -2249,8 +2275,7 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
if (mac == 0 && cry == 0) if (mac == 0 && cry == 0)
return (EINVAL); return (EINVAL);
*sidp = HIFN_SID(device_get_unit(sc->sc_dev), i); *sidp = HIFN_SID(device_get_unit(sc->sc_dev), sesn);
sc->sc_sessions[i].hs_state = HS_STATE_USED;
return (0); return (0);
} }
@ -2272,7 +2297,7 @@ hifn_freesession(void *arg, u_int64_t tid)
return (EINVAL); return (EINVAL);
session = HIFN_SESSION(sid); session = HIFN_SESSION(sid);
if (session >= sc->sc_maxses) if (session >= sc->sc_nsessions)
return (EINVAL); return (EINVAL);
bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session])); bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
@ -2293,7 +2318,7 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
} }
session = HIFN_SESSION(crp->crp_sid); session = HIFN_SESSION(crp->crp_sid);
if (sc == NULL || session >= sc->sc_maxses) { if (sc == NULL || session >= sc->sc_nsessions) {
err = EINVAL; err = EINVAL;
goto errout; goto errout;
} }
@ -2381,10 +2406,6 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
switch (enccrd->crd_alg) { switch (enccrd->crd_alg) {
case CRYPTO_ARC4: case CRYPTO_ARC4:
cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4; cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4;
if ((enccrd->crd_flags & CRD_F_ENCRYPT)
!= sc->sc_sessions[session].hs_prev_op)
sc->sc_sessions[session].hs_state =
HS_STATE_USED;
break; break;
case CRYPTO_DES_CBC: case CRYPTO_DES_CBC:
cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES | cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES |
@ -2442,6 +2463,7 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY; cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
cmd->ck = enccrd->crd_key; cmd->ck = enccrd->crd_key;
cmd->cklen = enccrd->crd_klen >> 3; cmd->cklen = enccrd->crd_klen >> 3;
cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
/* /*
* Need to specify the size for the AES key in the masks. * Need to specify the size for the AES key in the masks.
@ -2463,9 +2485,6 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
goto errout; goto errout;
} }
} }
if (sc->sc_sessions[session].hs_state == HS_STATE_USED)
cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
} }
if (maccrd) { if (maccrd) {
@ -2495,9 +2514,8 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
break; break;
} }
if ((maccrd->crd_alg == CRYPTO_SHA1_HMAC || if (maccrd->crd_alg == CRYPTO_SHA1_HMAC ||
maccrd->crd_alg == CRYPTO_MD5_HMAC) && maccrd->crd_alg == CRYPTO_MD5_HMAC) {
sc->sc_sessions[session].hs_state == HS_STATE_USED) {
cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY; cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY;
bcopy(maccrd->crd_key, cmd->mac, maccrd->crd_klen >> 3); bcopy(maccrd->crd_key, cmd->mac, maccrd->crd_klen >> 3);
bzero(cmd->mac + (maccrd->crd_klen >> 3), bzero(cmd->mac + (maccrd->crd_klen >> 3),
@ -2511,11 +2529,6 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
err = hifn_crypto(sc, cmd, crp, hint); err = hifn_crypto(sc, cmd, crp, hint);
if (!err) { if (!err) {
if (enccrd)
sc->sc_sessions[session].hs_prev_op =
enccrd->crd_flags & CRD_F_ENCRYPT;
if (sc->sc_sessions[session].hs_state == HS_STATE_USED)
sc->sc_sessions[session].hs_state = HS_STATE_KEY;
return 0; return 0;
} else if (err == ERESTART) { } else if (err == ERESTART) {
/* /*
@ -2612,11 +2625,6 @@ hifn_abort(struct hifn_softc *sc)
} }
dma->resk = i; dma->resu = u; dma->resk = i; dma->resu = u;
/* Force upload of key next time */
for (i = 0; i < sc->sc_maxses; i++)
if (sc->sc_sessions[i].hs_state == HS_STATE_KEY)
sc->sc_sessions[i].hs_state = HS_STATE_USED;
hifn_reset_board(sc, 1); hifn_reset_board(sc, 1);
hifn_init_dma(sc); hifn_init_dma(sc);
hifn_init_pci_registers(sc); hifn_init_pci_registers(sc);

View file

@ -111,8 +111,7 @@ struct hifn_dma {
}; };
struct hifn_session { struct hifn_session {
int hs_state; int hs_used;
int hs_prev_op; /* XXX collapse into hs_flags? */
u_int8_t hs_iv[HIFN_MAX_IV_LENGTH]; u_int8_t hs_iv[HIFN_MAX_IV_LENGTH];
}; };
@ -130,11 +129,6 @@ struct hifn_session {
#define HIFN_RES_SYNC(sc, i, f) \ #define HIFN_RES_SYNC(sc, i, f) \
bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f))
/* We use a state machine to on sessions */
#define HS_STATE_FREE 0 /* unused session entry */
#define HS_STATE_USED 1 /* allocated, but key not on card */
#define HS_STATE_KEY 2 /* allocated and key is on card */
/* /*
* Holds data specific to a single HIFN board. * Holds data specific to a single HIFN board.
*/ */
@ -164,6 +158,8 @@ struct hifn_softc {
int sc_dmansegs; int sc_dmansegs;
int32_t sc_cid; int32_t sc_cid;
int sc_maxses; int sc_maxses;
int sc_nsessions;
struct hifn_session *sc_sessions;
int sc_ramsize; int sc_ramsize;
int sc_flags; int sc_flags;
#define HIFN_HAS_RNG 0x1 /* includes random number generator */ #define HIFN_HAS_RNG 0x1 /* includes random number generator */
@ -186,7 +182,6 @@ struct hifn_softc {
int sc_needwakeup; /* ops q'd wating on resources */ int sc_needwakeup; /* ops q'd wating on resources */
int sc_curbatch; /* # ops submitted w/o int */ int sc_curbatch; /* # ops submitted w/o int */
int sc_suspended; int sc_suspended;
struct hifn_session sc_sessions[2048];
}; };
#define HIFN_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define HIFN_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)