18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/linkage.h>
78c2ecf20Sopenharmony_ci#include <asm/stackframe.h>
88c2ecf20Sopenharmony_ci#include <asm/asm.h>
98c2ecf20Sopenharmony_ci#include <asm/asmmacro.h>
108c2ecf20Sopenharmony_ci#include <asm/regdef.h>
118c2ecf20Sopenharmony_ci#include "kvm_compat.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define RESUME_HOST	(1 << 1)
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define GGPR_OFFSET(x)	(KVM_ARCH_GGPR + 8*x)
168c2ecf20Sopenharmony_ci#define PT_GPR_OFFSET(x)	(PT_R0 + 8*x)
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	.text
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci.macro kvm_save_guest_gprs base
218c2ecf20Sopenharmony_ci	.irp n,1,2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
228c2ecf20Sopenharmony_ci	KVM_LONG_S	$r\n, \base, GGPR_OFFSET(\n)
238c2ecf20Sopenharmony_ci	.endr
248c2ecf20Sopenharmony_ci.endm
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci.macro kvm_restore_guest_gprs base
278c2ecf20Sopenharmony_ci	.irp n,1,2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
288c2ecf20Sopenharmony_ci	KVM_LONG_L	$r\n, \base, GGPR_OFFSET(\n)
298c2ecf20Sopenharmony_ci	.endr
308c2ecf20Sopenharmony_ci.endm
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci.macro kvm_save_host_gpr base
338c2ecf20Sopenharmony_ci	.irp n,1,2,3,22,23,24,25,26,27,28,29,30,31
348c2ecf20Sopenharmony_ci	KVM_LONG_S	$r\n, \base, PT_GPR_OFFSET(\n)
358c2ecf20Sopenharmony_ci	.endr
368c2ecf20Sopenharmony_ci.endm
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci.macro kvm_restore_host_gpr base
398c2ecf20Sopenharmony_ci	.irp n,1,2,3,22,23,24,25,26,27,28,29,30,31
408c2ecf20Sopenharmony_ci	KVM_LONG_L	$r\n, \base, PT_GPR_OFFSET(\n)
418c2ecf20Sopenharmony_ci	.endr
428c2ecf20Sopenharmony_ci.endm
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/*
458c2ecf20Sopenharmony_ci * prepare switch to guest
468c2ecf20Sopenharmony_ci * @param:
478c2ecf20Sopenharmony_ci *  KVM_ARCH: kvm_vcpu_arch, don't touch it until 'ertn'
488c2ecf20Sopenharmony_ci *  GPRNUM: KVM_ARCH gpr number
498c2ecf20Sopenharmony_ci *  tmp, tmp1: temp register
508c2ecf20Sopenharmony_ci */
518c2ecf20Sopenharmony_ci.macro kvm_switch_to_guest KVM_ARCH GPRNUM tmp tmp1
528c2ecf20Sopenharmony_ci	/* set host excfg.VS=0, all exceptions share one exception entry */
538c2ecf20Sopenharmony_ci	csrrd	\tmp, KVM_CSR_ECFG
548c2ecf20Sopenharmony_ci	bstrins.w	\tmp, zero, (KVM_ECFG_VS_SHIFT + KVM_ECFG_VS_WIDTH - 1), KVM_ECFG_VS_SHIFT
558c2ecf20Sopenharmony_ci	csrwr	\tmp, KVM_CSR_ECFG
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	/* Load up the new EENTRY */
588c2ecf20Sopenharmony_ci	KVM_LONG_L	\tmp, \KVM_ARCH, KVM_ARCH_GEENTRY
598c2ecf20Sopenharmony_ci	csrwr		\tmp, KVM_CSR_EENTRY
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	/* Set Guest ERA */
628c2ecf20Sopenharmony_ci	KVM_LONG_L	\tmp, \KVM_ARCH, KVM_ARCH_GPC
638c2ecf20Sopenharmony_ci	csrwr		\tmp, KVM_CSR_ERA
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	/* Save host PGDL */
668c2ecf20Sopenharmony_ci	csrrd	\tmp, KVM_CSR_PGDL
678c2ecf20Sopenharmony_ci	KVM_LONG_S	\tmp, \KVM_ARCH, KVM_ARCH_HPGD
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	/* Switch to kvm */
708c2ecf20Sopenharmony_ci	KVM_LONG_L	\tmp1, \KVM_ARCH, KVM_VCPU_KVM - KVM_VCPU_ARCH
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/* Load guest PGDL */
738c2ecf20Sopenharmony_ci	lu12i.w \tmp, KVM_GPGD
748c2ecf20Sopenharmony_ci	srli.w \tmp, \tmp, 12
758c2ecf20Sopenharmony_ci	ldx.d  \tmp, \tmp1, \tmp
768c2ecf20Sopenharmony_ci	csrwr	\tmp, KVM_CSR_PGDL
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	/* Mix GID and RID */
798c2ecf20Sopenharmony_ci	csrrd	\tmp1, KVM_CSR_GSTAT
808c2ecf20Sopenharmony_ci	bstrpick.w	\tmp1, \tmp1, (KVM_GSTAT_GID_SHIFT + KVM_GSTAT_GID_WIDTH - 1), KVM_GSTAT_GID_SHIFT
818c2ecf20Sopenharmony_ci	csrrd	\tmp, KVM_CSR_GTLBC
828c2ecf20Sopenharmony_ci	bstrins.w	\tmp, \tmp1, (KVM_GTLBC_TGID_SHIFT + KVM_GTLBC_TGID_WIDTH - 1), KVM_GTLBC_TGID_SHIFT
838c2ecf20Sopenharmony_ci	csrwr	\tmp, KVM_CSR_GTLBC
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	/*
868c2ecf20Sopenharmony_ci	 * Switch to guest:
878c2ecf20Sopenharmony_ci	 *  GSTAT.PGM = 1, ERRCTL.ISERR = 0, TLBRPRMD.ISTLBR = 0
888c2ecf20Sopenharmony_ci	 *  ertn
898c2ecf20Sopenharmony_ci	 */
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	/*
928c2ecf20Sopenharmony_ci         * Enable intr in root mode with future ertn so that host interrupt
938c2ecf20Sopenharmony_ci         * can be responsed during VM runs
948c2ecf20Sopenharmony_ci         * guest crmd comes from separate gcsr_CRMD register
958c2ecf20Sopenharmony_ci         */
968c2ecf20Sopenharmony_ci	ori	\tmp, zero, KVM_PRMD_PIE
978c2ecf20Sopenharmony_ci	csrxchg	\tmp, \tmp, KVM_CSR_PRMD
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	/* Set PVM bit to setup ertn to guest context */
1008c2ecf20Sopenharmony_ci	ori	\tmp, zero, KVM_GSTAT_PVM
1018c2ecf20Sopenharmony_ci	csrxchg	\tmp, \tmp, KVM_CSR_GSTAT
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	/* Load Guest gprs */
1048c2ecf20Sopenharmony_ci	kvm_restore_guest_gprs	\KVM_ARCH
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	/* Load KVM_ARCH register */
1078c2ecf20Sopenharmony_ci	KVM_LONG_L	\KVM_ARCH, \KVM_ARCH, GGPR_OFFSET(\GPRNUM)
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	ertn
1108c2ecf20Sopenharmony_ci.endm
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci#ifndef	EXCPTION_ENTRY
1138c2ecf20Sopenharmony_ci#define EXCPTION_ENTRY(name)	\
1148c2ecf20Sopenharmony_ci	.globl name ASM_NL	\
1158c2ecf20Sopenharmony_ci	.p2align	12;	\
1168c2ecf20Sopenharmony_ci	name:			\
1178c2ecf20Sopenharmony_ci	.cfi_startproc;
1188c2ecf20Sopenharmony_ci#endif
1198c2ecf20Sopenharmony_ci#ifndef	EXCPTION_ENDPROC
1208c2ecf20Sopenharmony_ci#define EXCPTION_ENDPROC(name)	\
1218c2ecf20Sopenharmony_ci	.cfi_endproc;		\
1228c2ecf20Sopenharmony_ci	SYM_END(name, SYM_T_FUNC)
1238c2ecf20Sopenharmony_ci#endif
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci/* load kvm_vcpu to a2 and store a1 for free use */
1268c2ecf20Sopenharmony_ciEXCPTION_ENTRY(kvm_exception_entry)
1278c2ecf20Sopenharmony_ci	csrwr	a2, KVM_TEMP_KS
1288c2ecf20Sopenharmony_ci	csrrd	a2, KVM_VCPU_KS
1298c2ecf20Sopenharmony_ci	KVM_LONG_ADDI	a2, a2, KVM_VCPU_ARCH
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	/* After save gprs, free to use any gpr */
1328c2ecf20Sopenharmony_ci	kvm_save_guest_gprs	a2
1338c2ecf20Sopenharmony_ci	/* Save guest a2 */
1348c2ecf20Sopenharmony_ci	csrrd	t0, KVM_TEMP_KS
1358c2ecf20Sopenharmony_ci	KVM_LONG_S	t0, a2, GGPR_OFFSET(REG_A2)
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	b	kvm_exit_entry
1388c2ecf20Sopenharmony_ciEXCPTION_ENDPROC(kvm_exception_entry)
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/* a2: kvm_vcpu_arch, a1 is free to use */
1418c2ecf20Sopenharmony_ciSYM_FUNC_START(kvm_exit_entry)
1428c2ecf20Sopenharmony_ci	csrrd	s1, KVM_VCPU_KS
1438c2ecf20Sopenharmony_ci	KVM_LONG_L	s0, s1, KVM_VCPU_RUN
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	csrrd		t0, KVM_CSR_ESTAT
1468c2ecf20Sopenharmony_ci	KVM_LONG_S	t0, a2, KVM_ARCH_HESTAT
1478c2ecf20Sopenharmony_ci	csrrd		t0, KVM_CSR_ERA
1488c2ecf20Sopenharmony_ci	KVM_LONG_S	t0, a2, KVM_ARCH_GPC
1498c2ecf20Sopenharmony_ci	csrrd		t0, KVM_CSR_BADV
1508c2ecf20Sopenharmony_ci	KVM_LONG_S	t0, a2, KVM_ARCH_HBADV
1518c2ecf20Sopenharmony_ci	csrrd		t0, KVM_CSR_BADI
1528c2ecf20Sopenharmony_ci	KVM_LONG_S	t0, a2, KVM_ARCH_HBADI
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	/* Restore host excfg.VS */
1558c2ecf20Sopenharmony_ci	csrrd		t0, KVM_CSR_ECFG
1568c2ecf20Sopenharmony_ci	KVM_LONG_L	t1, a2, KVM_ARCH_HECFG
1578c2ecf20Sopenharmony_ci	or		t0, t0, t1
1588c2ecf20Sopenharmony_ci	csrwr		t0, KVM_CSR_ECFG
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	/* Restore host eentry */
1618c2ecf20Sopenharmony_ci	KVM_LONG_L	t0, a2, KVM_ARCH_HEENTRY
1628c2ecf20Sopenharmony_ci	csrwr		t0, KVM_CSR_EENTRY
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	/* restore host pgd table */
1658c2ecf20Sopenharmony_ci	KVM_LONG_L	t0, a2, KVM_ARCH_HPGD
1668c2ecf20Sopenharmony_ci	csrwr	t0, KVM_CSR_PGDL
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	/*
1698c2ecf20Sopenharmony_ci	 * Disable PGM bit to enter root mode by default with next ertn
1708c2ecf20Sopenharmony_ci	 */
1718c2ecf20Sopenharmony_ci	ori	t0, zero, KVM_GSTAT_PVM
1728c2ecf20Sopenharmony_ci	csrxchg	zero, t0, KVM_CSR_GSTAT
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	/*
1758c2ecf20Sopenharmony_ci	 * Clear GTLBC.TGID field
1768c2ecf20Sopenharmony_ci	 *       0: for root  tlb update in future tlb instr
1778c2ecf20Sopenharmony_ci         *  others: for guest tlb update like gpa to hpa in future tlb instr
1788c2ecf20Sopenharmony_ci	 */
1798c2ecf20Sopenharmony_ci	csrrd	t0, KVM_CSR_GTLBC
1808c2ecf20Sopenharmony_ci	bstrins.w	t0, zero, KVM_GTLBC_TGID_SHIFT + KVM_GTLBC_TGID_WIDTH - 1, KVM_GTLBC_TGID_SHIFT
1818c2ecf20Sopenharmony_ci	csrwr	t0, KVM_CSR_GTLBC
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	KVM_LONG_L	tp, a2, KVM_ARCH_HGP
1848c2ecf20Sopenharmony_ci	KVM_LONG_L	sp, a2, KVM_ARCH_HSTACK
1858c2ecf20Sopenharmony_ci	/* Restore per cpu base register */
1868c2ecf20Sopenharmony_ci	KVM_LONG_L	$r21, a2, KVM_ARCH_HPERCPU
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	KVM_LONG_ADDI	sp, sp, -PT_SIZE
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	/* Prepare handle exception */
1918c2ecf20Sopenharmony_ci	or		a0, s0, zero
1928c2ecf20Sopenharmony_ci	or		a1, s1, zero
1938c2ecf20Sopenharmony_ci	KVM_LONG_L	t8, a2, KVM_ARCH_HANDLE_EXIT
1948c2ecf20Sopenharmony_ci	jirl		ra,t8, 0
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	or	a2, s1, zero
1978c2ecf20Sopenharmony_ci	KVM_LONG_ADDI	a2, a2, KVM_VCPU_ARCH
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	andi	t0, a0, RESUME_HOST
2008c2ecf20Sopenharmony_ci	bnez	t0, ret_to_host
2018c2ecf20Sopenharmony_ci	INT_S	zero, a2, KVM_ARCH_ISHYPCALL
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ciret_to_guest:
2048c2ecf20Sopenharmony_ci	/* Save per cpu register again, maybe switched to another cpu */
2058c2ecf20Sopenharmony_ci	KVM_LONG_S	$r21, a2, KVM_ARCH_HPERCPU
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	/* Save kvm_vcpu to kscratch */
2088c2ecf20Sopenharmony_ci	csrwr	s1, KVM_VCPU_KS
2098c2ecf20Sopenharmony_ci	kvm_switch_to_guest a2 REG_A2 t0 t1
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ciret_to_host:
2128c2ecf20Sopenharmony_ci	KVM_LONG_L  a2, a2, KVM_ARCH_HSTACK
2138c2ecf20Sopenharmony_ci	addi.d  a2, a2, -PT_SIZE
2148c2ecf20Sopenharmony_ci	srai.w  a3, a0, 2
2158c2ecf20Sopenharmony_ci	or      a0, a3, zero
2168c2ecf20Sopenharmony_ci	kvm_restore_host_gpr    a2
2178c2ecf20Sopenharmony_ci	jirl    zero, ra, 0
2188c2ecf20Sopenharmony_ciSYM_FUNC_END(kvm_exit_entry)
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci/*
2218c2ecf20Sopenharmony_ci * int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu)
2228c2ecf20Sopenharmony_ci *
2238c2ecf20Sopenharmony_ci * @register_param:
2248c2ecf20Sopenharmony_ci *  a0: kvm_run* run
2258c2ecf20Sopenharmony_ci *  a1: kvm_vcpu* vcpu
2268c2ecf20Sopenharmony_ci */
2278c2ecf20Sopenharmony_ciSYM_FUNC_START(kvm_enter_guest)
2288c2ecf20Sopenharmony_ci	/* allocate space in stack bottom */
2298c2ecf20Sopenharmony_ci	KVM_LONG_ADDI	a2, sp, -PT_SIZE
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* save host gprs */
2328c2ecf20Sopenharmony_ci	kvm_save_host_gpr a2
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	/* save host crmd,prmd csr to stack */
2358c2ecf20Sopenharmony_ci	csrrd		a3, KVM_CSR_CRMD
2368c2ecf20Sopenharmony_ci	KVM_LONG_S	a3, a2, PT_CRMD
2378c2ecf20Sopenharmony_ci	csrrd		a3, KVM_CSR_PRMD
2388c2ecf20Sopenharmony_ci	KVM_LONG_S	a3, a2, PT_PRMD
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	KVM_LONG_ADDI	a2, a1, KVM_VCPU_ARCH
2418c2ecf20Sopenharmony_ci	KVM_LONG_S	sp, a2, KVM_ARCH_HSTACK
2428c2ecf20Sopenharmony_ci	KVM_LONG_S	tp, a2, KVM_ARCH_HGP
2438c2ecf20Sopenharmony_ci	/* Save per cpu base register */
2448c2ecf20Sopenharmony_ci	KVM_LONG_S	$r21, a2, KVM_ARCH_HPERCPU
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	/* Save kvm_vcpu to kscratch */
2478c2ecf20Sopenharmony_ci	csrwr	a1, KVM_VCPU_KS
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	kvm_switch_to_guest	a2 REG_A2 t0 t1
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ciSYM_FUNC_END(kvm_enter_guest)
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ciSYM_FUNC_START(__kvm_save_fpu)
2548c2ecf20Sopenharmony_ci	fpu_save_csr    a0 t1
2558c2ecf20Sopenharmony_ci	fpu_save_double a0 t1
2568c2ecf20Sopenharmony_ci	fpu_save_cc     a0 t1 t2
2578c2ecf20Sopenharmony_ci	jirl    zero, ra, 0
2588c2ecf20Sopenharmony_ciSYM_FUNC_END(__kvm_save_fpu)
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ciSYM_FUNC_START(__kvm_restore_fpu)
2618c2ecf20Sopenharmony_ci	fpu_restore_double a0 t1                # clobbers t1
2628c2ecf20Sopenharmony_ci	fpu_restore_cc     a0 t1 t2             # clobbers t1, t2
2638c2ecf20Sopenharmony_ci	fpu_restore_csr    a0 t1
2648c2ecf20Sopenharmony_ci	jirl    zero, ra, 0
2658c2ecf20Sopenharmony_ciSYM_FUNC_END(__kvm_restore_fpu)
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_HAS_LSX
2688c2ecf20Sopenharmony_ciSYM_FUNC_START(__kvm_save_lsx)
2698c2ecf20Sopenharmony_ci	fpu_save_csr    a0 t1
2708c2ecf20Sopenharmony_ci	fpu_save_cc     a0 t1 t2
2718c2ecf20Sopenharmony_ci	lsx_save_data   a0 t1
2728c2ecf20Sopenharmony_ci	jirl    zero, ra, 0
2738c2ecf20Sopenharmony_ciSYM_FUNC_END(__kvm_save_lsx)
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ciSYM_FUNC_START(__kvm_restore_lsx)
2768c2ecf20Sopenharmony_ci	lsx_restore_data a0 t1
2778c2ecf20Sopenharmony_ci	fpu_restore_cc   a0 t1 t2                # clobbers t1, t2
2788c2ecf20Sopenharmony_ci	fpu_restore_csr  a0 t1
2798c2ecf20Sopenharmony_ci	jirl    zero, ra, 0
2808c2ecf20Sopenharmony_ciSYM_FUNC_END(__kvm_restore_lsx)
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ciSYM_FUNC_START(__kvm_restore_lsx_upper)
2838c2ecf20Sopenharmony_ci	lsx_restore_all_upper a0 t0 t1
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	jirl    zero, ra, 0
2868c2ecf20Sopenharmony_ciSYM_FUNC_END(__kvm_restore_lsx_upper)
2878c2ecf20Sopenharmony_ci#endif
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_HAS_LASX
2908c2ecf20Sopenharmony_ciSYM_FUNC_START(__kvm_save_lasx)
2918c2ecf20Sopenharmony_ci	fpu_save_csr    a0 t1
2928c2ecf20Sopenharmony_ci	fpu_save_cc     a0 t1 t2
2938c2ecf20Sopenharmony_ci	lasx_save_data  a0 t1
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	jirl    zero, ra, 0
2968c2ecf20Sopenharmony_ciSYM_FUNC_END(__kvm_save_lasx)
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ciSYM_FUNC_START(__kvm_restore_lasx)
2998c2ecf20Sopenharmony_ci	lasx_restore_data a0 t1
3008c2ecf20Sopenharmony_ci	fpu_restore_cc    a0 t1 t2                # clobbers t1, t2
3018c2ecf20Sopenharmony_ci	fpu_restore_csr   a0 t1
3028c2ecf20Sopenharmony_ci	jirl    zero, ra, 0
3038c2ecf20Sopenharmony_ciSYM_FUNC_END(__kvm_restore_lasx)
3048c2ecf20Sopenharmony_ci#endif
305