162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * User memory copy functions for kernel
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci * The right way to do this involves valignb
1062306a36Sopenharmony_ci * The easy way to do this is only speed up src/dest similar alignment.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/*
1462306a36Sopenharmony_ci * Copy to/from user are the same, except that for packets with a load and
1562306a36Sopenharmony_ci * a store, I don't know how to tell which kind of exception we got.
1662306a36Sopenharmony_ci * Therefore, we duplicate the function, and handle faulting addresses
1762306a36Sopenharmony_ci * differently for each function
1862306a36Sopenharmony_ci */
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * copy from user: loads can fault
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci#define src_sav r13
2462306a36Sopenharmony_ci#define dst_sav r12
2562306a36Sopenharmony_ci#define src_dst_sav r13:12
2662306a36Sopenharmony_ci#define d_dbuf r15:14
2762306a36Sopenharmony_ci#define w_dbuf r15
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define dst r0
3062306a36Sopenharmony_ci#define src r1
3162306a36Sopenharmony_ci#define bytes r2
3262306a36Sopenharmony_ci#define loopcount r5
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define FUNCNAME raw_copy_from_user
3562306a36Sopenharmony_ci#include "copy_user_template.S"
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	/* LOAD FAULTS from COPY_FROM_USER */
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	/* Alignment loop.  r2 has been updated. Return it. */
4062306a36Sopenharmony_ci	.falign
4162306a36Sopenharmony_ci1009:
4262306a36Sopenharmony_ci2009:
4362306a36Sopenharmony_ci4009:
4462306a36Sopenharmony_ci	{
4562306a36Sopenharmony_ci		r0 = r2
4662306a36Sopenharmony_ci		jumpr r31
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci	/* Normal copy loops. Do epilog. Use src-src_sav to compute distance */
4962306a36Sopenharmony_ci	/* X - (A - B) == X + B - A */
5062306a36Sopenharmony_ci	.falign
5162306a36Sopenharmony_ci8089:
5262306a36Sopenharmony_ci	{
5362306a36Sopenharmony_ci		memd(dst) = d_dbuf
5462306a36Sopenharmony_ci		r2 += sub(src_sav,src)
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci	{
5762306a36Sopenharmony_ci		r0 = r2
5862306a36Sopenharmony_ci		jumpr r31
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci	.falign
6162306a36Sopenharmony_ci4089:
6262306a36Sopenharmony_ci	{
6362306a36Sopenharmony_ci		memw(dst) = w_dbuf
6462306a36Sopenharmony_ci		r2 += sub(src_sav,src)
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci	{
6762306a36Sopenharmony_ci		r0 = r2
6862306a36Sopenharmony_ci		jumpr r31
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci	.falign
7162306a36Sopenharmony_ci2089:
7262306a36Sopenharmony_ci	{
7362306a36Sopenharmony_ci		memh(dst) = w_dbuf
7462306a36Sopenharmony_ci		r2 += sub(src_sav,src)
7562306a36Sopenharmony_ci	}
7662306a36Sopenharmony_ci	{
7762306a36Sopenharmony_ci		r0 = r2
7862306a36Sopenharmony_ci		jumpr r31
7962306a36Sopenharmony_ci	}
8062306a36Sopenharmony_ci	.falign
8162306a36Sopenharmony_ci1089:
8262306a36Sopenharmony_ci	{
8362306a36Sopenharmony_ci		memb(dst) = w_dbuf
8462306a36Sopenharmony_ci		r2 += sub(src_sav,src)
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci	{
8762306a36Sopenharmony_ci		r0 = r2
8862306a36Sopenharmony_ci		jumpr r31
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	/* COPY FROM USER: only loads can fail */
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	.section __ex_table,"a"
9462306a36Sopenharmony_ci	.long 1000b,1009b
9562306a36Sopenharmony_ci	.long 2000b,2009b
9662306a36Sopenharmony_ci	.long 4000b,4009b
9762306a36Sopenharmony_ci	.long 8080b,8089b
9862306a36Sopenharmony_ci	.long 4080b,4089b
9962306a36Sopenharmony_ci	.long 2080b,2089b
10062306a36Sopenharmony_ci	.long 1080b,1089b
10162306a36Sopenharmony_ci	.previous
102