cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

octeon_switch.S (14945B)


      1/*
      2 * This file is subject to the terms and conditions of the GNU General Public
      3 * License.  See the file "COPYING" in the main directory of this archive
      4 * for more details.
      5 *
      6 * Copyright (C) 1994, 1995, 1996, 1998, 1999, 2002, 2003 Ralf Baechle
      7 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
      8 * Copyright (C) 1994, 1995, 1996, by Andreas Busse
      9 * Copyright (C) 1999 Silicon Graphics, Inc.
     10 * Copyright (C) 2000 MIPS Technologies, Inc.
     11 *    written by Carsten Langgaard, carstenl@mips.com
     12 */
     13#include <asm/asm.h>
     14#include <asm/export.h>
     15#include <asm/asm-offsets.h>
     16#include <asm/mipsregs.h>
     17#include <asm/regdef.h>
     18#include <asm/stackframe.h>
     19
     20/*
     21 * task_struct *resume(task_struct *prev, task_struct *next,
     22 *		       struct thread_info *next_ti)
     23 */
     24	.align	7
     25	LEAF(resume)
     26	.set arch=octeon
     27	mfc0	t1, CP0_STATUS
     28	LONG_S	t1, THREAD_STATUS(a0)
     29	cpu_save_nonscratch a0
     30	LONG_S	ra, THREAD_REG31(a0)
     31
     32#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
     33	/* Check if we need to store CVMSEG state */
     34	dmfc0	t0, $11,7	/* CvmMemCtl */
     35	bbit0	t0, 6, 3f	/* Is user access enabled? */
     36
     37	/* Store the CVMSEG state */
     38	/* Extract the size of CVMSEG */
     39	andi	t0, 0x3f
     40	/* Multiply * (cache line size/sizeof(long)/2) */
     41	sll	t0, 7-LONGLOG-1
     42	li	t1, -32768	/* Base address of CVMSEG */
     43	LONG_ADDI t2, a0, THREAD_CVMSEG /* Where to store CVMSEG to */
     44	synciobdma
     452:
     46	.set noreorder
     47	LONG_L	t8, 0(t1)	/* Load from CVMSEG */
     48	subu	t0, 1		/* Decrement loop var */
     49	LONG_L	t9, LONGSIZE(t1)/* Load from CVMSEG */
     50	LONG_ADDU t1, LONGSIZE*2 /* Increment loc in CVMSEG */
     51	LONG_S	t8, 0(t2)	/* Store CVMSEG to thread storage */
     52	LONG_ADDU t2, LONGSIZE*2 /* Increment loc in thread storage */
     53	bnez	t0, 2b		/* Loop until we've copied it all */
     54	 LONG_S t9, -LONGSIZE(t2)/* Store CVMSEG to thread storage */
     55	.set reorder
     56
     57	/* Disable access to CVMSEG */
     58	dmfc0	t0, $11,7	/* CvmMemCtl */
     59	xori	t0, t0, 0x40	/* Bit 6 is CVMSEG user enable */
     60	dmtc0	t0, $11,7	/* CvmMemCtl */
     61#endif
     623:
     63
     64#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
     65	PTR_LA	t8, __stack_chk_guard
     66	LONG_L	t9, TASK_STACK_CANARY(a1)
     67	LONG_S	t9, 0(t8)
     68#endif
     69
     70	/*
     71	 * The order of restoring the registers takes care of the race
     72	 * updating $28, $29 and kernelsp without disabling ints.
     73	 */
     74	move	$28, a2
     75	cpu_restore_nonscratch a1
     76
     77	PTR_ADDU	t0, $28, _THREAD_SIZE - 32
     78	set_saved_sp	t0, t1, t2
     79
     80	mfc0	t1, CP0_STATUS		/* Do we really need this? */
     81	li	a3, 0xff01
     82	and	t1, a3
     83	LONG_L	a2, THREAD_STATUS(a1)
     84	nor	a3, $0, a3
     85	and	a2, a3
     86	or	a2, t1
     87	mtc0	a2, CP0_STATUS
     88	move	v0, a0
     89	jr	ra
     90	END(resume)
     91
     92/*
     93 * void octeon_cop2_save(struct octeon_cop2_state *a0)
     94 */
     95	.align	7
     96	.set push
     97	.set noreorder
     98	LEAF(octeon_cop2_save)
     99
    100	dmfc0	t9, $9,7	/* CvmCtl register. */
    101
    102	/* Save the COP2 CRC state */
    103	dmfc2	t0, 0x0201
    104	dmfc2	t1, 0x0202
    105	dmfc2	t2, 0x0200
    106	sd	t0, OCTEON_CP2_CRC_IV(a0)
    107	sd	t1, OCTEON_CP2_CRC_LENGTH(a0)
    108	/* Skip next instructions if CvmCtl[NODFA_CP2] set */
    109	bbit1	t9, 28, 1f
    110	 sd	t2, OCTEON_CP2_CRC_POLY(a0)
    111
    112	/* Save the LLM state */
    113	dmfc2	t0, 0x0402
    114	dmfc2	t1, 0x040A
    115	sd	t0, OCTEON_CP2_LLM_DAT(a0)
    116
    1171:	bbit1	t9, 26, 3f	/* done if CvmCtl[NOCRYPTO] set */
    118	 sd	t1, OCTEON_CP2_LLM_DAT+8(a0)
    119
    120	/* Save the COP2 crypto state */
    121	/* this part is mostly common to both pass 1 and later revisions */
    122	dmfc2	t0, 0x0084
    123	dmfc2	t1, 0x0080
    124	dmfc2	t2, 0x0081
    125	dmfc2	t3, 0x0082
    126	sd	t0, OCTEON_CP2_3DES_IV(a0)
    127	dmfc2	t0, 0x0088
    128	sd	t1, OCTEON_CP2_3DES_KEY(a0)
    129	dmfc2	t1, 0x0111			/* only necessary for pass 1 */
    130	sd	t2, OCTEON_CP2_3DES_KEY+8(a0)
    131	dmfc2	t2, 0x0102
    132	sd	t3, OCTEON_CP2_3DES_KEY+16(a0)
    133	dmfc2	t3, 0x0103
    134	sd	t0, OCTEON_CP2_3DES_RESULT(a0)
    135	dmfc2	t0, 0x0104
    136	sd	t1, OCTEON_CP2_AES_INP0(a0)	/* only necessary for pass 1 */
    137	dmfc2	t1, 0x0105
    138	sd	t2, OCTEON_CP2_AES_IV(a0)
    139	dmfc2	t2, 0x0106
    140	sd	t3, OCTEON_CP2_AES_IV+8(a0)
    141	dmfc2	t3, 0x0107
    142	sd	t0, OCTEON_CP2_AES_KEY(a0)
    143	dmfc2	t0, 0x0110
    144	sd	t1, OCTEON_CP2_AES_KEY+8(a0)
    145	dmfc2	t1, 0x0100
    146	sd	t2, OCTEON_CP2_AES_KEY+16(a0)
    147	dmfc2	t2, 0x0101
    148	sd	t3, OCTEON_CP2_AES_KEY+24(a0)
    149	mfc0	v0, $15,0	/* Get the processor ID register */
    150	sd	t0, OCTEON_CP2_AES_KEYLEN(a0)
    151	li	v1, 0x000d0000	/* This is the processor ID of Octeon Pass1 */
    152	sd	t1, OCTEON_CP2_AES_RESULT(a0)
    153	/* Skip to the Pass1 version of the remainder of the COP2 state */
    154	beq	v0, v1, 2f
    155	 sd	t2, OCTEON_CP2_AES_RESULT+8(a0)
    156
    157	/* the non-pass1 state when !CvmCtl[NOCRYPTO] */
    158	dmfc2	t1, 0x0240
    159	dmfc2	t2, 0x0241
    160	ori	v1, v1, 0x9500 /* lowest OCTEON III PrId*/
    161	dmfc2	t3, 0x0242
    162	subu	v1, v0, v1 /* prid - lowest OCTEON III PrId */
    163	dmfc2	t0, 0x0243
    164	sd	t1, OCTEON_CP2_HSH_DATW(a0)
    165	dmfc2	t1, 0x0244
    166	sd	t2, OCTEON_CP2_HSH_DATW+8(a0)
    167	dmfc2	t2, 0x0245
    168	sd	t3, OCTEON_CP2_HSH_DATW+16(a0)
    169	dmfc2	t3, 0x0246
    170	sd	t0, OCTEON_CP2_HSH_DATW+24(a0)
    171	dmfc2	t0, 0x0247
    172	sd	t1, OCTEON_CP2_HSH_DATW+32(a0)
    173	dmfc2	t1, 0x0248
    174	sd	t2, OCTEON_CP2_HSH_DATW+40(a0)
    175	dmfc2	t2, 0x0249
    176	sd	t3, OCTEON_CP2_HSH_DATW+48(a0)
    177	dmfc2	t3, 0x024A
    178	sd	t0, OCTEON_CP2_HSH_DATW+56(a0)
    179	dmfc2	t0, 0x024B
    180	sd	t1, OCTEON_CP2_HSH_DATW+64(a0)
    181	dmfc2	t1, 0x024C
    182	sd	t2, OCTEON_CP2_HSH_DATW+72(a0)
    183	dmfc2	t2, 0x024D
    184	sd	t3, OCTEON_CP2_HSH_DATW+80(a0)
    185	dmfc2	t3, 0x024E
    186	sd	t0, OCTEON_CP2_HSH_DATW+88(a0)
    187	dmfc2	t0, 0x0250
    188	sd	t1, OCTEON_CP2_HSH_DATW+96(a0)
    189	dmfc2	t1, 0x0251
    190	sd	t2, OCTEON_CP2_HSH_DATW+104(a0)
    191	dmfc2	t2, 0x0252
    192	sd	t3, OCTEON_CP2_HSH_DATW+112(a0)
    193	dmfc2	t3, 0x0253
    194	sd	t0, OCTEON_CP2_HSH_IVW(a0)
    195	dmfc2	t0, 0x0254
    196	sd	t1, OCTEON_CP2_HSH_IVW+8(a0)
    197	dmfc2	t1, 0x0255
    198	sd	t2, OCTEON_CP2_HSH_IVW+16(a0)
    199	dmfc2	t2, 0x0256
    200	sd	t3, OCTEON_CP2_HSH_IVW+24(a0)
    201	dmfc2	t3, 0x0257
    202	sd	t0, OCTEON_CP2_HSH_IVW+32(a0)
    203	dmfc2	t0, 0x0258
    204	sd	t1, OCTEON_CP2_HSH_IVW+40(a0)
    205	dmfc2	t1, 0x0259
    206	sd	t2, OCTEON_CP2_HSH_IVW+48(a0)
    207	dmfc2	t2, 0x025E
    208	sd	t3, OCTEON_CP2_HSH_IVW+56(a0)
    209	dmfc2	t3, 0x025A
    210	sd	t0, OCTEON_CP2_GFM_MULT(a0)
    211	dmfc2	t0, 0x025B
    212	sd	t1, OCTEON_CP2_GFM_MULT+8(a0)
    213	sd	t2, OCTEON_CP2_GFM_POLY(a0)
    214	sd	t3, OCTEON_CP2_GFM_RESULT(a0)
    215	bltz	v1, 4f
    216	 sd	t0, OCTEON_CP2_GFM_RESULT+8(a0)
    217	/* OCTEON III things*/
    218	dmfc2	t0, 0x024F
    219	dmfc2	t1, 0x0050
    220	sd	t0, OCTEON_CP2_SHA3(a0)
    221	sd	t1, OCTEON_CP2_SHA3+8(a0)
    2224:
    223	jr	ra
    224	 nop
    225
    2262:	/* pass 1 special stuff when !CvmCtl[NOCRYPTO] */
    227	dmfc2	t3, 0x0040
    228	dmfc2	t0, 0x0041
    229	dmfc2	t1, 0x0042
    230	dmfc2	t2, 0x0043
    231	sd	t3, OCTEON_CP2_HSH_DATW(a0)
    232	dmfc2	t3, 0x0044
    233	sd	t0, OCTEON_CP2_HSH_DATW+8(a0)
    234	dmfc2	t0, 0x0045
    235	sd	t1, OCTEON_CP2_HSH_DATW+16(a0)
    236	dmfc2	t1, 0x0046
    237	sd	t2, OCTEON_CP2_HSH_DATW+24(a0)
    238	dmfc2	t2, 0x0048
    239	sd	t3, OCTEON_CP2_HSH_DATW+32(a0)
    240	dmfc2	t3, 0x0049
    241	sd	t0, OCTEON_CP2_HSH_DATW+40(a0)
    242	dmfc2	t0, 0x004A
    243	sd	t1, OCTEON_CP2_HSH_DATW+48(a0)
    244	sd	t2, OCTEON_CP2_HSH_IVW(a0)
    245	sd	t3, OCTEON_CP2_HSH_IVW+8(a0)
    246	sd	t0, OCTEON_CP2_HSH_IVW+16(a0)
    247
    2483:	/* pass 1 or CvmCtl[NOCRYPTO] set */
    249	jr	ra
    250	 nop
    251	END(octeon_cop2_save)
    252	.set pop
    253
    254/*
    255 * void octeon_cop2_restore(struct octeon_cop2_state *a0)
    256 */
    257	.align	7
    258	.set push
    259	.set noreorder
    260	LEAF(octeon_cop2_restore)
    261	/* First cache line was prefetched before the call */
    262	pref	4,  128(a0)
    263	dmfc0	t9, $9,7	/* CvmCtl register. */
    264
    265	pref	4,  256(a0)
    266	ld	t0, OCTEON_CP2_CRC_IV(a0)
    267	pref	4,  384(a0)
    268	ld	t1, OCTEON_CP2_CRC_LENGTH(a0)
    269	ld	t2, OCTEON_CP2_CRC_POLY(a0)
    270
    271	/* Restore the COP2 CRC state */
    272	dmtc2	t0, 0x0201
    273	dmtc2	t1, 0x1202
    274	bbit1	t9, 28, 2f	/* Skip LLM if CvmCtl[NODFA_CP2] is set */
    275	 dmtc2	t2, 0x4200
    276
    277	/* Restore the LLM state */
    278	ld	t0, OCTEON_CP2_LLM_DAT(a0)
    279	ld	t1, OCTEON_CP2_LLM_DAT+8(a0)
    280	dmtc2	t0, 0x0402
    281	dmtc2	t1, 0x040A
    282
    2832:
    284	bbit1	t9, 26, done_restore	/* done if CvmCtl[NOCRYPTO] set */
    285	 nop
    286
    287	/* Restore the COP2 crypto state common to pass 1 and pass 2 */
    288	ld	t0, OCTEON_CP2_3DES_IV(a0)
    289	ld	t1, OCTEON_CP2_3DES_KEY(a0)
    290	ld	t2, OCTEON_CP2_3DES_KEY+8(a0)
    291	dmtc2	t0, 0x0084
    292	ld	t0, OCTEON_CP2_3DES_KEY+16(a0)
    293	dmtc2	t1, 0x0080
    294	ld	t1, OCTEON_CP2_3DES_RESULT(a0)
    295	dmtc2	t2, 0x0081
    296	ld	t2, OCTEON_CP2_AES_INP0(a0) /* only really needed for pass 1 */
    297	dmtc2	t0, 0x0082
    298	ld	t0, OCTEON_CP2_AES_IV(a0)
    299	dmtc2	t1, 0x0098
    300	ld	t1, OCTEON_CP2_AES_IV+8(a0)
    301	dmtc2	t2, 0x010A		    /* only really needed for pass 1 */
    302	ld	t2, OCTEON_CP2_AES_KEY(a0)
    303	dmtc2	t0, 0x0102
    304	ld	t0, OCTEON_CP2_AES_KEY+8(a0)
    305	dmtc2	t1, 0x0103
    306	ld	t1, OCTEON_CP2_AES_KEY+16(a0)
    307	dmtc2	t2, 0x0104
    308	ld	t2, OCTEON_CP2_AES_KEY+24(a0)
    309	dmtc2	t0, 0x0105
    310	ld	t0, OCTEON_CP2_AES_KEYLEN(a0)
    311	dmtc2	t1, 0x0106
    312	ld	t1, OCTEON_CP2_AES_RESULT(a0)
    313	dmtc2	t2, 0x0107
    314	ld	t2, OCTEON_CP2_AES_RESULT+8(a0)
    315	mfc0	t3, $15,0	/* Get the processor ID register */
    316	dmtc2	t0, 0x0110
    317	li	v0, 0x000d0000	/* This is the processor ID of Octeon Pass1 */
    318	dmtc2	t1, 0x0100
    319	bne	v0, t3, 3f	/* Skip the next stuff for non-pass1 */
    320	 dmtc2	t2, 0x0101
    321
    322	/* this code is specific for pass 1 */
    323	ld	t0, OCTEON_CP2_HSH_DATW(a0)
    324	ld	t1, OCTEON_CP2_HSH_DATW+8(a0)
    325	ld	t2, OCTEON_CP2_HSH_DATW+16(a0)
    326	dmtc2	t0, 0x0040
    327	ld	t0, OCTEON_CP2_HSH_DATW+24(a0)
    328	dmtc2	t1, 0x0041
    329	ld	t1, OCTEON_CP2_HSH_DATW+32(a0)
    330	dmtc2	t2, 0x0042
    331	ld	t2, OCTEON_CP2_HSH_DATW+40(a0)
    332	dmtc2	t0, 0x0043
    333	ld	t0, OCTEON_CP2_HSH_DATW+48(a0)
    334	dmtc2	t1, 0x0044
    335	ld	t1, OCTEON_CP2_HSH_IVW(a0)
    336	dmtc2	t2, 0x0045
    337	ld	t2, OCTEON_CP2_HSH_IVW+8(a0)
    338	dmtc2	t0, 0x0046
    339	ld	t0, OCTEON_CP2_HSH_IVW+16(a0)
    340	dmtc2	t1, 0x0048
    341	dmtc2	t2, 0x0049
    342	b done_restore	 /* unconditional branch */
    343	 dmtc2	t0, 0x004A
    344
    3453:	/* this is post-pass1 code */
    346	ld	t2, OCTEON_CP2_HSH_DATW(a0)
    347	ori	v0, v0, 0x9500 /* lowest OCTEON III PrId*/
    348	ld	t0, OCTEON_CP2_HSH_DATW+8(a0)
    349	ld	t1, OCTEON_CP2_HSH_DATW+16(a0)
    350	dmtc2	t2, 0x0240
    351	ld	t2, OCTEON_CP2_HSH_DATW+24(a0)
    352	dmtc2	t0, 0x0241
    353	ld	t0, OCTEON_CP2_HSH_DATW+32(a0)
    354	dmtc2	t1, 0x0242
    355	ld	t1, OCTEON_CP2_HSH_DATW+40(a0)
    356	dmtc2	t2, 0x0243
    357	ld	t2, OCTEON_CP2_HSH_DATW+48(a0)
    358	dmtc2	t0, 0x0244
    359	ld	t0, OCTEON_CP2_HSH_DATW+56(a0)
    360	dmtc2	t1, 0x0245
    361	ld	t1, OCTEON_CP2_HSH_DATW+64(a0)
    362	dmtc2	t2, 0x0246
    363	ld	t2, OCTEON_CP2_HSH_DATW+72(a0)
    364	dmtc2	t0, 0x0247
    365	ld	t0, OCTEON_CP2_HSH_DATW+80(a0)
    366	dmtc2	t1, 0x0248
    367	ld	t1, OCTEON_CP2_HSH_DATW+88(a0)
    368	dmtc2	t2, 0x0249
    369	ld	t2, OCTEON_CP2_HSH_DATW+96(a0)
    370	dmtc2	t0, 0x024A
    371	ld	t0, OCTEON_CP2_HSH_DATW+104(a0)
    372	dmtc2	t1, 0x024B
    373	ld	t1, OCTEON_CP2_HSH_DATW+112(a0)
    374	dmtc2	t2, 0x024C
    375	ld	t2, OCTEON_CP2_HSH_IVW(a0)
    376	dmtc2	t0, 0x024D
    377	ld	t0, OCTEON_CP2_HSH_IVW+8(a0)
    378	dmtc2	t1, 0x024E
    379	ld	t1, OCTEON_CP2_HSH_IVW+16(a0)
    380	dmtc2	t2, 0x0250
    381	ld	t2, OCTEON_CP2_HSH_IVW+24(a0)
    382	dmtc2	t0, 0x0251
    383	ld	t0, OCTEON_CP2_HSH_IVW+32(a0)
    384	dmtc2	t1, 0x0252
    385	ld	t1, OCTEON_CP2_HSH_IVW+40(a0)
    386	dmtc2	t2, 0x0253
    387	ld	t2, OCTEON_CP2_HSH_IVW+48(a0)
    388	dmtc2	t0, 0x0254
    389	ld	t0, OCTEON_CP2_HSH_IVW+56(a0)
    390	dmtc2	t1, 0x0255
    391	ld	t1, OCTEON_CP2_GFM_MULT(a0)
    392	dmtc2	t2, 0x0256
    393	ld	t2, OCTEON_CP2_GFM_MULT+8(a0)
    394	dmtc2	t0, 0x0257
    395	ld	t0, OCTEON_CP2_GFM_POLY(a0)
    396	dmtc2	t1, 0x0258
    397	ld	t1, OCTEON_CP2_GFM_RESULT(a0)
    398	dmtc2	t2, 0x0259
    399	ld	t2, OCTEON_CP2_GFM_RESULT+8(a0)
    400	dmtc2	t0, 0x025E
    401	subu	v0, t3, v0 /* prid - lowest OCTEON III PrId */
    402	dmtc2	t1, 0x025A
    403	bltz	v0, done_restore
    404	 dmtc2	t2, 0x025B
    405	/* OCTEON III things*/
    406	ld	t0, OCTEON_CP2_SHA3(a0)
    407	ld	t1, OCTEON_CP2_SHA3+8(a0)
    408	dmtc2	t0, 0x0051
    409	dmtc2	t1, 0x0050
    410done_restore:
    411	jr	ra
    412	 nop
    413	END(octeon_cop2_restore)
    414	.set pop
    415
    416/*
    417 * void octeon_mult_save()
    418 * sp is assumed to point to a struct pt_regs
    419 *
    420 * NOTE: This is called in SAVE_TEMP in stackframe.h. It can
    421 *       safely modify v1,k0, k1,$10-$15, and $24.  It will
    422 *	 be overwritten with a processor specific version of the code.
    423 */
    424	.p2align 7
    425	.set push
    426	.set noreorder
    427	LEAF(octeon_mult_save)
    428	jr	ra
    429	 nop
    430	.space 30 * 4, 0
    431octeon_mult_save_end:
    432	EXPORT(octeon_mult_save_end)
    433	END(octeon_mult_save)
    434
    435	LEAF(octeon_mult_save2)
    436	/* Save the multiplier state OCTEON II and earlier*/
    437	v3mulu	k0, $0, $0
    438	v3mulu	k1, $0, $0
    439	sd	k0, PT_MTP(sp)	      /* PT_MTP	   has P0 */
    440	v3mulu	k0, $0, $0
    441	sd	k1, PT_MTP+8(sp)      /* PT_MTP+8  has P1 */
    442	ori	k1, $0, 1
    443	v3mulu	k1, k1, $0
    444	sd	k0, PT_MTP+16(sp)     /* PT_MTP+16 has P2 */
    445	v3mulu	k0, $0, $0
    446	sd	k1, PT_MPL(sp)	      /* PT_MPL	   has MPL0 */
    447	v3mulu	k1, $0, $0
    448	sd	k0, PT_MPL+8(sp)      /* PT_MPL+8  has MPL1 */
    449	jr	ra
    450	 sd	k1, PT_MPL+16(sp)     /* PT_MPL+16 has MPL2 */
    451octeon_mult_save2_end:
    452	EXPORT(octeon_mult_save2_end)
    453	END(octeon_mult_save2)
    454
    455	LEAF(octeon_mult_save3)
    456	/* Save the multiplier state OCTEON III */
    457	v3mulu	$10, $0, $0		/* read P0 */
    458	v3mulu	$11, $0, $0		/* read P1 */
    459	v3mulu	$12, $0, $0		/* read P2 */
    460	sd	$10, PT_MTP+(0*8)(sp)	/* store P0 */
    461	v3mulu	$10, $0, $0		/* read P3 */
    462	sd	$11, PT_MTP+(1*8)(sp)	/*  store P1 */
    463	v3mulu	$11, $0, $0		/* read P4 */
    464	sd	$12, PT_MTP+(2*8)(sp)	/* store P2 */
    465	ori	$13, $0, 1
    466	v3mulu	$12, $0, $0		/* read P5 */
    467	sd	$10, PT_MTP+(3*8)(sp)	/* store P3 */
    468	v3mulu	$13, $13, $0		/* P4-P0 = MPL5-MPL1, $13 = MPL0 */
    469	sd	$11, PT_MTP+(4*8)(sp)	/* store P4 */
    470	v3mulu	$10, $0, $0		/* read MPL1 */
    471	sd	$12, PT_MTP+(5*8)(sp)	/* store P5 */
    472	v3mulu	$11, $0, $0		/* read MPL2 */
    473	sd	$13, PT_MPL+(0*8)(sp)	/* store MPL0 */
    474	v3mulu	$12, $0, $0		/* read MPL3 */
    475	sd	$10, PT_MPL+(1*8)(sp)	/* store MPL1 */
    476	v3mulu	$10, $0, $0		/* read MPL4 */
    477	sd	$11, PT_MPL+(2*8)(sp)	/* store MPL2 */
    478	v3mulu	$11, $0, $0		/* read MPL5 */
    479	sd	$12, PT_MPL+(3*8)(sp)	/* store MPL3 */
    480	sd	$10, PT_MPL+(4*8)(sp)	/* store MPL4 */
    481	jr	ra
    482	 sd	$11, PT_MPL+(5*8)(sp)	/* store MPL5 */
    483octeon_mult_save3_end:
    484	EXPORT(octeon_mult_save3_end)
    485	END(octeon_mult_save3)
    486	.set pop
    487
    488/*
    489 * void octeon_mult_restore()
    490 * sp is assumed to point to a struct pt_regs
    491 *
    492 * NOTE: This is called in RESTORE_TEMP in stackframe.h.
    493 */
    494	.p2align 7
    495	.set push
    496	.set noreorder
    497	LEAF(octeon_mult_restore)
    498	jr	ra
    499	 nop
    500	.space 30 * 4, 0
    501octeon_mult_restore_end:
    502	EXPORT(octeon_mult_restore_end)
    503	END(octeon_mult_restore)
    504
    505	LEAF(octeon_mult_restore2)
    506	ld	v0, PT_MPL(sp)        	/* MPL0 */
    507	ld	v1, PT_MPL+8(sp)      	/* MPL1 */
    508	ld	k0, PT_MPL+16(sp)     	/* MPL2 */
    509	/* Restore the multiplier state */
    510	ld	k1, PT_MTP+16(sp)     	/* P2 */
    511	mtm0	v0			/* MPL0 */
    512	ld	v0, PT_MTP+8(sp)	/* P1 */
    513	mtm1	v1			/* MPL1 */
    514	ld	v1, PT_MTP(sp)   	/* P0 */
    515	mtm2	k0			/* MPL2 */
    516	mtp2	k1			/* P2 */
    517	mtp1	v0			/* P1 */
    518	jr	ra
    519	 mtp0	v1			/* P0 */
    520octeon_mult_restore2_end:
    521	EXPORT(octeon_mult_restore2_end)
    522	END(octeon_mult_restore2)
    523
    524	LEAF(octeon_mult_restore3)
    525	ld	$12, PT_MPL+(0*8)(sp)	/* read MPL0 */
    526	ld	$13, PT_MPL+(3*8)(sp)	/* read MPL3 */
    527	ld	$10, PT_MPL+(1*8)(sp)	/* read MPL1 */
    528	ld	$11, PT_MPL+(4*8)(sp)	/* read MPL4 */
    529	.word	0x718d0008
    530	/* mtm0	$12, $13		   restore MPL0 and MPL3 */
    531	ld	$12, PT_MPL+(2*8)(sp)	/* read MPL2 */
    532	.word	0x714b000c
    533	/* mtm1	$10, $11		   restore MPL1 and MPL4 */
    534	ld	$13, PT_MPL+(5*8)(sp)	/* read MPL5 */
    535	ld	$10, PT_MTP+(0*8)(sp)	/* read P0 */
    536	ld	$11, PT_MTP+(3*8)(sp)	/* read P3 */
    537	.word	0x718d000d
    538	/* mtm2	$12, $13		   restore MPL2 and MPL5 */
    539	ld	$12, PT_MTP+(1*8)(sp)	/* read P1 */
    540	.word	0x714b0009
    541	/* mtp0	$10, $11		   restore P0 and P3 */
    542	ld	$13, PT_MTP+(4*8)(sp)	/* read P4 */
    543	ld	$10, PT_MTP+(2*8)(sp)	/* read P2 */
    544	ld	$11, PT_MTP+(5*8)(sp)	/* read P5 */
    545	.word	0x718d000a
    546	/* mtp1	$12, $13		   restore P1 and P4 */
    547	jr	ra
    548	.word	0x714b000b
    549	/* mtp2	$10, $11		   restore P2 and P5 */
    550
    551octeon_mult_restore3_end:
    552	EXPORT(octeon_mult_restore3_end)
    553	END(octeon_mult_restore3)
    554	.set pop