From: Michal Simek <monstr@monstr.eu>
To: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arch@vger.kernel.org,
Remis Lima Baima <remis.developer@googlemail.com>,
linux-kernel@vger.kernel.org,
Russell King <rmk+lkml@arm.linux.org.uk>
Subject: Re: [PATCH V3] asm-generic: add a generic uaccess.h
Date: Mon, 04 May 2009 08:07:25 +0200 [thread overview]
Message-ID: <49FE861D.5050808@monstr.eu> (raw)
In-Reply-To: <200905011513.25344.arnd@arndb.de>
Arnd Bergmann wrote:
> This adds a new asm-generic/uaccess.h file that should be usable
> by both all NOMMU architectures out of the box. Architectures with
> an MMU should override the __access_ok(), __copy_from_user() and
> __copy_to_user definitions with their own functions to provide
> correct exception handling.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>
> diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
> new file mode 100644
> index 0000000..deb1722
> --- /dev/null
> +++ b/include/asm-generic/uaccess.h
> @@ -0,0 +1,319 @@
> +#ifndef __ASM_GENERIC_UACCESS_H
> +#define __ASM_GENERIC_UACCESS_H
> +
> +/*
> + * User space memory access functions, these should work
> + * on a ny machine that has kernel and user data in the same
> + * address space, e.g. all NOMMU machines.
> + */
> +#include <linux/sched.h>
> +#include <linux/mm.h>
> +#include <linux/string.h>
> +
> +#include <asm/segment.h>
> +
> +#ifndef get_fs
> +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
> +#define KERNEL_DS MAKE_MM_SEG(~0UL)
> +#define USER_DS MAKE_MM_SEG(TASK_SIZE - 1)
> +
> +#define get_ds() (KERNEL_DS)
> +#define get_fs() (current_thread_info()->addr_limit)
> +
> +static inline void set_fs(mm_segment_t fs)
> +{
> + current_thread_info()->addr_limit = fs;
> +}
> +#endif
This part should be rewrite to this style.
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
#ifndef KERNEL_DS
#define KERNEL_DS MAKE_MM_SEG(~0UL)
#endif
#ifndef USER_DS
#define USER_DS MAKE_MM_SEG(TASK_SIZE - 1)
#endif
#ifndef get_fs
#define get_ds() (KERNEL_DS)
#define get_fs() (current_thread_info()->addr_limit)
static inline void set_fs(mm_segment_t fs)
{
current_thread_info()->addr_limit = fs;
}
#endif
What do you think?
Michal
> +
> +#define segment_eq(a, b) ((a).seg == (b).seg)
> +
> +#define VERIFY_READ 0
> +#define VERIFY_WRITE 1
> +
> +#define access_ok(type, addr, size) __access_ok((unsigned long)(addr),(size))
> +
> +/*
> + * The architecture should really override this if possible, at least
> + * doing a check on the get_fs()
> + */
> +#ifndef __access_ok
> +static inline int __access_ok(unsigned long addr, unsigned long size)
> +{
> + return 1;
> +}
> +#endif
> +
> +/*
> + * The exception table consists of pairs of addresses: the first is the
> + * address of an instruction that is allowed to fault, and the second is
> + * the address at which the program should continue. No registers are
> + * modified, so it is entirely up to the continuation code to figure out
> + * what to do.
> + *
> + * All the routines below use bits of fixup code that are out of line
> + * with the main instruction path. This means when everything is well,
> + * we don't even have to jump over them. Further, they do not intrude
> + * on our cache or tlb entries.
> + */
> +
> +struct exception_table_entry
> +{
> + unsigned long insn, fixup;
> +};
> +
> +/* Returns 0 if exception not found and fixup otherwise. */
> +extern unsigned long search_exception_table(unsigned long);
> +
> +/*
> + * architectures with an MMU should override these two
> + */
> +#ifndef __copy_from_user
> +static inline __must_check long __copy_from_user(void *to,
> + const void __user * from, unsigned long n)
> +{
> + if (__builtin_constant_p(n)) {
> + switch(n) {
> + case 1:
> + *(u8 *)to = *(u8 __force *)from;
> + return 0;
> + case 2:
> + *(u16 *)to = *(u16 __force *)from;
> + return 0;
> + case 4:
> + *(u32 *)to = *(u32 __force *)from;
> + return 0;
> +#ifdef CONFIG_64BIT
> + case 8:
> + *(u64 *)to = *(u64 __force *)from;
> + return 0;
> +#endif
> + default:
> + break;
> + }
> + }
> +
> + memcpy(to, (const void __force *)from, n);
> + return 0;
> +}
> +#endif
> +
> +#ifndef __copy_to_user
> +static inline __must_check long __copy_to_user(void __user *to,
> + const void *from, unsigned long n)
> +{
> + if (__builtin_constant_p(n)) {
> + switch(n) {
> + case 1:
> + *(u8 __force *)to = *(u8 *)from;
> + return 0;
> + case 2:
> + *(u16 __force *)to = *(u16 *)from;
> + return 0;
> + case 4:
> + *(u32 __force *)to = *(u32 *)from;
> + return 0;
> +#ifdef CONFIG_64BIT
> + case 8:
> + *(u64 __force *)to = *(u64 *)from;
> + return 0;
> +#endif
> + default:
> + break;
> + }
> + }
> +
> + memcpy((void __force *)to, from, n);
> + return 0;
> +}
> +#endif
> +
> +/*
> + * These are the main single-value transfer routines. They automatically
> + * use the right size if we just have the right pointer type.
> + * This version just falls back to copy_{from,to}_user, which should
> + * provide a fast-path for small values.
> + */
> +#define __put_user(x, ptr) \
> +({ \
> + __typeof__(*(ptr)) __x = (x); \
> + int __pu_err = -EFAULT; \
> + __chk_user_ptr(ptr); \
> + switch (sizeof (*(ptr))) { \
> + case 1: \
> + case 2: \
> + case 4: \
> + case 8: \
> + __pu_err = __put_user_fn(sizeof (*(ptr)), \
> + ptr, &__x); \
> + break; \
> + default: \
> + __put_user_bad(); \
> + break; \
> + } \
> + __pu_err; \
> +})
> +
> +#define put_user(x, ptr) \
> +({ \
> + might_sleep(); \
> + __access_ok(ptr, sizeof (*ptr)) ? \
> + __put_user(x, ptr) : \
> + -EFAULT; \
> +})
> +
> +static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
> +{
> + size = __copy_to_user(ptr, x, size);
> + return size ? -EFAULT : size;
> +}
> +
> +extern int __put_user_bad(void) __attribute__((noreturn));
> +
> +#define __get_user(x, ptr) \
> +({ \
> + int __gu_err = -EFAULT; \
> + __chk_user_ptr(ptr); \
> + switch (sizeof(*(ptr))) { \
> + case 1: { \
> + unsigned char __x; \
> + __gu_err = __get_user_fn(sizeof (*(ptr)), \
> + ptr, &__x); \
> + (x) = *(__force __typeof__(*(ptr)) *) &__x; \
> + break; \
> + }; \
> + case 2: { \
> + unsigned short __x; \
> + __gu_err = __get_user_fn(sizeof (*(ptr)), \
> + ptr, &__x); \
> + (x) = *(__force __typeof__(*(ptr)) *) &__x; \
> + break; \
> + }; \
> + case 4: { \
> + unsigned int __x; \
> + __gu_err = __get_user_fn(sizeof (*(ptr)), \
> + ptr, &__x); \
> + (x) = *(__force __typeof__(*(ptr)) *) &__x; \
> + break; \
> + }; \
> + case 8: { \
> + unsigned long long __x; \
> + __gu_err = __get_user_fn(sizeof (*(ptr)), \
> + ptr, &__x); \
> + (x) = *(__force __typeof__(*(ptr)) *) &__x; \
> + break; \
> + }; \
> + default: \
> + __get_user_bad(); \
> + break; \
> + } \
> + __gu_err; \
> +})
> +
> +#define get_user(x, ptr) \
> +({ \
> + might_sleep(); \
> + __access_ok(ptr, sizeof (*ptr)) ? \
> + __get_user(x, ptr) : \
> + -EFAULT; \
> +})
> +
> +static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
> +{
> + size = __copy_from_user(x, ptr, size);
> + return size ? -EFAULT : size;
> +}
> +
> +extern int __get_user_bad(void) __attribute__((noreturn));
> +
> +#ifndef __copy_from_user_inatomic
> +#define __copy_from_user_inatomic __copy_from_user
> +#endif
> +
> +#ifndef __copy_to_user_inatomic
> +#define __copy_to_user_inatomic __copy_to_user
> +#endif
> +
> +static inline long copy_from_user(void *to,
> + const void __user * from, unsigned long n)
> +{
> + might_sleep();
> + if (__access_ok(from, n))
> + return __copy_from_user(to, from, n);
> + else
> + return n;
> +}
> +
> +static inline long copy_to_user(void __user *to,
> + const void *from, unsigned long n)
> +{
> + might_sleep();
> + if (__access_ok(to, n))
> + return __copy_to_user(to, from, n);
> + else
> + return n;
> +}
> +
> +/*
> + * Copy a null terminated string from userspace.
> + */
> +#ifndef __strncpy_from_user
> +static inline long
> +__strncpy_from_user(char *dst, const char __user *src, long count)
> +{
> + char *tmp;
> + strncpy(dst, (const char __force *)src, count);
> + for (tmp = dst; *tmp && count > 0; tmp++, count--)
> + ;
> + return (tmp - dst);
> +}
> +#endif
> +
> +static inline long
> +strncpy_from_user(char *dst, const char __user *src, long count)
> +{
> + if (!__access_ok(src, 1))
> + return -EFAULT;
> + return __strncpy_from_user(dst, src, count);
> +}
> +
> +/*
> + * Return the size of a string (including the ending 0)
> + *
> + * Return 0 on exception, a value greater than N if too long
> + */
> +#ifndef strnlen_user
> +static inline long strnlen_user(const char __user *src, long n)
> +{
> + return strlen((void * __force)src) + 1;
> +}
> +#endif
> +
> +static inline long strlen_user(const char __user *src)
> +{
> + return strnlen_user(src, 32767);
> +}
> +
> +/*
> + * Zero Userspace
> + */
> +#ifndef __clear_user
> +static inline __must_check unsigned long
> +__clear_user(void __user *to, unsigned long n)
> +{
> + memset((void __force *)to, 0, n);
> + return 0;
> +}
> +#endif
> +
> +static inline __must_check unsigned long
> +clear_user(void __user *to, unsigned long n)
> +{
> + might_sleep();
> + if (!__access_ok(to, n))
> + return n;
> +
> + return __clear_user(to, n);
> +}
> +
> +#endif /* __ASM_GENERIC_UACCESS_H */
--
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
next prev parent reply other threads:[~2009-05-04 6:07 UTC|newest]
Thread overview: 111+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-30 15:34 [PATCH 00/27] more non-ABI asm-generic headers Arnd Bergmann
2009-04-30 15:34 ` Arnd Bergmann
2008-11-06 12:08 ` [PATCH 01/27] asm-generic: rename atomic.h to atomic-long.h Arnd Bergmann
2008-11-06 12:08 ` Arnd Bergmann
2009-04-30 16:06 ` Ingo Molnar
2009-04-30 16:06 ` Ingo Molnar
2008-11-06 12:24 ` [PATCH 03/27] asm-generic: make pci.h usable directly Arnd Bergmann
2008-11-06 12:24 ` Arnd Bergmann
2008-11-06 13:16 ` [PATCH 04/27] asm-generic: add legacy I/O header files Arnd Bergmann
2008-11-06 13:16 ` Arnd Bergmann
[not found] ` <c1a198be0904302309w4154f97dqddd0b2df1924a821@mail.gmail.com>
2009-05-01 12:22 ` Arnd Bergmann
2009-05-01 12:25 ` Michal Simek
2009-05-01 12:37 ` Russell King
2009-05-01 12:53 ` Arnd Bergmann
2009-05-01 13:14 ` Alan Cox
2009-05-01 13:20 ` Arnd Bergmann
2009-05-01 13:40 ` Alan Cox
2009-05-01 13:09 ` Alan Cox
2009-05-01 13:29 ` Arnd Bergmann
2009-05-01 13:44 ` Alan Cox
2009-05-01 13:56 ` Arnd Bergmann
2009-05-01 14:03 ` Alan Cox
2009-05-01 14:07 ` Arnd Bergmann
2009-05-01 12:36 ` Russell King
2008-11-06 13:38 ` [PATCH 05/27] asm-generic: add generic io.h Arnd Bergmann
2008-11-06 13:38 ` Arnd Bergmann
2009-05-04 7:07 ` Geert Uytterhoeven
2009-05-04 7:07 ` Geert Uytterhoeven
2009-05-04 10:48 ` Arnd Bergmann
2008-11-06 13:40 ` [PATCH 07/27] asm-generic: add minimal cache description Arnd Bergmann
2008-11-06 13:40 ` Arnd Bergmann
[not found] ` <c1a198be0904302303h73c5168fi73f8dc24dc677965@mail.gmail.com>
2009-05-01 12:27 ` Arnd Bergmann
2009-05-01 12:52 ` Michal Simek
2008-11-06 15:10 ` [PATCH 09/27] asm-generic: add generic NOMMU versions of some headers Arnd Bergmann
2008-11-06 15:10 ` Arnd Bergmann
2008-11-06 15:26 ` [PATCH 10/27] asm-generic: rename page.h to getorder.h Arnd Bergmann
2008-11-06 15:26 ` Arnd Bergmann
2008-11-06 15:31 ` [PATCH 12/27] asm-generic: add a NOMMU uaccess.h Arnd Bergmann
2008-11-06 15:31 ` Arnd Bergmann
2009-05-01 10:07 ` Michal Simek
2009-05-01 10:22 ` Russell King
[not found] ` <c1a198be0904302337x714621d8xc4685a634c5cf222@mail.gmail.com>
2009-05-01 12:36 ` Arnd Bergmann
2009-05-01 12:36 ` Arnd Bergmann
2009-05-01 12:38 ` Michal Simek
2009-05-01 13:13 ` [PATCH V3] asm-generic: add a generic uaccess.h Arnd Bergmann
2009-05-01 13:47 ` Michal Simek
2009-05-01 14:06 ` Arnd Bergmann
2009-05-01 14:11 ` Michal Simek
2009-05-04 6:07 ` Michal Simek [this message]
2009-05-04 10:32 ` Arnd Bergmann
2009-05-04 7:24 ` [PATCH 12/27] asm-generic: add a NOMMU uaccess.h Geert Uytterhoeven
2008-11-07 20:43 ` [PATCH 14/27] asm-generic: make bitops.h usable Arnd Bergmann
2008-11-07 20:43 ` Arnd Bergmann
2008-11-08 10:37 ` [PATCH 15/27] asm-generic: Add missing generic tlb_flush definition Arnd Bergmann
2008-11-08 10:37 ` Arnd Bergmann
2009-03-31 13:30 ` [PATCH 17/27] add generic lib/checksum.c Arnd Bergmann
2009-03-31 13:30 ` Arnd Bergmann
2009-04-30 22:35 ` Jan-Benedict Glaw
2009-05-01 9:14 ` Arnd Bergmann
2009-05-01 9:20 ` Russell King
2009-05-01 9:23 ` Michal Simek
2009-05-01 9:35 ` Arnd Bergmann
2009-05-01 9:37 ` Michal Simek
2009-04-01 12:35 ` [PATCH 19/27] microblaze: make syscall_table implementation generic Arnd Bergmann
2009-04-01 12:35 ` Arnd Bergmann
2009-04-14 13:12 ` [PATCH 20/27] microblaze: use the generic lib/checksum.c Remis Lima Baima
2009-04-14 13:12 ` Remis Lima Baima
2009-04-15 13:00 ` [PATCH 23/27] microblaze: convert all simple headers to use asm-generic Remis Lima Baima
2009-04-15 13:00 ` Remis Lima Baima
2009-04-15 15:28 ` [PATCH 22/27] microblaze: don't include asm/mmu.h in hw_exception_handler Arnd Bergmann
2009-04-15 15:28 ` Arnd Bergmann
2009-04-20 11:53 ` [PATCH 25/27] microblaze: use generic uaccess.h Remis Lima Baima
2009-04-20 11:53 ` Remis Lima Baima
2009-04-27 11:04 ` [PATCH 06/27] asm-generic: clean up asm-generic/io.h Remis Lima Baima
2009-04-27 11:04 ` Remis Lima Baima
2009-04-27 11:10 ` [PATCH 26/27] microblaze: make io.h use asm-generic/io.h Remis Lima Baima
2009-04-27 11:10 ` Remis Lima Baima
2009-04-27 12:42 ` [PATCH 27/27] microblaze: use generic system.h Remis Lima Baima
2009-04-27 12:42 ` Remis Lima Baima
2009-04-27 15:18 ` [PATCH 21/27] microblaze: use generic swab.h Arnd Bergmann
2009-04-27 15:18 ` Arnd Bergmann
2009-04-27 15:34 ` [PATCH 16/27] asm-generic: introduce generic syscalls.h Arnd Bergmann
2009-04-27 15:34 ` Arnd Bergmann
2009-04-27 15:38 ` [PATCH 24/27] microblaze: use generic dma-mapping.h Arnd Bergmann
2009-04-27 15:38 ` Arnd Bergmann
2009-04-28 14:15 ` [PATCH 08/27] asm-generic: add generic versions of common headers Arnd Bergmann
2009-04-28 14:15 ` Arnd Bergmann
2009-04-30 16:41 ` David Miller
2009-04-30 16:49 ` Arnd Bergmann
2009-04-30 16:51 ` David Miller
2009-04-30 17:07 ` Arnd Bergmann
2009-04-30 17:12 ` David Miller
2009-04-30 17:34 ` Arnd Bergmann
2009-04-30 17:39 ` David Miller
2009-04-30 18:01 ` Sam Ravnborg
2009-04-29 13:33 ` [PATCH 13/27] asm-generic: make uaccess.h usable by mmu archs Arnd Bergmann
2009-04-29 13:33 ` Arnd Bergmann
2009-04-29 14:25 ` [PATCH 18/27] microblaze: use generic syscalls.h Arnd Bergmann
2009-04-29 14:25 ` Arnd Bergmann
2009-04-29 14:51 ` [PATCH 02/27] asm-generic: add generic atomic.h Arnd Bergmann
2009-04-29 14:51 ` Arnd Bergmann
2009-04-29 14:55 ` [PATCH 11/27] asm-generic: add generic page.h Arnd Bergmann
2009-04-29 14:55 ` Arnd Bergmann
2009-05-04 7:11 ` Geert Uytterhoeven
2009-04-30 16:39 ` [PATCH 0/2] use generic headers in x86 Arnd Bergmann
2009-04-30 16:40 ` [PATCH 1/2] x86: two small fixes in termios.h Arnd Bergmann
2009-04-30 16:42 ` [PATCH 2/2] x86: adapt simple headers to use generic headers Arnd Bergmann
2009-05-03 11:17 ` [PATCH 00/27] more non-ABI asm-generic headers Geert Uytterhoeven
2009-05-04 14:32 ` Arnd Bergmann
2009-05-08 14:04 ` Geert Uytterhoeven
2009-05-14 11:59 ` Arnd Bergmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=49FE861D.5050808@monstr.eu \
--to=monstr@monstr.eu \
--cc=arnd@arndb.de \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=remis.developer@googlemail.com \
--cc=rmk+lkml@arm.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.