From a702ec91d1960a1d75cebedfe310096377682ff8 Mon Sep 17 00:00:00 2001 From: Alex Hornung Date: Sat, 21 Aug 2010 11:46:17 +0100 Subject: [PATCH] padlock - Properly align data * Most parameters to the xcrypt instruction need to be aligned to 16 bytes. So far we haven't been aligning some of the data such as the key, iv and control structure. Refer to the "VIA PadLock Programming Guide" for more details. * Address this by allocating a bit more space and setting stuff up at 16-byte boundaries and ensuring gcc aligns the whole structure 16-bytish. While this wastes some memory, it is negligible. * This fixes the issue with encryption and decryption with padlock causing general protection faults. Reported-by: Jan Lentfer (lentferj@) --- sys/crypto/via/padlock.c | 14 +++++++++++--- sys/crypto/via/padlock.h | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/sys/crypto/via/padlock.c b/sys/crypto/via/padlock.c index de8b0eb645..7054153efb 100644 --- a/sys/crypto/via/padlock.c +++ b/sys/crypto/via/padlock.c @@ -155,7 +155,7 @@ padlock_detach(device_t dev) } while ((ses = TAILQ_FIRST(&sc->sc_sessions)) != NULL) { TAILQ_REMOVE(&sc->sc_sessions, ses, ses_next); - kfree(ses, M_PADLOCK); + kfree(ses->ses_freeaddr, M_PADLOCK); } lockuninit(&sc->sc_sessions_lock); crypto_unregister_all(sc->sc_cid); @@ -166,7 +166,7 @@ static int padlock_newsession(device_t dev, uint32_t *sidp, struct cryptoini *cri) { struct padlock_softc *sc = device_get_softc(dev); - struct padlock_session *ses = NULL; + struct padlock_session *ases, *ses = NULL; struct cryptoini *encini, *macini; int error; @@ -215,11 +215,19 @@ padlock_newsession(device_t dev, uint32_t *sidp, struct cryptoini *cri) */ ses = TAILQ_FIRST(&sc->sc_sessions); if (ses == NULL || ses->ses_used) { - ses = kmalloc(sizeof(*ses), M_PADLOCK, M_NOWAIT | M_ZERO); + ses = kmalloc(sizeof(*ses) + 16, M_PADLOCK, M_NOWAIT | M_ZERO); if (ses == NULL) { lockmgr(&sc->sc_sessions_lock, LK_RELEASE); return (ENOMEM); } + /* Check if 'ses' is 16-byte aligned. If not, align it. */ + if (((uintptr_t)ses & 0xf) != 0) { + ases = PADLOCK_ALIGN(ses); + ases->ses_freeaddr = ses; + ses = ases; + } else { + ses->ses_freeaddr = ses; + } ses->ses_id = sc->sc_sid++; } else { TAILQ_REMOVE(&sc->sc_sessions, ses, ses_next); diff --git a/sys/crypto/via/padlock.h b/sys/crypto/via/padlock.h index 96707baaf1..ca82e6a9c5 100644 --- a/sys/crypto/via/padlock.h +++ b/sys/crypto/via/padlock.h @@ -70,7 +70,8 @@ struct padlock_session { int ses_used; uint32_t ses_id; TAILQ_ENTRY(padlock_session) ses_next; -}; + void *ses_freeaddr; +} __aligned(16); #define PADLOCK_ALIGN(p) (void *)(roundup2((uintptr_t)(p), 16)) -- 2.41.0