unicore32 additional architecture files: low-level lib: uaccess

This patch implements low-level uaccess libraries.

Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Acked-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
GuanXuetao 2011-02-26 18:49:26 +08:00
parent 28bab059a2
commit 77c93b2f23
8 changed files with 648 additions and 0 deletions

View file

@ -0,0 +1,47 @@
/*
* linux/arch/unicore32/include/asm/uaccess.h
*
* Code specific to PKUnity SoC and UniCore ISA
*
* Copyright (C) 2001-2010 GUAN Xue-tao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __UNICORE_UACCESS_H__
#define __UNICORE_UACCESS_H__
#include <linux/thread_info.h>
#include <linux/errno.h>
#include <asm/memory.h>
#include <asm/system.h>
#define __copy_from_user __copy_from_user
#define __copy_to_user __copy_to_user
#define __strncpy_from_user __strncpy_from_user
#define __strnlen_user __strnlen_user
#define __clear_user __clear_user
#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
#define __user_ok(addr, size) (((size) <= TASK_SIZE) \
&& ((addr) <= TASK_SIZE - (size)))
#define __access_ok(addr, size) (__kernel_ok || __user_ok((addr), (size)))
extern unsigned long __must_check
__copy_from_user(void *to, const void __user *from, unsigned long n);
extern unsigned long __must_check
__copy_to_user(void __user *to, const void *from, unsigned long n);
extern unsigned long __must_check
__clear_user(void __user *addr, unsigned long n);
extern unsigned long __must_check
__strncpy_from_user(char *to, const char __user *from, unsigned long count);
extern unsigned long
__strnlen_user(const char __user *s, long n);
#include <asm-generic/uaccess.h>
extern int fixup_exception(struct pt_regs *regs);
#endif /* __UNICORE_UACCESS_H__ */

View file

@ -0,0 +1,57 @@
/*
* linux/arch/unicore32/lib/clear_user.S
*
* Code specific to PKUnity SoC and UniCore ISA
*
* Copyright (C) 2001-2010 GUAN Xue-tao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
.text
/* Prototype: int __clear_user(void *addr, size_t sz)
* Purpose : clear some user memory
* Params : addr - user memory address to clear
* : sz - number of bytes to clear
* Returns : number of bytes NOT cleared
*/
WEAK(__clear_user)
stm.w (lr), [sp-]
stm.w (r1), [sp-]
mov r2, #0
csub.a r1, #4
bsl 2f
and.a ip, r0, #3
beq 1f
csub.a ip, #2
strusr r2, r0, 1
strusr r2, r0, 1, el
strusr r2, r0, 1, sl
rsub ip, ip, #4
sub r1, r1, ip @ 7 6 5 4 3 2 1
1: sub.a r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
strusr r2, r0, 4, ns, rept=2
bns 1b
add.a r1, r1, #4 @ 3 2 1 0 -1 -2 -3
strusr r2, r0, 4, ns
2: cand.a r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
strusr r2, r0, 1, ne, rept=2
cand.a r1, #1 @ x1 x0 x1 x0 x1 x0 x1
beq 3f
USER( stb.u r2, [r0])
3: mov r0, #0
ldm.w (r1), [sp]+
ldm.w (pc), [sp]+
ENDPROC(__clear_user)
.pushsection .fixup,"ax"
.align 0
9001: ldm.w (r0), [sp]+
ldm.w (pc), [sp]+
.popsection

View file

@ -0,0 +1,108 @@
/*
* linux/arch/unicore32/lib/copy_from_user.S
*
* Code specific to PKUnity SoC and UniCore ISA
*
* Copyright (C) 2001-2010 GUAN Xue-tao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Prototype:
*
* size_t __copy_from_user(void *to, const void *from, size_t n)
*
* Purpose:
*
* copy a block to kernel memory from user memory
*
* Params:
*
* to = kernel memory
* from = user memory
* n = number of bytes to copy
*
* Return value:
*
* Number of bytes NOT copied.
*/
.macro ldr1w ptr reg abort
ldrusr \reg, \ptr, 4, abort=\abort
.endm
.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
100: ldm.w (\reg1, \reg2, \reg3, \reg4), [\ptr]+
.pushsection __ex_table, "a"
.align 3
.long 100b, \abort
.popsection
.endm
.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
100: ldm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
.pushsection __ex_table, "a"
.align 3
.long 100b, \abort
.popsection
.endm
.macro ldr1b ptr reg cond=al abort
ldrusr \reg, \ptr, 1, \cond, abort=\abort
.endm
.macro str1w ptr reg abort
stw.w \reg, [\ptr]+, #4
.endm
.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
stm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
.endm
.macro str1b ptr reg cond=al abort
.ifnc \cond, al
b\cond 201f
b 202f
.endif
201: stb.w \reg, [\ptr]+, #1
202:
.endm
.macro enter
mov r3, #0
stm.w (r0, r2, r3), [sp-]
.endm
.macro exit
add sp, sp, #8
ldm.w (r0), [sp]+
mov pc, lr
.endm
.text
ENTRY(__copy_from_user)
#include "copy_template.S"
ENDPROC(__copy_from_user)
.pushsection .fixup,"ax"
.align 0
copy_abort_preamble
ldm.w (r1, r2), [sp]+
sub r3, r0, r1
rsub r2, r3, r2
stw r2, [sp]
mov r1, #0
b.l memset
ldw.w r0, [sp]+, #4
copy_abort_end
.popsection

View file

@ -0,0 +1,39 @@
/*
* linux/arch/unicore32/lib/copy_page.S
*
* Code specific to PKUnity SoC and UniCore ISA
*
* Copyright (C) 2001-2010 GUAN Xue-tao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* ASM optimised string functions
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <generated/asm-offsets.h>
#include <asm/cache.h>
#define COPY_COUNT (PAGE_SZ/256)
.text
.align 5
/*
* UniCore optimised copy_page routine
*/
ENTRY(copy_page)
stm.w (r17 - r19, lr), [sp-]
mov r17, r0
mov r18, r1
mov r19, #COPY_COUNT
1:
.rept 4
ldm.w (r0 - r15), [r18]+
stm.w (r0 - r15), [r17]+
.endr
sub.a r19, r19, #1
bne 1b
ldm.w (r17 - r19, pc), [sp]+
ENDPROC(copy_page)

View file

@ -0,0 +1,214 @@
/*
* linux/arch/unicore32/lib/copy_template.S
*
* Code specific to PKUnity SoC and UniCore ISA
*
* Copyright (C) 2001-2010 GUAN Xue-tao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* Theory of operation
* -------------------
*
* This file provides the core code for a forward memory copy used in
* the implementation of memcopy(), copy_to_user() and copy_from_user().
*
* The including file must define the following accessor macros
* according to the need of the given function:
*
* ldr1w ptr reg abort
*
* This loads one word from 'ptr', stores it in 'reg' and increments
* 'ptr' to the next word. The 'abort' argument is used for fixup tables.
*
* ldr4w ptr reg1 reg2 reg3 reg4 abort
* ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
*
* This loads four or eight words starting from 'ptr', stores them
* in provided registers and increments 'ptr' past those words.
* The'abort' argument is used for fixup tables.
*
* ldr1b ptr reg cond abort
*
* Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
* It also must apply the condition code if provided, otherwise the
* "al" condition is assumed by default.
*
* str1w ptr reg abort
* str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
* str1b ptr reg cond abort
*
* Same as their ldr* counterparts, but data is stored to 'ptr' location
* rather than being loaded.
*
* enter
*
* Preserve the provided registers on the stack plus any additional
* data as needed by the implementation including this code. Called
* upon code entry.
*
* exit
*
* Restore registers with the values previously saved with the
* 'preserv' macro. Called upon code termination.
*/
enter
sub.a r2, r2, #4
bsl 8f
and.a ip, r0, #3
bne 9f
and.a ip, r1, #3
bne 10f
1: sub.a r2, r2, #(28)
stm.w (r5 - r8), [sp-]
bsl 5f
3:
4: ldr8w r1, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
sub.a r2, r2, #32
str8w r0, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
beg 3b
5: and.a ip, r2, #28
rsub ip, ip, #32
beq 7f
add pc, pc, ip @ C is always clear here
nop
ldr1w r1, r3, abort=20f
ldr1w r1, r4, abort=20f
ldr1w r1, r5, abort=20f
ldr1w r1, r6, abort=20f
ldr1w r1, r7, abort=20f
ldr1w r1, r8, abort=20f
ldr1w r1, r11, abort=20f
add pc, pc, ip
nop
str1w r0, r3, abort=20f
str1w r0, r4, abort=20f
str1w r0, r5, abort=20f
str1w r0, r6, abort=20f
str1w r0, r7, abort=20f
str1w r0, r8, abort=20f
str1w r0, r11, abort=20f
7: ldm.w (r5 - r8), [sp]+
8: mov.a r2, r2 << #31
ldr1b r1, r3, ne, abort=21f
ldr1b r1, r4, ea, abort=21f
ldr1b r1, r10, ea, abort=21f
str1b r0, r3, ne, abort=21f
str1b r0, r4, ea, abort=21f
str1b r0, r10, ea, abort=21f
exit
9: rsub ip, ip, #4
csub.a ip, #2
ldr1b r1, r3, sg, abort=21f
ldr1b r1, r4, eg, abort=21f
ldr1b r1, r11, abort=21f
str1b r0, r3, sg, abort=21f
str1b r0, r4, eg, abort=21f
sub.a r2, r2, ip
str1b r0, r11, abort=21f
bsl 8b
and.a ip, r1, #3
beq 1b
10: andn r1, r1, #3
csub.a ip, #2
ldr1w r1, r11, abort=21f
beq 17f
bsg 18f
.macro forward_copy_shift a b
sub.a r2, r2, #28
bsl 14f
11: stm.w (r5 - r9), [sp-]
12:
ldr4w r1, r4, r5, r6, r7, abort=19f
mov r3, r11 pull #\a
sub.a r2, r2, #32
ldr4w r1, r8, r9, r10, r11, abort=19f
or r3, r3, r4 push #\b
mov r4, r4 pull #\a
or r4, r4, r5 push #\b
mov r5, r5 pull #\a
or r5, r5, r6 push #\b
mov r6, r6 pull #\a
or r6, r6, r7 push #\b
mov r7, r7 pull #\a
or r7, r7, r8 push #\b
mov r8, r8 pull #\a
or r8, r8, r9 push #\b
mov r9, r9 pull #\a
or r9, r9, r10 push #\b
mov r10, r10 pull #\a
or r10, r10, r11 push #\b
str8w r0, r3, r4, r5, r6, r7, r8, r9, r10, , abort=19f
beg 12b
ldm.w (r5 - r9), [sp]+
14: and.a ip, r2, #28
beq 16f
15: mov r3, r11 pull #\a
ldr1w r1, r11, abort=21f
sub.a ip, ip, #4
or r3, r3, r11 push #\b
str1w r0, r3, abort=21f
bsg 15b
16: sub r1, r1, #(\b / 8)
b 8b
.endm
forward_copy_shift a=8 b=24
17: forward_copy_shift a=16 b=16
18: forward_copy_shift a=24 b=8
/*
* Abort preamble and completion macros.
* If a fixup handler is required then those macros must surround it.
* It is assumed that the fixup code will handle the private part of
* the exit macro.
*/
.macro copy_abort_preamble
19: ldm.w (r5 - r9), [sp]+
b 21f
299: .word 0 @ store lr
@ to avoid function call in fixup
20: ldm.w (r5 - r8), [sp]+
21:
adr r1, 299b
stw lr, [r1]
.endm
.macro copy_abort_end
adr lr, 299b
ldw pc, [lr]
.endm

