Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <abi/reg_ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #define MTCR_MASK	0xFC00FFE0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #define MFCR_MASK	0xFC00FFE0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #define MTCR_DIST	0xC0006420
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #define MFCR_DIST	0xC0006020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * fpu_libc_helper() is to help libc to excute:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *  - mfcr %a, cr<1, 2>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *  - mfcr %a, cr<2, 2>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *  - mtcr %a, cr<1, 2>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *  - mtcr %a, cr<2, 2>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) int fpu_libc_helper(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	int fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	unsigned long instrptr, regx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	unsigned long index = 0, tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	unsigned long tinstr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	u16 instr_hi, instr_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	instrptr = instruction_pointer(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	if (instrptr & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	fault = __get_user(instr_low, (u16 *)instrptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	if (fault)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	fault = __get_user(instr_hi, (u16 *)(instrptr + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	if (fault)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	tinstr = instr_hi | ((unsigned long)instr_low << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	if (((tinstr >> 21) & 0x1F) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	if ((tinstr & MTCR_MASK) == MTCR_DIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		index = (tinstr >> 16) & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		if (index > 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		tmp = tinstr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		if (tmp > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		regx =  *(&regs->a0 + index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		if (tmp == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 			mtcr("cr<1, 2>", regx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		else if (tmp == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			mtcr("cr<2, 2>", regx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		regs->pc += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if ((tinstr & MFCR_MASK) == MFCR_DIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		index = tinstr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		if (index > 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		tmp = ((tinstr >> 16) & 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		if (tmp > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		if (tmp == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 			regx = mfcr("cr<1, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		else if (tmp == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 			regx = mfcr("cr<2, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		*(&regs->a0 + index) = regx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		regs->pc += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) void fpu_fpe(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	int sig, code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	unsigned int fesr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	fesr = mfcr("cr<2, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	sig = SIGFPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	code = FPE_FLTUNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	if (fesr & FPE_ILLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		sig = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		code = ILL_ILLOPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	} else if (fesr & FPE_IDC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		sig = SIGILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		code = ILL_ILLOPN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	} else if (fesr & FPE_FEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		sig = SIGFPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		if (fesr & FPE_IOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			code = FPE_FLTINV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		else if (fesr & FPE_DZC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			code = FPE_FLTDIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		else if (fesr & FPE_UFC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 			code = FPE_FLTUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		else if (fesr & FPE_OFC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			code = FPE_FLTOVF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		else if (fesr & FPE_IXC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			code = FPE_FLTRES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	force_sig_fault(sig, code, (void __user *)regs->pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define FMFVR_FPU_REGS(vrx, vry)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	"fmfvrl %0, "#vrx"\n"		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	"fmfvrh %1, "#vrx"\n"		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	"fmfvrl %2, "#vry"\n"		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	"fmfvrh %3, "#vry"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define FMTVR_FPU_REGS(vrx, vry)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	"fmtvrl "#vrx", %0\n"		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	"fmtvrh "#vrx", %1\n"		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	"fmtvrl "#vry", %2\n"		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	"fmtvrh "#vry", %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define STW_FPU_REGS(a, b, c, d)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	"stw    %0, (%4, "#a")\n"	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	"stw    %1, (%4, "#b")\n"	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	"stw    %2, (%4, "#c")\n"	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	"stw    %3, (%4, "#d")\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define LDW_FPU_REGS(a, b, c, d)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	"ldw    %0, (%4, "#a")\n"	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	"ldw    %1, (%4, "#b")\n"	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	"ldw    %2, (%4, "#c")\n"	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	"ldw    %3, (%4, "#d")\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) void save_to_user_fp(struct user_fp *user_fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	unsigned long flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	unsigned long tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	unsigned long *fpregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	local_irq_save(flg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	tmp1 = mfcr("cr<1, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	tmp2 = mfcr("cr<2, 2>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	user_fp->fcr = tmp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	user_fp->fesr = tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	fpregs = &user_fp->vr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #ifdef CONFIG_CPU_HAS_FPUV2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #ifdef CONFIG_CPU_HAS_VDSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		"vstmu.32    vr0-vr3,   (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		"vstmu.32    vr4-vr7,   (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		"vstmu.32    vr8-vr11,  (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		"vstmu.32    vr12-vr15, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		"fstmu.64    vr16-vr31, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		: "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		"fstmu.64    vr0-vr31,  (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		: "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	unsigned long tmp3, tmp4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		FMFVR_FPU_REGS(vr0, vr1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		STW_FPU_REGS(0, 4, 16, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		FMFVR_FPU_REGS(vr2, vr3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		STW_FPU_REGS(32, 36, 48, 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		FMFVR_FPU_REGS(vr4, vr5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		STW_FPU_REGS(64, 68, 80, 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		FMFVR_FPU_REGS(vr6, vr7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		STW_FPU_REGS(96, 100, 112, 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		"addi	%4, 128\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		FMFVR_FPU_REGS(vr8, vr9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		STW_FPU_REGS(0, 4, 16, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		FMFVR_FPU_REGS(vr10, vr11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		STW_FPU_REGS(32, 36, 48, 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		FMFVR_FPU_REGS(vr12, vr13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		STW_FPU_REGS(64, 68, 80, 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		FMFVR_FPU_REGS(vr14, vr15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		STW_FPU_REGS(96, 100, 112, 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		: "=a"(tmp1), "=a"(tmp2), "=a"(tmp3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		  "=a"(tmp4), "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	local_irq_restore(flg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) void restore_from_user_fp(struct user_fp *user_fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	unsigned long flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	unsigned long tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	unsigned long *fpregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	local_irq_save(flg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	tmp1 = user_fp->fcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	tmp2 = user_fp->fesr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	mtcr("cr<1, 2>", tmp1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	mtcr("cr<2, 2>", tmp2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	fpregs = &user_fp->vr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #ifdef CONFIG_CPU_HAS_FPUV2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #ifdef CONFIG_CPU_HAS_VDSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		"vldmu.32    vr0-vr3,   (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		"vldmu.32    vr4-vr7,   (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		"vldmu.32    vr8-vr11,  (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		"vldmu.32    vr12-vr15, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		"fldmu.64    vr16-vr31, (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		: "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		"fldmu.64    vr0-vr31,  (%0)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		: "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	unsigned long tmp3, tmp4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		LDW_FPU_REGS(0, 4, 16, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		FMTVR_FPU_REGS(vr0, vr1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		LDW_FPU_REGS(32, 36, 48, 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		FMTVR_FPU_REGS(vr2, vr3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		LDW_FPU_REGS(64, 68, 80, 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		FMTVR_FPU_REGS(vr4, vr5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		LDW_FPU_REGS(96, 100, 112, 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		FMTVR_FPU_REGS(vr6, vr7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		"addi	%4, 128\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		LDW_FPU_REGS(0, 4, 16, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		FMTVR_FPU_REGS(vr8, vr9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		LDW_FPU_REGS(32, 36, 48, 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		FMTVR_FPU_REGS(vr10, vr11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		LDW_FPU_REGS(64, 68, 80, 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		FMTVR_FPU_REGS(vr12, vr13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		LDW_FPU_REGS(96, 100, 112, 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		FMTVR_FPU_REGS(vr14, vr15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		: "=a"(tmp1), "=a"(tmp2), "=a"(tmp3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		  "=a"(tmp4), "+a"(fpregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	local_irq_restore(flg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }