|
@@ -411,3 +411,79 @@ extern void __do_clear_user(void);
|
|
extern inline long
|
|
extern inline long
|
|
__clear_user(void __user *to, long len)
|
|
__clear_user(void __user *to, long len)
|
|
{
|
|
{
|
|
|
|
+ register void __user * __cl_to __asm__("$6") = to;
|
|
|
|
+ register long __cl_len __asm__("$0") = len;
|
|
|
|
+ __asm__ __volatile__(
|
|
|
|
+ __module_call(28, 2, __do_clear_user)
|
|
|
|
+ : "=r"(__cl_len), "=r"(__cl_to)
|
|
|
|
+ : __module_address(__do_clear_user)
|
|
|
|
+ "0"(__cl_len), "1"(__cl_to)
|
|
|
|
+ : "$1","$2","$3","$4","$5","$28","memory");
|
|
|
|
+ return __cl_len;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+extern inline long
|
|
|
|
+clear_user(void __user *to, long len)
|
|
|
|
+{
|
|
|
|
+ if (__access_ok((unsigned long)to, len, get_fs()))
|
|
|
|
+ len = __clear_user(to, len);
|
|
|
|
+ return len;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#undef __module_address
|
|
|
|
+#undef __module_call
|
|
|
|
+
|
|
|
|
+#define user_addr_max() \
|
|
|
|
+ (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL)
|
|
|
|
+
|
|
|
|
+extern long strncpy_from_user(char *dest, const char __user *src, long count);
|
|
|
|
+extern __must_check long strlen_user(const char __user *str);
|
|
|
|
+extern __must_check long strnlen_user(const char __user *str, long n);
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * About the exception table:
|
|
|
|
+ *
|
|
|
|
+ * - insn is a 32-bit pc-relative offset from the faulting insn.
|
|
|
|
+ * - nextinsn is a 16-bit offset off of the faulting instruction
|
|
|
|
+ * (not off of the *next* instruction as branches are).
|
|
|
|
+ * - errreg is the register in which to place -EFAULT.
|
|
|
|
+ * - valreg is the final target register for the load sequence
|
|
|
|
+ * and will be zeroed.
|
|
|
|
+ *
|
|
|
|
+ * Either errreg or valreg may be $31, in which case nothing happens.
|
|
|
|
+ *
|
|
|
|
+ * The exception fixup information "just so happens" to be arranged
|
|
|
|
+ * as in a MEM format instruction. This lets us emit our three
|
|
|
|
+ * values like so:
|
|
|
|
+ *
|
|
|
|
+ * lda valreg, nextinsn(errreg)
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+struct exception_table_entry
|
|
|
|
+{
|
|
|
|
+ signed int insn;
|
|
|
|
+ union exception_fixup {
|
|
|
|
+ unsigned unit;
|
|
|
|
+ struct {
|
|
|
|
+ signed int nextinsn : 16;
|
|
|
|
+ unsigned int errreg : 5;
|
|
|
|
+ unsigned int valreg : 5;
|
|
|
|
+ } bits;
|
|
|
|
+ } fixup;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/* Returns the new pc */
|
|
|
|
+#define fixup_exception(map_reg, _fixup, pc) \
|
|
|
|
+({ \
|
|
|
|
+ if ((_fixup)->fixup.bits.valreg != 31) \
|
|
|
|
+ map_reg((_fixup)->fixup.bits.valreg) = 0; \
|
|
|
|
+ if ((_fixup)->fixup.bits.errreg != 31) \
|
|
|
|
+ map_reg((_fixup)->fixup.bits.errreg) = -EFAULT; \
|
|
|
|
+ (pc) + (_fixup)->fixup.bits.nextinsn; \
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+#define ARCH_HAS_SORT_EXTABLE
|
|
|
|
+#define ARCH_HAS_SEARCH_EXTABLE
|
|
|
|
+
|
|
|
|
+#endif /* __ALPHA_UACCESS_H */
|