View file

@ -0,0 +1,96 @@
/*
* linux/arch/unicore32/lib/copy_to_user.S
*
* Code specific to PKUnity SoC and UniCore ISA
*
* Copyright (C) 2001-2010 GUAN Xue-tao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Prototype:
*
* size_t __copy_to_user(void *to, const void *from, size_t n)
*
* Purpose:
*
* copy a block to user memory from kernel memory
*
* Params:
*
* to = user memory
* from = kernel memory
* n = number of bytes to copy
*
* Return value:
*
* Number of bytes NOT copied.
*/
.macro ldr1w ptr reg abort
ldw.w \reg, [\ptr]+, #4
.endm
.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
ldm.w (\reg1, \reg2, \reg3, \reg4), [\ptr]+
.endm
.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
ldm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
.endm
.macro ldr1b ptr reg cond=al abort
notcond \cond, .+8
ldb.w \reg, [\ptr]+, #1
.endm
.macro str1w ptr reg abort
strusr \reg, \ptr, 4, abort=\abort
.endm
.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
100: stm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
.pushsection __ex_table, "a"
.long 100b, \abort
.popsection
.endm
.macro str1b ptr reg cond=al abort
strusr \reg, \ptr, 1, \cond, abort=\abort
.endm
.macro enter
mov r3, #0
stm.w (r0, r2, r3), [sp-]
.endm
.macro exit
add sp, sp, #8
ldm.w (r0), [sp]+
mov pc, lr
.endm
.text
WEAK(__copy_to_user)
#include "copy_template.S"
ENDPROC(__copy_to_user)
.pushsection .fixup,"ax"
.align 0
copy_abort_preamble
ldm.w (r1, r2, r3), [sp]+
sub r0, r0, r1
rsub r0, r0, r2
copy_abort_end
.popsection

View file

@ -0,0 +1,45 @@
/*
* linux/arch/unicore32/lib/strncpy_from_user.S
*
* Code specific to PKUnity SoC and UniCore ISA
*
* Copyright (C) 2001-2010 GUAN Xue-tao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/errno.h>
.text
.align 5
/*
* Copy a string from user space to kernel space.
* r0 = dst, r1 = src, r2 = byte length
* returns the number of characters copied (strlen of copied string),
* -EFAULT on exception, or "len" if we fill the whole buffer
*/
ENTRY(__strncpy_from_user)
mov ip, r1
1: sub.a r2, r2, #1
ldrusr r3, r1, 1, ns
bfs 2f
stb.w r3, [r0]+, #1
cxor.a r3, #0
bne 1b
sub r1, r1, #1 @ take NUL character out of count
2: sub r0, r1, ip
mov pc, lr
ENDPROC(__strncpy_from_user)
.pushsection .fixup,"ax"
.align 0
9001: mov r3, #0
stb r3, [r0+], #0 @ null terminate
mov r0, #-EFAULT
mov pc, lr
.popsection

View file

@ -0,0 +1,42 @@
/*
* linux/arch/unicore32/lib/strnlen_user.S
*
* Code specific to PKUnity SoC and UniCore ISA
*
* Copyright (C) 2001-2010 GUAN Xue-tao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/errno.h>
.text
.align 5
/* Prototype: unsigned long __strnlen_user(const char *str, long n)
* Purpose : get length of a string in user memory
* Params : str - address of string in user memory
* Returns : length of string *including terminator*
* or zero on exception, or n + 1 if too long
*/
ENTRY(__strnlen_user)
mov r2, r0
1:
ldrusr r3, r0, 1
cxor.a r3, #0
beq 2f
sub.a r1, r1, #1
bne 1b
add r0, r0, #1
2: sub r0, r0, r2
mov pc, lr
ENDPROC(__strnlen_user)
.pushsection .fixup,"ax"
.align 0
9001: mov r0, #0
mov pc, lr
.popsection