freebsd-skq/sys/mips/cavium/octeon_cop2.S
Oleksandr Tymoshenko 6cc1d135cd - Add better COP2 (crypto coprocessor) context handler for Octeon. Keep
COP2 disabled and lazily allocate COP2 context structure in exception
    handler. Keep kernel and userland contexts separated.
2012-01-06 01:23:26 +00:00

226 lines
6.8 KiB
ArmAsm

/*-
* Copyright (c) 2011 Oleksandr Tymoshenko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <machine/asm.h>
#include <mips/cavium/octeon_cop2.h>
#include "assym.s"
.set noreorder
#define SAVE_COP2_REGISTER(reg) \
dmfc2 t1, reg; sd t1, reg##_OFFSET(a0)
#define RESTORE_COP2_REGISTER(reg) \
ld t1, reg##_OFFSET(a0); dmtc2 t1, reg##_SET
LEAF(octeon_cop2_save)
/* Get CvmCtl register */
dmfc0 t0, $9, 7
/* CRC state */
SAVE_COP2_REGISTER(COP2_CRC_IV)
SAVE_COP2_REGISTER(COP2_CRC_LENGTH)
SAVE_COP2_REGISTER(COP2_CRC_POLY)
/* if CvmCtl[NODFA_CP2] -> save_nodfa */
bbit1 t0, 28, save_nodfa
nop
/* LLM state */
SAVE_COP2_REGISTER(COP2_LLM_DAT0)
SAVE_COP2_REGISTER(COP2_LLM_DAT1)
save_nodfa:
/* crypto stuff is irrelevant if CvmCtl[NOCRYPTO] */
bbit1 t0, 26, save_done
nop
SAVE_COP2_REGISTER(COP2_3DES_IV)
SAVE_COP2_REGISTER(COP2_3DES_KEY0)
SAVE_COP2_REGISTER(COP2_3DES_KEY1)
SAVE_COP2_REGISTER(COP2_3DES_KEY2)
SAVE_COP2_REGISTER(COP2_3DES_RESULT)
SAVE_COP2_REGISTER(COP2_AES_INP0)
SAVE_COP2_REGISTER(COP2_AES_IV0)
SAVE_COP2_REGISTER(COP2_AES_IV1)
SAVE_COP2_REGISTER(COP2_AES_KEY0)
SAVE_COP2_REGISTER(COP2_AES_KEY1)
SAVE_COP2_REGISTER(COP2_AES_KEY2)
SAVE_COP2_REGISTER(COP2_AES_KEY3)
SAVE_COP2_REGISTER(COP2_AES_KEYLEN)
SAVE_COP2_REGISTER(COP2_AES_RESULT0)
SAVE_COP2_REGISTER(COP2_AES_RESULT1)
dmfc0 t0, $15
li t1, 0x000d0000 /* Octeon Pass1 */
beq t0, t1, save_pass1
nop
SAVE_COP2_REGISTER(COP2_HSH_DATW0)
SAVE_COP2_REGISTER(COP2_HSH_DATW1)
SAVE_COP2_REGISTER(COP2_HSH_DATW2)
SAVE_COP2_REGISTER(COP2_HSH_DATW3)
SAVE_COP2_REGISTER(COP2_HSH_DATW4)
SAVE_COP2_REGISTER(COP2_HSH_DATW5)
SAVE_COP2_REGISTER(COP2_HSH_DATW6)
SAVE_COP2_REGISTER(COP2_HSH_DATW7)
SAVE_COP2_REGISTER(COP2_HSH_DATW8)
SAVE_COP2_REGISTER(COP2_HSH_DATW9)
SAVE_COP2_REGISTER(COP2_HSH_DATW10)
SAVE_COP2_REGISTER(COP2_HSH_DATW11)
SAVE_COP2_REGISTER(COP2_HSH_DATW12)
SAVE_COP2_REGISTER(COP2_HSH_DATW13)
SAVE_COP2_REGISTER(COP2_HSH_DATW14)
SAVE_COP2_REGISTER(COP2_HSH_IVW0)
SAVE_COP2_REGISTER(COP2_HSH_IVW1)
SAVE_COP2_REGISTER(COP2_HSH_IVW2)
SAVE_COP2_REGISTER(COP2_HSH_IVW3)
SAVE_COP2_REGISTER(COP2_HSH_IVW4)
SAVE_COP2_REGISTER(COP2_HSH_IVW5)
SAVE_COP2_REGISTER(COP2_HSH_IVW6)
SAVE_COP2_REGISTER(COP2_HSH_IVW7)
SAVE_COP2_REGISTER(COP2_GFM_MULT0)
SAVE_COP2_REGISTER(COP2_GFM_MULT1)
SAVE_COP2_REGISTER(COP2_GFM_POLY)
SAVE_COP2_REGISTER(COP2_GFM_RESULT0)
SAVE_COP2_REGISTER(COP2_GFM_RESULT1)
jr ra
nop
save_pass1:
SAVE_COP2_REGISTER(COP2_HSH_DATW0_PASS1)
SAVE_COP2_REGISTER(COP2_HSH_DATW1_PASS1)
SAVE_COP2_REGISTER(COP2_HSH_DATW2_PASS1)
SAVE_COP2_REGISTER(COP2_HSH_DATW3_PASS1)
SAVE_COP2_REGISTER(COP2_HSH_DATW4_PASS1)
SAVE_COP2_REGISTER(COP2_HSH_DATW5_PASS1)
SAVE_COP2_REGISTER(COP2_HSH_DATW6_PASS1)
SAVE_COP2_REGISTER(COP2_HSH_IVW0_PASS1)
SAVE_COP2_REGISTER(COP2_HSH_IVW1_PASS1)
SAVE_COP2_REGISTER(COP2_HSH_IVW2_PASS1)
save_done:
jr ra
nop
END(octeon_cop2_save)
LEAF(octeon_cop2_restore)
/* Get CvmCtl register */
dmfc0 t0, $9, 7
/* CRC state */
RESTORE_COP2_REGISTER(COP2_CRC_IV)
RESTORE_COP2_REGISTER(COP2_CRC_LENGTH)
RESTORE_COP2_REGISTER(COP2_CRC_POLY)
/* if CvmCtl[NODFA_CP2] -> save_nodfa */
bbit1 t0, 28, restore_nodfa
nop
/* LLM state */
RESTORE_COP2_REGISTER(COP2_LLM_DAT0)
RESTORE_COP2_REGISTER(COP2_LLM_DAT1)
restore_nodfa:
/* crypto stuff is irrelevant if CvmCtl[NOCRYPTO] */
bbit1 t0, 26, restore_done
nop
RESTORE_COP2_REGISTER(COP2_3DES_IV)
RESTORE_COP2_REGISTER(COP2_3DES_KEY0)
RESTORE_COP2_REGISTER(COP2_3DES_KEY1)
RESTORE_COP2_REGISTER(COP2_3DES_KEY2)
RESTORE_COP2_REGISTER(COP2_3DES_RESULT)
RESTORE_COP2_REGISTER(COP2_AES_INP0)
RESTORE_COP2_REGISTER(COP2_AES_IV0)
RESTORE_COP2_REGISTER(COP2_AES_IV1)
RESTORE_COP2_REGISTER(COP2_AES_KEY0)
RESTORE_COP2_REGISTER(COP2_AES_KEY1)
RESTORE_COP2_REGISTER(COP2_AES_KEY2)
RESTORE_COP2_REGISTER(COP2_AES_KEY3)
RESTORE_COP2_REGISTER(COP2_AES_KEYLEN)
RESTORE_COP2_REGISTER(COP2_AES_RESULT0)
RESTORE_COP2_REGISTER(COP2_AES_RESULT1)
dmfc0 t0, $15
li t1, 0x000d0000 /* Octeon Pass1 */
beq t0, t1, restore_pass1
nop
RESTORE_COP2_REGISTER(COP2_HSH_DATW0)
RESTORE_COP2_REGISTER(COP2_HSH_DATW1)
RESTORE_COP2_REGISTER(COP2_HSH_DATW2)
RESTORE_COP2_REGISTER(COP2_HSH_DATW3)
RESTORE_COP2_REGISTER(COP2_HSH_DATW4)
RESTORE_COP2_REGISTER(COP2_HSH_DATW5)
RESTORE_COP2_REGISTER(COP2_HSH_DATW6)
RESTORE_COP2_REGISTER(COP2_HSH_DATW7)
RESTORE_COP2_REGISTER(COP2_HSH_DATW8)
RESTORE_COP2_REGISTER(COP2_HSH_DATW9)
RESTORE_COP2_REGISTER(COP2_HSH_DATW10)
RESTORE_COP2_REGISTER(COP2_HSH_DATW11)
RESTORE_COP2_REGISTER(COP2_HSH_DATW12)
RESTORE_COP2_REGISTER(COP2_HSH_DATW13)
RESTORE_COP2_REGISTER(COP2_HSH_DATW14)
RESTORE_COP2_REGISTER(COP2_HSH_IVW0)
RESTORE_COP2_REGISTER(COP2_HSH_IVW1)
RESTORE_COP2_REGISTER(COP2_HSH_IVW2)
RESTORE_COP2_REGISTER(COP2_HSH_IVW3)
RESTORE_COP2_REGISTER(COP2_HSH_IVW4)
RESTORE_COP2_REGISTER(COP2_HSH_IVW5)
RESTORE_COP2_REGISTER(COP2_HSH_IVW6)
RESTORE_COP2_REGISTER(COP2_HSH_IVW7)
RESTORE_COP2_REGISTER(COP2_GFM_MULT0)
RESTORE_COP2_REGISTER(COP2_GFM_MULT1)
RESTORE_COP2_REGISTER(COP2_GFM_POLY)
RESTORE_COP2_REGISTER(COP2_GFM_RESULT0)
RESTORE_COP2_REGISTER(COP2_GFM_RESULT1)
jr ra
nop
restore_pass1:
RESTORE_COP2_REGISTER(COP2_HSH_DATW0_PASS1)
RESTORE_COP2_REGISTER(COP2_HSH_DATW1_PASS1)
RESTORE_COP2_REGISTER(COP2_HSH_DATW2_PASS1)
RESTORE_COP2_REGISTER(COP2_HSH_DATW3_PASS1)
RESTORE_COP2_REGISTER(COP2_HSH_DATW4_PASS1)
RESTORE_COP2_REGISTER(COP2_HSH_DATW5_PASS1)
RESTORE_COP2_REGISTER(COP2_HSH_DATW6_PASS1)
RESTORE_COP2_REGISTER(COP2_HSH_IVW0_PASS1)
RESTORE_COP2_REGISTER(COP2_HSH_IVW1_PASS1)
RESTORE_COP2_REGISTER(COP2_HSH_IVW2_PASS1)
restore_done:
jr ra
nop
END(octeon_cop2_restore)