162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * User memory copying routines for the Hexagon Kernel
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/* The right way to do this involves valignb
962306a36Sopenharmony_ci * The easy way to do this is only speed up src/dest similar alignment.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * Copy to/from user are the same, except that for packets with a load and
1462306a36Sopenharmony_ci * a store, I don't know how to tell which kind of exception we got.
1562306a36Sopenharmony_ci * Therefore, we duplicate the function, and handle faulting addresses
1662306a36Sopenharmony_ci * differently for each function
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*
2062306a36Sopenharmony_ci * copy to user: stores can fault
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_ci#define src_sav r13
2362306a36Sopenharmony_ci#define dst_sav r12
2462306a36Sopenharmony_ci#define src_dst_sav r13:12
2562306a36Sopenharmony_ci#define d_dbuf r15:14
2662306a36Sopenharmony_ci#define w_dbuf r15
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define dst r0
2962306a36Sopenharmony_ci#define src r1
3062306a36Sopenharmony_ci#define bytes r2
3162306a36Sopenharmony_ci#define loopcount r5
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define FUNCNAME raw_copy_to_user
3462306a36Sopenharmony_ci#include "copy_user_template.S"
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	/* STORE FAULTS from COPY_TO_USER */
3762306a36Sopenharmony_ci	.falign
3862306a36Sopenharmony_ci1109:
3962306a36Sopenharmony_ci2109:
4062306a36Sopenharmony_ci4109:
4162306a36Sopenharmony_ci	/* Alignment loop.  r2 has been updated.  Return it. */
4262306a36Sopenharmony_ci	{
4362306a36Sopenharmony_ci		r0 = r2
4462306a36Sopenharmony_ci		jumpr r31
4562306a36Sopenharmony_ci	}
4662306a36Sopenharmony_ci	/* Normal copy loops.  Use dst-dst_sav to compute distance */
4762306a36Sopenharmony_ci	/* dst holds best write, no need to unwind any loops */
4862306a36Sopenharmony_ci	/* X - (A - B) == X + B - A */
4962306a36Sopenharmony_ci	.falign
5062306a36Sopenharmony_ci8189:
5162306a36Sopenharmony_ci8199:
5262306a36Sopenharmony_ci4189:
5362306a36Sopenharmony_ci4199:
5462306a36Sopenharmony_ci2189:
5562306a36Sopenharmony_ci2199:
5662306a36Sopenharmony_ci1189:
5762306a36Sopenharmony_ci1199:
5862306a36Sopenharmony_ci	{
5962306a36Sopenharmony_ci		r2 += sub(dst_sav,dst)
6062306a36Sopenharmony_ci	}
6162306a36Sopenharmony_ci	{
6262306a36Sopenharmony_ci		r0 = r2
6362306a36Sopenharmony_ci		jumpr r31
6462306a36Sopenharmony_ci	}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	/* COPY TO USER: only stores can fail */
6762306a36Sopenharmony_ci	.section __ex_table,"a"
6862306a36Sopenharmony_ci	.long 1100b,1109b
6962306a36Sopenharmony_ci	.long 2100b,2109b
7062306a36Sopenharmony_ci	.long 4100b,4109b
7162306a36Sopenharmony_ci	.long 8180b,8189b
7262306a36Sopenharmony_ci	.long 8190b,8199b
7362306a36Sopenharmony_ci	.long 4180b,4189b
7462306a36Sopenharmony_ci	.long 4190b,4199b
7562306a36Sopenharmony_ci	.long 2180b,2189b
7662306a36Sopenharmony_ci	.long 2190b,2199b
7762306a36Sopenharmony_ci	.long 1180b,1189b
7862306a36Sopenharmony_ci	.long 1190b,1199b
7962306a36Sopenharmony_ci	.previous
80