From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
To: Ingo Molnar <mingo@elte.hu>, Thomas Gleixner <tglx@linutronix.de>,
"H. Peter Anvin" <hpa@zytor.com>
Cc: linux-kernel@vger.kernel.org
Subject: [RFC -tip 2/4] x86: uaccess: introduce __{get|put}_user exception handling framework
Date: Mon, 22 Dec 2008 21:22:56 -0800 [thread overview]
Message-ID: <495075B0.9020104@ct.jp.nec.com> (raw)
In-Reply-To: <49507534.5080401@ct.jp.nec.com>
From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
Impact: introduce new framework
Introduce exception handling framework.
__{get|put}_user_ex_try() begins exception block and
__{get|put}_user_ex_catch() ends block and if an exception occurred in this
block using __{get|put}_user_ex, direct jump to __{get|put}_user_ex_catch()
and err is set to specified value.
int func()
{
int err = 0;
__get_user_ex_try(&err, -EFAULT);
__get_user_ex(...);
__get_user_ex(...);
:
__get_user_ex_catch();
return err;
}
Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
---
arch/x86/include/asm/uaccess.h | 110 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 1a38180..cf293fe 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -199,12 +199,21 @@ extern int __get_user_bad(void);
: "=r" (err) \
: "A" (x), "r" (addr), "i" (-EFAULT), "0" (err))
+#define __put_user_asm_ex_u64(x, addr, label) \
+ asm volatile("1: movl %%eax,0(%1)\n" \
+ "2: movl %%edx,4(%1)\n" \
+ _ASM_EXTABLE(1b, label) \
+ _ASM_EXTABLE(2b, label) \
+ : : "A" (x), "r" (addr))
+
#define __put_user_x8(x, ptr, __ret_pu) \
asm volatile("call __put_user_8" : "=a" (__ret_pu) \
: "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
#else
#define __put_user_asm_u64(x, ptr, retval) \
__put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT)
+#define __put_user_asm_ex_u64(x, addr, label) \
+ __put_user_asm_ex(x, addr, "q", "", "Zr", label)
#define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu)
#endif
@@ -286,6 +295,27 @@ do { \
} \
} while (0)
+#define __put_user_size_ex(x, ptr, size, label) \
+do { \
+ __chk_user_ptr(ptr); \
+ switch (size) { \
+ case 1: \
+ __put_user_asm_ex(x, ptr, "b", "b", "iq", label); \
+ break; \
+ case 2: \
+ __put_user_asm_ex(x, ptr, "w", "w", "ir", label); \
+ break; \
+ case 4: \
+ __put_user_asm_ex(x, ptr, "l", "k", "ir", label); \
+ break; \
+ case 8: \
+ __put_user_asm_ex_u64((__typeof__(*ptr))(x), ptr, label);\
+ break; \
+ default: \
+ __put_user_bad(); \
+ } \
+} while (0)
+
#else
#define __put_user_size(x, ptr, size, retval, errret) \
@@ -311,9 +341,12 @@ do { \
#ifdef CONFIG_X86_32
#define __get_user_asm_u64(x, ptr, retval, errret) (x) = __get_user_bad()
+#define __get_user_asm_ex_u64(x, ptr, label) (x) = __get_user_bad()
#else
#define __get_user_asm_u64(x, ptr, retval, errret) \
__get_user_asm(x, ptr, retval, "q", "", "=r", errret)
+#define __get_user_asm_ex_u64(x, ptr, label) \
+ __get_user_asm_ex(x, ptr, "q", "", "=r", label)
#endif
#define __get_user_size(x, ptr, size, retval, errret) \
@@ -350,6 +383,36 @@ do { \
: "=r" (err), ltype(x) \
: "m" (__m(addr)), "i" (errret), "0" (err))
+#define __get_user_size_ex(x, ptr, size, label) \
+do { \
+ __chk_user_ptr(ptr); \
+ switch (size) { \
+ case 1: \
+ __get_user_asm_ex(x, ptr, "b", "b", "=q", label); \
+ break; \
+ case 2: \
+ __get_user_asm_ex(x, ptr, "w", "w", "=r", label); \
+ break; \
+ case 4: \
+ __get_user_asm_ex(x, ptr, "l", "k", "=r", label); \
+ break; \
+ case 8: \
+ __get_user_asm_ex_u64(x, ptr, label); \
+ break; \
+ default: \
+ (x) = __get_user_bad(); \
+ } \
+} while (0)
+
+#define __get_user_asm_ex(x, addr, itype, rtype, ltype, label) \
+ asm volatile("1: mov"itype" %1,%"rtype"0\n" \
+ ".section .fixup,\"ax\"\n" \
+ "2: xor"itype" %"rtype"0,%"rtype"0\n" \
+ " jmp " #label "\n" \
+ ".previous\n" \
+ _ASM_EXTABLE(1b, 2b) \
+ : ltype(x) : "m" (__m(addr)))
+
#define __put_user_nocheck(x, ptr, size) \
({ \
int __pu_err; \
@@ -366,6 +429,16 @@ do { \
__gu_err; \
})
+#define __put_user_ex_label(x, ptr, size, label) do { \
+ __put_user_size_ex((x), (ptr), (size), label); \
+} while (0)
+
+#define __get_user_ex_label(x, ptr, size, label) do { \
+ unsigned long __gue_val; \
+ __get_user_size_ex((__gue_val), (ptr), (size), label); \
+ (x) = (__force __typeof__(*(ptr)))__gue_val; \
+} while (0)
+
/* FIXME: this hack is definitely wrong -AK */
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct __user *)(x))
@@ -385,6 +458,23 @@ struct __large_struct { unsigned long buf[100]; };
_ASM_EXTABLE(1b, 3b) \
: "=r"(err) \
: ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
+
+#define __put_user_asm_ex(x, addr, itype, rtype, ltype, label) \
+ asm volatile("1: mov"itype" %"rtype"0,%1\n" \
+ _ASM_EXTABLE(1b, label) \
+ : : ltype(x), "m" (__m(addr)))
+
+#define __ex_try_label(err, errval, label, out_label) do { \
+ asm volatile(".section .fixup,\"ax\"\n" \
+ #label ": mov %1,%0\n" \
+ " jmp " #out_label "\n" \
+ ".previous\n" \
+ : "=r" (err) : "i" (errval), "0" (err))
+
+#define __ex_catch_label(label) \
+ asm volatile(#label ":\n"); \
+} while (0)
+
/**
* __get_user: - Get a simple variable from user space, with less checking.
* @x: Variable to store result.
@@ -408,6 +498,16 @@ struct __large_struct { unsigned long buf[100]; };
#define __get_user(x, ptr) \
__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+
+#define __get_user_ex(x, ptr) \
+ __get_user_ex_label((x), (ptr), sizeof(*(ptr)), 880b)
+
+#define __get_user_ex_try(perr, errval) \
+ __ex_try_label((*(perr)), (errval), 880, 881f)
+
+#define __get_user_ex_catch() \
+ __ex_catch_label(881)
+
/**
* __put_user: - Write a simple value into user space, with less checking.
* @x: Value to copy to user space.
@@ -431,6 +531,16 @@ struct __large_struct { unsigned long buf[100]; };
#define __put_user(x, ptr) \
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+#define __put_user_ex(x, ptr) \
+ __put_user_ex_label((__typeof__(*(ptr)))(x), (ptr), \
+ sizeof(*(ptr)), 882b)
+
+#define __put_user_ex_try(perr, errval) \
+ __ex_try_label((*(perr)), (errval), 882, 883f)
+
+#define __put_user_ex_catch() \
+ __ex_catch_label(883)
+
#define __get_user_unaligned __get_user
#define __put_user_unaligned __put_user
--
1.6.0.4
next prev parent reply other threads:[~2008-12-23 5:23 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-23 5:20 [RFC -tip 0/4] x86: improve uaccess in signal Hiroshi Shimamoto
2008-12-23 5:22 ` [RFC -tip 1/4] x86: uaccess: rename __put_user_u64() to __put_user_asm_u64() Hiroshi Shimamoto
2008-12-23 5:22 ` Hiroshi Shimamoto [this message]
2008-12-23 5:38 ` [RFC -tip 2/4] x86: uaccess: introduce __{get|put}_user exception handling framework Brian Gerst
2008-12-23 5:47 ` Hiroshi Shimamoto
2008-12-23 14:30 ` Ingo Molnar
2008-12-23 19:59 ` Hiroshi Shimamoto
2008-12-23 5:23 ` [RFC -tip 3/4] x86: signal: use " Hiroshi Shimamoto
2008-12-23 5:24 ` [RFC -tip 4/4] x86: ia32_signal: " Hiroshi Shimamoto
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=495075B0.9020104@ct.jp.nec.com \
--to=h-shimamoto@ct.jp.nec.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=tglx@linutronix.de \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox